Merge branch 'Test.Study' into Uat.Study

Uat_Study
hang 2023-11-03 12:15:48 +08:00
commit 7ed60bc1d7
54 changed files with 613 additions and 1080 deletions

View File

@ -66,28 +66,28 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.1" />
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.7.0" />
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.7.0" />
<PackageReference Include="EntityFrameworkCore.Triggered.Extensions" Version="3.2.1" />
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.1" />
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.5" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.5" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.6.2" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.6.2" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="1.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.23" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.2" />
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.7.0" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.7.0" />
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.1" />
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
</ItemGroup>
<ItemGroup>

View File

@ -29,6 +29,7 @@ using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Http;
using Autofac.Core;
using DocumentFormat.OpenXml.InkML;
using EasyCaching.Core;
namespace IRaCIS.Core.API
{
@ -112,9 +113,9 @@ namespace IRaCIS.Core.API
//JWT Token 验证
services.AddJWTAuthSetup(_configuration);
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
// EasyCaching 缓存
services.AddEasyCachingSetup();
services.AddEasyCachingSetup(_configuration);
//services.AddDistributedMemoryCache();

View File

@ -1,8 +1,12 @@
using IRaCIS.Core.Application.Triggers;
using Hangfire.SqlServer;
using IRaCIS.Core.Application.Triggers;
using IRaCIS.Core.Infra.EFCore;
using Medallion.Threading;
using Medallion.Threading.SqlServer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;
namespace IRaCIS.Core.API
{
@ -52,6 +56,13 @@ namespace IRaCIS.Core.API
});
//注意区分 easy caching 也有 IDistributedLockProvider
services.AddSingleton<IDistributedLockProvider>(sp =>
{
//var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
});
//services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly);
}

View File

@ -1,17 +1,26 @@
using EasyCaching.Core;
using EasyCaching.Core.Configurations;
using EasyCaching.Interceptor.Castle;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
{
public static class EasyCachingSetup
{
public static void AddEasyCachingSetup(this IServiceCollection services)
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
{
services.AddEasyCaching(options =>
{
options.UseInMemory();
//options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
});
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
}
}

View File

@ -21,7 +21,7 @@ namespace IRaCIS.Core.API
.MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
.MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
.Enrich.WithClientIp()
.Enrich.WithClientAgent()
.Enrich.FromLogContext()
//控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型

View File

@ -1,55 +0,0 @@
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
using System.Linq;
namespace IRaCIS.Core.API
{
public class JsonPatchDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var schemas = swaggerDoc.Components.Schemas.ToList();
foreach (var item in schemas)
{
if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
swaggerDoc.Components.Schemas.Remove(item.Key);
}
swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>
{
{ "op", new OpenApiSchema { Type = "string" } },
{"value", new OpenApiSchema{ Type = "object", Nullable = true } },
{ "path", new OpenApiSchema { Type = "string" } }
}
});
swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema
{
Type = "array",
Items = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" }
},
Description = "Array of operations to perform"
});
foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
.Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
{
foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
path.Value.RequestBody.Content.Remove(item.Key);
var response = path.Value.RequestBody.Content.SingleOrDefault(c => c.Key == "application/json-patch+json");
response.Value.Schema = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" }
};
}
}
}
}

View File

@ -18,7 +18,6 @@ namespace IRaCIS.Core.API
{
public static void AddSwaggerSetup(this IServiceCollection services)
{
services.AddSwaggerExamplesFromAssemblyOf<JsonPatchUserRequestExample>();
services.AddSwaggerGen(options =>
{
@ -63,7 +62,6 @@ namespace IRaCIS.Core.API
// 在header中添加token传递到后台
options.OperationFilter<SecurityRequirementsOperationFilter>();
options.DocumentFilter<JsonPatchDocumentFilter>();
// 添加登录按钮
options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()

View File

@ -23,13 +23,13 @@
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenUserComplexPassword": true,
"OpenSignDocumentBeforeWork": false,
"OpenSignDocumentBeforeWork": true,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"OpenLoginLimit": true,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30
@ -40,7 +40,7 @@
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "study@extimaging.com",
"FromName": "study.extimaging",
"FromName": "研究单位阅片系统",
"AuthorizationCode": "zhanying123",
"SiteUrl": "https://study.extimaging.com/login"
}

View File

@ -57,6 +57,26 @@
"EnableReadDeepClone": true,
"EnableWriteDeepClone": false
}
},
"redis": {
"MaxRdSecond": 120,
"EnableLogging": false,
"LockMs": 5000,
"SleepMs": 300,
"dbconfig": {
"Password": "xc@123456",
"IsSsl": false,
"SslHost": null,
"ConnectionTimeout": 5000,
"AllowAdmin": true,
"Endpoints": [
{
"Host": "47.117.164.182",
"Port": 6379
}
],
"Database": 0
}
}
},
"IRaCISImageStore": {

View File

@ -15,14 +15,14 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591;1587</NoWarn>
<NoWarn>1701;1702;1591;1587</NoWarn>
</PropertyGroup>
<ItemGroup>
<Using Include="IRaCIS.Core.Application;" />
<Using Include="IRaCIS.Core.Application;" />
<Using Include="AutoMapper.QueryableExtensions;" />
<Using Include="Microsoft.EntityFrameworkCore;" />
<Using Include="IRaCIS.Core.Domain.Models;" />
@ -50,60 +50,56 @@
<ItemGroup>
<Content Include="Resources\zh-CN.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="Resources\en-US.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="Resources\zh-CN.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="Resources\en-US.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.1" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.3" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.1" />
<PackageReference Include="EasyCaching.Redis" Version="1.9.1" />
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.7.0" />
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.9.1" />
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
<PackageReference Include="fo-dicom.Codecs" Version="5.1.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="fo-dicom.Drawing" Version="4.0.8" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.0.3" />
<PackageReference Include="FreeSpire.Doc" Version="10.8.0" />
<PackageReference Include="fo-dicom" Version="5.1.1" />
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.0" />
<PackageReference Include="fo-dicom.Codecs" Version="5.10.8" />
<PackageReference Include="FreeSpire.Doc" Version="11.6.0" />
<PackageReference Include="Hangfire.Core" Version="1.8.5" />
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.2" />
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.2">
<TreatAsUsed>true</TreatAsUsed>
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.5" />
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.5">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.2">
<TreatAsUsed>true</TreatAsUsed>
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.5">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.2" />
<PackageReference Include="MailKit" Version="3.4.2" />
<PackageReference Include="MediatR" Version="11.0.0" />
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="MimeKit" Version="3.4.2" />
<PackageReference Include="MiniExcel" Version="1.30.1" />
<PackageReference Include="MiniWord" Version="0.6.1" />
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.5" />
<PackageReference Include="MailKit" Version="4.2.0" />
<PackageReference Include="MediatR" Version="12.1.1" />
<PackageReference Include="MimeKit" Version="4.2.0" />
<PackageReference Include="MiniExcel" Version="1.31.2" />
<PackageReference Include="MiniWord" Version="0.7.0" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.0.0">
<TreatAsUsed>true</TreatAsUsed>
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="NPOI" Version="2.6.0" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.0" />
<PackageReference Include="Quartz" Version="3.5.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
<PackageReference Include="WinSCP" Version="5.21.5" />
<PackageReference Include="NPOI" Version="2.6.2" />
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.1" />
<PackageReference Include="Quartz" Version="3.7.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.11" />
<PackageReference Include="WinSCP" Version="6.1.2" />
</ItemGroup>
<ItemGroup>

View File

@ -9509,11 +9509,6 @@
<member name="T:IRaCIS.Core.Application.Contracts.TrialSiteUserSurveyAddOrEdit">
<summary> TrialSiteUserSurveyAddOrEdit 列表查询参数模型</summary>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.JsonPatchUserRequestExample">
<summary>
实测 标注在服务方法上 没用
</summary>
</member>
<member name="T:IRaCIS.Core.Application.Contracts.TrialSiteEquipmentSurveyService">
<summary>
TrialSiteEquipmentSurveyService

View File

@ -25,6 +25,7 @@ using Quartz;
using IRaCIS.Application.Services.BackGroundJob;
using Magicodes.ExporterAndImporter.Core.Extension;
using Hangfire;
using MassTransit;
namespace IRaCIS.Core.Application.Service.Allocation
{
@ -1229,18 +1230,9 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{
var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in list)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result;
CopyForms(newTask, origenalTask);
}
}
//拷贝后续表单
@ -1248,15 +1240,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{
var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in list)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result;
CopyForms(newTask, origenalTask);
}
}
@ -1352,15 +1336,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{
var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in list)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result;
CopyForms(newTask, origenalTask);
}
}
@ -1370,15 +1346,7 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
{
var list = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in list)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _readingTaskQuestionAnswerRepository.AddRangeAsync(list).Result;
CopyForms(newTask, origenalTask);
}
}
@ -1437,7 +1405,69 @@ namespace IRaCIS.Core.Application.Service.Allocation
return ResponseOutput.Ok();
}
private void CopyForms(VisitTask newTask, VisitTask origenalTask)
{
//自定义
var readingCustomTagList = _repository.Where<ReadingCustomTag>(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in readingCustomTagList)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _repository.AddRangeAsync(readingCustomTagList).Result;
//var readingTaskQuestionMarkList = _repository.Where<ReadingTaskQuestionMark>(t => t.VisitTaskId == origenalTask.Id).ToList();
//foreach (var item in readingTaskQuestionMarkList)
//{
// item.Id = Guid.Empty;
// item.VisitTaskId = newTask.Id;
//}
//_ = _repository.AddRangeAsync(readingTaskQuestionMarkList).Result;
var readingTaskQuestionAnswerList = _repository.Where<ReadingTaskQuestionAnswer>(t => t.VisitTaskId == origenalTask.Id).ToList();
foreach (var item in readingTaskQuestionAnswerList)
{
item.Id = Guid.Empty;
item.VisitTaskId = newTask.Id;
}
_ = _repository.AddRangeAsync(readingTaskQuestionAnswerList).Result;
//ReadingTableAnswerRowInfo ReadingTableQuestionAnswer 一起加
var readingTableAnswerRowInfoList = _repository.Where<ReadingTableAnswerRowInfo>(t => t.VisitTaskId == origenalTask.Id).Include(t => t.LesionAnswerList).ToList();
foreach (var item in readingTableAnswerRowInfoList)
{
var originalVisitTaskId = item.VisitTaskId;
var originalFristAddTaskId = item.FristAddTaskId;
item.Id = NewId.NextSequentialGuid();
item.VisitTaskId = newTask.Id;
item.FristAddTaskId = originalVisitTaskId == originalFristAddTaskId ? newTask.Id : item.FristAddTaskId;
foreach (var item2 in item.LesionAnswerList)
{
item2.Id = Guid.Empty;
item2.RowId = item.Id;
item2.VisitTaskId = newTask.Id;
}
}
_ = _repository.AddRangeAsync(readingTableAnswerRowInfoList).Result;
}
/// <summary>
/// PM 设置任务 退回
/// </summary>

View File

@ -249,7 +249,7 @@ namespace IRaCIS.Application.Services
public async Task<Dictionary<string, List<BasicDicSelectCopy>>> GetBasicDataSelect(string[] searchArray)
{
var searchList = await _dicRepository.Where(t => searchArray.Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo<BasicDicSelectCopy>(_mapper.ConfigurationProvider).ToListAsync();
var searchList = await _dicRepository.Where(t => searchArray.Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo<BasicDicSelectCopy>(_mapper.ConfigurationProvider,new { isEn_Us = _userInfo.IsEn_Us}).ToListAsync();
return searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());

View File

@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Application.Auth;
using AutoMapper;
using IRaCIS.Application.Contracts;
using Nito.AsyncEx;
using Microsoft.Extensions.Options;
namespace IRaCIS.Application.Services
@ -55,7 +54,6 @@ namespace IRaCIS.Application.Services
private readonly AsyncLock _mutex = new AsyncLock();
private readonly SystemEmailSendConfig _systemEmailConfig;

View File

@ -58,7 +58,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap<Dictionary, BasicDicSelectCopy>()
.ForMember(o => o.ParentChildCodeEnum, t => t.MapFrom(u => u.Parent.ChildCodeEnum))
.ForMember(o => o.Value, t => t.MapFrom(u => u.MappedValue))
.ForMember(o => o.Value, t => t.MapFrom(u => isEn_Us? u.Value : u.ValueCN ))
.ForMember(o => o.ParentCode, t => t.MapFrom(u => u.Parent.Code));
CreateMap<Dictionary, BasicDicSelect>()

View File

@ -170,7 +170,7 @@ namespace IRaCIS.Core.Application.Services
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
Name = sysDoc.Name,
Path = sysDoc.Path,
FileType = sysDoc.FileType.MappedValue,
FileType = _userInfo.IsEn_Us? sysDoc.FileType.Value: sysDoc.FileType.ValueCN,
UpdateTime = sysDoc.UpdateTime,
FullFilePath = sysDoc.Path ,

View File

@ -57,7 +57,7 @@ namespace IRaCIS.Core.Application.Services
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == queryTrialDocument.TrialId)
.WhereIf(!string.IsNullOrEmpty(queryTrialDocument.Name), t => t.Name.Contains(queryTrialDocument.Name))
.WhereIf(queryTrialDocument.FileTypeId != null, t => t.FileTypeId == queryTrialDocument.FileTypeId)
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken });
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us=_userInfo.IsEn_Us });
return await trialDocumentQueryable.ToPagedListAsync(queryTrialDocument.PageIndex, queryTrialDocument.PageSize, queryTrialDocument.SortField, queryTrialDocument.Asc);
}
@ -157,7 +157,7 @@ namespace IRaCIS.Core.Application.Services
Name = needConfirmedUserType.SystemDocument.Name,
Path = needConfirmedUserType.SystemDocument.Path,
FileTypeId = needConfirmedUserType.SystemDocument.FileTypeId,
FileType = needConfirmedUserType.SystemDocument.FileType.MappedValue,
FileType = _userInfo.IsEn_Us? needConfirmedUserType.SystemDocument.FileType.Value: needConfirmedUserType.SystemDocument.FileType.ValueCN,
UpdateTime = needConfirmedUserType.SystemDocument.UpdateTime,
FullFilePath = needConfirmedUserType.SystemDocument.Path ,
@ -189,7 +189,7 @@ namespace IRaCIS.Core.Application.Services
Name = trialDoc.Name,
Path = trialDoc.Path,
FileTypeId = trialDoc.FileTypeId,
FileType = trialDoc.FileType.MappedValue,
FileType = _userInfo.IsEn_Us ? trialDoc.FileType.Value: trialDoc.FileType.ValueCN,
UpdateTime = trialDoc.UpdateTime,
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
@ -203,13 +203,35 @@ namespace IRaCIS.Core.Application.Services
};
#region 报错 奇怪的bug
var unionQuery = systemDocumentQueryable.Union(trialDocQueryable)
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId)
.WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null)
.WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null);
.WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId)
.WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null)
.WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null);
var result = await unionQuery.ToPagedListAsync(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
#endregion
#region 临时方案
//var list1 = systemDocumentQueryable
// .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
// .WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId)
// .WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null)
// .WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null).ToList();
//var list2 = trialDocQueryable
// .WhereIf(!string.IsNullOrEmpty(querySystemDocument.Name), t => t.Name.Contains(querySystemDocument.Name))
//.WhereIf(querySystemDocument.FileTypeId != null, t => t.FileTypeId == querySystemDocument.FileTypeId)
//.WhereIf(querySystemDocument.IsSign == true, t => t.ConfirmTime != null)
//.WhereIf(querySystemDocument.IsSign == false, t => t.ConfirmTime == null).ToList();
//var list3 = list1.Union(list2).ToList();
//var result = list3.ToPagedList(querySystemDocument.PageIndex, querySystemDocument.PageSize, querySystemDocument.SortField, querySystemDocument.Asc);
#endregion
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId== querySystemDocument.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped)
.Where(t => t.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id))
@ -311,7 +333,7 @@ namespace IRaCIS.Core.Application.Services
Name = trialDocumentNeedConfirmedUserType.TrialDocument.Name,
Path = trialDocumentNeedConfirmedUserType.TrialDocument.Path,
FileTypeId = trialDocumentNeedConfirmedUserType.TrialDocument.FileTypeId,
FileType = trialDocumentNeedConfirmedUserType.TrialDocument.FileType.MappedValue,
FileType = _userInfo.IsEn_Us ? trialDocumentNeedConfirmedUserType.TrialDocument.FileType.Value : trialDocumentNeedConfirmedUserType.TrialDocument.FileType.ValueCN,
UpdateTime = trialDocumentNeedConfirmedUserType.TrialDocument.UpdateTime,
@ -345,7 +367,7 @@ namespace IRaCIS.Core.Application.Services
SignViewMinimumMinutes = needConfirmEdUserType.SystemDocument.SignViewMinimumMinutes,
Name = needConfirmEdUserType.SystemDocument.Name,
Path = needConfirmEdUserType.SystemDocument.Path,
FileType = needConfirmEdUserType.SystemDocument.FileType.MappedValue,
FileType = _userInfo.IsEn_Us ? needConfirmEdUserType.SystemDocument.FileType.Value : needConfirmEdUserType.SystemDocument.FileType.ValueCN,
FileTypeId = needConfirmEdUserType.SystemDocument.FileTypeId,
UpdateTime = needConfirmEdUserType.SystemDocument.UpdateTime,

View File

@ -14,12 +14,13 @@ namespace IRaCIS.Core.Application.Service
var userId = Guid.Empty;
var token = string.Empty;
var isEn_Us = false;
CreateMap<SystemDocument, SystemDocumentView>()
.ForMember(d => d.FileType, u => u.MapFrom(s => s.FileType.Value))
.ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path));
CreateMap<TrialDocument, TrialDocumentView>()
.ForMember(d => d.FileType, u => u.MapFrom(s => s.FileType.MappedValue))
.ForMember(d => d.FileType, u => u.MapFrom(s => isEn_Us ? s.FileType.Value : s.FileType.ValueCN ))
.ForMember(d => d.IsSomeUserSigned, u => u.MapFrom(s => s.TrialDocConfirmedUserList.Any(t=>t.ConfirmTime!=null)))
.ForMember(d => d.FullFilePath, u => u.MapFrom(s => s.Path ));

View File

@ -1,5 +1,4 @@
using Dicom;
using Dicom.Imaging.Codec;

using EasyCaching.Core;
using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Domain.Share;
@ -8,10 +7,13 @@ using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using Microsoft.AspNetCore.Hosting;
using IRaCIS.Core.Infrastructure;
using FellowOakDicom;
using FellowOakDicom.Imaging.Codec;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Services
{
public class DicomArchiveService :BaseService, IDicomArchiveService
public class DicomArchiveService : BaseService, IDicomArchiveService
{
private readonly IRepository<DicomStudy> _studyRepository;
private readonly IRepository<DicomSeries> _seriesRepository;
@ -21,7 +23,7 @@ namespace IRaCIS.Core.Application.Services
private readonly IWebHostEnvironment _hostEnvironment;
private static object lockCodeGenerate = new object();
private readonly IDistributedLockProvider _distributedLockProvider;
private List<Guid> _instanceIdList = new List<Guid>();
@ -31,8 +33,9 @@ namespace IRaCIS.Core.Application.Services
IRepository<DicomInstance> instanceRepository,
IWebHostEnvironment hostEnvironment,
IRepository<Dictionary> dictionaryRepository,
IEasyCachingProvider provider)
IEasyCachingProvider provider, IDistributedLockProvider distributedLockProvider)
{
_distributedLockProvider = distributedLockProvider;
_hostEnvironment = hostEnvironment;
_studyRepository = studyRepository;
@ -50,7 +53,7 @@ namespace IRaCIS.Core.Application.Services
return success;
}
public async Task<(Guid StudyId, string StudyCode)> ArchiveDicomStreamAsync(Stream dicomStream,
@ -129,7 +132,7 @@ namespace IRaCIS.Core.Application.Services
DicomStudy dicomStudy = CreateDicomStudy(dataset, addtionalInfo, out bool isStudyNeedAdd);
DicomSeries dicomSeries = CreateDicomSeries(dataset, dicomStudy, out bool isSeriesNeedAdd);
DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries,out bool isInstanceNeedAdd);
DicomInstance dicomInstance = CreateDicomInstance(dataset, dicomStudy, dicomSeries, out bool isInstanceNeedAdd);
dicomSeries.DicomStudy = dicomStudy;
@ -183,7 +186,7 @@ namespace IRaCIS.Core.Application.Services
//正常保存 不做处理
await dicomFile.SaveAsync(physicalPath);
}
else
else
{
//RLELossless 保存
await dicomFile.Clone(DicomTransferSyntax.RLELossless).SaveAsync(physicalPath); //RLELossless
@ -235,7 +238,7 @@ namespace IRaCIS.Core.Application.Services
{
modalityForEdit = "PET";
}
if(modality== "PT、CT")
if (modality == "PT、CT")
{
modalityForEdit = "PET-CT";
}
@ -282,9 +285,10 @@ namespace IRaCIS.Core.Application.Services
dicomStudy.PatientBirthDate = $"{dicomStudy.PatientBirthDate[0]}{dicomStudy.PatientBirthDate[1]}{dicomStudy.PatientBirthDate[2]}{dicomStudy.PatientBirthDate[3]}-{dicomStudy.PatientBirthDate[4]}{dicomStudy.PatientBirthDate[5]}-{dicomStudy.PatientBirthDate[6]}{dicomStudy.PatientBirthDate[7]}";
}
lock (lockCodeGenerate)
{
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
using (@lock.Acquire())
{
//查询数据库获取最大的Code 没有记录则为0
var dbStudyCodeIntMax = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
@ -298,9 +302,9 @@ namespace IRaCIS.Core.Application.Services
dicomStudy.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy));
_provider.Set<int>($"{addtionalInfo.TrialId}_{StaticData.CacheKey.StudyMaxCode}", dicomStudy.Code, TimeSpan.FromMinutes(30));
}
#region Setting Code old
//var studyCode = _studyRepository.Where(s => s.TrialId == addtionalInfo.TrialId).Select(t => t.StudyCode).OrderByDescending(c => c).FirstOrDefault();
@ -468,7 +472,7 @@ namespace IRaCIS.Core.Application.Services
_instanceIdList.Add(instanceId);
}
return dicomInstance;
}

View File

@ -14,16 +14,13 @@ using IRaCIS.Core.Application.MediatR.Handlers;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Threading;
using Nito.AsyncEx;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
[ApiExplorerSettings(GroupName = "Image")]
public class StudyService : BaseService, IStudyService
{
private static object lockObj = new object();
private static readonly AsyncLock _mutex = new AsyncLock();
private static readonly AsyncLock _mutex2 = new AsyncLock();
private readonly IEasyCachingProvider _provider;
@ -35,12 +32,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
private readonly IRepository<Dictionary> _dictionaryRepository;
private readonly IRepository<StudyMonitor> _studyMonitorRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
public StudyService(IEasyCachingProvider provider
, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<DicomInstance> dicomInstanceRepository,
IRepository<DicomSeries> dicomSeriesRepository, IRepository<DicomStudy> dicomstudyRepository, IRepository<Dictionary> dictionaryRepository, IRepository<StudyMonitor> studyMonitorRepository)
IRepository<DicomSeries> dicomSeriesRepository, IRepository<DicomStudy> dicomstudyRepository, IRepository<Dictionary> dictionaryRepository, IRepository<StudyMonitor> studyMonitorRepository, IDistributedLockProvider distributedLockProvider)
{
_provider = provider;
_subjectVisitRepository = subjectVisitRepository;
@ -49,6 +46,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
_dicomstudyRepository = dicomstudyRepository;
_dictionaryRepository = dictionaryRepository;
_studyMonitorRepository = studyMonitorRepository;
_distributedLockProvider = distributedLockProvider;
}
@ -160,7 +158,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
var study = _mapper.Map<DicomStudy>(incommand.Study);
using (await _mutex.LockAsync())
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
using (await @lock.AcquireAsync())
{
//查询数据库获取最大的Code 没有记录则为0
var dbStudyCodeIntMax = _dicomstudyRepository.Where(s => s.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
@ -306,11 +306,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
using (await _mutex2.LockAsync())
var @lock2 = _distributedLockProvider.CreateLock($"StudyCommit");
using (await @lock2.AcquireAsync())
{
await _dicomInstanceRepository.SaveChangesAsync();
}
}
catch (Exception ex)
@ -765,7 +765,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
if (_provider.Exists($"StudyUid_{trialId}_{studyInstanceUid}"))
{
result.AllowUpload = false;
result.AllowReUpload = false;
@ -826,22 +826,22 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
result.StudyInstanceUid = studyInstanceUid;
var @lock = _distributedLockProvider.CreateLock($"StudyUpload");
if (result.AllowReUpload || result.AllowUpload)
using (@lock.Acquire())
{
lock (lockObj)
if (result.AllowReUpload || result.AllowUpload)
{
_provider.Set($"StudyUid_{trialId}_{studyInstanceUid}", _userInfo.Id, TimeSpan.FromSeconds(30));
}
}
else
{
lock (lockObj)
else
{
_provider.Remove($"StudyUid_{trialId}_{studyInstanceUid}");
}
}
return result;
}

View File

@ -3,7 +3,7 @@ using IRaCIS.Application.Contracts;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Domain.Share;
using Nito.AsyncEx;
using Medallion.Threading;
namespace IRaCIS.Application.Services
{
@ -12,13 +12,13 @@ namespace IRaCIS.Application.Services
{
private readonly IRepository<Site> _siteRepository;
private readonly IRepository<TrialSiteUser> _trialSiteUserRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
private readonly AsyncLock _mutex = new AsyncLock();
public SiteService(IRepository<Site> siteRepository, IRepository<TrialSiteUser> trialSiteUserRepository)
public SiteService(IRepository<Site> siteRepository, IRepository<TrialSiteUser> trialSiteUserRepository, IDistributedLockProvider distributedLockProvider)
{
_siteRepository = siteRepository;
this._trialSiteUserRepository = trialSiteUserRepository;
_trialSiteUserRepository = trialSiteUserRepository;
_distributedLockProvider = distributedLockProvider;
}
/// <summary> 分页获取研究中心列表 </summary>
@ -27,7 +27,7 @@ namespace IRaCIS.Application.Services
{
var siteQueryable = _siteRepository
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName)||t.SiteNameCN.Contains(searchModel.SiteName))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.SiteName), t => t.SiteName.Contains(searchModel.SiteName) || t.SiteNameCN.Contains(searchModel.SiteName))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country))
@ -58,7 +58,9 @@ namespace IRaCIS.Application.Services
VerifyMsg = _localizer["Site_DupName"]
};
using (await _mutex.LockAsync())
var @lock = _distributedLockProvider.CreateLock($"SiteAdd");
using (await @lock.AcquireAsync())
{
if (siteCommand.Id == null)
{

View File

@ -8,10 +8,10 @@ using Panda.DynamicWebApi.Attributes;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Caching.Memory;
using IRaCIS.Core.Infra.Common.Cache;
using Microsoft.Identity.Client;
using static IRaCIS.Core.Domain.Share.StaticData;
using IRaCIS.Core.Application.ViewModel;
using Medallion.Threading;
namespace IRaCIS.Application.Services
{
@ -24,7 +24,7 @@ namespace IRaCIS.Application.Services
private readonly IRepository<TrialUser> _userTrialRepository;
private readonly IRepository<UserLog> _userLogRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
private readonly IMemoryCache _cache;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
@ -38,7 +38,8 @@ namespace IRaCIS.Application.Services
IRepository<TrialUser> userTrialRepository,
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig,
IRepository<UserLog> userLogRepository
)
,
IDistributedLockProvider distributedLockProvider)
{
_userLogRepository = userLogRepository;
@ -47,9 +48,10 @@ namespace IRaCIS.Application.Services
_userRepository = userRepository;
_mailVerificationService = mailVerificationService;
_verificationCodeRepository = verificationCodeRepository;
_userTrialRepository = userTrialRepository;
_userLogRepository = userLogRepository;
_distributedLockProvider = distributedLockProvider;
}
@ -502,29 +504,32 @@ namespace IRaCIS.Application.Services
var saveItem = _mapper.Map<User>(userAddModel);
saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
var @lock = _distributedLockProvider.CreateLock($"UserAccount");
saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
if (saveItem.IsZhiZhun)
using (await @lock.AcquireAsync())
{
saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName;
saveItem.Code = await _userRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
saveItem.UserCode = AppSettings.GetCodeStr(saveItem.Code, nameof(User));
if (saveItem.IsZhiZhun)
{
saveItem.OrganizationName = AppSettings.DefaultInternalOrganizationName;
}
saveItem.Password = MD5Helper.Md5("123456");
await _userRepository.AddAsync(saveItem);
var success = await _userRepository.SaveChangesAsync();
}
saveItem.Password = MD5Helper.Md5("123456");
await _userRepository.AddAsync(saveItem);
var success = await _userRepository.SaveChangesAsync();
await _mailVerificationService.AddUserSendEmailAsync(saveItem.Id, userAddModel.BaseUrl, userAddModel.RouteUrl);
return ResponseOutput.Result(success, new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
return ResponseOutput.Ok( new UserAddedReturnDTO { Id = saveItem.Id, UserCode = saveItem.UserCode });
}

View File

@ -5,10 +5,10 @@
//--------------------------------------------------------------------
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Filter;
using Nito.AsyncEx;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Share;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Contracts
{
@ -20,19 +20,19 @@ namespace IRaCIS.Core.Application.Contracts
{
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository;
private readonly AsyncLock _mutex = new AsyncLock();
private readonly IDistributedLockProvider _distributedLockProvider;
private readonly QCCommon _qCCommon;
public NoneDicomStudyService(IRepository<NoneDicomStudy> noneDicomStudyRepository,
QCCommon qCCommon,
IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository)
IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository, IDistributedLockProvider distributedLockProvider)
{
_qCCommon = qCCommon;
_noneDicomStudyRepository = noneDicomStudyRepository;
_noneDicomStudyFileRepository = noneDicomStudyFileRepository;
_distributedLockProvider = distributedLockProvider;
}
@ -62,7 +62,9 @@ namespace IRaCIS.Core.Application.Contracts
}
NoneDicomStudy? optEntity = null;
using (await _mutex.LockAsync())
var @lock = _distributedLockProvider.CreateLock($"NoneDicomCode");
using (await @lock.AcquireAsync())
{
if (addOrEditNoneDicomStudy.Id == Guid.Empty || addOrEditNoneDicomStudy.Id == null)
{

View File

@ -10,13 +10,13 @@ using WinSCP;
using Newtonsoft.Json;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Service.Inspection.DTO;
using Nito.AsyncEx;
using System.ComponentModel.DataAnnotations;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Service;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Image.QA
{
@ -35,8 +35,7 @@ namespace IRaCIS.Core.Application.Image.QA
private readonly IRepository<Trial> _trialRepository;
private readonly IRepository<VisitTask> _visitTaskRepository;
private readonly IVisitTaskHelpeService _IVisitTaskHelpeService;
private readonly AsyncLock _mutex = new AsyncLock();
private readonly IDistributedLockProvider _distributedLockProvider;
public QCOperationService(IRepository<SubjectVisit> subjectVisitRepository,
IRepository<QCChallenge> qcChallengeRepository,
@ -48,7 +47,8 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<ReadingClinicalData> readingClinicalDataRepository,
IRepository<QCChallengeDialog> qCChallengeDialogrepository,
IRepository<CheckChallengeDialog> checkChallengeDialogrepository,
IVisitTaskHelpeService visitTaskHelpeService
IVisitTaskHelpeService visitTaskHelpeService,
IDistributedLockProvider distributedLockProvider
)
{
_subjectVisitRepository = subjectVisitRepository;
@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Image.QA
_trialRepository = trialRepository;
this._visitTaskRepository = visitTaskRepository;
_IVisitTaskHelpeService = visitTaskHelpeService;
_distributedLockProvider = distributedLockProvider;
}
#region QC质疑 以及回复 关闭
@ -108,9 +109,9 @@ namespace IRaCIS.Core.Application.Image.QA
var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefaultAsync()).IfNullThrowException();
var @lock = _distributedLockProvider.CreateLock($"QCChallengeCode");
using (await _mutex.LockAsync())
using (await @lock.AcquireAsync())
{
//获取编号
var code = _qcChallengeRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();

View File

@ -266,7 +266,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public string ImagePath { get; set; } = string.Empty;
public List<ImageInfo> FileList { get; set; } = new List<ImageInfo>();
public List<OSSImageInfo> FileList { get; set; } = new List<OSSImageInfo>();
}
@ -314,7 +314,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public List<ImageInfo> FileList { get; set; } = new List<ImageInfo>();
public List<OSSImageInfo> FileList { get; set; } = new List<OSSImageInfo>();
@ -455,7 +455,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public Guid TaskMedicalReviewId { get; set; }
public List<ImageInfo> FileList { get; set; } = new List<ImageInfo>();
public List<OSSImageInfo> FileList { get; set; } = new List<OSSImageInfo>();
/// <summary>
@ -502,7 +502,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
public string Questioning { get; set; } = string.Empty;
public List<ImageInfo> FileList { get; set; } = new List<ImageInfo>();
public List<OSSImageInfo> FileList { get; set; } = new List<OSSImageInfo>();
/// <summary>
/// 审核建议

View File

@ -15,6 +15,7 @@ using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Caching.Memory;
using IRaCIS.Core.Application.Filter;
using DocumentFormat.OpenXml.Drawing;
using EasyCaching.Core;
using Quartz;
using IRaCIS.Application.Services.BackGroundJob;
using EasyCaching.Core;

View File

@ -1,51 +0,0 @@
using Microsoft.AspNetCore.JsonPatch.Operations;
using Swashbuckle.AspNetCore.Filters;
namespace IRaCIS.Core.Application.Contracts
{
/// <summary>
/// 实测 标注在服务方法上 没用
/// </summary>
public class JsonPatchUserRequestExample : IExamplesProvider<object>
{
public Operation[] GetExamples()
{
return new[]
{
new Operation
{
op = "replace",
path = "/name",
value = "Gordon"
},
new Operation
{
op = "replace",
path = "/surname",
value = "Freeman"
}
};
}
object IExamplesProvider<object>.GetExamples()
{
return new[]
{
new Operation
{
op = "replace",
path = "/name",
value = "Gordon"
},
new Operation
{
op = "replace",
path = "/surname",
value = "Freeman"
}
};
}
}
}

View File

@ -20,7 +20,7 @@ using Microsoft.VisualBasic;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.ViewModel;
using Dicom;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Contracts
{
@ -36,13 +36,14 @@ namespace IRaCIS.Core.Application.Contracts
private readonly IRepository<TrialSite> _trialSiteRepository;
private readonly IRepository<TrialUser> _trialUserRepository;
private readonly IRepository<TrialSiteUser> _trialSiteUserRepository;
private readonly IDistributedLockProvider _distributedLockProvider;
private readonly ITokenService _tokenService;
private readonly IMailVerificationService _mailVerificationService;
public TrialSiteSurveyService(IRepository<TrialSiteSurvey> trialSiteSurveyRepository, IRepository<TrialUser> trialUserRepository, IRepository<TrialSiteUserSurvey> trialSiteUserSurveyRepository,
IRepository<User> userRepository, IRepository<TrialSite> trialSiteRepository,
ITokenService tokenService,
IMailVerificationService mailVerificationService, IRepository<TrialSiteUser> trialSiteUserRepository)
IMailVerificationService mailVerificationService, IRepository<TrialSiteUser> trialSiteUserRepository, IDistributedLockProvider distributedLockProvider)
{
_trialSiteSurveyRepository = trialSiteSurveyRepository;
_trialSiteUserSurveyRepository = trialSiteUserSurveyRepository;
@ -52,9 +53,9 @@ namespace IRaCIS.Core.Application.Contracts
_tokenService = tokenService;
_mailVerificationService = mailVerificationService;
_trialSiteUserRepository = trialSiteUserRepository;
_distributedLockProvider = distributedLockProvider;
}
private object lockObj { get; set; } = new object();
/// <summary>
/// 发送验证码
@ -792,7 +793,9 @@ namespace IRaCIS.Core.Application.Contracts
if (sysUserInfo == null)
{
lock (lockObj)
var @lock = _distributedLockProvider.CreateLock($"UserCode");
using (await @lock.AcquireAsync())
{
var saveItem = _mapper.Map<User>(item);
@ -972,7 +975,9 @@ namespace IRaCIS.Core.Application.Contracts
if (sysUserInfo == null)
{
lock (lockObj)
var @lock = _distributedLockProvider.CreateLock($"UserCode");
using (await @lock.AcquireAsync())
{
var saveItem = _mapper.Map<User>(item);

View File

@ -1031,7 +1031,7 @@ namespace IRaCIS.Core.Application
.WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code))
.WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName))
.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 && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false)
.Select(t => new TrialToBeDoneDto()
{
TrialId = t.Id,

View File

@ -16,6 +16,7 @@ using Panda.DynamicWebApi.Attributes;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Application.Services;
using IRaCIS.Core.Application.Filter;
using Medallion.Threading;
namespace IRaCIS.Core.Application.Service
{
@ -31,10 +32,11 @@ namespace IRaCIS.Core.Application.Service
private readonly IRepository<TrialSiteUserSurvey> _trialSiteSurveyUserRepository;
private readonly IRepository<TrialSiteUser> _trialSiteUserRepository;
private readonly IMailVerificationService _mailVerificationService;
private readonly IDistributedLockProvider _distributedLockProvider;
public TrialExternalUserService(IRepository<TrialExternalUser> trialExternalUseRepository, IRepository<User> userRepository, IRepository<TrialUser> trialUserRepository,
IRepository<TrialSiteUserSurvey> trialSiteSurveyUserRepository, IRepository<TrialSiteUser> trialSiteUserRepository,
IMailVerificationService mailVerificationService)
IMailVerificationService mailVerificationService, IDistributedLockProvider distributedLockProvider)
{
_trialExternalUseRepository = trialExternalUseRepository;
_userRepository = userRepository;
@ -43,6 +45,7 @@ namespace IRaCIS.Core.Application.Service
_trialSiteUserRepository = trialSiteUserRepository;
_mailVerificationService = mailVerificationService;
_distributedLockProvider = distributedLockProvider;
}
@ -75,121 +78,125 @@ namespace IRaCIS.Core.Application.Service
if (addOrEditTrialExternalUser.Id == null)
{
var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
var @lock = _distributedLockProvider.CreateLock($"UserCode");
if (existSysUser != null)
using (await @lock.AcquireAsync())
{
if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName)
var existSysUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
if (existSysUser != null)
{
//$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存",
return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips);
if (existSysUser.LastName != addOrEditTrialExternalUser.LastName || existSysUser.FirstName != addOrEditTrialExternalUser.FirstName)
{
//$"该用户在系统中的用户名为:{existSysUser.LastName + " / " + existSysUser.FirstName} 电话:{existSysUser.Phone},与填写信息存在不一致项, 请将界面信息修改为与系统一致,再进行保存",
return ResponseOutput.NotOk(_localizer["TrialExternalUser_Inconsistency", existSysUser.LastName + " / " + existSysUser.FirstName, existSysUser.Phone], new { existSysUser.LastName, existSysUser.FirstName, existSysUser.Phone, existSysUser.IsZhiZhun, existSysUser.IsTestUser }, ApiResponseCodeEnum.NeedTips);
}
}
}
//处理 生成账户
//处理 生成账户
if (await _trialExternalUseRepository.AnyAsync(t =>
t.Email == addOrEditTrialExternalUser.Email &&
t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId))
{
//---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。
return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]);
}
if (await _trialExternalUseRepository.AnyAsync(t =>
t.Email == addOrEditTrialExternalUser.Email &&
t.UserTypeId == addOrEditTrialExternalUser.UserTypeId && t.TrialId == addOrEditTrialExternalUser.TrialId))
{
//---系统已经存在与列表中填写的邮箱和用户类型相同的账户,请确认。
return ResponseOutput.NotOk(_localizer["TrialExternalUser_EmailTypeDuplicate"]);
}
var addEntity = _mapper.Map<TrialExternalUser>(addOrEditTrialExternalUser);
var addEntity = _mapper.Map<TrialExternalUser>(addOrEditTrialExternalUser);
await _trialExternalUseRepository.AddAsync(addEntity);
await _trialExternalUseRepository.AddAsync(addEntity);
var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
var trialType = await _repository.Where<Trial>(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync();
var existUser = await _userRepository.FirstOrDefaultAsync(t => t.EMail == addOrEditTrialExternalUser.Email && t.UserTypeId == addOrEditTrialExternalUser.UserTypeId);
var trialType = await _repository.Where<Trial>(t => t.Id == addOrEditTrialExternalUser.TrialId).Select(t => t.TrialType).FirstOrDefaultAsync();
if (existUser != null)
{
addEntity.IsSystemUser = true;
addEntity.SystemUserId = existUser.Id;
if (existUser != null)
{
addEntity.IsSystemUser = true;
addEntity.SystemUserId = existUser.Id;
}
else
{
}
else
{
//生成账户 并插入
//生成账户 并插入
var generateUser = _mapper.Map<User>(addOrEditTrialExternalUser);
var generateUser = _mapper.Map<User>(addOrEditTrialExternalUser);
if (trialType == TrialType.NoneOfficial)
{
generateUser.IsTestUser = true;
}
// 外部人员生成账号 都是外部的
generateUser.IsZhiZhun = false;
generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User));
generateUser.UserName = generateUser.UserCode;
generateUser.UserTypeEnum = _repository.Where<UserType>(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First();
generateUser.Password = MD5Helper.Md5("123456");
generateUser.Status = UserStateEnum.Disable;
var newAddUser = await _repository.AddAsync(generateUser);
addEntity.IsSystemUser = false;
addEntity.SystemUserId = newAddUser.Id;
existUser = newAddUser;
}
#region 验证用户 能否加入
if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training)
{
if (existUser.IsTestUser)
{
//---正式类型 、培训类型的项目 不允许加入测试用户
throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]);
}
}
if (trialType == TrialType.NoneOfficial)
{
generateUser.IsTestUser = true;
if (existUser.IsTestUser == false)
{
//---测试项目 不允许加入正式用户
throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]);
}
}
// 外部人员生成账号 都是外部的
generateUser.IsZhiZhun = false;
generateUser.Code = _userRepository.Select(t => t.Code).DefaultIfEmpty().Max() + 1;
#endregion
generateUser.UserCode = AppSettings.GetCodeStr(generateUser.Code, nameof(User));
generateUser.UserName = generateUser.UserCode;
generateUser.UserTypeEnum = _repository.Where<UserType>(t => t.Id == generateUser.UserTypeId).Select(t => t.UserTypeEnum).First();
generateUser.Password = MD5Helper.Md5("123456");
generateUser.Status = UserStateEnum.Disable;
var newAddUser = await _repository.AddAsync(generateUser);
await _trialExternalUseRepository.SaveChangesAsync();
addEntity.IsSystemUser = false;
addEntity.SystemUserId = newAddUser.Id;
existUser = newAddUser;
}
#region 验证用户 能否加入
if (trialType == TrialType.OfficialTrial || trialType == TrialType.Training)
{
if (existUser.IsTestUser)
//添加的时候就发邮件 现在省略
if (addOrEditTrialExternalUser.IsSendEmail)
{
//---正式类型 、培训类型的项目 不允许加入测试用户
throw new BusinessValidationFailedException(_localizer["TrialExternalUser_TestUserNotAllowed"]);
}
}
if (trialType == TrialType.NoneOfficial)
{
if (existUser.IsTestUser == false )
{
//---测试项目 不允许加入正式用户
throw new BusinessValidationFailedException(_localizer["TrialExternalUser_FormalUserNotAllowed"]);
}
}
#endregion
await _trialExternalUseRepository.SaveChangesAsync();
//添加的时候就发邮件 现在省略
if (addOrEditTrialExternalUser.IsSendEmail)
{
await SendExternalUserJoinEmail(new TrialExternalUserSendEmail()
{
BaseUrl = addOrEditTrialExternalUser.BaseUrl,
RouteUrl = addOrEditTrialExternalUser.RouteUrl,
TrialId = addOrEditTrialExternalUser.TrialId,
SendUsers = new List<UserEmail>()
await SendExternalUserJoinEmail(new TrialExternalUserSendEmail()
{
BaseUrl = addOrEditTrialExternalUser.BaseUrl,
RouteUrl = addOrEditTrialExternalUser.RouteUrl,
TrialId = addOrEditTrialExternalUser.TrialId,
SendUsers = new List<UserEmail>()
{
new UserEmail()
{
@ -199,12 +206,13 @@ namespace IRaCIS.Core.Application.Service
SystemUserId=addEntity.SystemUserId
}
}
});
});
}
return ResponseOutput.Ok(addEntity.Id.ToString());
}
return ResponseOutput.Ok(addEntity.Id.ToString());
}
else
{

View File

@ -25,13 +25,17 @@ namespace IRaCIS.Application.Services
private readonly IRepository<TrialUser> _trialUserRepository;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
private readonly IOptionsMonitor<SystemEmailSendConfig> _systemEmailSendConfig;
public bool TrialExpeditedChange { get; set; } = false;
public TrialService(IEasyCachingProvider provider, IRepository<Trial> trialRepository,
IRepository<TrialUser> trialUserRepository, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig
, IOptionsMonitor<SystemEmailSendConfig> systemEmailSendConfig
)
{
_systemEmailSendConfig = systemEmailSendConfig;
_verifyConfig = verifyConfig;
_provider = provider;
_trialRepository = trialRepository;
@ -92,7 +96,7 @@ namespace IRaCIS.Application.Services
.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(_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 });
.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);
@ -118,7 +122,7 @@ namespace IRaCIS.Application.Services
[HttpGet("{projectId:guid}")]
public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId)
{
return (await _trialRepository.Where(o => o.Id == projectId).IgnoreQueryFilters().ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
return (await _trialRepository.Where(o => o.Id == projectId).IgnoreQueryFilters().ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
}
@ -213,6 +217,15 @@ namespace IRaCIS.Application.Services
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true });
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1" });
//默认采用系统邮件
trial.EmailAuthorizationCode = _systemEmailSendConfig.CurrentValue.AuthorizationCode;
trial.EmailFromEmail = _systemEmailSendConfig.CurrentValue.FromEmail;
trial.EmailFromName = _systemEmailSendConfig.CurrentValue.FromName;
trial.EmailSMTPServerAddress = _systemEmailSendConfig.CurrentValue.Host;
trial.EmailSMTPServerPort = _systemEmailSendConfig.CurrentValue.Port;
trial.IsConfigureEmail = true;
var success = await _repository.SaveChangesAsync();

View File

@ -65,16 +65,17 @@ namespace IRaCIS.Core.Application.Service
var userId = Guid.Empty;
var userTypeEnumInt = 0;
var isEn_Us = false;
CreateMap<Trial, TrialDetailDTO>()
.ForMember(x=>x.CriterionList,y=>y.MapFrom(z=>z.ReadingQuestionCriterionTrialList.Where(n=>n.IsConfirm).Select(m=>m.CriterionName)))
.ForMember(d => d.DictionaryList, u => u.MapFrom(s => s.TrialDicList.Select(t => t.Dictionary).OrderBy(t => t.ShowOrder)))
//.ForMember(d => d.Code, u => u.MapFrom(s => s.TrialCode))
.ForMember(d => d.Sponsor, u => u.MapFrom(s => s.Sponsor.SponsorName))
.ForMember(d => d.Phase, u => u.MapFrom(s => s.Phase.MappedValue))
.ForMember(d => d.Phase, u => u.MapFrom(s => isEn_Us? s.Phase.Value: s.Phase.ValueCN))
//.ForMember(d => d.DeclarationType, u => u.MapFrom(s => s.DeclarationType.MappedValue))
.ForMember(d => d.IndicationType, u => u.MapFrom(s => s.IndicationType.MappedValue))
.ForMember(d => d.IndicationType, u => u.MapFrom(s => isEn_Us ? s.IndicationType.Value:s.IndicationType.ValueCN))
.ForMember(d => d.CRO, u => u.MapFrom(s => s.CRO.CROName))
.ForMember(d => d.ReviewMode, u => u.MapFrom(s => s.ReviewMode.MappedValue))
.ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value:s.ReviewMode.ValueCN))
//.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value))
//.ForMember(d => d.SiteCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.TrialSiteUserList.Count(k => k.UserId == userId) : s.TrialSiteList.Count()))
@ -106,7 +107,6 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.TrialId, u => u.MapFrom(s => trialId))
.ForMember(d => d.IsSelect, u => u.MapFrom(t => t.UserTrials.Any(t => t.TrialId == trialId)));
var isEn_Us = false;
CreateMap<Site, SiteSelectDTO>()
.ForMember(d => d.HospitalName, u => u.MapFrom(s => s.Hospital.HospitalName));

View File

@ -1,15 +1,19 @@
using IRaCIS.Core.Application.Service;
using DocumentFormat.OpenXml.Office2010.Excel;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Medallion.Threading;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using System.Linq.Expressions;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@ -20,6 +24,8 @@ namespace IRaCIS.Application.Services
[ApiExplorerSettings(GroupName = "Institution")]
public class TestService : BaseService
{
public static int IntValue = 100;
private readonly IRepository<Dictionary> _dicRepository;
private readonly IRepository<Trial> _trialRepository;
@ -30,10 +36,13 @@ namespace IRaCIS.Application.Services
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _basicConfig;
private readonly IRepository<VisitTask> _visitTaskRepositoryy;
private readonly IDistributedLockProvider _distributedLockProvider;
public TestService(IRepository<Dictionary> dicRepository, IRepository<Trial> trialRepository/*, IDistributedCache cache*/
private readonly ILogger<TestService> _logger;
, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IOptionsMonitor<ServiceVerifyConfigOption> basicConfig, IRepository<VisitTask> visitTaskRepository)
public TestService(IRepository<Dictionary> dicRepository, IRepository<Trial> trialRepository,ILogger<TestService> logger
, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IOptionsMonitor<ServiceVerifyConfigOption> basicConfig, IRepository<VisitTask> visitTaskRepository, IDistributedLockProvider distributedLockProvider)
{
_visitTaskRepositoryy = visitTaskRepository;
@ -42,10 +51,39 @@ namespace IRaCIS.Application.Services
_dicRepository = dicRepository;
_trialRepository = trialRepository;
_distributedLockProvider= distributedLockProvider;
_logger= logger;
//_cache = cache;
}
[AllowAnonymous]
public async Task<IResponseOutput> TestDistributedLock( )
{
_repository.Where<User>().Select(t => t.FullName).FirstOrDefault();
Console.WriteLine($"我进来了当前值是:" + IntValue);
_logger.LogWarning($"我进来了当前值是:" + IntValue);
var @lock = _distributedLockProvider.CreateLock($"UserAccount");
using (await @lock.AcquireAsync())
{
await Task.Delay(4);
IntValue--;
_logger.LogWarning( IntValue.ToString());
Console.WriteLine(IntValue);
}
return ResponseOutput.Ok(IntValue);
}
[AllowAnonymous]
public async Task<IResponseOutput> GetMemoryStoreData()
{

View File

@ -8,8 +8,4 @@
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
</ItemGroup>
</Project>

View File

@ -178,7 +178,7 @@ namespace IRaCIS.Core.Domain.Models
/// 文件
/// </summary>
[NotMapped]
public List<ImageInfo> FileList
public List<OSSImageInfo> FileList
{
get
{
@ -186,13 +186,13 @@ namespace IRaCIS.Core.Domain.Models
try
{
var result= JsonConvert.DeserializeObject<List<ImageInfo>>(this.ImagePath);
return result==null?new List<ImageInfo>() : result;
var result= JsonConvert.DeserializeObject<List<OSSImageInfo>>(this.ImagePath);
return result==null?new List<OSSImageInfo>() : result;
}
catch (Exception)
{
return new List<ImageInfo>();
return new List<OSSImageInfo>();
}
}
@ -210,7 +210,7 @@ namespace IRaCIS.Core.Domain.Models
#region 文件对象
public class ImageInfo
public class OSSImageInfo
{
public string FileName { get; set; }

View File

@ -1,4 +1,3 @@
using EntityFrameworkCore.Projectables;
using IRaCIS.Core.Domain.Share;
using System;
using System.Collections.Generic;
@ -56,12 +55,6 @@ namespace IRaCIS.Core.Domain.Models
public List<Dictionary> ChildList { get; set; } = new List<Dictionary>();
[NotMapped]
public string MappedValue { get; set; }
[Projectable]
public string TranslateValue( string value, string valueCN,bool isCN) => isCN?valueCN:value;
}

View File

@ -1,29 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EntityFrameworkCore.Projectables.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Domain.Share\IRaCIS.Core.Domain.Share.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Domain.Share\IRaCIS.Core.Domain.Share.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="EntityFrameworkCore.Projectables.Abstractions" Version="2.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<Using Include=" Newtonsoft.Json;" />
<!-- Global using -->
<ItemGroup>
<Using Include=" Newtonsoft.Json;" />
<!-- Global using -->
</ItemGroup>
</ItemGroup>
</Project>

View File

@ -87,7 +87,8 @@ namespace IRaCIS.Core.Domain.Models
/// </summary>
public bool AutoCutNextTask { get; set; } = false;
[Projectable] public string FullName => LastName + " / " + FirstName;
[Projectable]
public string FullName => LastName + " / " + FirstName;
//[Projectable] public string FullName => $"{LastName} / {FirstName}";
}

View File

@ -113,7 +113,7 @@ namespace IRaCIS.Core.Domain.Models
/// 文件
/// </summary>
[NotMapped]
public List<ImageInfo> FileList
public List<OSSImageInfo> FileList
{
get
{
@ -121,13 +121,13 @@ namespace IRaCIS.Core.Domain.Models
try
{
var result = JsonConvert.DeserializeObject<List<ImageInfo>>(this.ImagePath);
return result == null ? new List<ImageInfo>() : result;
var result = JsonConvert.DeserializeObject<List<OSSImageInfo>>(this.ImagePath);
return result == null ? new List<OSSImageInfo>() : result;
}
catch (Exception)
{
return new List<ImageInfo>();
return new List<OSSImageInfo>();
}
}

View File

@ -212,7 +212,7 @@ namespace IRaCIS.Core.Domain.Share
get
{
return _accessor?.HttpContext?.Connection.RemoteIpAddress.ToString();
return _accessor?.HttpContext.GetClientIP();
}
}
@ -341,4 +341,33 @@ namespace IRaCIS.Core.Domain.Share
}
public static class HttpContextExtension
{
public static string GetClientIP(this HttpContext context)
{
var ip = context.Request.Headers["Cdn-Src-Ip"].FirstOrDefault();
if (!string.IsNullOrEmpty(ip))
return IpReplace(ip);
ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
if (!string.IsNullOrEmpty(ip))
return IpReplace(ip);
ip = context.Connection.RemoteIpAddress.ToString();
return IpReplace(ip);
}
static string IpReplace(string inip)
{
//::ffff:
//::ffff:192.168.2.131 这种IP处理
if (inip.Contains("::ffff:"))
{
inip = inip.Replace("::ffff:", "");
}
return inip;
}
}
}

View File

@ -122,14 +122,15 @@ namespace IRaCIS.Core.Infra.EFCore
modelBuilder.Entity<Dictionary>().HasMany(t => t.ChildList).WithOne(t => t.Parent);
if (_userInfo.IsEn_Us)
{
modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.Value));
}
else
{
modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.ValueCN));
}
//if (_userInfo.IsEn_Us)
//{
// modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.Value));
//}
//else
//{
// modelBuilder.Entity<Dictionary>().Property(t => t.MappedValue).HasColumnName(nameof(Domain.Models.Dictionary.ValueCN));
//}
//遍历实体模型手动配置
@ -557,6 +558,12 @@ namespace IRaCIS.Core.Infra.EFCore
throw new DBSaveFailedException("SQL 事务失败,请检查环境。");
}
catch (Exception ex)
{
_logger.LogError(ex.InnerException is null ? ex.Message : ex.InnerException?.Message);
throw new DBSaveFailedException("数据保存异常。");
}
}

View File

@ -36,8 +36,7 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration
public void Configure(EntityTypeBuilder<Dictionary> builder)
{
builder.Property(e => e.MappedValue).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
builder.Property(e => e.MappedValue).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
}
}

View File

@ -8,7 +8,9 @@
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
@ -17,15 +19,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="EFCore.BulkExtensions" Version="6.5.6" />
<PackageReference Include="AutoMapper" Version="12.0.0" />
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="6.0.3.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
<PackageReference Include="EntityFrameworkCore.Projectables" Version="2.3.0" />
<PackageReference Include="NewId" Version="3.0.3" />
<PackageReference Include="EFCore.BulkExtensions" Version="7.1.6" />
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.2" />
<PackageReference Include="EntityFrameworkCore.Projectables" Version="2.3.0" />
<PackageReference Include="EntityFrameworkCore.Exceptions.SqlServer" Version="6.0.3.2" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.12" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
<PackageReference Include="NewId" Version="4.0.1" />
</ItemGroup>
</Project>

View File

@ -1,18 +0,0 @@

namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 缓存类型
/// </summary>
public enum CacheType
{
/// <summary>
/// 内存缓存
/// </summary>
Memory,
/// <summary>
/// Redis缓存
/// </summary>
Redis
}
}

View File

@ -1,107 +0,0 @@
using System;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 缓存接口
/// </summary>
public interface ICache
{
/// <summary>
/// 用于在 key 存在时删除 key
/// </summary>
/// <param name="key">键</param>
long Del(params string[] key);
/// <summary>
/// 用于在 key 存在时删除 key
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<long> DelAsync(params string[] key);
/// <summary>
/// 用于在 key 模板存在时删除
/// </summary>
/// <param name="pattern">key模板</param>
/// <returns></returns>
Task<long> DelByPatternAsync(string pattern);
/// <summary>
/// 检查给定 key 是否存在
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
bool Exists(string key);
/// <summary>
/// 检查给定 key 是否存在
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<bool> ExistsAsync(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
string Get(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T">byte[] 或其他类型</typeparam>
/// <param name="key">键</param>
/// <returns></returns>
T Get<T>(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<string> GetAsync(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T">byte[] 或其他类型</typeparam>
/// <param name="key">键</param>
/// <returns></returns>
Task<T> GetAsync<T>(string key);
/// <summary>
/// 设置指定 key 的值所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
bool Set(string key, object value);
/// <summary>
/// 设置指定 key 的值所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expire">有效期</param>
bool Set(string key, object value, TimeSpan expire);
/// <summary>
/// 设置指定 key 的值所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns></returns>
Task<bool> SetAsync(string key, object value);
/// <summary>
/// 设置指定 key 的值所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expire">有效期</param>
/// <returns></returns>
Task<bool> SetAsync(string key, object value, TimeSpan expire);
}
}

View File

@ -1,127 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 内存缓存
/// </summary>
public class MemoryCache : ICache
{
private readonly IMemoryCache _memoryCache;
public MemoryCache(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public long Del(params string[] key)
{
foreach(var k in key)
{
_memoryCache.Remove(k);
}
return key.Length;
}
public Task<long> DelAsync(params string[] key)
{
foreach (var k in key)
{
_memoryCache.Remove(k);
}
return Task.FromResult((long)key.Length);
}
public async Task<long> DelByPatternAsync(string pattern)
{
if (string.IsNullOrEmpty(pattern))
return default;
pattern = Regex.Replace(pattern, @"\{.*\}", "(.*)");
var keys = GetAllKeys().Where(k => Regex.IsMatch(k, pattern));
if(keys != null && keys.Count() > 0)
{
return await DelAsync(keys.ToArray());
}
return default;
}
public bool Exists(string key)
{
return _memoryCache.TryGetValue(key, out _);
}
public Task<bool> ExistsAsync(string key)
{
return Task.FromResult(_memoryCache.TryGetValue(key, out _));
}
public string Get(string key)
{
return _memoryCache.Get(key)?.ToString();
}
public T Get<T>(string key)
{
return _memoryCache.Get<T>(key);
}
public Task<string> GetAsync(string key)
{
return Task.FromResult(Get(key));
}
public Task<T> GetAsync<T>(string key)
{
return Task.FromResult(Get<T>(key));
}
public bool Set(string key, object value)
{
_memoryCache.Set(key, value);
return true;
}
public bool Set(string key, object value, TimeSpan expire)
{
_memoryCache.Set(key, value, expire);
return true;
}
public Task<bool> SetAsync(string key, object value)
{
Set(key, value);
return Task.FromResult(true);
}
public Task<bool> SetAsync(string key, object value, TimeSpan expire)
{
Set(key, value, expire);
return Task.FromResult(true);
}
private List<string> GetAllKeys()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache);
var cacheItems = entries as IDictionary;
var keys = new List<string>();
if (cacheItems == null) return keys;
foreach (DictionaryEntry cacheItem in cacheItems)
{
keys.Add(cacheItem.Key.ToString());
}
return keys;
}
}
}

View File

@ -1,88 +0,0 @@
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// Redis缓存
/// </summary>
public class RedisCache : ICache
{
public long Del(params string[] key)
{
return RedisHelper.Del(key);
}
public Task<long> DelAsync(params string[] key)
{
return RedisHelper.DelAsync(key);
}
public async Task<long> DelByPatternAsync(string pattern)
{
if (string.IsNullOrEmpty(pattern))
return default;
pattern = Regex.Replace(pattern, @"\{.*\}", "*");
var keys = (await RedisHelper.KeysAsync(pattern));
if(keys != null && keys.Length > 0)
{
return await RedisHelper.DelAsync(keys);
}
return default;
}
public bool Exists(string key)
{
return RedisHelper.Exists(key);
}
public Task<bool> ExistsAsync(string key)
{
return RedisHelper.ExistsAsync(key);
}
public string Get(string key)
{
return RedisHelper.Get(key);
}
public T Get<T>(string key)
{
return RedisHelper.Get<T>(key);
}
public Task<string> GetAsync(string key)
{
return RedisHelper.GetAsync(key);
}
public Task<T> GetAsync<T>(string key)
{
return RedisHelper.GetAsync<T>(key);
}
public bool Set(string key, object value)
{
return RedisHelper.Set(key, value);
}
public bool Set(string key, object value, TimeSpan expire)
{
return RedisHelper.Set(key, value, expire);
}
public Task<bool> SetAsync(string key, object value)
{
return RedisHelper.SetAsync(key, value);
}
public Task<bool> SetAsync(string key, object value, TimeSpan expire)
{
return RedisHelper.SetAsync(key, value, expire);
}
}
}

View File

@ -1,158 +0,0 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace IRaCIS.Core.Infrastructure.Extention
{
public static class HttpContextExtension
{
public static T GetService<T>(this HttpContext context) where T : class
{
return context.RequestServices.GetService(typeof(T)) as T;
}
public static string GetUserIp(this HttpContext context)
{
string realIP = null;
string forwarded = null;
string remoteIpAddress = context.Connection.RemoteIpAddress.ToString();
if (context.Request.Headers.ContainsKey("X-Real-IP"))
{
realIP = context.Request.Headers["X-Real-IP"].ToString();
if (realIP != remoteIpAddress)
{
remoteIpAddress = realIP;
}
}
if (context.Request.Headers.ContainsKey("X-Forwarded-For"))
{
forwarded = context.Request.Headers["X-Forwarded-For"].ToString();
if (forwarded != remoteIpAddress)
{
remoteIpAddress = forwarded;
}
}
return remoteIpAddress;
}
/// <summary>
/// 获取Request值
/// </summary>
/// <param name="context"></param>
/// <param name="parameter"></param>
/// <returns></returns>
public static string Request(this HttpContext context, string parameter)
{
try
{
if (context == null)
return null;
if (context.Request.Method == "POST")
return context.Request.Form[parameter].ToString();
else
return context.Request.Query[parameter].ToString();
}
catch (System.Exception ex)
{
Console.Write(ex.Message + ex.InnerException);
return context.RequestString(parameter);
}
}
public static T Request<T>(this HttpContext context, string parameter) where T : class
{
return context.RequestString(parameter)?.DeserializeObject<T>();
}
public static string RequestString(this HttpContext context, string parameter)
{
string requestParam = context.GetRequestParameters();
if (string.IsNullOrEmpty(requestParam)) return null;
Dictionary<string, object> keyValues = requestParam.DeserializeObject<Dictionary<string, object>>();
if (keyValues == null || keyValues.Count == 0) return null;
if (keyValues.TryGetValue(parameter, out object value))
{
if (value == null) return null;
if (value.GetType() == typeof(string))
{
return value?.ToString();
}
return value.Serialize();
}
return null;
}
/// <summary>
/// 是否为ajax请求
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public static bool IsAjaxRequest(this HttpContext context)
{
return context.Request("X-Requested-With") == "XMLHttpRequest"
|| (context.Request.Headers != null
&& context.Request.Headers["X-Requested-With"] == "XMLHttpRequest");
}
public static UserAgent GetAgentType(this HttpContext context)
{
string agent = context.Request.Headers["User-Agent"].ToString().ToLower();
if (agent.Contains("ios") || agent.Contains("ipod") || agent.Contains("ipad"))
{
return UserAgent.IOS;
}
if (agent.Contains("windows"))
{
return UserAgent.Windows;
}
return UserAgent.Android;
}
/// <summary>
/// 获取请求的参数
/// net core 2.0已增加回读方法 context.Request.EnableRewind();
///
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static string GetRequestParameters(this HttpContext context)
{
if (context.Request.Body == null || !context.Request.Body.CanRead || !context.Request.Body.CanSeek)
return null;
if (context.Request.Body.Length == 0)
return null;
if (context.Request.Body.Position > 0)
context.Request.Body.Position = 0;
string prarameters = null;
var bodyStream = context.Request.Body;
using (var buffer = new MemoryStream())
{
bodyStream.CopyToAsync(buffer);
buffer.Position = 0L;
bodyStream.Position = 0L;
using (var reader = new StreamReader(buffer, Encoding.UTF8))
{
buffer.Seek(0, SeekOrigin.Begin);
prarameters = reader.ReadToEnd();
}
}
return prarameters;
}
}
public enum UserAgent
{
IOS = 0,
Android = 1,
Windows = 2,
Linux
}
}

View File

@ -1,43 +0,0 @@
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
namespace IRaCIS.Core.Infrastructure
{
public class IPHelper
{
/// <summary>
/// 是否为ip
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static bool IsIP(string ip)
{
return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
}
public static string GetIP(HttpRequest request)
{
if (request == null)
{
return "";
}
string ip = request.Headers["X-Real-IP"].FirstOrDefault();
if (string.IsNullOrEmpty(ip))
{
ip = request.Headers["X-Forwarded-For"].FirstOrDefault();
}
if (string.IsNullOrEmpty(ip))
{
ip = request.HttpContext?.Connection?.RemoteIpAddress?.ToString();
}
if (string.IsNullOrEmpty(ip) || !IsIP(ip))
{
ip = "127.0.0.1";
}
return ip;
}
}
}

View File

@ -1,27 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CSRedisCore" Version="3.8.669" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
<PackageReference Include="SharpCompress" Version="0.32.2" />
<PackageReference Include="SharpZipLib" Version="1.4.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.20" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.12" />
<PackageReference Include="SharpCompress" Version="0.34.1" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.3.5" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

View File

@ -3,11 +3,50 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
using System.Collections.Generic;
namespace IRaCIS.Core.Infrastructure.Extention
{
public static class QueryablePageListExtensions
{
//内存排序 后期删除
public static PageOutput<T> ToPagedList<T>(this IList<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
{
if (pageIndex <= 0)
{
pageIndex = 1;
}
if (pageSize <= 0)
{
pageSize = 10;
}
var count = source.Count();
if (count == 0)
{
return new PageOutput<T>() { CurrentPageData = new List<T>() };
}
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
IQueryable<T> sourceQuery = isAsc ? source.AsQueryable().OrderBy(propName) : source.AsQueryable().OrderBy(propName + " desc");
sourceQuery = sourceQuery.Skip((pageIndex - 1) * pageSize);
var items = sourceQuery
.Take(pageSize)
.ToArray();
var pagedList = new PageOutput<T>()
{
PageIndex = pageIndex,
PageSize = pageSize,
TotalCount = count,
CurrentPageData = items
};
return pagedList;
}
//单字段排序
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
{

View File

@ -13,10 +13,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
#region AuditContext
public class AuditContext : DbContext
{
private readonly string _connectionString;
public AuditContext(string connectionString)
{
_connectionString = connectionString;
}
//protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
// => optionsBuilder.Usesq(_connectionString);
public DbSet<SaveChangesAudit> SaveChangesAudits { get; set; }
}
public class SaveChangesAudit
{
public int Id { get; set; }
public Guid AuditId { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public bool Succeeded { get; set; }
public string ErrorMessage { get; set; }
public ICollection<EntityAudit> Entities { get; } = new List<EntityAudit>();
}
public class EntityAudit
{
public int Id { get; set; }
public EntityState State { get; set; }
public string AuditMessage { get; set; }
public SaveChangesAudit SaveChangesAudit { get; set; }
}
#endregion