添加项目文件。

master
DK 2022-03-28 09:57:06 +08:00
parent 3338504c58
commit 9e9868bc4c
527 changed files with 38592 additions and 0 deletions

61
IRaCIS.Core.API.sln Normal file
View File

@ -0,0 +1,61 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30128.74
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.API", "IRaCIS.Core.API\IRaCIS.Core.API.csproj", "{F15CE209-6039-46A6-AE7F-E81ADA795F28}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Domain", "IRaCIS.Core.Domain\IRaCIS.Core.Domain.csproj", "{D4DF27AC-3739-4264-BFB8-AED6DC2B84C7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Common\IRaCIS.Core.Infrastructure.csproj", "{7EDF1EFA-7BAA-4EB7-B9D6-B06FA22D9DF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Application", "IRaCIS.Core.Application\IRaCIS.Core.Application.csproj", "{037E7DE9-0AE2-4987-8C69-F51D5B9CA19D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore", "IRaCIS.Core.Infra.EF\IRaCIS.Core.Infra.EFCore.csproj", "{3787D877-AEF4-4C7B-8694-49232D9F99AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Domain.Share", "IRaCIS.Core.Domain.Share\IRaCIS.Core.Domain.Share.csproj", "{7CBC76F5-3817-46B7-8D9D-79253A89B578}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Application.Contracts", "IRaCIS.Core.Application.Contracts\IRaCIS.Core.Application.Contracts.csproj", "{7AA9C49B-9958-4371-B0B3-371391A2A7F7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F15CE209-6039-46A6-AE7F-E81ADA795F28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F15CE209-6039-46A6-AE7F-E81ADA795F28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F15CE209-6039-46A6-AE7F-E81ADA795F28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F15CE209-6039-46A6-AE7F-E81ADA795F28}.Release|Any CPU.Build.0 = Release|Any CPU
{D4DF27AC-3739-4264-BFB8-AED6DC2B84C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4DF27AC-3739-4264-BFB8-AED6DC2B84C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4DF27AC-3739-4264-BFB8-AED6DC2B84C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4DF27AC-3739-4264-BFB8-AED6DC2B84C7}.Release|Any CPU.Build.0 = Release|Any CPU
{7EDF1EFA-7BAA-4EB7-B9D6-B06FA22D9DF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EDF1EFA-7BAA-4EB7-B9D6-B06FA22D9DF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EDF1EFA-7BAA-4EB7-B9D6-B06FA22D9DF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EDF1EFA-7BAA-4EB7-B9D6-B06FA22D9DF0}.Release|Any CPU.Build.0 = Release|Any CPU
{037E7DE9-0AE2-4987-8C69-F51D5B9CA19D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{037E7DE9-0AE2-4987-8C69-F51D5B9CA19D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{037E7DE9-0AE2-4987-8C69-F51D5B9CA19D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{037E7DE9-0AE2-4987-8C69-F51D5B9CA19D}.Release|Any CPU.Build.0 = Release|Any CPU
{3787D877-AEF4-4C7B-8694-49232D9F99AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3787D877-AEF4-4C7B-8694-49232D9F99AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3787D877-AEF4-4C7B-8694-49232D9F99AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3787D877-AEF4-4C7B-8694-49232D9F99AC}.Release|Any CPU.Build.0 = Release|Any CPU
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Release|Any CPU.Build.0 = Release|Any CPU
{7AA9C49B-9958-4371-B0B3-371391A2A7F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AA9C49B-9958-4371-B0B3-371391A2A7F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AA9C49B-9958-4371-B0B3-371391A2A7F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AA9C49B-9958-4371-B0B3-371391A2A7F7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BCC2EB19-3914-489B-B1D7-B7303E0218A3}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "6.0.3",
"commands": [
"dotnet-ef"
]
}
}
}

View File

@ -0,0 +1,106 @@
{
"needAnonymizeTag": [
{ //PatientsName
"Group": "0010",
"Element": "0010",
"ReplaceValue": "",
"Enable": true
},
{ // PatientID
"Group": "0010",
"Element": "0020",
"ReplaceValue": "",
"Enable": true
},
{ // IssuerOfPatientID
"Group": "0010",
"Element": "0021",
"ReplaceValue": "",
"Enable": true
},
{ // PatientsBirthDate
"Group": "0010",
"Element": "0030",
"ReplaceValue": "",
"Enable": true
},
{ // PatientsBirthTime
"Group": "0010",
"Element": "0032",
"ReplaceValue": "",
"Enable": false
},
{ // PatientsSex
"Group": "0010",
"Element": "0040",
"ReplaceValue": "",
"Enable": false
},
{ // OtherPatientIDs
"Group": "0010",
"Element": "1000",
"ReplaceValue": "",
"Enable": false
},
{ // OtherPatientNames
"Group": "0010",
"Element": "1001",
"ReplaceValue": "",
"Enable": false
},
{ // OtherPatientNames
"Group": "0010",
"Element": "1005",
"ReplaceValue": "",
"Enable": true
},
{ // PatientBirthName
"Group": "0010",
"Element": "1005",
"ReplaceValue": "",
"Enable": true
},
{ // PatientsAge
"Group": "0010",
"Element": "1010",
"ReplaceValue": "",
"Enable": true
},
{ // PatientsAddress
"Group": "0010",
"Element": "1040",
"ReplaceValue": "",
"Enable": true
},
{ // PatientsMothersBirthName
"Group": "0010",
"Element": "1060",
"ReplaceValue": "",
"Enable": true
},
{
"Group": "0010",
"Element": "2150",
"ReplaceValue": "",
"Enable": true
},
{
"Group": "0010",
"Element": "2152",
"ReplaceValue": "",
"Enable": true
},
{
"Group": "0010",
"Element": "2154",
"ReplaceValue": "",
"Enable": true
},
{
"Group": "0012",
"Element": "0040",
"ReplaceValue": "XXX",
"Enable": true
}
]
}

View File

@ -0,0 +1,63 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Threading.Tasks;
using EasyCaching.Core;
using IRaCIS.Application;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
namespace IRaCIS.WX.CoreApi.Auth
{
public class AuthMiddleware
{
private readonly RequestDelegate _next;
private readonly IEasyCachingProvider _provider;
public AuthMiddleware(RequestDelegate next, IEasyCachingProvider provider)
{
_next = next;
_provider = provider;
}
public async Task Invoke(HttpContext httpContext)
{
var isLogin = httpContext.Request.Path.ToString().ToLower().Contains("login");
var result = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
if (!isLogin)
{
if (!result.Succeeded)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized");
}
else
{
var toekn = result.Properties.Items[".Token.access_token"];
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(toekn);
object userId;
jwtToken.Payload.TryGetValue("id", out userId);
var cacheValueExist = await _provider.ExistsAsync(userId.ToString()); //Get<string>(userId.ToString()).ToString();
if (!cacheValueExist)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Unauthorized");
}
else
{
await _provider.SetAsync(userId.ToString(), userId.ToString(), TimeSpan.FromMinutes(SystemConfig.LoginExpiredTimeSpan));
httpContext.User = result.Principal;
await _next.Invoke(httpContext);
}
}
}
else await _next.Invoke(httpContext);
}
}
}

View File

@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace IRaCIS.WX.CoreApi.Auth
{
public class JwtSetting
{
/// <summary>
/// 颁发者
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 接收者
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 令牌密码
/// </summary>
public string SecurityKey { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public int TokenExpireDays { get; set; }
public Dictionary<string, object> Claims { get; set; }
/// <summary>
/// 签名
/// </summary>
public SigningCredentials Credentials
{
get {
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey));
return new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
}
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using IRaCIS.WX.CoreApi.Auth;
using Microsoft.Extensions.Options;
namespace IRaCIS.Core.API.Auth
{
public interface ITokenService
{
string GetToken(UserClaims user);
}
public class TokenService : ITokenService
{
private readonly JwtSetting _jwtSetting;
public TokenService(IOptions<JwtSetting> option)
{
_jwtSetting = option.Value;
}
public string GetToken(UserClaims user)
{
//创建用户身份标识,可按需要添加更多信息
var claims = new Claim[]
{
new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("id", user.Id.ToString()),
new Claim("name", user.FullName),
new Claim("realName", user.RealName),
new Claim("reviewerCode",user.ReviewerCode),
};
////创建令牌
var token = new JwtSecurityToken(
issuer: _jwtSetting.Issuer,
audience: _jwtSetting.Audience,
signingCredentials: _jwtSetting.Credentials,
claims: claims,
notBefore: DateTime.Now,
expires: DateTime.Now.AddDays(_jwtSetting.TokenExpireDays)
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
return jwtToken;
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using IRaCIS.Application.ViewModels;
namespace IRaCIS.Core.API.Auth
{
public class UserClaims
{
public Guid Id { get; set; }
public string[] Role { get; set; }
public string FullName { get; set; }
public string ReviewerCode { get; set; }
public string RealName { get; set; }
public string Phone { get; set; }
public string PhotoPath { get; set; }
public static UserClaims Create(UserBasicInfo user)
{
string[] roles = { "SysUser" };
return new UserClaims
{
Id = user.Id,
Role = roles,
FullName = user.UserName,
RealName = user.RealName,
PhotoPath = string.Empty,
ReviewerCode = user.ReviewerCode
};
}
public static UserClaims Create(DoctorAccountDTO doctor)
{
string[] roles = { "Doctor" };
return new UserClaims
{
Id = doctor.Id,
Role = roles,
FullName = doctor.FirstName + doctor.LastName,
Phone = doctor.Phone,
PhotoPath = string.Empty
};
}
}
}

View File

@ -0,0 +1,34 @@
using IRaCIS.WX.CoreApi.Auth;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;
namespace IRaCIS.Core.API
{
public class AuthConfigure
{
public static void ConfigureAuth(IServiceCollection services, IConfiguration configuration)
{
services.Configure<JwtSetting>(configuration.GetSection("JwtSetting"));
var jwtSetting = new JwtSetting();
configuration.Bind("JwtSetting", jwtSetting);
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = jwtSetting.Issuer,
ValidAudience = jwtSetting.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.SecurityKey)),
// 默认 300s
ClockSkew = TimeSpan.Zero
};
});
}
}
}

View File

@ -0,0 +1,16 @@
using AutoMapper;
using IRaCIS.Core.Application.Contracts.AutoMapper;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
{
public class AutoMapperConfigure
{
public static void ConfigureSwagger(IServiceCollection services)
{
AutoMapper.IConfigurationProvider config = AutoMapperConfig.RegisterMappings();
services.AddSingleton(config);
services.AddScoped<IMapper, Mapper>();
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Reflection;
using Autofac;
using Autofac.Extras.DynamicProxy;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Services;
using IRaCIS.Core.API;
using IRaCIS.Core.API.Auth;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.WX.CoreApi.Utility
{
// ReSharper disable once IdentifierTypo
public class CustomAutofacModule : Autofac.Module
{
protected override void Load(ContainerBuilder containerBuilder)
{
//containerBuilder.RegisterType<TokenService>().As<ITokenService>();
//containerBuilder.RegisterType<LogService>().As<ILogService>().SingleInstance();
//containerBuilder.RegisterType<DoctorService>().As<IDoctorService>().InstancePerLifetimeScope().EnableInterfaceInterceptors();
//Assembly domain = Assembly.Load("IRaCIS.Core.Domain");
//containerBuilder.RegisterAssemblyTypes(domain).AsImplementedInterfaces();
//Assembly domainShare = Assembly.Load("IRaCIS.Core.Domain.Share");
//containerBuilder.RegisterAssemblyTypes(domainShare).AsImplementedInterfaces();
//Assembly infrastructure = Assembly.Load("IRaCIS.Core.Infra.EFCore");
//containerBuilder.RegisterAssemblyTypes(infrastructure).AsImplementedInterfaces();
//Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "IRaCIS.Core.Application.dll");
//containerBuilder.RegisterAssemblyTypes(application).AsImplementedInterfaces();
#region 指定控制器也由autofac 来进行实例获取
#region 老方式
//var assembly = this.GetType().GetTypeInfo().Assembly;
//var builder = new ContainerBuilder();
//var manager = new ApplicationPartManager();
//manager.ApplicationParts.Add(new AssemblyPart(assembly));
//manager.FeatureProviders.Add(new ControllerFeatureProvider());
//var feature = new ControllerFeature();
//manager.PopulateFeature(feature);
//builder.RegisterType<ApplicationPartManager>().AsSelf().SingleInstance();
//builder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();
#endregion
//获取所有控制器类型并使用属性注入
//var controllerBaseType = typeof(ControllerBase);
//containerBuilder.RegisterAssemblyTypes(typeof(Program).Assembly)
// .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
// .PropertiesAutowired();
#endregion
}
}
}

View File

@ -0,0 +1,22 @@
using IRaCIS.Core.Infra.EFCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace IRaCIS.Core.API
{
public class EFConfigure
{
public static void ConfigureEF(IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<DbContext, IRaCISDBContext>();
//这个注入没有成功--注入是没问题的构造函数也只是支持参数就好错在注入的地方不能写DbContext
services.AddDbContext<IRaCISDBContext>(options =>
{
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value,contextOptionsBuilder=> contextOptionsBuilder.EnableRetryOnFailure());
options.EnableSensitiveDataLogging();
});
}
}
}

View File

@ -0,0 +1,81 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Profiling.Storage;
namespace IRaCIS.Core.API
{
public class MiniProfilerConfigure
{
public static void ConfigureMiniProfiler(IServiceCollection services)
{
services.AddMiniProfiler(options =>
{
// All of this is optional. You can simply call .AddMiniProfiler() for all defaults
// (Optional) Path to use for profiler URLs, default is /mini-profiler-resources
options.RouteBasePath = "/profiler";
//// (Optional) Control storage
//// (default is 30 minutes in MemoryCacheStorage)
(options.Storage as MemoryCacheStorage).CacheDuration = TimeSpan.FromMinutes(10);
//// (Optional) Control which SQL formatter to use, InlineFormatter is the default
//options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
//// (Optional) To control authorization, you can use the Func<HttpRequest, bool> options:
//// (default is everyone can access profilers)
//options.ResultsAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;
//options.ResultsListAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;
//// Or, there are async versions available:
//options.ResultsAuthorizeAsync = async request => (await MyGetUserFunctionAsync(request)).CanSeeMiniProfiler;
//options.ResultsAuthorizeListAsync = async request => (await MyGetUserFunctionAsync(request)).CanSeeMiniProfilerLists;
//// (Optional) To control which requests are profiled, use the Func<HttpRequest, bool> option:
//// (default is everything should be profiled)
//options.ShouldProfile = request => MyShouldThisBeProfiledFunction(request);
//// (Optional) Profiles are stored under a user ID, function to get it:
//// (default is null, since above methods don't use it by default)
//options.UserIdProvider = request => MyGetUserIdFunction(request);
//// (Optional) Swap out the entire profiler provider, if you want
//// (default handles async and works fine for almost all applications)
//options.ProfilerProvider = new MyProfilerProvider();
//// (Optional) You can disable "Connection Open()", "Connection Close()" (and async variant) tracking.
//// (defaults to true, and connection opening/closing is tracked)
//options.TrackConnectionOpenClose = true;
//// (Optional) Use something other than the "light" color scheme.
//// (defaults to "light")
//options.ColorScheme = StackExchange.Profiling.ColorScheme.Auto;
//// The below are newer options, available in .NET Core 3.0 and above:
//// (Optional) You can disable MVC filter profiling
//// (defaults to true, and filters are profiled)
//options.EnableMvcFilterProfiling = true;
//// ...or only save filters that take over a certain millisecond duration (including their children)
//// (defaults to null, and all filters are profiled)
//// options.MvcFilterMinimumSaveMs = 1.0m;
//// (Optional) You can disable MVC view profiling
//// (defaults to true, and views are profiled)
//options.EnableMvcViewProfiling = true;
//// ...or only save views that take over a certain millisecond duration (including their children)
//// (defaults to null, and all views are profiled)
//// options.MvcViewMinimumSaveMs = 1.0m;
//// (Optional) listen to any errors that occur within MiniProfiler itself
//// options.OnInternalError = e => MyExceptionLogger(e);
//// (Optional - not recommended) You can enable a heavy debug mode with stacks and tooltips when using memory storage
//// It has a lot of overhead vs. normal profiling and should only be used with that in mind
//// (defaults to false, debug/heavy mode is off)
////options.EnableDebugMode = true;
});
//.AddEntityFramework();
}
}
}

View File

@ -0,0 +1,101 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
namespace IRaCIS.Core.API
{
public class SwaggerConfigure
{
public static void ConfigureSwagger(IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
//此处的Name 是控制器上分组的名称 Title是界面的大标题
//分组
options.SwaggerDoc("Reviewer", new OpenApiInfo {Title = "医生模块",Version = "Reviewer", });
options.SwaggerDoc("Trial", new OpenApiInfo { Title = "项目模块", Version = "Trial" });
options.SwaggerDoc("Enroll", new OpenApiInfo { Title = "入组模块", Version = "Enroll" });
options.SwaggerDoc("Workload", new OpenApiInfo { Title = "工作量模块", Version = "Workload" });
options.SwaggerDoc("Common", new OpenApiInfo { Title = "通用信息获取", Version = "Common" });
options.SwaggerDoc("Institution", new OpenApiInfo { Title = "机构信息模块", Version = "Institution" });
options.SwaggerDoc("Dashboard&Statistics", new OpenApiInfo { Title = "统计模块", Version = "Dashboard&Statistics" });
options.SwaggerDoc("Financial", new OpenApiInfo { Title = "财务模块", Version = "Financial" });
options.SwaggerDoc("Management", new OpenApiInfo { Title = "管理模块", Version = "Management" });
options.SwaggerDoc("Image", new OpenApiInfo { Title = "影像模块", Version = "Image" });
options.SwaggerDoc("Reading", new OpenApiInfo { Title = "读片模块", Version = "Reading" });
// 接口排序
options.OrderActionsBy(o => o.GroupName);
options.DocInclusionPredicate((docName, apiDes) =>
{
if (!apiDes.TryGetMethodInfo(out MethodInfo methodInfo)) return false;
var versions = methodInfo.DeclaringType.GetCustomAttributes(true)
.OfType<ApiExplorerSettingsAttribute>()
.Select(attr => attr.GroupName);
return versions.Any(v => v.ToString() == docName);
});
var xmlPath = Path.Combine(AppContext.BaseDirectory, "IRaCIS.Core.API.xml");//这个就是刚刚配置的xml文件名
options.IncludeXmlComments(xmlPath, true);
//默认的第二个参数是false这个是controller的注释记得修改
// 在header中添加token传递到后台
options.OperationFilter<SecurityRequirementsOperationFilter>();
// Bearer
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "bearer",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT"
});
});
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
//此处的Name 是页面 选择文档下拉框 显示的名称
options.SwaggerEndpoint($"swagger/Reviewer/swagger.json", "医生模块");
options.SwaggerEndpoint($"swagger/Trial/swagger.json", "项目模块");
options.SwaggerEndpoint($"swagger/Enroll/swagger.json", "入组模块");
options.SwaggerEndpoint($"swagger/Workload/swagger.json", "工作量模块");
options.SwaggerEndpoint($"swagger/Dashboard&Statistics/swagger.json", "统计模块");
options.SwaggerEndpoint($"swagger/Common/swagger.json", "通用模块");
options.SwaggerEndpoint($"swagger/Financial/swagger.json", "财务模块");
options.SwaggerEndpoint($"swagger/Institution/swagger.json", "机构信息模块");
options.SwaggerEndpoint($"swagger/Management/swagger.json", "管理模块");
options.SwaggerEndpoint($"swagger/Image/swagger.json", "影像模块");
options.SwaggerEndpoint($"swagger/Reading/swagger.json", "读片模块");
//路径配置设置为空表示直接在根域名localhost:8001访问该文件,
//注意localhost:8001/swagger是访问不到的去launchSettings.json把launchUrl去掉如果你想换一个路径直接写名字即可比如直接写c.Route = "doc";
options.RoutePrefix = string.Empty;
//DocExpansion设置为none可折叠所有方法
options.DocExpansion(DocExpansion.None);
//DefaultModelsExpandDepth设置为 - 1 可不显示models
options.DefaultModelsExpandDepth(-1);
});
}
}
}

View File

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 数据字典-基础数据维护
/// </summary>
[Route("dictionary")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Common")]
public class DictionaryController : ControllerBase
{
private IDictionaryService _dictionaryService;
public DictionaryController(IDictionaryService dictionaryService)
{
_dictionaryService = dictionaryService;
}
/// <summary>
/// 获取项目多选字典
/// </summary>
/// <param name="searchArray">Title、Department、Rank、Position、ReadingType、Subspeciality Sponsor CROCompany ReadingStandard ReviewMode ReviewType ProjectState</param>
/// <returns></returns>
[HttpPost, Route("getDictionary")]
public IResponseOutput<DicResultDTO> GetDic(string[] searchArray)
{
var dicResult = _dictionaryService.GetDictionaryResult(searchArray);
return ResponseOutput.Ok(dicResult);
}
/// <summary>
/// 获取所有字典数据
/// </summary>
[HttpGet, Route("getAllDictionary")]
public IResponseOutput<DicResultDTO> GetAllDic()
{
return ResponseOutput.Ok(_dictionaryService.GetAllDictionary());
}
/// <summary>
/// 获取下拉框数据
/// </summary>
/// <returns></returns>
[HttpGet, Route("getDictionarySelect")]
public IResponseOutput<IEnumerable<string>> GetDicSelect()
{
return ResponseOutput.Ok(_dictionaryService.GetDicSelect());
}
/// <summary>
/// 获取下拉框某个keyName的列表
/// </summary>
/// <returns></returns>
[HttpPost, Route("getDictionarySelectList")]
public IResponseOutput<PageOutput<DicViewModelDTO>> GetDicSelectList(DicQueryDTO dicSearchModel)
{
return ResponseOutput.Ok(_dictionaryService.GetDicSelectList(dicSearchModel));
}
/// <summary> 添加字典 项 </summary>
[HttpPost, Route("addOrUpdateDictionary")]
public IResponseOutput AddOrUpdateDictionaryItem(DicViewModelDTO item)
{
return ResponseOutput.Ok(_dictionaryService.AddOrUpdateDictionary(item));
}
/// <summary>
/// 根据Id 删除字典数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete, Route("deleteDictionary/{id:guid}")]
public IResponseOutput DeleteDictionary(Guid id)
{
return _dictionaryService.DeleteDictionary(id);
}
/// <summary>
/// 获取字典Tree
/// </summary>
/// <returns></returns>
[HttpGet, Route("getDicTree")]
public IResponseOutput<List<DictionaryTreeNode>> GetDicTree()
{
return ResponseOutput.Ok(_dictionaryService.GetDicTree());
}
}
}

View File

@ -0,0 +1,354 @@
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.API.Controllers.Common;
using IRaCIS.Core.API.Filter;
using IRaCIS.Core.API.Utility;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 文件上传
/// </summary>
[Route("file")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Common")]
public class FileController : ControllerBase
{
private readonly IFileService _fileService;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly IHostEnvironment _hostEnvironment;
private ILogger<FileController> _logger;
private string _targetFilePath;
private readonly long _fileSizeLimit;
private readonly string[] _permittedExtensions = { ".pdf", ".doc", ".docx" };
public string trustedFileNameForFileStorage = "";
// Get the default form options so that we can use them to set the default
// limits for request body data.
private static readonly FormOptions _defaultFormOptions = new FormOptions();
private string defaultUploadFilePath = string.Empty;
public FileController(IFileService fileService, IConfiguration config,
IHostEnvironment hostEnvironment, ILogger<FileController> logger,
IWebHostEnvironment webHostEnvironment)
{
_fileService = fileService;
_hostEnvironment = hostEnvironment;
_webHostEnvironment = webHostEnvironment;
_fileSizeLimit = config.GetValue<long>("FileSizeLimit");
defaultUploadFilePath = Directory.GetParent(_hostEnvironment.ContentRootPath).FullName;
_logger = logger;
_logger.LogError("File Path:"+ defaultUploadFilePath);
// To save physical files to a path provided by configuration:
//_targetFilePath = config.GetValue<string>("StoredFilesPath");
// To save physical files to the temporary files folder, use:
//_targetFilePath = Path.GetTempPath();
}
/// <summary>
/// 上传文件[FileUpload]
/// </summary>
/// <param name="attachmentType">附件类型</param>
/// <param name="doctorId">医生Id</param>
/// <returns>返回文件信息</returns>
[HttpPost, Route("uploadFile/{attachmentType}/{doctorId}")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadOrdinaryFile(string attachmentType, Guid doctorId)
{
_logger.LogError("aaaa");
#region 官方文档方式
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error
return BadRequest(ModelState);
}
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
// This check assumes that there's a file
// present without form data. If form data
// is present, this method immediately fails
// and returns the model error.
if (!MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error
return BadRequest(ModelState);
}
else
{
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);
//var trustedFileNameForFileStorage = Path.GetRandomFileName();
trustedFileNameForFileStorage = contentDisposition.FileName.Value;
// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample.
var streamedFileContent = await FileHelpers.ProcessStreamedFile(
section, contentDisposition, ModelState,
_permittedExtensions, _fileSizeLimit);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//实际文件处理
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "UploadFile/" + doctorId + "/");
var doctorAttachmentUploadFolder = Path.Combine(uploadFolderPath, attachmentType);
_targetFilePath = doctorAttachmentUploadFolder;
if (!Directory.Exists(doctorAttachmentUploadFolder)) Directory.CreateDirectory(doctorAttachmentUploadFolder);
using (var targetStream = System.IO.File.Create(
Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);
var attachmentPath = $"/UploadFile/{doctorId}/{attachmentType}/{trustedFileNameForFileStorage}";
return new JsonResult(ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = attachmentPath }));
}
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileTestController), null);
#endregion
}
/// <summary>
/// 上传文件( 不是医生个人的文件)[FileUpload]
/// 例如:阅片章程等
/// </summary>
/// <param name="type">文件类型</param>
/// <returns></returns>
[HttpPost, Route("uploadNonDoctorFile/{type}")]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadNonDoctorFile(string type)
{
#region New Test 实测OK
//上传根路径
string uploadFolderPath = Path.Combine(defaultUploadFilePath, "UploadFile");
if (uploadFolderPath != null)
{
//文件类型路径处理
var uploadTypePath = Path.Combine(uploadFolderPath, type);
if (!Directory.Exists(uploadTypePath)) Directory.CreateDirectory(uploadTypePath);
////实际文件处理
_targetFilePath = uploadTypePath;
//获取boundary
#region 方式二
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
#endregion
#region 方式一
//var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
#endregion
//得到reader
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
//{ BodyLengthLimit = 2000 };//
var section = await reader.ReadNextSectionAsync();
//读取section
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
trustedFileNameForFileStorage = contentDisposition.FileName.Value;
await WriteFileAsync(section.Body, Path.Combine(_targetFilePath, trustedFileNameForFileStorage));
#region 方式二
//using (var targetStream = System.IO.File.Create(
// Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
//{
// using (var memoryStream = new MemoryStream())
// {
// await section.Body.CopyToAsync(memoryStream);
// await targetStream.WriteAsync(memoryStream.ToArray());
// }
//}
#endregion
var attachmentPath = $"/UploadFile/{type}/{trustedFileNameForFileStorage}";
return new JsonResult(ResponseOutput.Ok(new UploadFileInfoDTO() { FilePath = attachmentPath }));
}
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileController), null);
}
return new JsonResult(ResponseOutput.NotOk("服务器端映射路径操作失败"));
#endregion
}
/// <summary>
/// 写文件导到磁盘
/// </summary>
/// <param name="stream">流</param>
/// <param name="path">文件保存路径</param>
/// <returns></returns>
public static async Task<int> WriteFileAsync(System.IO.Stream stream, string path)
{
const int FILE_WRITE_SIZE = 84975;//写出缓冲区大小
int writeCount = 0;
using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write, FILE_WRITE_SIZE, true))
{
byte[] byteArr = new byte[FILE_WRITE_SIZE];
int readCount = 0;
while ((readCount = await stream.ReadAsync(byteArr, 0, byteArr.Length)) > 0)
{
await fileStream.WriteAsync(byteArr, 0, readCount);
writeCount += readCount;
}
}
return writeCount;
}
#region 上传无影响部分
/// <summary>
/// 下载多个医生的所有附件
/// </summary>
/// <param name="doctorIds"></param>
/// <returns></returns>
[HttpPost, Route("downloadDoctorAttachments")]
public IResponseOutput<UploadFileInfoDTO> DownloadAttachment(Guid[] doctorIds)
{
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = _fileService.CreateDoctorsAllAttachmentZip(doctorIds)
});
}
/// <summary>
/// 下载医生官方简历
/// </summary>
/// <param name="doctorIds"></param>
/// <returns></returns>
[HttpPost, Route("downloadOfficialCV")]
public IResponseOutput<UploadFileInfoDTO> DownloadOfficialResume(Guid[] doctorIds)
{
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = _fileService.CreateOfficialResumeZip(doctorIds)
});
}
/// <summary>
/// 下载指定医生的指定附件
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="attachmentIds">要下载的附件Id</param>
/// <returns></returns>
[HttpPost, Route("downloadByAttachmentId/{doctorId}")]
public IResponseOutput<UploadFileInfoDTO> DownloadAttachmentById(Guid doctorId, Guid[] attachmentIds)
{
return ResponseOutput.Ok(new UploadFileInfoDTO
{
FilePath = _fileService.CreateZipPackageByAttachment(doctorId, attachmentIds)
});
}
#endregion
}
}

View File

@ -0,0 +1,124 @@
using System.IO;
using System.Net;
using System.Threading.Tasks;
using IRaCIS.Core.API.Filter;
using IRaCIS.Core.API.Utility;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Net.Http.Headers;
namespace IRaCIS.Core.API.Controllers.Common
{
public class FileTestController : ControllerBase
{
private readonly string _targetFilePath;
private readonly long _fileSizeLimit;
private readonly string[] _permittedExtensions = { ".txt" ,".pdf"};
// Get the default form options so that we can use them to set the default
// limits for request body data.
private static readonly FormOptions _defaultFormOptions = new FormOptions();
public FileTestController(IConfiguration config)
{
_fileSizeLimit = config.GetValue<long>("FileSizeLimit");
// To save physical files to a path provided by configuration:
_targetFilePath = config.GetValue<string>("StoredFilesPath");
// To save physical files to the temporary files folder, use:
//_targetFilePath = Path.GetTempPath();
}
#region snippet_UploadPhysical 上传到服务器物理路径
[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UploadPhysical()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 1).");
// Log error
return BadRequest(ModelState);
}
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
// This check assumes that there's a file
// present without form data. If form data
// is present, this method immediately fails
// and returns the model error.
if (!MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
ModelState.AddModelError("File",
$"The request couldn't be processed (Error 2).");
// Log error
return BadRequest(ModelState);
}
else
{
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
contentDisposition.FileName.Value);
var trustedFileNameForFileStorage = Path.GetRandomFileName();
// **WARNING!**
// In the following example, the file is saved without
// scanning the file's contents. In most production
// scenarios, an anti-virus/anti-malware scanner API
// is used on the file before making the file available
// for download or for use by other systems.
// For more information, see the topic that accompanies
// this sample.
var streamedFileContent = await FileHelpers.ProcessStreamedFile(
section, contentDisposition, ModelState,
_permittedExtensions, _fileSizeLimit);
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
using (var targetStream = System.IO.File.Create(
Path.Combine(_targetFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);
}
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
return Created(nameof(FileTestController), null);
}
#endregion
}
}

View File

@ -0,0 +1,31 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 系统日志
/// </summary>
[Route("log")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Common")]
public class LogController : ControllerBase
{
private ILogService _logService;
public LogController(ILogService logService)
{
_logService = logService;
}
/// <summary> 查询系统日志信息 </summary>
[HttpPost, Route("getLogList")]
public IResponseOutput<PageOutput<SystemLogDTO>> GetLogList(QueryLogQueryDTO param)
{
return ResponseOutput.Ok(_logService.GetLogList(param)) ;
}
}
}

View File

@ -0,0 +1,62 @@
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace IRaCIS.Api.Controllers
{
[Route("message")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Common")]
public class MessageController : ControllerBase
{
private IMessageService _app;
public MessageController(IMessageService app)
{
_app = app;
}
/// <summary>
/// 删除消息
/// </summary>
/// <param name="messageId">消息Id</param>
/// <returns></returns>
[HttpDelete, Route("deleteMessage/{messageId:guid}")]
public IResponseOutput DeleteSysMessage(Guid messageId)
{
return _app.DeleteSysMessage(messageId);
}
/// <summary>
/// 分页获取系统消息
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="pageSize">分页大小</param>
/// <param name="pageIndex">也索引</param>
/// <returns></returns>
[HttpGet, Route("getMessageList/{doctorId:guid}/{pageIndex:int:min(1)}/{pageSize:int:range(1,100)}")]
public IResponseOutput<PageOutput<SysMessageDTO>> GetMessageList(Guid doctorId, int pageSize, int pageIndex)
{
return ResponseOutput.Ok(_app.GetMessageList(doctorId, pageSize, pageIndex)) ;
}
/// <summary>
/// 将消息标记已读
/// </summary>
/// <param name="messageId"></param>
/// <returns></returns>
[HttpGet, Route("markedAsRead/{messageId:guid}")]
public IResponseOutput MarkedAsRead(Guid messageId)
{
return _app.MarkedAsRead(messageId);
}
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生文档关联关系维护
/// </summary>
[Route("attachment")]
[ApiController, Authorize,ApiExplorerSettings(GroupName ="Reviewer")]
public class DocumentController : ControllerBase
{
private IAttachmentService _attachmentService;
public DocumentController(IAttachmentService doctorAttachmentApp)
{
_attachmentService = doctorAttachmentApp;
}
/// <summary>
/// 添加多个记录
/// </summary>
/// <param name="attachment"></param>
/// <returns></returns>
[HttpPost, Route("saveAttachments")]
public IResponseOutput<IEnumerable<AttachmentDTO>> AddDoctorAttachment(IEnumerable<AttachmentDTO> attachment)
{
return ResponseOutput.Ok(_attachmentService.SaveAttachmentRange(attachment));
}
/// <summary>
/// 删除记录
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpDelete, Route("deleteAttachment")]
public IResponseOutput DeleteAttachment(AttachementCommand param)
{
//var attachment = _doctorAttachmentApp.GetDetailById(id);
//string file = HostingEnvironment.MapPath(attachment.Path);
//if (File.Exists(file))
//{
// File.Delete(file);
//}
//var temp = HostingEnvironment.MapPath(param.Path);
//if (File.Exists(temp))
//{
// File.Delete(temp);
//}
return ResponseOutput.Ok(_attachmentService.DeleteAttachment(param.Id));
}
/// <summary>
/// 根据医生Id 和 附件类型,获取记录
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="type">附件类型</param>
/// <returns></returns>
[HttpGet, Route("getAttachmentByType/{doctorId:guid}/{type}")]
public IResponseOutput<IEnumerable<AttachmentDTO>> GetAttachmentListByType(Guid doctorId, string type)
{
return ResponseOutput.Ok(_attachmentService.GetAttachmentByType(doctorId, type));
}
/// <summary>
/// 获取单个医生的多种证书附件
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <param name="types">类型数组</param>
/// <returns></returns>
[HttpPost, Route("getAttachmentByTypes/{doctorId:guid}")]
public IResponseOutput<IEnumerable<AttachmentDTO>> GetAttachmentListByTypes(Guid doctorId, string[] types)
{
return ResponseOutput.Ok(_attachmentService.GetAttachmentByTypes(doctorId, types));
}
/// <summary>
/// 根据医生Id获取医生附件
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <returns></returns>
[HttpGet, Route("getAttachments/{doctorId:guid}")]
public IResponseOutput<IEnumerable<AttachmentDTO>> GetAttachmentList(Guid doctorId)
{
//var a = _attachmentService.GetAttachments(doctorId).ToList();
return ResponseOutput.Ok(_attachmentService.GetAttachments(doctorId));
}
/// <summary>
/// 将简历设置为官方简历
/// </summary>
/// <param name="doctorId"></param>
/// <param name="attachmentId"></param>
/// <returns></returns>
[HttpPost, Route("setOfficial/{doctorId:guid}/{attachmentId:guid}")]
public IResponseOutput SetOfficial(Guid doctorId, Guid attachmentId)
{
return _attachmentService.SetOfficial(doctorId, attachmentId);
}
}
}

View File

@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生基本信息 、工作信息 专业信息、审核状态
/// </summary>
[Route("doctor")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reviewer")]
public class DoctorController : ControllerBase
{
private readonly IDoctorService _doctorService;
public DoctorController(IDoctorService doctorService)
{
_doctorService = doctorService;
}
#region 医生列表查询接口
/// <summary>
/// 分页获取医生列表 (带查询条件)
/// </summary>
//
[HttpPost, Route("getDoctorSearchList")]
public IResponseOutput<PageOutput<DoctorDTO>> GetDoctorList([FromServices] IDoctorListQueryService _doctorListQueryService, DoctorSearchDTO doctorSearchModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return ResponseOutput.Ok(_doctorListQueryService.GetReviewerList(doctorSearchModel, userId)) ;
}
#endregion
#region 医生基本信息管理
/// <summary>
///详情、编辑-获取 医生基本信息 BasicInfo
/// </summary>
/// <param name="doctorId">ReviewerID</param>
/// <returns></returns>
[HttpGet, Route("getBasicInfo/{doctorId:guid}")]
public IResponseOutput<DoctorBasicInfoDTO> GetDoctorBasicInfoById(Guid doctorId)
{
var doctorInfo = _doctorService.GetDoctorBasicInfo(doctorId);
return ResponseOutput.Ok(doctorInfo);
}
/// <summary>
/// Get Statement of Work list.[New]
/// </summary>
/// <param name="doctorId"></param>
/// <returns></returns>
[HttpGet, Route("getDoctorSowList/{doctorId:guid}")]
public IResponseOutput<List<SowDTO>> GetDoctorSow(Guid doctorId)
{
var list = _doctorService.GetDoctorSow(doctorId);
return ResponseOutput.Ok(list);
}
/// <summary>
/// Get Ack Statement of Work[New]
/// </summary>
/// <param name="doctorId"></param>
/// <returns></returns>
[HttpGet, Route("getDoctorAckSowList/{doctorId:guid}")]
public IResponseOutput<List<SowDTO>> GetDoctorAckSow(Guid doctorId)
{
var list = _doctorService.GetDoctorAckSow(doctorId);
return ResponseOutput.Ok(list);
}
/// <summary>
/// 添加/更新 医生基本信息 BasicInfo
/// </summary>
[HttpPost, Route("addOrUpdateDoctorBasicInfo")]
public IResponseOutput<DoctorBasicInfoCommand> AddOrUpdateDoctorBasicInfo(DoctorBasicInfoCommand addBasicInfoViewModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _doctorService.AddOrUpdateDoctorBasicInfo(addBasicInfoViewModel, userId);
}
#endregion
#region 医生工作信息 Employment
/// <summary>
/// 详情、编辑-获取医生工作信息 Employment
/// </summary>
/// <param name="doctorId"></param>
/// <returns></returns>
[HttpGet, Route("getEmploymentInfo/{doctorId:Guid}")]
public IResponseOutput<EmploymentDTO> GetDoctorWorkInfoById(Guid doctorId)
{
var doctorInfo = _doctorService.GetEmploymentInfo(doctorId);
return ResponseOutput.Ok(doctorInfo);
}
/// <summary> 更新-医生工作信息 WorkInfo </summary>
[HttpPost, Route("updateEmploymentInfo")]
public IResponseOutput UpdateEmploymentInfoInfo(EmploymentCommand updateEmploymentInfoViewModel)
{
return _doctorService.UpdateDoctorEmploymentInfo(updateEmploymentInfoViewModel);
}
#endregion
#region Reviewer 专业信息
/// <summary> 获取医生专业信息 </summary>
[HttpGet, Route("getSpecialtyInfo/{doctorId:Guid}")]
public IResponseOutput<SpecialtyDTO> GetDoctorSpecialty(Guid doctorId)
{
var doctorInfo = _doctorService.GetDoctorSpecialty(doctorId);
return ResponseOutput.Ok(doctorInfo);
}
/// <summary> 更新专业信息 </summary>
[HttpPost, Route("updateSpecialtyInfo")]
public IResponseOutput UpdateDoctorSpecialty(SpecialtyCommand specialtyUpdateModel)
{
return _doctorService.UpdateDoctorSpecialty(specialtyUpdateModel);
//return new IResponseOutput<string>()
//{
// IsSuccess = success,
// ErrorMessage = success ? "Update Successfully." : "Update Failed."
//};
}
#endregion
#region Reviewer 状态
/// <summary> 获取医生审核状态 </summary>
[HttpGet, Route("getAuditState/{doctorId:guid}")]
public IResponseOutput<ResumeConfirmDTO> GetResumeAuditState([FromServices] IVacationService _vacationService, Guid doctorId)
{
var result = _doctorService.GetDoctorAuditStatus(doctorId);
result.InHoliday = _vacationService.OnVacation(doctorId).IsSuccess;
return ResponseOutput.Ok(result);
}
/// <summary>
/// 审核简历状态
/// </summary>
/// <param name="auditResumeParam">复审状态ReviewStatus 0-未复审1-复审通过2-未通过 </param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("updateAuditResume")]
public IResponseOutput AuditResume(ResumeConfirmCommand auditResumeParam)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _doctorService.AuditResume(auditResumeParam, userId);
}
/// <summary>
/// 获取医生入组信息 正在提交的数量 已同意入组项目个数 正在读的
/// </summary>
[HttpPost, Route("getDoctorIntoGroupInfo/{doctorId:guid}")]
public IResponseOutput<DoctorEnrollInfoDTO> GetDoctorEnrollInfo(Guid doctorId)
{
return ResponseOutput.Ok(_doctorService.GetDoctorEnrollInfo(doctorId));
}
#endregion
#region 医生详情
/// <summary>
/// 获取医生详情
/// </summary>
/// <param name="_vacationService"></param>
/// <param name="doctorId">医生Id</param>
/// <param name="attachmentService"></param>
/// <param name="_educationService"></param>
/// <param name="_trialExperienceService"></param>
/// <param name="_researchPublicationService"></param>
/// <returns></returns>
[HttpGet, Route("getDetail/{doctorId:guid}")]
public IResponseOutput<DoctorDetailDTO> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService, [FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService, Guid doctorId)
{
var education = _educationService.GetEducation(doctorId);
var sowList = _doctorService.GetDoctorSow(doctorId);
var ackSowList = _doctorService.GetDoctorAckSow(doctorId);
var doctorDetail = new DoctorDetailDTO
{
AuditView = _doctorService.GetDoctorAuditStatus(doctorId),
BasicInfoView = _doctorService.GetDoctorBasicInfo(doctorId),
EmploymentView = _doctorService.GetEmploymentInfo(doctorId),
AttachmentList = attachmentService.GetAttachments(doctorId),
EducationList = education.EducationList,
PostgraduateList = education.PostgraduateList,
TrialExperienceView = _trialExperienceService.GetTrialExperience(doctorId),
ResearchPublicationView = _researchPublicationService.GetResearchPublication(doctorId),
SpecialtyView = _doctorService.GetDoctorSpecialty(doctorId),
InHoliday = _vacationService.OnVacation(doctorId).IsSuccess,
IntoGroupInfo = _doctorService.GetDoctorEnrollInfo(doctorId),
SowList = sowList,
AckSowList = ackSowList
};
return ResponseOutput.Ok(doctorDetail);
}
#endregion
}
}

View File

@ -0,0 +1,87 @@
using System;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生教育经历、继续学习经历
/// </summary>
[Route("doctor")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reviewer")]
public class EducationController : ControllerBase
{
private readonly IEducationService _doctorEducationService;
public EducationController(IEducationService doctorEducationService)
{
_doctorEducationService = doctorEducationService;
}
/// <summary>
/// 根据医生Id获取医生教育经历和继续学习经历列表
/// </summary>
[HttpGet, Route("getEducation/{doctorId:Guid}")]
public IResponseOutput<DoctorEducationExperienceDTO> GetDoctorEducationList(Guid doctorId)
{
return ResponseOutput.Ok(_doctorEducationService.GetEducation(doctorId)) ;
}
#region 教育经历
/// <summary>
/// 新增医生教育经历
/// </summary>
/// <param name="doctorEducationInfoViewModel"></param>
/// <returns></returns>
[HttpPost, Route("addOrUpdateEducationInfo")]
public IResponseOutput AddEducationInfo(EducationCommand doctorEducationInfoViewModel)
{
return _doctorEducationService.AddOrUpdateEducationInfo(doctorEducationInfoViewModel);
}
/// <summary>
/// 删除医生教育经历
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <returns></returns>
[HttpDelete, Route("deleteEducationInfo/{doctorId:guid}")]
public IResponseOutput DeleteEducationInfo(Guid doctorId)
{
return _doctorEducationService.DeleteEducationInfo(doctorId);
}
#endregion
#region 继续学习经历
/// <summary> 添加/更新医生继续学习经历</summary>
[HttpPost, Route("addOrUpdatePostgraduateInfo")]
public IResponseOutput AddPostgraduateInfo(PostgraduateCommand doctorEducationInfoViewModel)
{
return _doctorEducationService.AddOrUpdatePostgraduateInfo(doctorEducationInfoViewModel);
}
/// <summary>
/// 删除医生继续学习经历
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <returns></returns>
[HttpDelete, Route("deletePostgraduateInfo/{doctorId:guid}")]
public IResponseOutput DeleteContinueLearningInfo(Guid doctorId)
{
return _doctorEducationService.DeletePostgraduateInfo(doctorId);
}
#endregion
}
}

View File

@ -0,0 +1,44 @@
using System;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生科研信息
/// </summary>
[Route("doctor")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reviewer")]
public class ResearchPublicationController : ControllerBase
{
private readonly IResearchPublicationService _researchPublicationService;
public ResearchPublicationController(IResearchPublicationService researchPublicationService)
{
_researchPublicationService = researchPublicationService;
}
/// <summary>
/// 查询-医生科学研究信息
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <returns></returns>
[HttpGet, Route("getResearchPublication/{doctorId:guid}")]
public IResponseOutput<ResearchPublicationDTO> GetDoctorScientificResearch(Guid doctorId)
{
return ResponseOutput.Ok(_researchPublicationService.GetResearchPublication(doctorId)) ;
}
/// <summary> 添加或跟新医生 科研信息 </summary>
[HttpPost, Route("addResearchPublication")]
public IResponseOutput AddOrUpdateScientificResearch(
ResearchPublicationDTO researchPublicationViewModel)
{
return _researchPublicationService.AddOrUpdateResearchPublication(researchPublicationViewModel);
}
}
}

View File

@ -0,0 +1,82 @@
using System;
using IRaCIS.Application;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生临床试验经历
/// </summary>
[Route("doctor")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reviewer")]
public class TrialExperienceController : ControllerBase
{
private readonly ITrialExperienceService _doctorTrialExperienceService;
public TrialExperienceController(ITrialExperienceService doctorTrialExperienceService)
{
_doctorTrialExperienceService = doctorTrialExperienceService;
}
/// <summary>
/// 根据医生Id获取临床试验经历 界面所有数据
/// </summary>
[HttpGet, Route("getTrialExperience/{doctorId:guid}")]
public IResponseOutput<TrialExperienceViewModel> GetClinicalTrialExperience(Guid doctorId)
{
return ResponseOutput.Ok(_doctorTrialExperienceService.GetTrialExperience(doctorId)) ;
}
/// <summary> 添加或更新医生临床经验列表项</summary>
[HttpPost, Route("addOrUpdateTrialExperience")]
public IResponseOutput AddOrUpdateClinicalTrialExperience(TrialExperienceCommand trialExperienceViewModel)
{
return _doctorTrialExperienceService.AddOrUpdateTrialExperience(trialExperienceViewModel);
}
/// <summary>
/// 更新-GCP和其他临床经验
/// </summary>
/// <param name="trialExperienceGcpViewModel"></param>
/// <returns></returns>
[HttpPost, Route("updateGcpExperience")]
public IResponseOutput UpdateDoctorGcpAndOtherExperience(
GCPExperienceCommand trialExperienceGcpViewModel)
{
return _doctorTrialExperienceService.UpdateGcpExperience(trialExperienceGcpViewModel);
}
/// <summary>
/// 更新其他技能经验
/// </summary>
[HttpPost, Route("updateOtherExperience")]
public IResponseOutput UpdateOtherExperience(ClinicalExperienceCommand updateOtherClinicalExperience)
{
return _doctorTrialExperienceService.UpdateOtherExperience(updateOtherClinicalExperience.DoctorId, updateOtherClinicalExperience.OtherClinicalExperience);
}
/// <summary>
/// 删除临床经验
/// </summary>
[HttpDelete, Route("deleteTrialExperience/{doctorId:guid}")]
public IResponseOutput DeleteDoctorTrialExperience(Guid doctorId)
{
return _doctorTrialExperienceService.DeleteTrialExperience(doctorId);
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers.Doctor
{
/// <summary>
/// 医生休假安排
/// </summary>
[Route("holiday")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reviewer")]
public class VacationController : ControllerBase
{
private readonly IVacationService _vacationService;
public VacationController(IVacationService vacationService)
{
_vacationService = vacationService;
}
/// <summary>
/// 添加休假时间段
/// </summary>
/// <param name="vacationViewModel">Status不传</param>
/// <returns></returns>
[HttpPost, Route("addOrUpdateVacation")]
public IResponseOutput AddOrUpdateVacation(VacationCommand vacationViewModel)
{
return _vacationService.AddOrUpdateVacation(vacationViewModel);
}
/// <summary>
/// 删除休假时间段
/// </summary>
/// <param name="holidayId">记录Id</param>
/// <returns></returns>
[HttpDelete, Route("deleteVacation/{holidayId:guid}")]
public IResponseOutput DeleteVacation(Guid holidayId)
{
return _vacationService.DeleteVacation(holidayId);
}
/// <summary>
/// 获取休假时间段列表
/// </summary>
/// <returns></returns>
[HttpGet, Route("getVacationList/{doctorId:guid}/{pageIndex:int}/{pageSize:int}")]
public IResponseOutput<PageOutput<VacationCommand>> GetVacationList(Guid doctorId, int pageIndex, int pageSize)
{
return ResponseOutput.Ok(_vacationService.GetVacationList(doctorId, pageIndex, pageSize)) ;
}
}
}

View File

@ -0,0 +1,81 @@
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers.Pay
{
/// <summary>
/// Financial 支撑信息---汇率
/// </summary>
[Route("exchangeRate")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class ExchangeRateController : ControllerBase
{
private readonly IExchangeRateService _exchangeRateService;
private readonly ICalculateService _calculateService;
private readonly IPaymentAdjustmentService _costAdjustmentService;
public ExchangeRateController(IExchangeRateService exchangeRateService,
ICalculateService calculateService,
IPaymentAdjustmentService costAdjustmentService)
{
_exchangeRateService = exchangeRateService;
_calculateService = calculateService;
_costAdjustmentService = costAdjustmentService;
}
/// <summary>
/// 添加或更新汇率(会触发没有对锁定的费用计算)
/// </summary>
[LogFilter]
[HttpPost, Route("addOrUpdateExchangeRate")]
public IResponseOutput AddOrUpdateExchangeRate(ExchangeRateCommand addOrUpdateModel)
{
var result = _exchangeRateService.AddOrUpdateExchangeRate(addOrUpdateModel);
var calcList = _calculateService.GetNeedCalculateReviewerList(Guid.Empty, addOrUpdateModel.YearMonth);
foreach (var item in calcList)
{
if (item != null)
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
item.DoctorId
},
CalculateMonth = DateTime.Parse(item.YearMonth)
}, User.FindFirst("id").Value);
}
}
_costAdjustmentService.CalculateCNY(addOrUpdateModel.YearMonth,addOrUpdateModel.Rate);
return result;
}
/// <summary>
/// 分页获取汇率列表
/// </summary>
[HttpPost, Route("getRateList")]
public IResponseOutput<PageOutput<ExchangeRateCommand>> GetAwardPriceList(ExchangeRateQueryDTO queryParam)
{
return ResponseOutput.Ok(_exchangeRateService.GetExchangeRateList(queryParam));
}
/// <summary>
/// 根据记录Id删除汇率记录
/// </summary>
/// <param name="id">汇率记录Id</param>
[HttpDelete, Route("deleteExchangeRate/{id:guid}")]
public IResponseOutput DeleteExchangeRate(Guid id)
{
return _exchangeRateService.DeleteExchangeRate(id);
}
}
}

View File

@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Application.ViewModels.Pay;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 费用查询(月度付费、月度付费明细、历史范围付费、历史范围付费明细、收入、收入支出分析)
/// </summary>
[Route("financial")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class FinancialController : ControllerBase
{
private readonly IPaymentService _paymentService;
private readonly IExchangeRateService _exchangeRateService;
private readonly ICalculateService _calculateService;
public FinancialController(IPaymentService paymentService,
IExchangeRateService exchangeRateService,
ICalculateService calculateService)
{
_paymentService = paymentService;
_exchangeRateService = exchangeRateService;
_calculateService = calculateService;
}
/// <summary>
/// 计算医生月度费用,并将计算的结果存入费用表
/// </summary>
[HttpPost, Route("calculateMonthlyPayment")]
public IResponseOutput CalculateMonthlyPayment(CalculateDoctorAndMonthDTO param)
{
if (!ModelState.IsValid)
{
return ResponseOutput.NotOk("Invalid parameter.");
}
return _calculateService.CalculateMonthlyPayment(param, User.FindFirst("id").Value);
}
/// <summary>
/// Financials /Monthly Payment 列表查询接口
/// </summary>
[HttpPost, Route("getMonthlyPaymentList")]
public IResponseOutput<PaymentDTO> GetMonthlyPaymentList(MonthlyPaymentQueryDTO queryParam)
{
return ResponseOutput.Ok(new PaymentDTO
{
CostList = _paymentService.GetMonthlyPaymentList(queryParam),
ExchangeRate = _exchangeRateService.GetExchangeRateByMonth(queryParam.StatisticsDate.ToString("yyyy-MM"))
});
}
/// <summary>
/// Financials /MonthlyPaymentDetail 详情查询接口
/// </summary>
[HttpPost, Route("getMonthlyPaymentDetailList/{paymentId:guid}/{doctorId:guid}/{yearMonth:datetime}")]
public IResponseOutput<PayDetailDTO> GetMonthlyPaymentDetailList(Guid paymentId, Guid doctorId, DateTime yearMonth)
{
return ResponseOutput.Ok(_paymentService.GetMonthlyPaymentDetailList(paymentId, doctorId, yearMonth));
}
/// <summary>
/// NEW 导出Excel压缩包 数据获取
/// </summary>
/// <param name="manyReviewers"></param>
/// <returns></returns>
[HttpPost, Route("getReviewersMonthlyPaymentDetail")]
public IResponseOutput<List<PayDetailDTO>> GetReviewersMonthlyPaymentDetail(List<MonthlyPaymentDetailQuery> manyReviewers)
{
return ResponseOutput.Ok(_paymentService.GetReviewersMonthlyPaymentDetail(manyReviewers));
}
/// <summary>
/// 获取劳务费用列表
/// </summary>
/// <param name="paymentIds"></param>
/// <returns></returns>
[HttpPost, Route("getLaborPaymentList")]
public IResponseOutput<List<LaborPayment>> GetLaborPaymentList(List<Guid> paymentIds)
{
return ResponseOutput.Ok(_paymentService.GetLaborPaymentList(paymentIds));
}
/// <summary>
/// 锁定医生费用,锁定后,无法变更该医生对应月份的费用和工作量[New]
/// </summary>
[HttpPost, Route("lockMonthlyPayment")]
public IResponseOutput LockMonthlyPayment(LockPaymentDTO param)
{
var yearMonth = param.Month.ToString("yyyy-MM");
return _calculateService.UpdateLockStatus(param.ReviewerIdList, yearMonth, true);
}
/// <summary>
/// Financials / Payment History 列表查询接口(已经支付锁定的数据,包含调整的)[New]
/// </summary>
[HttpPost, Route("getPaymentHistoryList")]
public IResponseOutput<PageOutput<MonthlyPaymentDTO>> GetPaymentHistoryList(PaymentQueryDTO param)
{
return ResponseOutput.Ok(_paymentService.GetPaymentHistoryList(param)) ;
}
/// <summary>
/// Financials / Payment History 详情接口[New]
/// </summary>
[HttpPost, Route("getPaymentHistoryDetailList")]
public IResponseOutput<List<VolumeStatisticsDTO>> GetPaymentHistoryDetailList(VolumeQueryDTO param)
{
var result = _paymentService.GetPaymentHistoryDetailList(param);
return ResponseOutput.Ok(result);
}
/// <summary>
/// Revenues列表接口收入统计[New] 0是Detail 1是按照项目 2是按照人 3按照月份
/// </summary>
[HttpPost, Route("getRevenuesStatistics")]
public IResponseOutput<PageOutput<RevenuesDTO>> GetRevenuesStatistics(StatisticsQueryDTO param)
{
var result = _paymentService.GetRevenuesList(param);
return ResponseOutput.Ok(result) ;
}
/// <summary>
/// 收入支出分析接口,按照医生维度分析统计
/// </summary>
[HttpPost, Route("getReviewerAnalysisList")]
public IResponseOutput<List<ReviewerAnalysisDTO>> GetReviewerAnalysisList(AnalysisQueryDTO param)
{
return ResponseOutput.Ok(_paymentService.GetReviewerAnalysisList(param));
}
/// <summary>
/// 收入支出分析接口,按照项目维度分析统计
/// </summary>
[HttpPost, Route("getTrialAnalysisList")]
public IResponseOutput<List<TrialAnalysisDTO>> GetTrialAnalysisList(TrialAnalysisQueryDTO param)
{
return ResponseOutput.Ok(_paymentService.GetTrialAnalysisList(param));
}
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels.Pay;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers.Pay
{
/// <summary>
/// Financial 支撑信息---医生月度调整
/// </summary>
[Route("paymentAdjustment")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class PaymentAdjustmentController : ControllerBase
{
private readonly IPaymentAdjustmentService _paymentAdjustmentService;
public PaymentAdjustmentController(IPaymentAdjustmentService paymentAdjustmentService)
{
_paymentAdjustmentService = paymentAdjustmentService;
}
/// <summary>
/// 获取费用调整列表
/// </summary>
[HttpPost, Route("getPaymentAdjustmentList")]
public IResponseOutput<PageOutput<PaymentAdjustmentDetailDTO>> GetPaymentAdjustmentList(
PaymentAdjustmentQueryDTO queryParam)
{
var result = _paymentAdjustmentService.GetPaymentAdjustmentList(queryParam);
return ResponseOutput.Ok(result);
}
/// <summary>
/// 添加或更新费用调整[AUTH]
/// </summary>
[LogFilter]
[HttpPost, Route("addOrUpdatePaymentAdjustment")]
public IResponseOutput AddOrUpdatePaymentAdjustment(PaymentAdjustmentCommand addOrUpdateModel)
{
return _paymentAdjustmentService.AddOrUpdatePaymentAdjustment(addOrUpdateModel,Guid.Parse(User.FindFirst("id").Value));
}
/// <summary>
/// 删除费用调整记录
/// </summary>
[LogFilter]
[HttpDelete, Route("deletePaymentAdjustment/{id:guid}")]
public IResponseOutput DeleteCostAdjustment(Guid id)
{
return _paymentAdjustmentService.DeleteCostAdjustment(id);
}
/// <summary>
/// 获取医生列表
/// </summary>
[HttpGet, Route("getReviewerSelectList")]
public IResponseOutput<List<DoctorSelectDTO>> GetReviewerSelectList()
{
return ResponseOutput.Ok(_paymentAdjustmentService.GetReviewerSelectList());
}
}
}

View File

@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers.Pay
{
/// <summary>
/// Financial 支撑信息---职称付费价格
/// </summary>
[Route("rankPrice")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class RankPriceController : ControllerBase
{
private readonly IRankPriceService _rankPriceService;
private readonly ICalculateService _calculateService;
private readonly IReviewerPayInfoService _reviewerPayInfoService;
public RankPriceController(IRankPriceService rankPriceService,
ICalculateService calculateService, IReviewerPayInfoService reviewerPayInfoService)
{
_rankPriceService = rankPriceService;
_calculateService = calculateService;
_reviewerPayInfoService = reviewerPayInfoService;
}
/// <summary>
/// 添加或更新 职称单价[AUTH]
/// </summary>
[LogFilter]
[HttpPost, Route("addOrUpdateRankPrice")]
public IResponseOutput AddOrUpdateRankPrice(RankPriceCommand addOrUpdateModel)
{
if (addOrUpdateModel.Id != Guid.Empty&& addOrUpdateModel.Id !=null)
{
var needCalReviewerIds = _reviewerPayInfoService.GetReviewerIdByRankId(Guid.Parse(addOrUpdateModel.Id.ToString()));
var calcList = _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
foreach (var item in calcList)
{
if (item != null && needCalReviewerIds.Contains(item.DoctorId))
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
item.DoctorId
},
CalculateMonth = DateTime.Parse(item.YearMonth)
}, User.FindFirst("id").Value);
}
}
}
var userId = Guid.Parse(User.FindFirst("id").Value);
return _rankPriceService.AddOrUpdateRankPrice(addOrUpdateModel, userId);
}
/// <summary>
/// 获取职称单价列表
/// </summary>
[HttpPost, Route("getRankPriceList")]
public IResponseOutput<PageOutput<RankPriceDTO>> GetRankPriceList(RankPriceQueryDTO queryParam)
{
return ResponseOutput.Ok(_rankPriceService.GetRankPriceList(queryParam));
}
/// <summary>
/// 删除职称单价记录
/// </summary>
[HttpDelete, Route("deleteRankPrice/{id:guid}")]
public IResponseOutput DeleteRankPrice(Guid id)
{
return _rankPriceService.DeleteRankPrice(id);
}
/// <summary>
/// 获取职称字典数据
/// </summary>
[HttpGet, Route("getRankDic")]
public IResponseOutput<List<RankDic>> GetRankDic()
{
return ResponseOutput.Ok(_rankPriceService.GetRankDic());
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Financial 支撑信息---医生付费信息及支付标准配置
/// </summary>
[Route("reviewerPayInfomation")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class ReviewerPayInfomationController : ControllerBase
{
private IReviewerPayInfoService _doctorPayInfoService;
private readonly ICalculateService _calculateService;
public ReviewerPayInfomationController(IReviewerPayInfoService doctorPayInfoService,
ICalculateService calculateService)
{
_doctorPayInfoService = doctorPayInfoService;
_calculateService = calculateService;
}
/// <summary>
/// 添加或更新(替换)医生支付展信息[AUTH]
/// </summary>
[HttpPost, Route("addOrUpdateReviewerPayInfo")]
public IResponseOutput AddOrUpdateReviewerPayInfo(ReviewerPayInfoCommand addOrUpdateModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
var result = _doctorPayInfoService.AddOrUpdateReviewerPayInfo(addOrUpdateModel, userId);
var calcList = _calculateService.GetNeedCalculateReviewerList(addOrUpdateModel.DoctorId, string.Empty);
foreach (var item in calcList)
{
if (item != null)
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
item.DoctorId
},
CalculateMonth = DateTime.Parse(item.YearMonth)
}, User.FindFirst("id").Value);
}
}
return result;
}
/// <summary>
/// 获取医生支付信息列表
/// </summary>
[HttpPost, Route("getReviewerPayInfoList")]
public IResponseOutput<PageOutput<DoctorPayInfoQueryListDTO>> GetReviewerPayInfoList(DoctorPaymentInfoQueryDTO queryParam)
{
return ResponseOutput.Ok(_doctorPayInfoService.GetDoctorPayInfoList(queryParam)) ;
}
/// <summary>
/// 根据医生Id获取支付信息
/// </summary>
/// <param name="doctorId">医生Id</param>
/// <returns></returns>
[HttpGet, Route("getReviewerPayInfo/{doctorId:guid}")]
public IResponseOutput<DoctorPayInfoQueryListDTO> GetReviewerPayInfo(Guid doctorId)
{
return ResponseOutput.Ok(_doctorPayInfoService.GetReviewerPayInfo(doctorId)) ;
}
}
}

View File

@ -0,0 +1,97 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Financial 支撑信息---项目费用
/// </summary>
[Route("trialPaymentPrice")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class TrialPaymentPriceController : ControllerBase
{
private readonly ITrialPaymentPriceService _trialPaymentPriceService;
private readonly ICalculateService _calculateService;
private readonly ITrialService _trialService;
public TrialPaymentPriceController(ITrialPaymentPriceService trialPaymentPriceService,
ICalculateService calculateService,
ITrialService trialService)
{
_trialPaymentPriceService = trialPaymentPriceService;
_calculateService = calculateService;
_trialService = trialService;
}
/// <summary>
/// 保存(替换)项目支付价格信息(会触发没有被锁定的费用计算)[AUTH]
/// </summary>
[HttpPost, Route("addOrUpdateTrialPaymentPrice")]
public IResponseOutput AddOrUpdateTrialPaymentPrice(TrialPaymentPriceCommand addOrUpdateModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
var result = _trialPaymentPriceService.AddOrUpdateTrialPaymentPrice(addOrUpdateModel, userId);
var needCalReviewerIds = _trialService.GetTrialEnrollmentReviewerIds(addOrUpdateModel.TrialId);
var calcList = _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
foreach (var item in calcList)
{
if (item != null && needCalReviewerIds.Contains(item.DoctorId))
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
item.DoctorId
},
CalculateMonth = DateTime.Parse(item.YearMonth)
}, User.FindFirst("id").Value);
}
}
return result;
}
/// <summary>
/// 更新项目SOW 协议 [AUTH]
/// </summary>
/// <param name="trialSowPath"></param>
/// <returns></returns>
[HttpPost, Route("uploadTrialSOW")]
public IResponseOutput UploadTrialSOW(TrialSOWPathDTO trialSowPath)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialPaymentPriceService.UploadTrialSOW(userId, trialSowPath);
}
/// <summary>
///删除项目SOW [AUTH]
/// </summary>
/// <param name="trialSowPath"></param>
/// <returns></returns>
[HttpPost, Route("deleteTrialSOW")]
public IResponseOutput DeleteTrialSOW(DeleteSowPathDTO trialSowPath)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialPaymentPriceService.DeleteTrialSOW(userId, trialSowPath);
}
/// <summary>
/// 获取项目支付价格信息列表
/// </summary>
[HttpPost, Route("getTrialPaymentPriceList")]
public IResponseOutput<PageOutput<TrialPaymentPriceDTO>> GetTrialPaymentPriceList(TrialPaymentPriceQueryDTO queryParam)
{
return ResponseOutput.Ok(_trialPaymentPriceService.GetTrialPaymentPriceList(queryParam)) ;
}
}
}

View File

@ -0,0 +1,50 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Financial 支撑信息---项目收入费用
/// </summary>
[Route("trialRevenuesPrice")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class TrialRevenuesPriceController : ControllerBase
{
private readonly ITrialRevenuesPriceService _trialRevenuesPriceService;
public TrialRevenuesPriceController(ITrialRevenuesPriceService trialRevenuesPriceService)
{
_trialRevenuesPriceService = trialRevenuesPriceService;
}
/// <summary>
/// 保存(替换)项目费用收入单价信息[New]
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("addOrUpdateTrialRevenuesPrice")]
public IResponseOutput AddOrUpdateTrialRevenuesPrice(TrialRevenuesPriceDTO model)
{
return _trialRevenuesPriceService.AddOrUpdateTrialRevenuesPrice(model);
}
/// <summary>
/// 获取项目收入费用信息列表[New]
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost, Route("getTrialRevenuesPriceList")]
public IResponseOutput<PageOutput<TrialRevenuesPriceDetialDTO>> GetTrialRevenuesPriceList(TrialRevenuesPriceQueryDTO param)
{
return ResponseOutput.Ok(_trialRevenuesPriceService.GetTrialRevenuesPriceList(param));
}
}
}

View File

@ -0,0 +1,36 @@

using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Application.Contracts.Trial.DTO;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Financial---项目收入价格验证
/// </summary>
[Route("trialRevenuesPriceVerification")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class TrialRevenuesPriceVerificationController : ControllerBase
{
private readonly ITrialRevenuesPriceVerificationService _trialRevenuesPriceVerificationService;
public TrialRevenuesPriceVerificationController(ITrialRevenuesPriceVerificationService trialRevenuesPriceVerificationService)
{
_trialRevenuesPriceVerificationService = trialRevenuesPriceVerificationService;
}
[HttpPost, Route("getRevenuesVerifyList")]
public IResponseOutput<List<RevenusVerifyDTO>> GetRevenuesVerifyList(RevenusVerifyQueryDTO param)
{
return ResponseOutput.Ok(_trialRevenuesPriceVerificationService.GetTrialRevenuesVerifyResultList(param));
}
[HttpPost, Route("getAnalysisVerifyList")]
public IResponseOutput<AnalysisVerifyResultDTO> GetAnalysisVerifyList(RevenusVerifyQueryDTO param)
{
return ResponseOutput.Ok(_trialRevenuesPriceVerificationService.GetAnalysisVerifyList(param));
}
}
}

View File

@ -0,0 +1,71 @@
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers.Pay
{
/// <summary>
/// Financial 支撑信息---工作量奖励标准
/// </summary>
[Route("volumeReward")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Financial")]
public class VolumeRewardController : ControllerBase
{
private readonly IVolumeRewardService _volumeRewardService;
private readonly ICalculateService _calculateService;
public VolumeRewardController(IVolumeRewardService volumeRewardService,
ICalculateService calculateService)
{
_volumeRewardService = volumeRewardService;
_calculateService = calculateService;
}
/// <summary>
/// 批量更新奖励费用[AUTH]
/// </summary>
[LogFilter]
[HttpPost, Route("addOrUpdatevolumeRewardPriceList")]
public IResponseOutput AddOrUpdateAwardPriceList(IEnumerable<AwardPriceCommand> addOrUpdateModel)
{
var userId = User.FindFirst("id").Value;
var result = _volumeRewardService.AddOrUpdateVolumeRewardPriceList(addOrUpdateModel, Guid.Parse(userId));
var calcList = _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
foreach (var item in calcList)
{
if (item != null)
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
item.DoctorId
},
CalculateMonth = DateTime.Parse(item.YearMonth)
}, User.FindFirst("id").Value);
}
}
return result;
}
/// <summary>
/// 分页获取奖励单价列表
/// </summary>
[HttpPost, Route("getVolumeRewardPriceList")]
public IResponseOutput<PageOutput<AwardPriceDTO>> GetAwardPriceList(AwardPriceQueryDTO queryParam)
{
return ResponseOutput.Ok(_volumeRewardService.GetVolumeRewardPriceList(queryParam));
}
}
}

View File

@ -0,0 +1,78 @@
using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Dicom;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Instance
/// </summary>
[Route("instance")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
public class InstanceController : ControllerBase
{
private readonly IDicomArchiveService _dicomArchiveService;
public InstanceController(IDicomArchiveService dicomArchiveService)
{
_dicomArchiveService = dicomArchiveService;
}
/// <summary> 指定资源Id获取Dicom序列所属的实例信息列表 </summary>
/// <param name="seriesId"> Dicom序列的Id </param>
[HttpGet, Route("list/{seriesId:guid}")]
public IEnumerable<DicomInstanceDTO> GetInstanceList(Guid seriesId)
{
return _dicomArchiveService.GetInstanceList(seriesId);
}
/// <summary> 指定资源Id获取Dicom序列所属的实例Id列表 </summary>
/// <param name="seriesId"> Dicom序列的Id </param>
/// <param name="tpCode"></param>
/// <param name="key"></param>
[HttpGet, Route("list/id/{seriesId:guid}/{tpCode?}/{key?}")]
public IEnumerable<Guid> GetInstanceIdList(Guid seriesId, string tpCode, bool? key)
{
return _dicomArchiveService.GetInstanceIdList(seriesId, tpCode, key);
}
/// <summary> 指定资源Id渲染Dicom实例的Jpeg预览图像 </summary>
/// <param name="instanceId"> Dicom实例的Id </param>
[HttpGet, Route("preview/{instanceId:guid}")]
[AllowAnonymous]
public FileContentResult GetInstancePreview(Guid instanceId)
{
string path = _dicomArchiveService.GetInstancePreview(instanceId);
using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, "image/jpeg");
}
}
/// <summary> 指定资源Id获取Dicom实例文件的内容 </summary>
/// <param name="instanceId"> Dicom实例的Id </param>
[HttpGet, Route("content/{instanceId:guid}")]
[AllowAnonymous]
public FileContentResult GetInstanceContent(Guid instanceId)
{
var filePath = _dicomArchiveService.GetInstanceContent(instanceId);
using (var sw = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, "application/octet-stream");
}
}
}
}

View File

@ -0,0 +1,72 @@
using IRaCIS.Core.Application.Contracts.Dicom;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Application.Dicom;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Series
/// </summary>
[Route("series")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
public class SeriesController : ControllerBase
{
private readonly IDicomArchiveService _dicomArchiveService;
public SeriesController(IDicomArchiveService dicomArchiveService)
{
_dicomArchiveService = dicomArchiveService;
}
///// <summary> 指定资源Id获取Dicom检查所属序列信息列表 </summary>
///// <param name="studyId"> Dicom检查的Id </param>
//[HttpGet, Route("list/{studyId:guid}")]
//[AllowAnonymous]
//public IEnumerable<DicomSeriesDTO> GetSeriesList(Guid studyId)
//{
// return _dicomArchiveService.GetSeriesList(studyId);
//}
/// <summary> 指定资源Id获取Dicom检查所属序列信息列表 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
/// <param name="tpCode"></param>
[HttpGet, Route("serieslist/{studyId:guid}")]
[AllowAnonymous]
public IResponseOutput<IEnumerable<DicomSeriesWithLabelDTO>> GetSeriesList(Guid studyId,string tpCode)
{
return ResponseOutput.Ok( _dicomArchiveService.GetSeriesWithLabelList(studyId, tpCode));
}
[HttpGet, Route("list/{studyId:guid}/{tpCode?}")]
[AllowAnonymous]
public IEnumerable<DicomSeriesWithLabelDTO> GetSeriesWithLabelList(Guid studyId, string tpCode)
{
return _dicomArchiveService.GetSeriesWithLabelList(studyId, tpCode);
}
/// <summary> 指定资源Id渲染Dicom序列的Jpeg预览图像 </summary>
/// <param name="seriesId"> Dicom序列的Id </param>
[HttpGet, Route("preview/{seriesId:guid}")]
[AllowAnonymous]
public FileContentResult GetSeriesPreview(Guid seriesId)
{
string path = _dicomArchiveService.GetSeriesPreview(seriesId);
using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, "image/jpeg");
}
}
}
}

View File

@ -0,0 +1,536 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.WebUtilities;
using System.Threading.Tasks;
using IRaCIS.Core.Application.Contracts.Dicom;
using System.IO;
using System.IO.Compression;
using IRaCIS.Core.API.Filter;
using Microsoft.AspNetCore.Http.Features;
using IRaCIS.Core.Application.Dicom;
using IRaCIS.Core.Domain.Share;
using System.Linq;
using System.Threading;
using Microsoft.AspNetCore.Http;
using IRaCIS.Api.Filter;
using NLog;
using Microsoft.Extensions.Logging;
using System.Text;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Study
/// </summary>
[Route("study")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
public class StudyController : ControllerBase
{
private readonly IStudyService _studyService;
private readonly IDicomArchiveService _dicomArchiveService;
private readonly IDoctorService _doctorService;
private static readonly FormOptions _defaultFormOptions = new FormOptions();
private readonly ILogger<StudyController> _logger;
public StudyController(IStudyService studyService,
IDicomArchiveService dicomArchiveService, IDoctorService doctorService,
ILogger<StudyController> logger
)
{
_studyService = studyService;
_dicomArchiveService = dicomArchiveService;
_doctorService = doctorService;
_logger = logger;
}
///// <summary> 根据项目Id受试者Id获取受试者检查统计(不分页)</summary>
//[HttpGet, Route("getStudyStatList/{trialId:guid}/{subjectId:guid}/{siteId:guid}")]
//public IResponseOutput<IEnumerable<StudyStatDTO>> GetStudy(Guid trialId, Guid subjectId, Guid siteId)
//{
// return ResponseOutput.Ok(_studyService.GetStudyStatList(trialId, subjectId, siteId));
//}
[HttpPost, Route("getStudyList")]
public IResponseOutput<PageOutput<StudyDTO>> GetStudyList(StudyQueryDTO queryDto)
{
return ResponseOutput.Ok(_studyService.GetStudyList(queryDto));
}
[HttpPost, Route("getDistributeStudyList")]
public IResponseOutput<PageOutput<DistributeReviewerStudyStatusDTO>> GetDistributeStudyList(
StudyStatusQueryDTO studyStatusQueryDto)
{
return ResponseOutput.Ok(_studyService.GetDistributeStudyList(studyStatusQueryDto));
}
[HttpPost, Route("updateStudyBinding")]
//[LogFilter]
public IResponseOutput UpdateStudyBinding(StudyEditCommand studyEditCommand)
{
if (studyEditCommand.SubjectVisitId == Guid.Empty)
{
studyEditCommand.SubjectVisitId = _studyService.AddSubjectVisit(studyEditCommand.SubjectId, studyEditCommand.SiteId,
studyEditCommand.VisitStageId, studyEditCommand.SVSTDTC, studyEditCommand.SVENDTC);
}
else
{
_studyService.UpdateSubjectVisit(studyEditCommand.SubjectVisitId, studyEditCommand.SVSTDTC,
studyEditCommand.SVENDTC);
}
return ResponseOutput.Ok( _studyService.UpdateStudyBinding(studyEditCommand).Result);
}
/// <summary>
/// 获取受试者 这次访视 对应的study modality 列表
/// </summary>
/// <param name="trialId"></param>
/// <param name="siteId"></param>
/// <param name="subjectId"></param>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
[HttpPost, Route("getSubjectVisitStudyList/{trialId:guid}/{siteId:guid}/{subjectId:guid}/{subjectVisitId:guid}")]
[AllowAnonymous]
public IResponseOutput<List<SubjectVisitStudyDTO>> GetSubjectVisitStudyList(Guid trialId, Guid siteId, Guid subjectId,
Guid subjectVisitId)
{
return ResponseOutput.Ok(
_studyService.GetSubjectVisitStudyList(trialId, siteId, subjectId, subjectVisitId));
}
/// <summary>
/// 提示 该项目是否允许上传该study如果不允许 提示 已经上传到哪个受试者 哪次方式 studyCode是多少
/// </summary>
/// <param name="studyInstanceUid"></param>
/// <param name="trialId"></param>
/// <param name="abandonStudyId"></param>
/// <returns></returns>
[HttpGet, Route("verifyStudyAllowUpload/{trialId:guid}/{studyInstanceUid}/{abandonStudyId?}")]
[AllowAnonymous]
public IResponseOutput<VerifyStudyUploadResult> VerifyStudyAllowUpload(string studyInstanceUid, Guid trialId, Guid? abandonStudyId)
{
return ResponseOutput.Ok(_studyService.VerifyStudyAllowUpload(studyInstanceUid, trialId, abandonStudyId));
}
/// <summary> 归档</summary>
//[HttpPost, Route("archiveStudy/{trialId:guid}/{siteId:guid}/{subjectId:guid}/{visitStageId:guid}/{subjectVisitId:guid}/{SVSTDTC?}/{SVENDTC?}/{comment}")]
[HttpPost, Route("archiveStudy")]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[LogFilter]
//public async Task<IResponseOutput> ArchiveStudy(Guid trialId, Guid siteId, Guid subjectId, Guid visitStageId, Guid subjectVisitId, DateTime? SVSTDTC, DateTime? SVENDTC, string comment)
public async Task<IResponseOutput> ArchiveStudy([FromForm] ArchiveStudyCommand archiveStudyCommand)
{
//处理 受试者访视没有记录 系统自动添加
#region url方式
//if (subjectVisitId == Guid.Empty)
//{
// subjectVisitId = _studyService.AddSubjectVisit(subjectId, visitStageId);
//}
//string userName = User.FindFirst("realName").Value;
//StudyCommand addtionalInfo = new StudyCommand
//{
// SiteId = siteId,
// SubjectId = subjectId,
// TrialId = trialId,
// SubjectVisitId = subjectVisitId,
//};
//var savedInfo = _studyService.GetSaveToDicomInfo(addtionalInfo);
////加入comment
//savedInfo.Comment = comment;
#endregion
try
{
#region post body 方式 subjectVisitId
////var subjectVisitStudyOldList = new List<SubjectVisitStudyDTO>();
// 受试者方式计划一次性添加,因为没有了上传时添加逻辑
//if (archiveStudyCommand.SubjectVisitId == Guid.Empty)
//{
// archiveStudyCommand.SubjectVisitId = _studyService.AddSubjectVisit(archiveStudyCommand.SubjectId, archiveStudyCommand.SiteId,
// archiveStudyCommand.VisitStageId.Value, archiveStudyCommand.SVSTDTC, archiveStudyCommand.SVENDTC);
//}
//else
//{
//_studyService.UpdateSubjectVisit(archiveStudyCommand.SubjectVisitId, archiveStudyCommand.SVSTDTC,
// archiveStudyCommand.SVENDTC);
//#region 重传和上传放在一起 暂不用
////处理 重传 在归档前 事先查出 这次访视已经有的study列表
////subjectVisitStudyOldList = _studyService.GetSubjectVisitStudyList(archiveStudyCommand.TrialId,
//// archiveStudyCommand.SiteId, archiveStudyCommand.SubjectId, archiveStudyCommand.SubjectVisitId);
//#endregion
//}
var userName = User.FindFirst("realName").Value;
StudyCommand addtionalInfo = new StudyCommand
{
SiteId = archiveStudyCommand.SiteId,
SubjectId = archiveStudyCommand.SubjectId,
TrialId = archiveStudyCommand.TrialId,
SubjectVisitId = archiveStudyCommand.SubjectVisitId,
};
var savedInfo = _studyService.GetSaveToDicomInfo(addtionalInfo);
#endregion
var archiveResult = new DicomArchiveResult();
var archivedStudyIds = new List<Guid>();
var boundary = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(Request.ContentType).Boundary).Value;
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
string fileName = contentDisposition.FileName.Value;
try
{
//采用post方式 这里多加一个判断 过滤其他参数
if (string.IsNullOrEmpty(section.ContentType))
{
break;
}
string mediaType = section.ContentType;
if (mediaType.Contains("zip"))
{
var partStream = section.Body;
using (var zipArchive = new ZipArchive(partStream, ZipArchiveMode.Read))
{
foreach (var entry in zipArchive.Entries)
{
if (entry.FullName.EndsWith("/")) continue;
try
{
++archiveResult.ReceivedFileCount;
using (var memoryStream = new MemoryStream())
{
await section.Body.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
DicomInstanceDTO instance = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo);
if (!archivedStudyIds.Contains(instance.StudyId))
archivedStudyIds.Add(instance.StudyId);
}
}
catch
{
archiveResult.ErrorFiles.Add($"{fileName}/{entry.FullName}");
}
}
}
}
++archiveResult.ReceivedFileCount;
if (mediaType.Contains("octet-stream"))
{
using (var memoryStream = new MemoryStream())
{
await section.Body.CopyToAsync(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
DicomInstanceDTO instance = await _dicomArchiveService.ArchiveDicomStreamAsync(memoryStream, savedInfo);
if (!archivedStudyIds.Contains(instance.StudyId))
archivedStudyIds.Add(instance.StudyId);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
archiveResult.ErrorFiles.Add(fileName);
}
}
section = await reader.ReadNextSectionAsync();
}
if (archivedStudyIds.Count > 0)
{
//更新受试者访视信息 及上传状态
_studyService.UpdateSubjectVisit(archiveStudyCommand.SubjectVisitId, archiveStudyCommand.SVSTDTC,
archiveStudyCommand.SVENDTC);
//更新受试者最新的访视状态,访视号最大的
_studyService.UpdateSubjectLatestInfo(archiveStudyCommand.SubjectId, archiveStudyCommand.TrialId);
archiveResult.ArchivedDicomStudies = _dicomArchiveService.GetArchivedStudyList(archivedStudyIds);
//归档完成,插入记录表
foreach (var archivedDicomStudy in archiveResult.ArchivedDicomStudies)
{
var seriesModalityList = _dicomArchiveService.GetSeriesList(archivedDicomStudy.Id).Select(u => u.Modality).Distinct();
StringBuilder sb = new StringBuilder();
foreach (var item in seriesModalityList)
{
sb.Append(item).Append(",");
}
string ModaliyStr = sb.ToString();
if (ModaliyStr.Length > 0)
{
ModaliyStr = ModaliyStr.Substring(0, ModaliyStr.Length - 1);
}
string comment = string.Empty;// 上传或重传完成之后更新Comment信息
if (!string.IsNullOrWhiteSpace(archiveStudyCommand.Comment))
{
comment = archiveStudyCommand.Comment;
}
_studyService.UpdateStudyModaliyAndComment(archivedDicomStudy.Id, ModaliyStr,comment);
//重传 并且不是同一份文件
if (archiveStudyCommand.AbandonStudyId != null &&
archiveStudyCommand.AbandonStudyId != Guid.Empty && archiveStudyCommand.AbandonStudyId != archivedDicomStudy.Id)
{
//更新状态为废弃
_studyService.UpdateStudyStatus(new StudyStatusDetailCommand
{
StudyId = archiveStudyCommand.AbandonStudyId.Value,
Status = (int)StudyStatus.Abandon,
Note = string.Empty
}, userName);
//此时归档的新的Study 初始状态设置为 已重传完成
_studyService.UpdateStudyStatus(new StudyStatusDetailCommand
{
StudyId = archivedDicomStudy.Id,
Status = (int)StudyStatus.QAReuploaded,
Note = string.Empty
}, userName);
//更新新得study code 为废弃的
_studyService.UpdateReUploadNewStudyCode(archiveStudyCommand.AbandonStudyId.Value, archivedDicomStudy.Id);
}//重传 是同一份文件
else if (archiveStudyCommand.AbandonStudyId != null &&
archiveStudyCommand.AbandonStudyId != Guid.Empty && archiveStudyCommand.AbandonStudyId == archivedDicomStudy.Id)
{
//此时归档的新的Study 初始状态设置为 已重传完成
_studyService.UpdateStudyStatus(new StudyStatusDetailCommand
{
StudyId = archivedDicomStudy.Id,
Status = (int)StudyStatus.QAReuploaded,
Note = string.Empty
}, userName);
}//上传
else
{
_studyService.UpdateStudyStatus(new StudyStatusDetailCommand
{
StudyId = archivedDicomStudy.Id,
Status = (int)StudyStatus.Uploaded,
Note = string.Empty
}, userName);
}
}
}
return ResponseOutput.Ok(archiveResult);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
throw;
}
}
/// <summary> 删除检查</summary>
[HttpDelete, Route("deleteStudy/{id:guid}")]
[LogFilter]
public IResponseOutput DeleteStudy(Guid id)
{
return _studyService.DeleteStudy(id);
}
/// <summary> 指定资源Id渲染Dicom检查的Jpeg预览图像 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
[HttpGet, Route("preview/{studyId:guid}")]
[AllowAnonymous]
public FileContentResult GetStudyPreview(Guid studyId)
{
string path = _dicomArchiveService.GetStudyPreview(studyId);
using (var sw = DicomRenderingHelper.RenderPreviewJpeg(path))
{
var bytes = new byte[sw.Length];
sw.Read(bytes, 0, bytes.Length);
sw.Close();
return new FileContentResult(bytes, "image/jpeg");
}
}
/// <summary> 指定资源Id获取Dicom检查信息 </summary>
/// <param name="studyId"> Dicom检查的Id </param>
[HttpGet, Route("item/{studyId:guid}")]
public IResponseOutput<DicomStudyDTO> GetStudyItem(Guid studyId)
{
return ResponseOutput.Ok(_dicomArchiveService.GetStudyItem(studyId));
}
/// <summary> 更新Study状态并保存状态变更信息 </summary>
/// <param name="studyStatusDetailCommand"></param>
[HttpPost, Route("updateStudyStatus")]
[LogFilter]
public IResponseOutput UpdateStudyStatus(StudyStatusDetailCommand studyStatusDetailCommand)
{
string userName = User.FindFirst("realName").Value; ;
return ResponseOutput.Result(_studyService.UpdateStudyStatus(studyStatusDetailCommand, userName));
}
/// <summary>
/// Dicom匿名化
/// </summary>
/// <param name="studyId">需要匿名化的检查Id</param>
/// <returns></returns>
[HttpPost, Route("dicomAnonymize/{studyId:guid}")]
[LogFilter]
public async Task<IResponseOutput> DicomAnonymize(Guid studyId)
{
string userName = User.FindFirst("realName").Value; ;
return ResponseOutput.Result(await _studyService.DicomAnonymize(studyId, userName));
}
/// <summary> Study分配 </summary>
[HttpPost, Route("studyDistribution")]
[Obsolete]
public IResponseOutput StudyDistribution(StudyReviewerCommand studyReviewerCommand)
{
string userName = User.FindFirst("realName").Value;
var doctorInfo = _doctorService.GetDoctorBasicInfo(studyReviewerCommand.ReviewerId);
List<StudyStatusDetailCommand> studyStatusCommandList = new List<StudyStatusDetailCommand>();
foreach (var study in studyReviewerCommand.StudyList)
{
var studyStatus = new StudyStatusDetailCommand
{
StudyId = study.StudyId,
Status = (int)StudyStatus.Distributed,
Note = doctorInfo.LastName + " " + doctorInfo.FirstName
};
studyStatusCommandList.Add(studyStatus);
}
var result = _studyService.DistributeStudy(studyReviewerCommand);
_studyService.UpdateStudyStatus(studyStatusCommandList, userName);
return ResponseOutput.Result(result);
}
[Obsolete]
[HttpPost, Route("editStudyReviewer")]
public IResponseOutput EditStudyReviewer(StudyReviewerEditCommand studyReviewerEditCommand)
{
return _studyService.EditStudyReviewer(studyReviewerEditCommand);
}
/// <summary>
/// 根据项目Id 获取可选医生列表
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet, Route("GetReviewerList/{trialId:guid}")]
public IResponseOutput<List<ReviewerDistributionDTO>> GetReviewerListByTrialId(Guid trialId)
{
var result = _studyService.GetReviewerListByTrialId(trialId);
return ResponseOutput.Ok(result);
}
/// <summary>
/// 根据StudyId获取该Study的操作记录时间倒序
/// </summary>
/// <param name="studyId"></param>
/// <returns></returns>
[HttpGet, Route("getStudyStatusDetailList/{studyId:guid}")]
public IResponseOutput<List<StudyStatusDetailDTO>> GetStudyStatusDetailList(Guid studyId)
{
var result = _studyService.GetStudyStatusDetailList(studyId);
return ResponseOutput.Ok(result);
}
/// <summary>
/// 根据TPCode 获取所有的标记
/// </summary>
/// <param name="tpCode"></param>
/// <returns></returns>
[HttpGet, Route("getImageLabelList/{tpCode}")]
[AllowAnonymous]
public IResponseOutput<IEnumerable<ImageLabelDTO>> GetImageLabelList(string tpCode)
{
return ResponseOutput.Ok(_dicomArchiveService.GetImageLabel(tpCode));
}
/// <summary>
/// 保存标记(跟删除合并,每次保存最新的标记),会删除替换之前的标记
/// 外层的TPcode 必须传里面的标记数组可为空数组表示删除该Study的所有标记
/// </summary>
/// <param name="imageLabelCommand"></param>
/// <returns></returns>
[HttpPost, Route("saveImageLabelList")]
[AllowAnonymous]
[LogFilter]
public IResponseOutput SaveImageLabelList(ImageLabelCommand imageLabelCommand)
{
return ResponseOutput.Result(_dicomArchiveService.SaveImageLabelList(imageLabelCommand));
}
/// <summary>
/// 获取某个访视的关联访视
/// 用于获取关联影像(调用之前的接口:/series/list/根据StudyId获取访视的序列列表
/// </summary>
/// <param name="visitNum"></param>
/// <param name="tpCode"></param>
/// <returns></returns>
[HttpGet, Route("getRelationVisitList/{visitNum}/{tpCode}")]
[AllowAnonymous]
public IResponseOutput<IEnumerable<RelationVisitDTO>> GetRelationVisitList(decimal visitNum, string tpCode)
{
return ResponseOutput.Ok(_studyService.GetRelationVisitList(visitNum, tpCode));
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("cro")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Institution")]
public class CROController : ControllerBase
{
private readonly ICroService _croService;
public CROController(ICroService croCompanyService)
{
_croService = croCompanyService;
}
/// <summary> 分页获取CRO列表 </summary>
[HttpPost, Route("getCROPageList")]
public IResponseOutput<PageOutput<CROCompanyDTO>> GetCROCompanyList(CROCompanyQueryDTO croCompanySearchModel)
{
return ResponseOutput.Ok(_croService.GetCroList(croCompanySearchModel));
}
/// <summary> 获取所有CRO列表可根据名称搜索[AUTH] </summary>
[HttpPost, Route("getAllCROList")]
public IResponseOutput<IEnumerable<CroSelectDTO>> GetCROCompanySearchList()
{
return ResponseOutput.Ok(_croService.GetCroSearchList());
}
/// <summary> 添加CRO[AUTH] </summary>
[HttpPost, Route("addOrUpdateCro")]
public IResponseOutput AddCROCompany(CROCompanyDTO addCroCompanyViewModel)
{
var userId = User.FindFirst("id").Value;
return _croService.AddOrUpdateCro(addCroCompanyViewModel, Guid.Parse(userId));
}
/// <summary> 删除CRO </summary>
[HttpDelete, Route("deleteCROCompany/{croCompanyId:guid}")]
public IResponseOutput DeleteCROCompany(Guid croCompanyId)
{
return _croService.DeleteCro(croCompanyId);
}
}
}

View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("hospital")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Institution")]
public class HospitalController : ControllerBase
{
private readonly IHospitalService _hospitalService;
public HospitalController(IHospitalService hospitalService)
{
_hospitalService = hospitalService;
}
/// <summary> 获取所有医院列表 </summary>
[HttpGet, Route("hospitalList")]
public IResponseOutput<IEnumerable<HospitalDTO>> GetHospitalList()
{
var result = _hospitalService.GetHospitalList();
return ResponseOutput.Ok(result);
}
/// <summary> 分页获取医院信息列表 </summary>
[HttpPost, Route("getHospitalPageList")]
public IResponseOutput<PageOutput<HospitalDTO>> GetHospitalPageList(
HospitalQueryDTO hospitalSearchModel)
{
return ResponseOutput.Ok(_hospitalService.GetHospitalPageList(hospitalSearchModel));
}
/// <summary> 添加医院信息 </summary>
[HttpPost, Route("addOrUpdateHospital")]
public IResponseOutput AddOrUpdateHospital(HospitalCommand addViewModel)
{
return _hospitalService.AddOrUpdateHospital(addViewModel);
}
/// <summary> 删除医院信息 </summary>
[HttpDelete, Route("deleteHospital/{hospitalId:guid}")]
public IResponseOutput DeleteHospital(Guid hospitalId)
{
return _hospitalService.DeleteHospital(hospitalId);
}
}
}

View File

@ -0,0 +1,32 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 机构列表
/// </summary>
[Route("institution")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Institution")]
public class InstitutionController : ControllerBase
{
private readonly IInstitutionService _institutionService;
public InstitutionController(IInstitutionService institutionService)
{
_institutionService = institutionService;
}
/// <summary> 根据用户类型或机构类型,获取供选择的机构列表[New] </summary>
[HttpGet, Route("getInstitutionList/{typeId:guid}")]
public IResponseOutput<IEnumerable<InstitutionDTO>> GetInstitutionSelectionList(Guid typeId)
{
return ResponseOutput.Ok(_institutionService.GetInstitutionSelectionByTypeId(typeId)) ;
}
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("site")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Institution")]
public class SiteController : ControllerBase
{
private readonly ISiteService _siteService;
public SiteController(ISiteService siteService)
{
_siteService = siteService;
}
/// <summary> 分页获取研究中心列表 </summary>
[HttpPost, Route("getSiteList")]
public IResponseOutput<PageOutput<SiteSelectDTO>> GetSiteList(SiteQueryParam searchModel)
{
return ResponseOutput.Ok(_siteService.GetSiteList(searchModel)) ;
}
/// <summary> 获取研究中心列表[New] </summary>
[HttpGet, Route("getAllSiteList")]
public IResponseOutput<IEnumerable<SiteSelectionDTO>> GetAllSiteList()
{
return ResponseOutput.Ok(_siteService.GetSiteList()) ;
}
/// <summary> 添加研究中心[AUTH] </summary>
[HttpPost, Route("addOrUpdateSite")]
public IResponseOutput AddOrUpdateSite(SiteCommand addModel)
{
var userId = User.FindFirst("id").Value;
return _siteService.AddOrUpdateSite(addModel, Guid.Parse(userId)) ;
}
/// <summary> 删除研究中心[Auth] </summary>
[HttpDelete, Route("deleteSite/{siteId:guid}")]
public IResponseOutput DeleteResearchCenter(Guid siteId)
{
return _siteService.DeleteSite(siteId);
}
}
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("sponsor")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Institution")]
public class SponsorController : ControllerBase
{
private readonly ISponsorService _sponsorService;
public SponsorController(ISponsorService sponsorService)
{
_sponsorService = sponsorService;
}
/// <summary> 分页获取申办方列表 </summary>
[HttpPost, Route("getSponsorPageList")]
public IResponseOutput<PageOutput<SponsorDTO>> GetSponsorList(SponsorQueryDTO sponsorSearchModel)
{
return ResponseOutput.Ok(_sponsorService.GetSponsorList(sponsorSearchModel));
}
/// <summary> 获取所有申办方列表 下拉框 </summary>
[HttpPost, Route("getAllSponsorList")]
public IResponseOutput<IEnumerable<SponsorSelectDTO>> GetSponsorSearchList()
{
return ResponseOutput.Ok(_sponsorService.GetSponsorSearchList());
}
/// <summary> 添加或更新申办方信息 </summary>
[HttpPost, Route("addOrUpdateSponsor")]
public IResponseOutput AddSponsor(SponsorCommand addSponsorViewModel)
{
return _sponsorService.AddOrUpdateSponsor(addSponsorViewModel);
}
/// <summary> 删除申办方信息 </summary>
[HttpDelete, Route("deleteSponsor/{sponsorId:guid}")]
public IResponseOutput DeleteSponsor(Guid sponsorId)
{
return _sponsorService.DeleteSponsor(sponsorId);
}
}
}

View File

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("menu")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Management")]
public class MenuController : ControllerBase
{
private readonly IMenuService _menuService;
public MenuController(IMenuService menuService)
{
_menuService = menuService;
}
/// <summary> 获取完整菜单功能树形列表 </summary>
[HttpGet, Route("getMenuFunction")]
public IResponseOutput<List<MenuTreeNode>> GetMenuTreeAll()
{
return ResponseOutput.Ok(_menuService.GetTreeAll());
}
/// <summary> 在某个父节点下面 新增子菜单</summary>
[HttpPost, Route("addOrUpdateMenu")]
public IResponseOutput AddOrUpdateMenu(MenuFunctionCommand menuViewModel)
{
if (menuViewModel.ParentId == Guid.Empty)
{
return ResponseOutput.NotOk("ParentId 不能为空");
}
var userId = Guid.Parse(User.FindFirst("id").Value);
return _menuService.AddOrUpdateMenu(menuViewModel, userId);
}
/// <summary>根据Id删除节点</summary>
[HttpDelete, Route("deleteMenuFunction/{menuFunctionId:guid}")]
public IResponseOutput DeleteMenuFunction(Guid menuFunctionId)
{
return _menuService.DeleteMenuFunction(menuFunctionId);
}
/// <summary>
/// 获取某角色 菜单树 勾选情况 和 功能勾选情况
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
[HttpGet, Route("getRoleMenuFunction/{roleId:guid}")]
public IResponseOutput<List<MenuTreeNodeSelect>> GetTreeWithSelect(Guid roleId)
{
var treelist = _menuService.GetMenuFunctionIsSelectByRoleId(roleId);
return ResponseOutput.Ok(treelist);
}
/// <summary>
/// 获取路由节点下的功能选中情况
/// </summary>
/// <param name="roleId"></param>
/// <param name="parentId"></param>
/// <returns></returns>
[HttpGet, Route("getRoleFunction/{roleId:guid}/{parentId:guid}")]
public IResponseOutput<List<MenuTreeNodeSelect>> GetRoleFunctionTreeWithSelect(Guid roleId, Guid parentId)
{
var treelist = _menuService.GetFunctionIsSelectByRoleId(roleId, parentId);
return ResponseOutput.Ok(treelist);
}
/// <summary>
/// 更新角色拥有的菜单 只传递操作的项
/// </summary>
/// <param name="selectModel"></param>
/// <returns></returns>
[HttpPost, Route("updateRoleMenu")]
public IResponseOutput UpdateRoleMenuSelect(RoleMenuFunctionSelectDTO selectModel)
{
return _menuService.UpdateRoleMenuSelect(selectModel.RoleId, selectModel.MenuFunctionId);
}
/// <summary>
///
/// </summary>
[HttpPost, Route("updateRoleFunction")]
public IResponseOutput UpdateRoleFunctionSelect(FunctionSelectDTO selectModel)
{
return _menuService.UpdateRoleFunctionSelect(selectModel);
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Route("role")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Management")]
public class RoleController : ControllerBase
{
private readonly IRoleService _roleService;
public RoleController(IRoleService roleService)
{
_roleService = roleService;
}
/// <summary> 添加角色 </summary>
[HttpPost, Route("addOrUpdateRole")]
[LogFilter]
public IResponseOutput AddOrUpdateRole(RoleCommand role)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _roleService.AddOrUpdateRole(role, userId);
}
///// <summary> 复制角色 </summary>
//[HttpPost, Route("copyRole/{sourceRoleId:guid}")]
//public IResponseOutput<Guid> CopyRole(Guid sourceRoleId, RoleAddOrUpdateModel role)
//{
// return _roleService.CopyRole(sourceRoleId,role);
//}
/// <summary> 删除角色 </summary>
[HttpDelete, Route("deleteRole/{roleId:guid}")]
[LogFilter]
public IResponseOutput DeleteRole(Guid roleId)
{
return _roleService.DeleteRole(roleId);
}
/// <summary> 分页获取角色列表 </summary>
[HttpGet, Route("getRoleList/{pageIndex:int}/{pageSize:int}")]
public IResponseOutput<PageOutput<RoleDTO>> GetRoleListByPage(int pageIndex, int pageSize)
{
return ResponseOutput.Ok(_roleService.GetRoleListByPage(pageIndex, pageSize));
}
/// <summary> 获取用户角色列表 </summary>
[HttpGet, Route("getRoleList/{userId:guid}/{pageIndex:int}/{pageSize:int}")]
public IResponseOutput<PageOutput<UserSelectRoleDTO>> GetRoleListByPage(Guid userId, int pageIndex, int pageSize)
{
return ResponseOutput.Ok(_roleService.GetRoleListByPage(userId, pageIndex, pageSize));
}
/// <summary> 更新用户角色 </summary>
[HttpPost, Route("UpdateUserRole")]
[LogFilter]
public IResponseOutput UpdateUserRole(UserRoleSelectDTO userSelectRoleModel)
{
return _roleService.UpdateUserRole(userSelectRoleModel.userId, userSelectRoleModel.roleId, userSelectRoleModel.isSelect);
}
}
}

View File

@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyCaching.Core;
using IRaCIS.Api.Filter;
using IRaCIS.Application;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.API.Auth;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
[Authorize]
[Route("sysUser")]
[ApiController, ApiExplorerSettings(GroupName = "Management")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
private readonly ITokenService _tokenService;
public UserController(IUserService userService, ITokenService tokenService)
{
_userService = userService;
_tokenService = tokenService;
}
/// <summary>
/// 通过邮箱或者手机 发送验证码
/// </summary>
/// <param name="emailOrPhone"></param>
/// <param name="verificationType"></param>
/// <param name="isReviewer"></param>
/// <returns></returns>
[HttpGet, Route("sendVerificationCode/{emailOrPhone}/{verificationType:int}/{isReviewer:bool}")]
[AllowAnonymous]
public async Task<IResponseOutput> SendVerificationCode(string emailOrPhone, int verificationType, bool isReviewer)
{
return await _userService.SendVerificationCode(emailOrPhone, verificationType, isReviewer);
}
/// <summary>
/// 通过验证码设置新密码
/// </summary>
/// <param name="resetPwdModel"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost, Route("setNewPassword")]
public IResponseOutput SetNewPassword(ResetPasswordCommand resetPwdModel)
{
return _userService.SetNewPassword(resetPwdModel.EmailOrPhone, resetPwdModel.VerificationType, resetPwdModel.VerificationCode, resetPwdModel.NewPwd, resetPwdModel.IsReviewer);
}
/// <summary> 系统用户登录接口[New] </summary>
[HttpPost, Route("login")]
[AllowAnonymous]
[LogFilter]
public IResponseOutput<LoginReturnDTO> Login(UserLoginDTO loginUser, [FromServices]IEasyCachingProvider provider)
{
var returnModel = _userService.Login(loginUser.UserName, loginUser.Password);
if (returnModel.IsSuccess)
{
returnModel.Data.JWTStr = _tokenService.GetToken(UserClaims.Create(returnModel.Data.BasicInfo));
}
var userId = returnModel.Data.BasicInfo.Id.ToString();
provider.Set(userId, userId, TimeSpan.FromMinutes(SystemConfig.LoginExpiredTimeSpan));
return returnModel;
}
/// <summary> 签名认证[New] </summary>
[HttpGet, Route("VerifySignature/{userName}/{password}")]
[AllowAnonymous]
[LogFilter]
public IResponseOutput VerifySignature(string userName, string password)
{
var returnModel = _userService.VerifySignature(userName, password);
return returnModel;
//return ResponseOutput.Result(returnModel.IsSuccess);
}
/// <summary> 分页获取用户列表[New]</summary>
[HttpPost, Route("getUserList")]
[Authorize]
public IResponseOutput<PageOutput<UserListDTO>> GetUserList(UserListQueryDTO param)
{
return ResponseOutput.Ok(_userService.GetUserList(param));
}
/// <summary> 更新用户状态1 可用 0 禁用)[New]</summary>
[Authorize]
[LogFilter]
[HttpPost, Route("updateUserState/{userId:guid}/{state:int}")]
public IResponseOutput UpdateUserState(Guid userId, int state)
{
return _userService.UpdateUserState(userId, state);
}
/// <summary> 修改密码,当前支持旧密码修改密码,手机及邮箱验证码后续支持[New] </summary>
[HttpPost, Route("modifyPassword")]
[Authorize]
[LogFilter]
public IResponseOutput ModifyPassword(EditPasswordCommand editPwModel)
{
return _userService.ModifyPassword(editPwModel);
}
/// <summary> 根据用户Id获取用户角色列表和当前登录用户的最大权限级别[New][AUTH] </summary>
[HttpGet, Route("getUserRoles/{userId:guid}")]
[Authorize]
public IResponseOutput<UserRoleInfoDTO> GetUserRolesById(Guid userId)
{
var optUserId = User.FindFirst("id").Value;
return ResponseOutput.Ok(new UserRoleInfoDTO()
{
RoleList = _userService.GetUserRolesById(userId),
MaxPrivilegeLevel = _userService.GetUserRoleMaxPrivilegeLevel(Guid.Parse(optUserId))
});
}
/// <summary>添加用户[New][AUTH] </summary>
[HttpPost, Route("addUser")]
public IResponseOutput<UserAddedReturnDTO> AddUser(UserCommand userAddModel)
{
var userId = User.FindFirst("id").Value;
return _userService.AddUser(userAddModel, Guid.Parse(userId));
}
/// <summary> 更新用户信息[New][AUTH]</summary>
[HttpPost, Route("updateUser")]
[LogFilter]
public IResponseOutput UpdateUser(UserCommand userUpdateModel)
{
var userId = User.FindFirst("id").Value;
return _userService.UpdateUser(userUpdateModel, Guid.Parse(userId));
}
/// <summary> 根据用户Id获取用户详细信息[New] </summary>
[HttpGet, Route("getUser/{userId:guid}")]
public IResponseOutput<UserDetailDTO> GetUserById(Guid userId)
{
return ResponseOutput.Ok(_userService.GetUserById(userId));
}
/// <summary>获取所有用户列表 </summary>
[HttpGet, Route("getAllUser")]
public IResponseOutput<IEnumerable<UserDetailDTO>> GetAllUser()
{
return ResponseOutput.Ok(_userService.GetAllUser());
}
///// <summary>获取当前用户是否有复审权限和编辑权限[New][AUTH] </summary>
//[HttpGet, Route("getUserResumePermission/{reviewerId:guid}")]
//public IResponseOutput<ResumePermission> GetUserResumePermission(Guid reviewerId)
//{
// var userId = User.FindFirst("id").Value;
// return ResponseOutput.Ok(_userService.GetUserResumePermission(reviewerId, Guid.Parse(userId))) ;
//}
/// <summary> 后台重置密码为123456[New] </summary>
[HttpGet, Route("resetPassword/{userId:guid}")]
[LogFilter]
public IResponseOutput ResetPassword(Guid userId)
{
return _userService.ResetPassword(userId);
}
}
}

View File

@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.API.Controllers.QA
{
/// <summary>
/// QA 记录 和对话管理
/// </summary>
[Route("QARecord")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
[AllowAnonymous]
public class QARecordController : ControllerBase
{
private readonly IQARecordService _qaRecordService;
public QARecordController(IQARecordService qaRecordService)
{
_qaRecordService = qaRecordService;
}
/// <summary>
///QA记录表 包含信息 包含两部分 一部分 :字典项问题项 +对应得描述 如 缺少序列 + 5个
/// 第二部分 额外补充得信息 根据 QARecord 中得Id 是否传递 判断是添加还是更新
/// </summary>
/// <param name="qaTotalCommand"></param>
/// <returns></returns>
[HttpPost, Route("AddOrUpdateQARecord")]
public IResponseOutput AddOrUpdateQARecord(QAToalCommand qaTotalCommand)
{
return _qaRecordService.AddOrUpdateQARecord(qaTotalCommand);
}
/// <summary>
/// 删除Qa记录
/// </summary>
/// <param name="qaQARecordId"></param>
/// <returns></returns>
[HttpDelete, Route("DeleteQARecord/{qaQARecordId:guid}")]
public IResponseOutput DeleteQARecord(Guid qaQARecordId)
{
return _qaRecordService.DeleteQARecord(qaQARecordId);
}
/// <summary>
/// 获取QA记录列表 一个Study 可以进行多次QA 针对每次QA 可以添加回复
/// </summary>
/// <param name="studyId"></param>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet, Route("GetQARecordList/{studyId:guid}/{trialId:guid}")]
public IResponseOutput<QADTO> GetQARecordList(Guid studyId,Guid trialId)
{
return ResponseOutput.Ok(_qaRecordService.GetQARecordList(studyId, trialId));
}
/// <summary>
/// 针对 某条Qa 添加回复
/// </summary>
/// <param name="qaDialogCommand"></param>
/// <returns></returns>
[HttpPost, Route("AddQAReply")]
public IResponseOutput AddQAReply(QADialogCommand qaDialogCommand)
{
return _qaRecordService.AddQAReply(qaDialogCommand);
}
/// <summary>
/// 删除QA回复记录
/// </summary>
/// <param name="qaReplyId"></param>
/// <returns></returns>
[HttpDelete, Route("DeleteQAReply/{qaReplyId:guid}")]
public IResponseOutput DeleteQAReply(Guid qaReplyId)
{
return _qaRecordService.DeleteQAReply(qaReplyId);
}
/// <summary>
/// 展开 某一QA下得 聊天记录
/// </summary>
/// <param name="qaRecordId"></param>
/// <returns></returns>
[HttpGet, Route("GetQaRecordDialogList/{qaRecordId:guid}")]
public IResponseOutput<List<DialogDTO>> GetQaRecordDialogList(Guid qaRecordId)
{
return ResponseOutput.Ok(_qaRecordService.GetQaRecordDialogList(qaRecordId));
}
}
}

View File

@ -0,0 +1,101 @@

using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.API.Controllers.QA
{
/// <summary>
/// Qa模板管理
/// </summary>
[Route("QATemplate")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Image")]
[AllowAnonymous]
public class QATemplateController : ControllerBase
{
private readonly IQATemplateService _qaTemplateService;
public QATemplateController(IQATemplateService qaTemplateService)
{
_qaTemplateService = qaTemplateService;
}
[HttpPost, Route("AddOrUpdateQATemplate")]
public IResponseOutput AddOrUpdateQATemplate(QATemplateCommand qaTemplateCommand)
{
return _qaTemplateService.AddOrUpdateQATemplate(qaTemplateCommand);
}
/// <summary>
/// 获取QA模板列表
/// </summary>
/// <param name="qaTemplateQuery"></param>
/// <returns></returns>
[HttpPost, Route("GetQaTemplateList")]
public IResponseOutput<PageOutput<QATemplateDTO>> GetQaTemplateList(QATemplateQueryDTO qaTemplateQuery)
{
return ResponseOutput.Ok(_qaTemplateService.GetQaTemplateList(qaTemplateQuery));
}
/// <summary>
/// 添加Qa记录时 需要选择模板 这里是模板 下拉框选择列表
/// </summary>
/// <returns></returns>
[HttpGet, Route("GetQaTemplateSelectList")]
public IResponseOutput<List<QATemplateDTO>> GetQaTemplateSelectList()
{
return ResponseOutput.Ok(_qaTemplateService.GetQaTemplateSelectList());
}
/// <summary>
/// 删除 QA模板
/// </summary>
/// <param name="qaTemplateId"></param>
/// <returns></returns>
[HttpDelete, Route("DeleteQATemplate/{qaTemplateId:guid}")]
public IResponseOutput DeleteQATemplate(Guid qaTemplateId)
{
return _qaTemplateService.DeleteQATemplate(qaTemplateId);
}
/// <summary>
/// 获取某一Qa模板已配置项
/// </summary>
/// <param name="qaTemplateId"></param>
/// <returns></returns>
[HttpGet, Route("GetQaTemplateItemsById/{qaTemplateId:guid}")]
public IResponseOutput<List<QATemplateItemDTO>> GetQaTemplateItemsById(Guid qaTemplateId)
{
return ResponseOutput.Ok(_qaTemplateService.GetQaTemplateItemsById(qaTemplateId));
}
/// <summary>
/// 获取某一QA模板 配置列表拥有得Item IsSelect 为true
/// </summary>
/// <param name="qaTemplateId"></param>
/// <returns></returns>
[HttpGet, Route("GetQaTemplateConfigList/{qaTemplateId:guid}")]
public IResponseOutput<List<QATemplateItemSelect>> GetQaTemplateConfigList(Guid qaTemplateId)
{
return ResponseOutput.Ok(_qaTemplateService.GetQaTemplateConfigList(qaTemplateId));
}
/// <summary>
/// 配置Qa模板 和字典表中基础数据 关联关系 IsSelect 为true 添加 false 删除
/// </summary>
/// <param name="qaTemplateConfigCommand"></param>
/// <returns></returns>
[HttpPost, Route("ConfigQATemplate")]
public IResponseOutput ConfigQATemplate(QATemplateConfigCommand qaTemplateConfigCommand)
{
return _qaTemplateService.ConfigQATemplate(qaTemplateConfigCommand);
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.API.Controllers.Reading
{
[Route("reading")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reading")]
public class ReadingController : ControllerBase
{
private readonly IReviewerReadingService _reviewerReadingService;
public ReadingController(IReviewerReadingService reviewerReadingService)
{
_reviewerReadingService = reviewerReadingService;
}
/// <summary>
/// 获取医生个人任务列表
/// WorkloadType 1-tp,2-global,3-ad
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost, Route("getWorkloadList")]
public IResponseOutput<PageOutput<WorkloadReadingDTO>> GetWorkloadList(WorkloadQueryParam param)
{
return ResponseOutput.Ok(_reviewerReadingService.GetWorkloadList(param));
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.API.Controllers.Report
{
[Route("globalReport")]
[ApiController, ApiExplorerSettings(GroupName = "Reading")]
public class GlobalReportController : ControllerBase
{
private readonly IGlobalService _globalService;
public GlobalReportController(IGlobalService globalService)
{
_globalService = globalService;
}
[HttpGet, Route("getHistoryVisitRsList/{trialId}/{subjectId}/{visitNum}/{globalId}/{globalCode}")]
public IResponseOutput<IEnumerable<HistoryVisitRSDTO>> GetHistoryVisitRsList(Guid trialId, Guid subjectId, decimal visitNum, Guid globalId, string globalCode)
{
return ResponseOutput.Ok(_globalService.GetHistoryVisitRsList(trialId, subjectId, visitNum,globalId, globalCode));
}
[HttpGet, Route("getHistoryGlobalRsList/{trialId}/{subjectId}/{visitNum}/{globalId}")]
public IResponseOutput<PreviousGlobalReadsView> GetHistoryGlobalRsList(Guid trialId, Guid subjectId, decimal visitNum, Guid globalId)
{
return ResponseOutput.Ok(_globalService.GetHistoryGlobalRsList(trialId, subjectId, visitNum,globalId));
}
[HttpPost, Route("AddGlobalReport")]
public IResponseOutput AddGlobalReport(GlobalTaskReportCommand globalTaskReportCommand)
{
return ResponseOutput.Result(_globalService.AddGlobalReport(globalTaskReportCommand));
}
[HttpGet, Route("getAdReport/{adId}")]
public IResponseOutput<AdReportDTO> GetAdReport(Guid adId)
{
return ResponseOutput.Ok(_globalService.GetAdReport(adId));
}
[HttpPost, Route("addAdjudicationReport")]
public IResponseOutput AddAdjudicationReport(ADReportCommand adReportCommand)
{
return ResponseOutput.Result(_globalService.AddAdjudicationReport(adReportCommand));
}
}
}

View File

@ -0,0 +1,72 @@
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace IRaCIS.Core.API.Controllers.Reading
{
[Route("report")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Reading")]
public class ReportController : ControllerBase
{
private readonly IReportService _reportService;
public ReportController(IReportService reportService)
{
_reportService = reportService;
}
/// 获取基线期病灶信息及其他信息
[AllowAnonymous]
[HttpGet, Route("getBLLineLesion/{trialCode}/{subjectCode}/{tpCode}")]
public IResponseOutput<BaseLineReportDTO> GetBLLineLesion(string trialCode, string subjectCode,string tpCode)
{
return ResponseOutput.Ok(_reportService.GetBaseLineReport(trialCode, subjectCode, tpCode));
}
/// 获取其他访视病灶信息
[AllowAnonymous]
[HttpGet, Route("getVisitLineLesion/{trialCode}/{subjectCode}/{visitNum}/{tpCode}")]
public IResponseOutput<VisitLesionInfo> GetVisitLesion(string trialCode, string SubjectCode, decimal visitNum,string tpCode)
{
return ResponseOutput.Ok(_reportService.GetVisitLesion(trialCode, SubjectCode, visitNum,tpCode));
}
/// <summary>
/// 保存 基线期病灶及测量信息及其他信息,不会改变状态
/// </summary>
[AllowAnonymous]
[HttpPost, Route("addBaseLineLesion")]
public IResponseOutput AddBaseLineLesion(BaseLineReportCommand baseLineReportCommand)
{
// User.FindFirst("reviewerCode").Value;
return ResponseOutput.Result(_reportService.SaveBLReport(baseLineReportCommand));
}
/// <summary>
/// 添加访视报告信息
/// LesionInformation 为新病灶及测量信息(包括分裂及合并产生的)
/// TRList 已经存在的病灶的测量信息
/// RSList 疗效信息
/// </summary>
[AllowAnonymous]
[HttpPost, Route("saveVisitReport")]
public IResponseOutput AddVisitLesion(VisitReportCommand visitReportCommand)
{
return ResponseOutput.Result(_reportService.SaveVisitReport(visitReportCommand));
}
/// <summary>
/// 提交报告
/// </summary>
[AllowAnonymous]
[HttpPost, Route("submiteReport/{tpId:guid}")]
public IResponseOutput SubmiteReport(Guid tpId)
{
return ResponseOutput.Result(_reportService.SubmiteReport(tpId));
}
}
}

View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// Dashboard统计、全局工作量统计、入组两个维度统计按照项目、按照人
/// </summary>
[Route("statistics")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Dashboard&Statistics")]
public class StatisticsController : ControllerBase
{
private readonly IStatisticsService _statisticsService;
public StatisticsController(IStatisticsService statisticsService)
{
_statisticsService = statisticsService;
}
/// <summary> 根据项目和医生,分页获取工作量统计[New] </summary>
[HttpPost, Route("getWorkloadByTrialAndReviewer")]
public IResponseOutput<PageOutput<WorkloadByTrialAndReviewerDTO>> GetWorkloadByTrialAndReviewer(
StatisticsWorkloadQueryParam param)
{
return ResponseOutput.Ok(
_statisticsService.GetWorkloadByTrialAndReviewer(param, Guid.Parse(User.FindFirst("id").Value)));
}
/// <summary> 项目入组 医生维度统计[New] </summary>
[HttpPost, Route("getEnrollStatByReviewer")]
public IResponseOutput<PageOutput<EnrollStatByReviewerDTO>> GetEnrollStatByReviewer(
EnrollStatByReviewerQueryDTO param)
{
return ResponseOutput.Ok(_statisticsService.GetEnrollStatByReviewer(param));
}
[HttpPost, Route("getEnrollStatByTrial")]
public IResponseOutput<PageOutput<EnrollStatByTrialDTO>> GetEnrollStatByTrial(
EnrollStatByTrialQueryDTO param)
{
return ResponseOutput.Ok(_statisticsService.GetEnrollStatByTrial(param));
}
#region Dashbord
/// <summary> 读片数分类统计[New] </summary>
[HttpGet, Route("getReadingDataByType")]
public IResponseOutput<ReadingDataDTO> GetReadingDataByType()
{
return ResponseOutput.Ok(_statisticsService.GetReadingDataByType());
}
/// <summary> 获取最近几个月份的数据[New] </summary>
[HttpGet, Route("getReadingDataByMonth/{monthCount:int}")]
public IResponseOutput<List<ReadingDataMonthDTO>> GetReadingDataByMonth(int monthCount)
{
return ResponseOutput.Ok(_statisticsService.GetReadingDataByMonth(monthCount));
}
/// <summary> 读片数量排行前几的数据[New] </summary>
[HttpGet, Route("GetReadingDataRank/{topCount:int}")]
public IResponseOutput<List<ReadingDataRankDTO>> GetReadingDataRank(int topCount)
{
return ResponseOutput.Ok(_statisticsService.GetReadingDataRank(topCount));
}
/// <summary> 按Rank统计Reviewer 数量[New] </summary>
[HttpGet, Route("getReviewersByRank")]
public IResponseOutput<List<RankReviewersDTO>> GetReviewersByRank()
{
return ResponseOutput.Ok(_statisticsService.GetReviewersByRank());
}
///<summary> 最近几个季度入组人次[New] type==0 按照月份 </summary>
[HttpGet, Route("GetEnrollDataByQuarter/{type:int}/{count:int}")]
public IResponseOutput<List<EnrollQuartDataDTO>> GetEnrollDataByQuarter(int type, int count)
{
return ResponseOutput.Ok(_statisticsService.GetEnrollDataByQuarter(type, count));
}
///<summary> 参与项目数排行 [New] </summary>
[HttpGet, Route("getTrialCountRank/{topCount:int}")]
public IResponseOutput<List<TrialDataRankDTO>> GetTrialCountRank(int topCount)
{
return ResponseOutput.Ok(_statisticsService.GetTrialCountRank(topCount));
}
///<summary> 最新工作量 (已确定的)[New] </summary>
[HttpGet, Route("getLatestWorkLoadList/{searchCount:int}")]
public IResponseOutput<List<LatestWorkLoadDTO>> GetLatestWorkLoadList(int searchCount)
{
return ResponseOutput.Ok(_statisticsService.GetLatestWorkLoadList(searchCount));
}
#endregion
}
}

View File

@ -0,0 +1,180 @@
using IRaCIS.Api.Filter;
using IRaCIS.Application;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Domain.Interfaces;
using System.Linq;
namespace IRaCIS.Core.API.Controllers
{
/// <summary>
/// 入组具体流程各个医生列表信息、和提交动作
/// </summary>
[Route("enroll")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Enroll")]
public class EnrollController : ControllerBase
{
private readonly IFileService _fileService;
private readonly ITrialEnrollmentService _trialEnrollmentService;
private readonly IDoctorListQueryService _doctorListQueryService;
private readonly IEnrollRepository _enrollRepository;
private readonly IDoctorRepository _doctorRepository;
public EnrollController(IFileService fileService,
ITrialEnrollmentService trialEnrollmentService,
IDoctorListQueryService doctorListQueryService,
IEnrollRepository enrollRepository,
IDoctorRepository doctorRepository
)
{
_fileService = fileService;
_trialEnrollmentService = trialEnrollmentService;
_doctorListQueryService = doctorListQueryService;
_enrollRepository = enrollRepository;
_doctorRepository = doctorRepository;
}
#region Trial 入组相关
/// <summary> 为项目筛选医生 提交 【select】 </summary>
/// <param name="trialId">项目Id</param>
/// <param name="doctorIdArray">医生Id数组</param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("selectReviewers/{trialId:guid}")]
public IResponseOutput SelectReviewers(Guid trialId, Guid[] doctorIdArray)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialEnrollmentService.SelectReviewer(userId, trialId, doctorIdArray);
}
[LogFilter]
[HttpPost, Route("downloadResume/{trialId:guid}")]
public IResponseOutput<string> DownloadResume(Guid trialId, Guid[] doctorIdArray)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
var zipPath = _fileService.CreateOfficialResumeZip(doctorIdArray);
return ResponseOutput.Ok(SystemConfig.RootUrl + zipPath);
}
/// <summary>提交CRO列表 【Submit】</summary>
/// <param name="trialId">项目Id</param>
/// <param name="doctorIdArray">医生Id列表</param>
/// <param name="commitState"></param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("submitReviewer/{trialId:guid}/{commitState:int}")]
public IResponseOutput SubmitReviewer(Guid trialId, Guid[] doctorIdArray, int commitState)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialEnrollmentService.SubmitReviewer(userId, trialId, doctorIdArray, commitState);
}
/// <summary>入组名单确认 提交【 Approve】 </summary>
/// <param name="trialId">项目Id</param>
/// <param name="doctorIdArray">医生Id列表</param>
/// <param name="auditState"></param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("approveReviewer/{trialId:guid}/{auditState:int}")]
public IResponseOutput ApproveReviewer(Guid trialId, Guid[] doctorIdArray, int auditState)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialEnrollmentService.ApproveReviewer(userId, trialId, doctorIdArray, auditState);
}
/// <summary>
/// 获取医生项目列表
/// </summary>
/// <param name="challengeQuery"></param>
/// <returns></returns>
[HttpPost,Route("Enroll/GetTrialDoctorList")]
[LogFilter]
public PageOutput<EnrollViewModel> GetTrialDoctorList(EnrollGetQuery challengeQuery)
{
return _doctorListQueryService.GetTrialDoctorList(challengeQuery);
//return ResponseOutput.Ok(_doctorListQueryService.GetTrialDoctorList(challengeQuery));
}
/// <summary>
/// 添加或更新项目医生项目价格
/// </summary>
[LogFilter]
[HttpPost, Route("addOrUpdateModel")]
public IResponseOutput AddOrUpdateEnroll(EnrollCommand addOrUpdateModel)
{
return ResponseOutput.Ok(_doctorListQueryService.AddOrUpdateEnroll(addOrUpdateModel));
}
/// <summary>
/// 后台确认医生入组 【Confirm】
/// </summary>
[LogFilter]
[HttpPost, Route("confirmReviewer/{trialId:guid}/{confirmState:int}")]
public IResponseOutput ConfirmReviewer(Guid trialId, Guid[] doctorIdArray, int confirmState)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialEnrollmentService.ConfirmReviewer(userId, trialId, doctorIdArray, confirmState);
}
#endregion
#region 入组过程,各个状态的列表接口
/// <summary>
/// 筛选医生列表 [AUTH]
/// </summary>
[HttpPost, Route("getSelectionReviewerList")]
public IResponseOutput<PageOutput<SelectionReviewerDTO>> GetSelectionReviewerList(
ReviewerSelectionQueryDTO param)
{
return ResponseOutput.Ok(_doctorListQueryService.GetSelectionReviewerList(param));
}
/// <summary>
/// 根据状态获取医生列表,入组 相关接口 提交CRO-1 CRO确认-4
/// </summary>
[HttpPost, Route("getSubmissionOrApprovalReviewerList")]
public IResponseOutput<PageOutput<ConfirmationReviewerDTO>> GetSubmissionOrApprovalReviewerList(
ReviewerSubmissionQueryDTO param)
{
return ResponseOutput.Ok(_doctorListQueryService.GetSubmissionOrApprovalReviewerList(param));
}
/// <summary>
/// 获取项目下医生入组状态列表[Confirmation]
/// </summary>
[HttpPost, Route("getConfirmationReviewerList")]
public IResponseOutput<PageOutput<ConfirmationReviewerDTO>> GetConfirmationReviewerList(
ReviewerConfirmationQueryDTO trialIdPageModel)
{
return ResponseOutput.Ok(_doctorListQueryService.GetConfirmationReviewerList(trialIdPageModel));
}
#endregion
}
}

View File

@ -0,0 +1,66 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 临床受试者
/// </summary>
[Route("subject")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class SubjectController : ControllerBase
{
private readonly ISubjectService _subjectsService;
public SubjectController(ISubjectService subjectsService)
{
_subjectsService = subjectsService;
}
/// <summary>
/// 添加或更新受试者信息[New][AUTH]
/// </summary>
/// <param name="model">state:1-访视中2-出组。0-全部</param>
/// <returns></returns>
[HttpPost, Route("addOrUpdate")]
public IResponseOutput AddOrUpdateSubject(SubjectCommand model)
{
return _subjectsService.AddOrUpdateSubject(model);
}
/// <summary> 删除受试者[New] </summary>
[HttpDelete, Route("delete/{id:guid}")]
public IResponseOutput DeleteSubject(Guid id)
{
return _subjectsService.DeleteSubject(id);
}
/// <summary> 分页获取受试者列表[New] </summary>
/// /// <param name="param">state:1-访视中2-出组。0-全部</param>
[HttpPost, Route("getSubjectList")]
public IResponseOutput<PageOutput<SubjectQueryModel>> GetSubjectList(SubjectQueryParam param)
{
if (param.TrialId == Guid.Empty)
{
return ResponseOutput.NotOk("Trial Id needed.",new PageOutput<SubjectQueryModel>());
}
return ResponseOutput.Ok(_subjectsService.GetSubjectList(param));
}
/// <summary>
/// 上传影像时 获取受试者选择下拉框列表
/// </summary>
/// <param name="siteId"></param>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet, Route("getSubjectListBySiteId/{siteId:guid}/{trialId:guid}")]
public IResponseOutput<List<SubjectSelect>> GetSubjectListBySiteId(Guid siteId, Guid trialId)
{
return ResponseOutput.Ok(_subjectsService.GetSubjectListBySiteId(siteId, trialId));
}
}
}

View File

@ -0,0 +1,68 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using IRaCIS.Core.Application.Contracts.Trial;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 受试者访视
/// </summary>
[Route("subjectVisit")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class SubjectVisitController : ControllerBase
{
private readonly ISubjectVisitService _subjectvisitService;
public SubjectVisitController(ISubjectVisitService subjectvisitService)
{
_subjectvisitService = subjectvisitService;
}
[HttpPost, Route("getVisitList")]
public IResponseOutput<PageOutput<SubjectVisitNewDTO>> GetVisitList(SubjectVisitSearchDTO subjectVisitSearch)
{
return ResponseOutput.Ok(_subjectvisitService.GetVisitList(subjectVisitSearch));
}
/// <summary>
///
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("addOrUpdate")]
public IResponseOutput AddOrUpdateSV(SubjectVisitCommand model)
{
return ResponseOutput.Ok(_subjectvisitService.AddOrUpdateSV(model));
}
/// <summary> 删除受试者访视</summary>
[HttpDelete, Route("delete/{id:guid}")]
public IResponseOutput DeleteSV(Guid id)
{
return _subjectvisitService.DeleteSV(id);
}
/// <summary>
/// 上传影像时 需要选择是属于 受试者访视那个阶段
/// </summary>
/// <param name="trialId"></param>
/// <param name="siteId"></param>
/// <param name="subjectId"></param>
/// <returns></returns>
[HttpGet, Route("getSubjectVisitSelectList/{trialId:guid}/{siteId:guid}/{subjectId:guid}")]
public IResponseOutput<List<SubjectVisitSelectDTO>> GetSubjectVisitSelectList(Guid trialId, Guid siteId, Guid subjectId)
{
return ResponseOutput.Ok(_subjectvisitService.GetSubjectVisitSelectList(trialId, siteId,subjectId));
}
[HttpGet, Route("getSubjectVisitList/{trialId:guid}/{subjectId:guid}")]
public IResponseOutput<IEnumerable<SubjectVisitDTO>> GetSubjectVisitList(Guid trialId, Guid subjectId)
{
return ResponseOutput.Ok(_subjectvisitService.GetSubjectVisitList(trialId, subjectId));
}
}
}

View File

@ -0,0 +1,60 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
namespace IRaCIS.Api.Controllers.Trial
{
/// <summary>
/// 影像获取规范
/// </summary>
[Route("acquisitionSpecification")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class TrialAttachmentController : ControllerBase
{
private readonly ITrialAttachmentService _specificationService;
public TrialAttachmentController(ITrialAttachmentService specificationService)
{
_specificationService = specificationService;
}
/// <summary>
/// 添加或更新影像采集规范[New][AUTH]
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost, Route("addOrUpdate")]
public IResponseOutput AddOrUpdateSpecification(TrialAttachmentCommand model)
{
var userId = User.FindFirst("id").Value;
return _specificationService.AddOrUpdateSpecification(model, Guid.Parse(userId));
}
/// <summary> 删除采集规范[New]</summary>
[HttpDelete, Route("delete/{id:guid}")]
public IResponseOutput DeleteSpecification(Guid id)
{
return _specificationService.DeleteSpecification(id);
}
[HttpPost, Route("list/{trialId:guid}")]
public IResponseOutput<IEnumerable<AcquisitionSpecificationDTO>> GetAcquisitionSpecificationList(Guid trialId,string type)
{
return ResponseOutput.Ok(_specificationService.GetSpecificationList( trialId, type));
}
///// <summary> 分页获取影像采集规范[New]</summary>
//[HttpPost, Route("getPageList")]
//[ApiExplorerSettings(IgnoreApi = true)]
//public IResponseOutput<PageOutput<AcquisitionSpecificationDTO>> GetSpecificationList(ImageAcquisitionSpecificationQueryDTO param)
//{
// return ResponseOutput.Ok(_specificationService.GetSpecificationList(param));
//}
}
}

View File

@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Domain.Share.AuthUser;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 项目基本信息维护
/// </summary>
[Route("trial")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class TrialController : ControllerBase
{
private readonly ITrialService _trialService;
private readonly ITrialWorkloadService _trialWorkloadService;
private readonly IUserInfo _userInfo;
private readonly ICalculateService _calculateService;
public TrialController(ITrialService trialService,
ITrialWorkloadService trialWorkloadService,IUserInfo userInfo,ICalculateService calculateService)
{
_trialService = trialService;
_trialWorkloadService = trialWorkloadService;
_userInfo = userInfo;
_calculateService = calculateService;
}
#region 项目查询
/// <summary> 分页获取临床实验项目列表(查询条件)</summary>
/// <param name="param">查询参数</param>
/// <returns></returns>
[HttpPost, Route("getTrialList")]
public IResponseOutput<PageOutput<TrialDetailDTO>> GetTrialList(TrialQueryDTO param)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return ResponseOutput.Ok(_trialService.GetTrialList(param, userId)) ;
}
/// <summary> 查询项目基本信息 </summary>
/// <param name="trialId">项目Id</param>
/// <returns></returns>
[HttpGet, Route("getTrialInfo/{trialId:guid}")]
public IResponseOutput<TrialDetailDTO> GetTrialInfoAndLockState(Guid trialId)
{
var trial = _trialService.GetTrialInfoAndLockState(trialId);
return ResponseOutput.Ok(trial);
}
/// <summary> 查询项目基本信息 和项目最大状态,</summary>
/// <param name="trialId">项目Id</param>
/// <returns></returns>
[HttpGet, Route("getTrialInfoAndMaxTrialState/{trialId:guid}")]
public IResponseOutput<TrialAndTrialStateVieModel> GetTrialInfoAndMaxTrialState(Guid trialId)
{
var result = new TrialAndTrialStateVieModel()
{
TrialView = _trialService.GetTrialInfoAndLockState(trialId),
TrialMaxState = _trialService.GetTrialMaxState(trialId)
};
return ResponseOutput.Ok(result);
}
/// <summary> 查询项目加急状态</summary>
/// <param name="trialId">项目Id</param>
/// <returns></returns>
[HttpGet, Route("getTrialExpeditedState/{trialId:guid}")]
public IResponseOutput<int> GetTrialExpeditedState(Guid trialId)
{
return ResponseOutput.Ok(_trialService.GetTrialExpeditedState(trialId));
}
/// <summary>
/// 根据项目状态获取医生项目列表[New]
/// </summary>
/// <param name="param">5-Submitted,8-Approved,10-Reading</param>
/// <returns></returns>
[HttpPost, Route("getDoctorTrialListByStatus")]
[AllowAnonymous]
public IResponseOutput<PageOutput<TrialDetailDTO>> GetDoctorTrialListByStatus(
TrialByStatusQueryDTO param)
{
return ResponseOutput.Ok(_trialService.GetReviewerTrialListByEnrollmentStatus(param)) ;
}
#endregion
#region 项目更新删除
/// <summary> 添加实验项目-返回新增Id[AUTH]</summary>
/// <param name="param"></param>
/// <returns>新记录Id</returns>
[LogFilter]
[HttpPost, Route("addOrUpdateTrial")]
public IResponseOutput AddOrUpdateTrial(TrialCommand param)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
var result= _trialService.AddOrUpdateTrial(param, userId);
if (_trialService.TrialExpeditedChange)
{
var needCalReviewerIds = _trialService.GetTrialEnrollmentReviewerIds(param.Id);
var calcList = _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
calcList.ForEach(t=> {
if (needCalReviewerIds.Contains(t.DoctorId))
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
t.DoctorId
},
CalculateMonth = DateTime.Parse(t.YearMonth)
}, User.FindFirst("id").Value);
} });
}
return result;
}
[LogFilter]
[HttpPost, Route("confirmTrialVisitPlan/{trialId:guid}")]
public IResponseOutput ConfirmTrialVisitPlan(Guid trialId)
{
return _trialService.ConfirmTrialVisitPlan(trialId);
}
/// <summary>
/// 手动更新项目状态
/// </summary>
/// <param name="trialId">项目Id</param>
/// <param name="statusStr">状态值</param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("updateTrialStatus/{trialId:guid}/{statusStr}")]
public IResponseOutput UpdateTrialStatusStr(Guid trialId, string statusStr)
{
if (string.IsNullOrWhiteSpace(statusStr))
{
return ResponseOutput.NotOk("please select status.");
}
var result = _trialService.UpdateTrialStatus(trialId, statusStr);
return result;
}
/// <summary> 删除临床项目 </summary>
/// <param name="trialId">临床试验项目Id</param>
[LogFilter]
[HttpDelete, Route("deleteTrial/{trialId:guid}")]
public IResponseOutput DeleteTrial(Guid trialId)
{
return _trialService.DeleteTrial(trialId);
}
#endregion
#region ack sow
/// <summary>
/// 保存协议- ack Sow [AUTH]
/// </summary>
[HttpPost, Route("uploadReviewerAckSOW/{trialId}")]
public IResponseOutput UploadReviewerAckSOW(Guid trialId, ReviewerAckDTO attachmentViewModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return _trialWorkloadService.UploadReviewerAckSOW(userId, trialId, attachmentViewModel);
}
/// <summary>
/// 删除协议
/// </summary>
[HttpDelete, Route("deleteReviewerAckSOW/{trialId}/{doctorId}/{attachmentId}")]
public IResponseOutput DeleteReviewerAckSOW(Guid trialId, Guid doctorId, Guid attachmentId)
{
return _trialWorkloadService.DeleteReviewerAckSOW(trialId, doctorId, attachmentId);
}
/// <summary>
/// 0代表裁判和Tp 都可以 1、代表Tp 2 代表裁判
/// </summary>
/// <param name="trialId"></param>
/// <param name="doctorId"></param>
/// <param name="reviewerReadingType"></param>
/// <returns></returns>
[HttpPost, Route("updateReviewerReadingType/{trialId}/{doctorId}/{reviewerReadingType}")]
public IResponseOutput UpdateReviewerReadingType(Guid trialId, Guid doctorId, int reviewerReadingType)
{
return _trialWorkloadService.UpdateReviewerReadingType(trialId, doctorId, reviewerReadingType);
}
#endregion
#region 医生用户接口
/// <summary> 分页获取医生参与的临床实验项目列表(查询条件)</summary>
/// <param name="param">查询参数</param>
/// <returns></returns>
[HttpPost, Route("getTrialListByReviewer")]
public IResponseOutput<PageOutput<TrialDetailDTO>> GetTrialListByReviewer(ReviewerTrialQueryDTO param)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
return ResponseOutput.Ok(_trialService.GetTrialListByReviewer(param, userId));
}
/// <summary>
/// 医生确认入组或拒绝入组
/// </summary>
/// <param name="trialId">项目Id</param>
/// <param name="status">9-拒绝入组10-确认入组</param>
/// <returns></returns>
[HttpPost, Route("updateEnrollStatus/{trialId:guid}/{status:int}")]
public IResponseOutput UpdateTrialStatusStr(Guid trialId, int status)
{
return _trialService.UpdateEnrollStatus(trialId, status);
}
#endregion
}
}

View File

@ -0,0 +1,109 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 项目运维人员 、研究中心CRC 配置
/// </summary>
[Route("trialMaintenance")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class MaintenanceController : ControllerBase
{
private readonly IUserTrialService _userTrialService;
public MaintenanceController(IUserTrialService userTrialService)
{
_userTrialService = userTrialService;
}
[HttpGet, Route("getTrialSiteSelect/{trialId:guid}")]
public IResponseOutput<IEnumerable<TrialSiteSelect>> GetTrialSiteSelect(Guid trialId)
{
return ResponseOutput.Ok(_userTrialService.GetTrialSiteSelect(trialId));
}
/// <summary>
/// 获取项目运维人员列表[New] 分页暂时不用
/// </summary>
/// <param name="param">项目Id必须传</param>
/// <returns></returns>
[HttpPost, Route("GetUserTrialList")]
[ApiExplorerSettings(IgnoreApi = true)]
public IResponseOutput<PageOutput<UserTrialDTO>> GetUserTrialList(UserTrialListQueryDTO param)
{
return ResponseOutput.Ok(_userTrialService.GetUserTrialList(param));
}
/// <summary>
/// 获取项目运维人员列表[New]
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost, Route("getMaintenanceList")]
public IResponseOutput<IEnumerable<UserTrialDTO>> GetMaintenanceUserList(TrialMaintenanceQuery param)
{
return ResponseOutput.Ok(_userTrialService.GetMaintenanceUserList(param));
}
/// <summary>
/// 获取可用选择用户,用于给项目添加运维人员时的选择列表[New]
/// </summary>
/// <returns></returns>
[HttpGet, Route("getUserSelectionList/{userTypeId:guid}/{institutionId:guid}")]
public IResponseOutput<IEnumerable<UserSelectionModel>> GetUserTrialList(Guid userTypeId,Guid institutionId)
{
return ResponseOutput.Ok(_userTrialService.GetUserSelectionList(userTypeId, institutionId)) ;
}
/// <summary> 添加或更新运维人员[New]</summary>
[HttpPost, Route("AddOrUpdateMaintenanceUser")]
public IResponseOutput AddOrUpdateUserTrial(UserTrialCommand param)
{
return _userTrialService.AddOrUpdateUserTrial(param);
}
/// <summary> 删除运维人员[New]</summary>
[HttpDelete, Route("deleteMaintenanceUser/{id:guid}")]
public IResponseOutput DeleteUserTrial(Guid id)
{
return _userTrialService.DeleteUserTrial(id);
}
/// <summary>获取负责研究中心CRC列表</summary>
[HttpPost, Route("getSiteCRCList")]
public IResponseOutput<PageOutput<SiteStatDTO>> GetSiteCRCList(SiteCrcQueryDTO param)
{
return ResponseOutput.Ok(_userTrialService.GetSiteCRCList(param)) ;
}
/// <summary> 添加或更新CRC人员</summary>
[HttpPost, Route("addOrUpdateSiteCRC")]
public IResponseOutput AddOrUpdateSiteCRC(SiteCRCCommand param)
{
return _userTrialService.AddOrUpdateSiteCRC(param);
}
/// <summary> 删除CRC人员</summary>
[HttpDelete, Route("deleteSiteCRC/{id:guid}")]
public IResponseOutput DeleteSiteCRC(Guid id)
{
return _userTrialService.DeleteSiteCRC(id);
}
}
}

View File

@ -0,0 +1,65 @@
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 访视计划
/// </summary>
[Route("visitPlan")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class VisitPlanController : ControllerBase
{
private readonly IVisitPlanService _visitPlanService;
public VisitPlanController(IVisitPlanService visitPlanService)
{
_visitPlanService = visitPlanService;
}
/// <summary> 分页获取项目访视计划[New]</summary>
[HttpPost, Route("getTrialVisitStageList")]
[ApiExplorerSettings(IgnoreApi = true)]
public IResponseOutput<PageOutput<VisitStageDTO>> GetTrialVisitStageList(VisitPlanQueryDTO param)
{
return ResponseOutput.Ok(_visitPlanService.GetTrialVisitStageList(param));
}
/// <summary> 根据项目Id获取项目访视计划(不分页)[New]</summary>
[HttpGet, Route("getVisitStageList/{trialId:guid}")]
public IResponseOutput<IEnumerable<VisitStageDTO>> GetVisitStageList(Guid trialId)
{
return ResponseOutput.Ok(_visitPlanService.GetVisitStageList(trialId)) ;
}
/// <summary>
/// 获取访视计划下拉框列表
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet, Route("getTrialVisitStageSelect/{trialId:guid}")]
public IResponseOutput<IEnumerable<VisitStageSelectDTO>> GetTrialVisitStageSelect(Guid trialId)
{
return ResponseOutput.Ok(_visitPlanService.GetTrialVisitStageSelect(trialId));
}
/// <summary> 添加或更新访视计划某项[New]</summary>
[HttpPost, Route("addOrUpdateVisitStage")]
public IResponseOutput AddOrUpdateVisitStage(VisitPlanCommand param)
{
return _visitPlanService.AddOrUpdateVisitStage(param);
}
/// <summary> 删除项目计划某一项[New]</summary>
[HttpDelete, Route("deleteVisitStage/{id:guid}")]
public IResponseOutput DeleteVisitStage(Guid id)
{
return _visitPlanService.DeleteVisitStage(id);
}
}
}

View File

@ -0,0 +1,127 @@
using IRaCIS.Api.Filter;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Core.API.Controllers
{
/// <summary>
/// 入组之后 工作量维护
/// </summary>
[Route("workload")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Workload")]
public class WorkloadController : ControllerBase
{
private readonly ITrialWorkloadService _trialWorkloadService;
private readonly ICalculateService _calculateService;
public WorkloadController(ITrialWorkloadService trialWorkloadService, ICalculateService calculateService)
{
_trialWorkloadService = trialWorkloadService;
_calculateService = calculateService;
}
/// <summary>
/// 查询某个医生是否在某天有某个项目的工作量数据,处理添加来自医生自己的工作量数据
/// </summary>
[HttpPost, Route("existWorkLoad")]
public IResponseOutput<ExistWorkloadViewModel> WorkLoadExist(WorkloadExistQueryDTO param)
{
return _trialWorkloadService.WorkloadExist(param);
}
/// <summary> 查询项目入组医生的工作量统计信息 </summary>
[HttpPost, Route("getTrialEnrollmentWorkloadStats")]
public IResponseOutput<PageOutput<WorkLoadAndAgreementDTO>> GetTrialEnrollmentWorkloadStats(WorkLoadDoctorQueryDTO doctorSearchModel)
{
return ResponseOutput.Ok(_trialWorkloadService.GetTrialEnrollmentWorkloadStats(doctorSearchModel));
}
/// <summary>
/// 获取医生工作量(带有填充数据)
/// </summary>
/// <param name="workLoadSearch"></param>
/// <returns></returns>
[HttpPost, Route("getDoctorWorkLoadList")]
public IResponseOutput<PageOutput<WorkLoadDetailDTO>> GetDoctorWorkLoadList(
WorkLoadStatsQueryDTO workLoadSearch)
{
return ResponseOutput.Ok(_trialWorkloadService.GetEnrollmentWorkloadStatsDetail(workLoadSearch)) ;
}
/// <summary>
/// 获取来自医生端的工作量列表 详情
/// </summary>
/// <param name="workLoadSearch"></param>
/// <returns></returns>
[HttpPost, Route("getReviewerWorkLoadListDetail")]
public IResponseOutput<List<WorkLoadDetailViewModel>> GetReviewerWorkLoadListDetail(
WorkLoadDetailQueryDTO workLoadSearch)
{
return ResponseOutput.Ok(_trialWorkloadService.GetReviewerWorkLoadListDetail(workLoadSearch)) ;
}
/// <summary>
/// 添加或更新工作量[AUTH]
/// </summary>
/// <param name="workLoadAddOrUpdateModel"></param>
/// <returns></returns>
[LogFilter]
[HttpPost, Route("workLoadAddOrUpdate")]
public IResponseOutput WorkLoadAddOrUpdate(WorkloadCommand workLoadAddOrUpdateModel)
{
var userId = Guid.Parse(User.FindFirst("id").Value);
//var yearMonth = workLoadAddOrUpdateModel.WorkTime.ToString("yyyy-MM");
var result = _trialWorkloadService.AddOrUpdateWorkload(workLoadAddOrUpdateModel, userId);
//_calculateTaskService.AddCalculateTask(workLoadAddOrUpdateModel.DoctorId, yearMonth);
if (result.IsSuccess && workLoadAddOrUpdateModel.DataFrom == 2)
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
workLoadAddOrUpdateModel.DoctorId
},
CalculateMonth = workLoadAddOrUpdateModel.WorkTime
}, User.FindFirst("id").Value);
}
return result;
}
[LogFilter]
[HttpDelete, Route("deleteWorkLoad/{id:guid}")]
public IResponseOutput DeleteWorkLoad(Guid id)
{
//先判断该工作量的费用是否被锁定,如果被锁定,则不能删除
var workload = _trialWorkloadService.GetWorkloadDetailById(id);
var yearMonth = workload.WorkTime.ToString("yyyy-MM");
var isLock = _calculateService.IsLock(workload.DoctorId, yearMonth);
if (isLock)
{
return ResponseOutput.NotOk("Expenses have been settled and workload cannot be reset.");
}
var deleteResult = _trialWorkloadService.DeleteWorkload(id);
if (workload.DataFrom == (int)Domain.Share.WorkLoadFromStatus.FinalConfirm)
{
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
{
NeedCalculateReviewers = new List<Guid>()
{
workload.DoctorId
},
CalculateMonth = workload.WorkTime
}, User.FindFirst("id").Value);
}
return deleteResult;
}
}
}

View File

@ -0,0 +1,114 @@
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
namespace IRaCIS.Core.API.Controllers.Trial
{
/// <summary>
/// TP、Global、AD 工作量分配查看
/// </summary>
[Route("workload")]
[ApiController, Authorize, ApiExplorerSettings(GroupName = "Trial")]
public class WorkloadDistributionController : ControllerBase
{
private readonly IWorkloadDistributionService _workloadDistributionService;
public WorkloadDistributionController(IWorkloadDistributionService workloadDistributionService)
{
_workloadDistributionService = workloadDistributionService;
}
/// <summary>
/// TP 工作量分配列表
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost, Route("getWorkloadTPList")]
public IResponseOutput<PageOutput<WorkloadTPDTO>> GetWorkloadTPList(WorkloadDistributionQueryParam param)
{
return ResponseOutput.Ok(_workloadDistributionService.GetWorkloadTPList(param));
}
/// <summary>
/// 批量分配Tp
/// </summary>
/// <param name="workloadTPCommand"></param>
/// <returns></returns>
[HttpPost, Route("DistributeTP")]
public IResponseOutput DistributeTP(WorkloadTPCommand workloadTPCommand)
{
return _workloadDistributionService.DistributeTP(workloadTPCommand);
}
//修改单个TP
[HttpPost, Route("UpdateDistributeTP/{tpId:guid}/{reviewerId:guid}/{studyId:guid}")]
public IResponseOutput UpdateDistributeTP(Guid tpId, Guid reviewerId,Guid studyId)
{
return _workloadDistributionService.UpdateDistributeTP(tpId,reviewerId, studyId);
}
[HttpPost, Route("getWorkloadADList")]
public IResponseOutput<PageOutput<WorkloadADDTO>> GetWorkloadADList(WorkloadDistributionQueryParam param)
{
return ResponseOutput.Ok(_workloadDistributionService.GetWorkloadADList(param));
}
/// <summary>
/// 批量分配AD
/// </summary>
/// <param name="workloadTPCommand"></param>
/// <returns></returns>
[HttpPost, Route("DistributeAD")]
public IResponseOutput DistributeAD(WorkloadAdCommand workloadTPCommand)
{
return ResponseOutput.Result(_workloadDistributionService.DistributeAD(workloadTPCommand));
}
//修改单个TP
[HttpPost, Route("UpdateDistributeAD/{tpId:guid}/{reviewerId:guid}")]
public IResponseOutput UpdateDistributeAD(Guid tpId, Guid reviewerId)
{
return ResponseOutput.Result(_workloadDistributionService.UpdateDistributeAD(tpId, reviewerId));
}
[HttpPost, Route("getWorkloadGlobalList")]
public IResponseOutput<PageOutput<WorkloadGlobalDTO>> GetWorkloadGlobalList(WorkloadDistributionQueryParam param)
{
return ResponseOutput.Ok(_workloadDistributionService.GetWorkloadGlobalList(param));
}
/// <summary>
/// 批量分配Global
/// </summary>
/// <param name="workloadGCommand"></param>
/// <returns></returns>
[HttpPost, Route("DistributeGlobal")]
public IResponseOutput DistributeGlobal(WorkloadGlobalCommand workloadGCommand)
{
return _workloadDistributionService.DistributeGlobal(workloadGCommand);
}
//修改单个Global
[HttpPost, Route("UpdateDistributeGlobal/{tpId:guid}/{reviewerId:guid}/{subjectId:guid}/{visitNum}")]
public IResponseOutput UpdateDistributeGlobal(Guid tpId, Guid reviewerId,Guid subjectId, decimal visitNum)
{
return _workloadDistributionService.UpdateDistributeGlobal(tpId, reviewerId,subjectId,visitNum);
}
[HttpGet, Route("GetWorkloadDetailList/{workloadId:guid}")]
[AllowAnonymous]
public IResponseOutput GetWorkloadDetailList(Guid workloadId)
{
return _workloadDistributionService.GetWorkloadDetail(workloadId);
}
[HttpPost, Route("UpdateGlobalStatus/{globalId:guid}")]
public IResponseOutput UpdateGlobalStatus(Guid globalId)
{
return _workloadDistributionService.UpdateGlobalStatus(globalId);
}
}
}

View File

@ -0,0 +1,62 @@
using System;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application;
using IRaCIS.Core.Domain;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace EasyCaching.Demo.Interceptors.Controllers
{
[Route("test")]
[ApiController, AllowAnonymous, ApiExplorerSettings(GroupName = "Common")]
public class ValuesController : ControllerBase
{
//private readonly ITestRepository _testRepository;
//public ValuesController( ITestRepository testRepository)
//{
// _testRepository = testRepository;
//}
//[HttpPost]
//[Route("test")]
//public ActionResult test()
//{
// var test=new Test();
// test.Str = "T" + test.AutoIncrease;
// _testRepository.Add(test);
// var cc= _testRepository.SaveChanges();
// return Ok();
//}
//[HttpPost]
//[Route("castleasync")]
//public async Task<string> CastleAsync(int type = 1)
//{
// if (type == 1)
// {
// return await _cService.GetUtcTimeAsync();
// }
// else if (type == 2)
// {
// var res = await _cService.GetDemoAsync(999);
// return $"{res.Id}-{res.Name}-{res.CreateTime}";
// }
// else if (type == 3)
// {
// var res = await _cService.GetDemoListAsync(999);
// return $"{res.Count}";
// }
// else
// {
// return await Task.FromResult<string>("wait");
// }
//}
}
}

View File

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace IRaCIS.Core.API.Filter
{
public class EnableBufferingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
using IRaCIS.Core.Domain.Share.AuthUser;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
namespace IRaCIS.Api.Filter
{
public class LogActionFilter : IAsyncActionFilter
{
private readonly ILogService _logService;
private readonly IUserInfo _userInfo;
public LogActionFilter(ILogService logService, IUserInfo userInfo)
{
_logService = logService;
_userInfo = userInfo;
}
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(LogFilter)))
{
return LogAsync(context, next);
}
return next();
}
public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var sw = new Stopwatch();
sw.Start();
dynamic actionResult = (await next()).Result;
sw.Stop();
var args = JsonConvert.SerializeObject(context.ActionArguments);
var result = JsonConvert.SerializeObject(actionResult?.Value);
var attr = (ApiExplorerSettingsAttribute)context.ActionDescriptor.EndpointMetadata.FirstOrDefault(m => m.GetType() == typeof(ApiExplorerSettingsAttribute));
var groupName = attr?.GroupName;
var res = actionResult?.Value as IResponseOutput;
var input = new SystemLogDTO
{
ClientIP = string.Empty,
OptUserId = _userInfo.Id,
OptUserName = _userInfo.UserName,
ApiPath = context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(),
Params = args,
Result = result,
RequestTime = DateTime.Now,
ElapsedMilliseconds = sw.ElapsedMilliseconds,
Status =res?.IsSuccess?? false,
Message = res?.ErrorMessage,
LogCategory = groupName
};
_logService.SaveLog2Db(input);
}
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace IRaCIS.Api.Filter
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class LogFilter : Attribute
{
}
}

View File

@ -0,0 +1,29 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace IRaCIS.Core.API.Filter
{
#region snippet_DisableFormValueModelBindingAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
//factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
//factories.RemoveType<JQueryFormValueProviderFactory>();
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
#endregion
}

View File

@ -0,0 +1,69 @@
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
using IRaCIS.Common.Logger;
using IRaCIS.Common.Model;
namespace IRaCIS.Api.Filter
{
public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute
{
private ILogger<WebApiExceptionFilterAttribute> _logger;
public WebApiExceptionFilterAttribute()
{
_logger = new NLogLogger<WebApiExceptionFilterAttribute>();
}
//public override void OnException(ExceptionContext context)
public override void OnException(HttpActionExecutedContext context)
{
string controllerName = context.ActionContext.ControllerContext.ControllerDescriptor.ControllerName;
string actionName = context.ActionContext.ActionDescriptor.ActionName;
_logger.Error("controller=" + controllerName + " action=" + actionName + " " + context.Exception.Message);
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
else if (context.Exception is CommonException)
{
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
};
context.Response = msg;
}
else if (context.Exception is TimeoutException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
else if (context.Exception is NullReferenceException)
{
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("NullReferenceException"),
ReasonPhrase = "An unhandled exception was thrown .controller=" + controllerName + " action=" + actionName
};
context.Response = msg;
}
else
{
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent(context.Exception.Message),
//ReasonPhrase = "An unhandled exception was thrown ."
};
context.Response = msg;
}
base.OnException(context);
}
}
}

View File

@ -0,0 +1,82 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\IRaCIS.Core.API.xml</DocumentationFile>
<NoWarn>1701;1702;1591;</NoWarn>
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>bin\Release\IRaCIS.Core.API.xml</DocumentationFile>
<OutputPath>bin\Release\</OutputPath>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="UploadFile\**" />
<Content Remove="UploadFile\**" />
<EmbeddedResource Remove="UploadFile\**" />
<None Remove="UploadFile\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Filter\WebApiExceptionFilterAttribute.cs" />
</ItemGroup>
<ItemGroup>
<Content Remove="web.config" />
</ItemGroup>
<ItemGroup>
<None Remove="index.html" />
<None Remove="IRaCIS.Core.API.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="index.html" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="5.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.7" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.4" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="5.1.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.7.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IRaCIS.Core.Application.Contracts\IRaCIS.Core.Application.Contracts.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Application\IRaCIS.Core.Application.csproj" />
<ProjectReference Include="..\IRaCIS.Core.Infra.EF\IRaCIS.Core.Infra.EFCore.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Auth\" />
<Folder Include="Controllers\ReviewerApi\" />
<Folder Include="Properties\PublishProfiles\" />
<Folder Include="wwwroot\UploadFile\" />
</ItemGroup>
<ItemGroup>
<Content Update="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties anonymizetagsetting_1json__JsonSchema="http://json.schemastore.org/jovo-language-model" /></VisualStudio></ProjectExtensions>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="true"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<targets>
<target xsi:type="File" name="file" fileName="${basedir}/logs/${shortdate}.log"
layout="[${time}] ${level} ${logger} ${exception:format=message,stacktrace} ${newline} ${message}"
archiveFileName="${basedir}/logs/${shortdate}.{#####}.txt"
archiveAboveSize="10485760"
archiveNumbering="Rolling"
concurrentWrites="true"
maxArchiveFiles="5"
keepFileOpen="false" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="file" />
</rules>
</nlog>

View File

@ -0,0 +1,58 @@
using System;
using Autofac.Extensions.DependencyInjection;
using Dicom.Imaging;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;
namespace IRaCIS.Core.API
{
public class Program
{
public static void Main(string[] args)
{
ImageManager.SetImplementation(WinFormsImageManager.Instance);
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel((context, options) =>
{
//设置应用服务器Kestrel请求体最大为1GB // if don't set default value is: 30 MB
options.Limits.MaxRequestBodySize = long.MaxValue;
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(30);
options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(30);
});
webBuilder.UseStartup<Startup>();
})//使用Autofac替代本身容器
.UseServiceProviderFactory(new AutofacServiceProviderFactory()).
ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog()
; // NLog: Setup NLog for Dependency injection;
}
}

View File

@ -0,0 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57302",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IRaCIS.Core.API": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000"
}
}
}

161
IRaCIS.Core.API/Startup.cs Normal file
View File

@ -0,0 +1,161 @@
using Autofac;
using EasyCaching.Core;
using EasyCaching.Interceptor.Castle;
using IRaCIS.Api.Filter;
using IRaCIS.Application;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.Services;
using IRaCIS.Core.API.Auth;
using IRaCIS.Core.Domain.Share;
using IRaCIS.WX.CoreApi.Utility;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using System;
using System.Reflection;
namespace IRaCIS.Core.API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
//// ConfigureContainer is where you can register things directly
//// with Autofac. This runs after ConfigureServices so the things
//// here will override registrations made in ConfigureServices.
//// Don't build the container; that gets done for you by the factory.
// for castle
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<TokenService>().As<ITokenService>();
containerBuilder.RegisterType<LogService>().As<ILogService>().SingleInstance();
Assembly domain = Assembly.Load("IRaCIS.Core.Domain");
containerBuilder.RegisterAssemblyTypes(domain).AsImplementedInterfaces();
Assembly domainShare = Assembly.Load("IRaCIS.Core.Domain.Share");
containerBuilder.RegisterAssemblyTypes(domainShare).AsImplementedInterfaces();
Assembly infrastructure = Assembly.Load("IRaCIS.Core.Infra.EFCore");
containerBuilder.RegisterAssemblyTypes(infrastructure).AsImplementedInterfaces();
Assembly application = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "IRaCIS.Core.Application.dll");
containerBuilder.RegisterAssemblyTypes(application).AsImplementedInterfaces();
//containerBuilder.RegisterModule<CustomAutofacModule>();
containerBuilder.ConfigureCastleInterceptor();
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(options =>
{
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
// 不使用驼峰
options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); //new DefaultContractResolver();// new NullToEmptyStringResolver();
// 设置时间格式
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
options.ValueLengthLimit = int.MaxValue;
});
if (SystemConfig.OpenLog)
{
services.AddControllers(options =>
{
options.Filters.Add<LogActionFilter>();
});
}
services.AddLogging();
#region EasyCaching
services.AddEasyCaching(options =>
{
options.UseInMemory();
});
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
#endregion
//MiniProfilerConfigure.ConfigureMiniProfiler(services);
AuthConfigure.ConfigureAuth(services, Configuration);
AutoMapperConfigure.ConfigureSwagger(services);
EFConfigure.ConfigureEF(services, Configuration);
SwaggerConfigure.ConfigureSwagger(services);
//services.Configure<IISServerOptions>(options =>
//{
// options.MaxRequestBodySize = int.MaxValue;
//});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
////不能放在静态方法中
//app.UseSwaggerUI(options =>
//{
// options.IndexStream = () =>
// GetType().GetTypeInfo().Assembly
// .GetManifestResourceStream("IRaCIS.Core.API.index.html");
//});
//app.UseMiniProfiler();
}
app.UseDeveloperExceptionPage();
SwaggerConfigure.Configure(app, env);
app.UseStaticFiles();
//app.UseStaticFiles(new StaticFileOptions()
//{
// FileProvider = new PhysicalFileProvider(
// Path.Combine(Directory.GetCurrentDirectory(), @"UploadFile")),
// RequestPath = new PathString("/UploadFile")
//});
//app.UseMiddleware<AuthMiddleware>();
//app.Use(async (context, next) =>
//{
// context.Request.EnableBuffering();
// await next();
//});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

View File

@ -0,0 +1,270 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers;
namespace IRaCIS.Core.API.Utility
{
public static class FileHelpers
{
private static readonly byte[] _allowedChars = { };
// For more file signatures, see the File Signatures Database (https://www.filesignatures.net/)
// and the official specifications for the file types you wish to add.
private static readonly Dictionary<string, List<byte[]>> _fileSignature = new Dictionary<string, List<byte[]>>
{
{ ".gif", new List<byte[]> { new byte[] { 0x47, 0x49, 0x46, 0x38 } } },
{ ".png", new List<byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } },
{ ".jpeg", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 },
}
},
{ ".jpg", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 },
}
},
{ ".zip", new List<byte[]>
{
new byte[] { 0x50, 0x4B, 0x03, 0x04 },
new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x45 },
new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 },
new byte[] { 0x50, 0x4B, 0x05, 0x06 },
new byte[] { 0x50, 0x4B, 0x07, 0x08 },
new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70 },
}
},
};
// **WARNING!**
// In the following file processing methods, the file's content isn't scanned.
// In most production scenarios, an anti-virus/anti-malware scanner API is
// used on the file before making the file available to users or other
// systems. For more information, see the topic that accompanies this sample
// app.
public static async Task<byte[]> ProcessFormFile<T>(IFormFile formFile,
ModelStateDictionary modelState, string[] permittedExtensions,
long sizeLimit)
{
var fieldDisplayName = string.Empty;
// Use reflection to obtain the display name for the model
// property associated with this IFormFile. If a display
// name isn't found, error messages simply won't show
// a display name.
MemberInfo property =
typeof(T).GetProperty(
formFile.Name.Substring(formFile.Name.IndexOf(".",
StringComparison.Ordinal) + 1));
if (property != null)
{
if (property.GetCustomAttribute(typeof(DisplayAttribute)) is
DisplayAttribute displayAttribute)
{
fieldDisplayName = $"{displayAttribute.Name} ";
}
}
// Don't trust the file name sent by the client. To display
// the file name, HTML-encode the value.
var trustedFileNameForDisplay = WebUtility.HtmlEncode(
formFile.FileName);
// Check the file length. This check doesn't catch files that only have
// a BOM as their content.
if (formFile.Length == 0)
{
modelState.AddModelError(formFile.Name,
$"{fieldDisplayName}({trustedFileNameForDisplay}) is empty.");
return new byte[0];
}
if (formFile.Length > sizeLimit)
{
var megabyteSizeLimit = sizeLimit / 1048576;
modelState.AddModelError(formFile.Name,
$"{fieldDisplayName}({trustedFileNameForDisplay}) exceeds " +
$"{megabyteSizeLimit:N1} MB.");
return new byte[0];
}
try
{
using (var memoryStream = new MemoryStream())
{
await formFile.CopyToAsync(memoryStream);
// Check the content length in case the file's only
// content was a BOM and the content is actually
// empty after removing the BOM.
if (memoryStream.Length == 0)
{
modelState.AddModelError(formFile.Name,
$"{fieldDisplayName}({trustedFileNameForDisplay}) is empty.");
}
if (!IsValidFileExtensionAndSignature(
formFile.FileName, memoryStream, permittedExtensions))
{
modelState.AddModelError(formFile.Name,
$"{fieldDisplayName}({trustedFileNameForDisplay}) file " +
"type isn't permitted or the file's signature " +
"doesn't match the file's extension.");
}
else
{
return memoryStream.ToArray();
}
}
}
catch (Exception ex)
{
modelState.AddModelError(formFile.Name,
$"{fieldDisplayName}({trustedFileNameForDisplay}) upload failed. " +
$"Please contact the Help Desk for support. Error: {ex.HResult}");
}
return new byte[0];
}
public static async Task<byte[]> ProcessStreamedFile(
MultipartSection section, ContentDispositionHeaderValue contentDisposition,
ModelStateDictionary modelState, string[] permittedExtensions, long sizeLimit)
{
try
{
using (var memoryStream = new MemoryStream())
{
await section.Body.CopyToAsync(memoryStream);
// Check if the file is empty or exceeds the size limit.
if (memoryStream.Length == 0)
{
modelState.AddModelError("File", "The file is empty.");
}
else if (memoryStream.Length > sizeLimit)
{
var megabyteSizeLimit = sizeLimit / 1048576;
modelState.AddModelError("File",
$"The file exceeds {megabyteSizeLimit:N1} MB.");
}
else if (!IsValidFileExtensionAndSignature(
contentDisposition.FileName.Value, memoryStream,
permittedExtensions))
{
modelState.AddModelError("File",
"The file type isn't permitted or the file's " +
"signature doesn't match the file's extension.");
}
else
{
return memoryStream.ToArray();
}
}
}
catch (Exception ex)
{
modelState.AddModelError("File",
"The upload failed. Please contact the Help Desk " +
$" for support. Error: {ex.HResult}");
// Log the exception
}
return new byte[0];
}
private static bool IsValidFileExtensionAndSignature(string fileName, Stream data, string[] permittedExtensions)
{
if (string.IsNullOrEmpty(fileName) || data == null || data.Length == 0)
{
return false;
}
var ext = Path.GetExtension(fileName).ToLowerInvariant();
if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext))
{
return false;
}
data.Position = 0;
using (var reader = new BinaryReader(data))
{
if (ext.Equals(".txt") || ext.Equals(".csv") || ext.Equals(".prn"))
{
if (_allowedChars.Length == 0)
{
// Limits characters to ASCII encoding.
for (var i = 0; i < data.Length; i++)
{
if (reader.ReadByte() > sbyte.MaxValue)
{
return false;
}
}
}
else
{
// Limits characters to ASCII encoding and
// values of the _allowedChars array.
for (var i = 0; i < data.Length; i++)
{
var b = reader.ReadByte();
if (b > sbyte.MaxValue ||
!_allowedChars.Contains(b))
{
return false;
}
}
}
return true;
}
// Uncomment the following code block if you must permit
// files whose signature isn't provided in the _fileSignature
// dictionary. We recommend that you add file signatures
// for files (when possible) for all file types you intend
// to allow on the system and perform the file signature
// check.
//if (!_fileSignature.ContainsKey(ext))
//{
// return true;
//}
// File signature check
// --------------------
// With the file signatures provided in the _fileSignature
// dictionary, the following code tests the input content's
// file signature.
//var signatures = _fileSignature[ext];
//var headerBytes = reader.ReadBytes(signatures.Max(m => m.Length));
//return signatures.Any(signature =>
// headerBytes.Take(signature.Length).SequenceEqual(signature));
//test
return true;
}
}
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.IO;
using Microsoft.Net.Http.Headers;
namespace IRaCIS.Core.API.Utility
{
public static class MultipartRequestHelper
{
// Content-Type: multipart/form-data; boundary="----WebKitFormBoundarymx2fSWqWSd0OxQqq"
// The spec at https://tools.ietf.org/html/rfc2046#section-5.1 states that 70 characters is a reasonable limit.
public static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
{
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;
if (string.IsNullOrWhiteSpace(boundary))
{
throw new InvalidDataException("Missing content-type boundary.");
}
if (boundary.Length > lengthLimit)
{
throw new InvalidDataException(
$"Multipart boundary length limit {lengthLimit} exceeded.");
}
return boundary;
}
public static bool IsMultipartContentType(string contentType)
{
return !string.IsNullOrEmpty(contentType)
&& contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}
public static bool HasFormDataContentDisposition(ContentDispositionHeaderValue contentDisposition)
{
// Content-Disposition: form-data; name="key";
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& string.IsNullOrEmpty(contentDisposition.FileName.Value)
&& string.IsNullOrEmpty(contentDisposition.FileNameStar.Value);
}
public static bool HasFileContentDisposition(ContentDispositionHeaderValue contentDisposition)
{
// Content-Disposition: form-data; name="myfile1"; filename="Misc 002.jpg"
return contentDisposition != null
&& contentDisposition.DispositionType.Equals("form-data")
&& (!string.IsNullOrEmpty(contentDisposition.FileName.Value)
|| !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value));
}
}
}

View File

@ -0,0 +1,54 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
namespace IRaCIS.Core.API
{
public class NullToEmptyStringResolver : DefaultContractResolver
{
/// <summary>
/// 创建属性
/// </summary>
/// <param name="type">类型</param>
/// <param name="memberSerialization">序列化成员</param>
/// <returns></returns>
//protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
//{
// IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
// foreach (var jsonProperty in properties)
// {
// jsonProperty.DefaultValue = new NullToEmptyStringValueProvider(jsonProperty);
// }
// return properties;
//}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
var list= type.GetProperties()
.Select(p =>
{
var jp = base.CreateProperty(p, memberSerialization);
jp.ValueProvider = new NullToEmptyStringValueProvider(p);
return jp;
}).ToList();
var uu = list.Select(t => t.PropertyName).ToList();
//获取复杂对象属性
properties = properties.TakeWhile(t => !uu.Contains(t.PropertyName)).ToList();
list.AddRange(properties);
return list;
}
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Reflection;
using Newtonsoft.Json.Serialization;
namespace IRaCIS.Core.API
{
//public class NullToEmptyStringValueProvider : IValueProvider
//{
// private readonly JsonProperty _memberInfo;
// /// <summary>
// /// 构造函数
// /// </summary>
// /// <param name="memberInfo"></param>
// public NullToEmptyStringValueProvider(JsonProperty memberInfo)
// {
// _memberInfo = memberInfo;
// }
// /// <summary>
// /// 获取Value
// /// </summary>
// public object GetValue(object target)
// {
// var result = _memberInfo.DefaultValue;
// if (_memberInfo.PropertyType == typeof(string) && result == null)
// {
// result = string.Empty;
// }
// else if (_memberInfo.PropertyType == typeof(double?) && result == null)
// {
// result = 0;
// }
// else if (_memberInfo.PropertyType == typeof(double?) && result == null)
// {
// result = 0;
// }
// return result;
// }
// /// <summary>
// /// 设置Value
// /// </summary>
// public void SetValue(object target, object value)
// {
// //_memberInfo.SetValue(target, value);
// _memberInfo.DefaultValue = value;
// }
//}
public class NullToEmptyStringValueProvider : Newtonsoft.Json.Serialization.IValueProvider
{
PropertyInfo _MemberInfo;
public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
{
_MemberInfo = memberInfo;
}
public object GetValue(object target)
{
object result = _MemberInfo.GetValue(target);
if (_MemberInfo.PropertyType == typeof(string) && result == null) result = "";
else if (_MemberInfo.PropertyType == typeof(String[]) && result == null) result = new string[] { };
else if (_MemberInfo.PropertyType == typeof(Nullable<Int32>) && result == null) result = 0;
else if (_MemberInfo.PropertyType == typeof(Nullable<Decimal>) && result == null) result = 0.00M;
return result;
}
public void SetValue(object target, object value)
{
_MemberInfo.SetValue(target, value);
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@ -0,0 +1,47 @@
{
"ConnectionStrings": {
"RemoteNew": "Server=123.56.181.144,14333\\MSSQLExpress14;Database=IRaCIS_B;User ID=sa;Password=dev123456DEV;",
"hang": "Server=ZHOU;Database=IRaCIS;User ID=sa;Password=sa123456;"
//"RemoteTest": "Server=123.56.181.144,14333\\MSSQLExpress14;Database=IRaCIS_B;User ID=sa;Password=dev123456DEV;"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"JwtSetting": {
"SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f", //
"Issuer": "jwtIssuertest1", //
"Audience": "jwtAudiencetest1", //
"TokenExpireDays": "7" // 7day
},
"RootUrl": "http://123.56.181.144:8000",
"CodePrefix": "RE",
"UserCodePrefix": "U",
"VisitPlanNumPrefix": "VT",
"StoredFilesPath": "D:\\Upload", //
"DicomFileArchivedPath": "D:\\Upload", //
"Share": false, //
"FileSizeLimit": 1073741824,
"LoginExpiredTimeSpan": "15", // Minute
"OpenLog": true,
"AddClinicalInfo": true,
"easycaching": {
"inmemory": {
"MaxRdSecond": 120,
"EnableLogging": false,
"LockMs": 5000,
"SleepMs": 300,
"DBConfig": {
"SizeLimit": 10000,
"ExpirationScanFrequency": 60,
"EnableReadDeepClone": true,
"EnableWriteDeepClone": false
}
}
}
}

View File

@ -0,0 +1,89 @@

<script async="async" id="mini-profiler" src="/profiler/includes.min.js?v=4.2.1+gcc91adf599"
data-version="4.2.1+gcc91adf599" data-path="/profiler/"
data-current-id="4ec7c742-49d4-4eaf-8281-3c1e0efa748a" data-ids="" data-position="Left"
data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P"
data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script>
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>%(DocumentTitle)</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
</style>
%(HeadContent)
</head>
<body>
<div id="swagger-ui"></div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -1) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="./swagger-ui-bundle.js"></script>
<script src="./swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
// Workaround for https://github.com/swagger-api/swagger-ui/issues/5945
configObject.urls.forEach(function (item) {
if (item.url.startsWith("http") || item.url.startsWith("/")) return;
item.url = window.location.href.replace("index.html", item.url).split('#')[0];
});
// If validatorUrl is not explicitly provided, disable the feature by setting to null
if (!configObject.hasOwnProperty("validatorUrl"))
configObject.validatorUrl = null
// If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html").split('#')[0];
// Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout";
// Begin Swagger UI call region
const ui = SwaggerUIBundle(configObject);
ui.initOAuth(oauthConfigObject);
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<!--单位:字节。 -->
<requestLimits maxAllowedContentLength="1073741824" />
<!-- 1 GB -->
</requestFiltering>
</security>
</system.webServer>
</configuration>

View File

@ -0,0 +1,32 @@
using AutoMapper;
namespace IRaCIS.Core.Application.Contracts.AutoMapper
{
public class AutoMapperConfig
{
public static void Config()
{
//Mapper.Initialize(cfg =>
//{
// cfg.AddProfile<DomainToViewModelMappingProfile>();
// cfg.AddProfile(new ViewModelToDomainMappingProfile());
// cfg.AddProfile(new LogicChangeMappingProfile());
// cfg.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, sourceMember) => sourceMember != null)));
//});
}
public static MapperConfiguration RegisterMappings()
{
//创建AutoMapperConfiguration, 提供静态方法Configure一次加载所有层中Profile定义
//MapperConfiguration实例可以静态存储在一个静态字段中也可以存储在一个依赖注入容器中。 一旦创建,不能更改/修改。
return new MapperConfiguration(cfg =>
{
cfg.AddProfile<DomainToViewModelMappingProfile>();
cfg.AddProfile(new ViewModelToDomainMappingProfile());
cfg.AddProfile(new LogicChangeMappingProfile());
cfg.ForAllMaps((a, b) => b.ForAllMembers(opt => opt.Condition((src, dest, sourceMember) => sourceMember != null)));
});
}
}
}

View File

@ -0,0 +1,118 @@
using AutoMapper;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Application.ViewModels.Pay;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Domain.Models;
using System.Linq;
namespace IRaCIS.Core.Application.Contracts.AutoMapper
{
public class DomainToViewModelMappingProfile : Profile
{
public DomainToViewModelMappingProfile()
{
#region Reviewer
CreateMap<Doctor, DoctorBasicInfoCommand>();
CreateMap<Education, EducationInfoViewModel>();
CreateMap<Vacation, VacationCommand>();
CreateMap<Education, EducationInfoViewModel>();
CreateMap<ResearchPublication, ResearchPublicationDTO>();
CreateMap<Postgraduate, PostgraduateViewModel>();
CreateMap<Attachment, AttachmentDTO>();
CreateMap<Doctor, ResumeConfirmDTO>();
CreateMap<Doctor, DoctorSelectDTO>();
CreateMap<Doctor, TrialExperienceViewModel>();
CreateMap<TrialExperience, TrialExperienceCommand>();
CreateMap<Doctor, DoctorBasicInfo>();
#endregion
#region Management
CreateMap<User, UserDetailDTO>();
CreateMap<Role, RoleDTO>();
CreateMap<MenuFunction, MenuFunctionDTO>();
CreateMap<MenuFunction, MenuTreeNodeSelect>();
CreateMap<User, UserSelectionModel>();
#endregion
#region institution
CreateMap<Hospital, HospitalDTO>();
CreateMap<CRO, CROCompanyDTO>();
CreateMap<Sponsor, SponsorDTO>();
CreateMap<CRO, CroSelectDTO>();
CreateMap<Sponsor, SponsorSelectDTO>();
CreateMap<Site, SiteSelectionDTO>();
#endregion
#region WrokLoad
CreateMap<Workload, WorkloadDTO>();
#endregion
CreateMap<Dictionary, DicViewModelDTO>();
CreateMap<Dictionary, KeyNameType>();
#region finacial
CreateMap<RankPrice, RankPriceDTO>();
CreateMap<VolumeReward, AwardPriceDTO>();
CreateMap<RankPrice, RankDic>();
CreateMap<ExchangeRate, ExchangeRateCommand>();
CreateMap<Payment, CalculateNeededDTO>();
CreateMap<VolumeReward, AwardPriceCalculateDTO>();
CreateMap<PaymentDetail, PaymentDetailDTO>();
CreateMap<TrialPaymentPrice,TrialSOWPathDTO > ();
#endregion
#region image
CreateMap<VisitStage, VisitStageDTO>();
CreateMap<SubjectVisit, SubjectVisitDTO>();
CreateMap<StudyStatusDetail, StudyStatusDetailDTO>();
CreateMap<VisitStage, VisitStageSelectDTO>();
CreateMap<DicomInstance, DicomInstanceDTO>();
CreateMap<DicomStudy, DicomStudyDTO>();
CreateMap<DicomSeries, DicomSeriesDTO>();
#endregion
#region QA
CreateMap<QATemplate, QATemplateCommand>();
CreateMap<QATemplate, QATemplateDTO>();
CreateMap<QADictionary, QADictionaryCommand>();
CreateMap<QARecord, QARecordCommand>();
#endregion
CreateMap<TrialAttachment, AcquisitionSpecificationDTO>();
CreateMap<Report, ReportDTO>();
CreateMap<ImageLabel, ImageLabelDTO>();
CreateMap<DicomSeries, DicomSeriesWithLabelDTO>();
CreateMap<TrialPaymentPrice, TrialPaymentPriceDTO>()
.ForMember(t => t.TrialCode, u => u.MapFrom(t => t.Trial.Code))
.ForMember(t => t.ReviewMode, u => u.MapFrom(t => t.Trial.ReviewMode.Value))
.ForMember(t => t.Cro, u => u.MapFrom(t => t.Trial.CRO.CROName))
.ForMember(t => t.Indication, u => u.MapFrom(t => t.Trial.Indication))
.ForMember(t => t.Expedited, u => u.MapFrom(t => t.Trial.Expedited))
.ForMember(t => t.DoctorsNames, u => u.MapFrom(t => string.Join(",", t.Trial.EnrollList.Select(x => x.Doctor.ChineseName))));
}
}
}

View File

@ -0,0 +1,42 @@
using AutoMapper;
using IRaCIS.Application.ViewModels;
using IRaCIS.Application.ViewModels.Pay;
using IRaCIS.Core.Domain.Models;
namespace IRaCIS.Core.Application.Contracts.AutoMapper
{
public class LogicChangeMappingProfile : Profile
{
public LogicChangeMappingProfile()
{
//医生列表、项目显示列表模型转换
CreateMap<DoctorDTO, SelectionReviewerDTO>();
CreateMap<Message, SysMessageDTO>()
.ForMember(o => o.MessageTime, t => t.MapFrom(u => u.MessageTime.ToString()));
CreateMap<CRO, InstitutionDTO>()
.ForMember(o => o.InstitutionName, t => t.MapFrom(u => u.CROName));
CreateMap<Sponsor, InstitutionDTO>()
.ForMember(o => o.InstitutionName, t => t.MapFrom(u => u.SponsorName));
CreateMap<Hospital, InstitutionDTO>()
.ForMember(o => o.InstitutionName, t => t.MapFrom(u => u.HospitalName));
CreateMap<Site, InstitutionDTO>()
.ForMember(o => o.InstitutionName, t => t.MapFrom(u => u.SiteName));
CreateMap<PaymentAdjustmentCommand, PaymentAdjustment>()
.ForMember(t=>t.YearMonthDate,
u=>u.MapFrom(t=>t.YearMonth))
.ForMember(t=>t.YearMonth,
u=>u.MapFrom(t=>t.YearMonth.ToString("yyyy-MM")));
CreateMap<LesionInformation, VisitLesion>();
CreateMap<EnrollCommand, Enroll>();
}
}
}

View File

@ -0,0 +1,168 @@
using AutoMapper;
using IRaCIS.Application.Interfaces;
using IRaCIS.Application.ViewModels;
using IRaCIS.Application.ViewModels.Pay;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Domain.Models;
namespace IRaCIS.Core.Application.Contracts.AutoMapper
{
public class ViewModelToDomainMappingProfile : Profile
{
public ViewModelToDomainMappingProfile()
{
#region reviewer
//基本信息 工作信息 添加时转换使用
CreateMap<DoctorBasicInfoCommand, Doctor>();
//学习经历 添加时转换使用
CreateMap<EducationCommand, Education>();
CreateMap<PostgraduateCommand, Postgraduate>();
CreateMap<ResearchPublicationDTO, ResearchPublication>();
CreateMap<TrialExperienceCommand, TrialExperience>();
//医生账户
CreateMap<DoctorAccountLoginDTO, Doctor>();
CreateMap<DoctorAccountRegisterDTO, Doctor>();
CreateMap<VacationCommand, Vacation>();
CreateMap<AttachmentDTO, Attachment>();
CreateMap<ReviewerAckDTO, Attachment>();
#endregion
#region trial
//临床项目
CreateMap<TrialCommand, IRaCIS.Core.Domain.Models.Trial>();
#endregion
#region workLoad
//工作量
CreateMap<WorkloadCommand, Workload>();
#endregion
CreateMap<DicViewModelDTO, Dictionary>();
CreateMap<UserTrialCommand, UserTrial>();
CreateMap<SiteCRCCommand, UserTrial>();
CreateMap<SystemLogDTO, SystemLog>();
#region management
CreateMap<RoleCommand, Role>();
CreateMap<UserCommand, User>();
CreateMap<UserCommand, User>();
CreateMap<MenuFunctionCommand, MenuFunction>();
//CreateMap<FunctionAddOrUpdateModel, Function>();
#endregion
#region institution
CreateMap<HospitalCommand, Hospital>();
CreateMap<CROCompanyDTO, CRO>();
CreateMap<SiteCommand, Site>();
CreateMap<SponsorCommand, Sponsor>();
//CreateMap<SiteViewModel, Site>();
//CreateMap<HospitalViewModel, Hospital>();
//CreateMap<SponsorViewModel, Sponsor>();
#endregion
#region financial
CreateMap<TrialPaymentPriceCommand, TrialPaymentPrice>();
CreateMap<ReviewerPayInfoCommand, ReviewerPayInformation>();
CreateMap<RankPriceCommand, RankPrice>();
CreateMap<AwardPriceCommand, VolumeReward>();
CreateMap<PaymentCommand, Payment>();
CreateMap<PaymentDetailCommand, PaymentDetail>();
CreateMap<ExchangeRateCommand, ExchangeRate>();
CreateMap<AwardPriceCommand, VolumeReward>();
CreateMap<TrialRevenuesPriceDTO, TrialRevenuesPrice>();
CreateMap<TrialSOWPathDTO, TrialPaymentPrice>();
#endregion
#region image
CreateMap<TrialAttachmentCommand, TrialAttachment>();
CreateMap<VisitPlanCommand, VisitStage>();
CreateMap<SubjectVisitCommand, SubjectVisit>();
CreateMap<StudyCommand, DicomStudy>();
CreateMap<SubjectDTO, Subject>();
CreateMap<SubjectCommand, Subject>();
CreateMap<ImageQACommand, ImageQA>();
#endregion
#region QA
CreateMap<QATemplateCommand, QATemplate>();
CreateMap<QARecordCommand, QARecord>();
CreateMap<QADictionaryCommand,QADictionary>();
CreateMap<QADialogCommand, QADialog>();
CreateMap<QATemplateConfigCommand, QATemplateDictionary>();
#endregion
CreateMap<ReportDTO, Report>();
CreateMap<ImageLabelDTO, ImageLabel>();
CreateMap<GlobalReportCommand, GlobalRS>();
}
}
}

View File

@ -0,0 +1,65 @@
using EasyCaching.Core.Interceptor;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Domain.Interfaces;
using IRaCIS.Core.Domain.Share;
using System;
using System.Linq;
namespace IRaCIS.Core.Application
{
public interface ICastleService
{
[EasyCachingAble(Expiration = 10)]
DoctorBasicInfoDTO GetDoctorBasicInfo(Guid doctorId);
}
public class CastleService : ICastleService
{
private readonly IDoctorRepository _doctorRepository;
public CastleService(IDoctorRepository doctorRepository)
{
_doctorRepository = doctorRepository;
}
public DoctorBasicInfoDTO GetDoctorBasicInfo(Guid doctorId)
{
var doctorQueryable = _doctorRepository
.Find(t => t.Id == doctorId)
.Select(doctor => new DoctorBasicInfoDTO()
{
Id = doctor.Id,
Code = doctor.Code,
ChineseName = doctor.ChineseName,
EMail = doctor.EMail,
FirstName = doctor.FirstName,
Introduction = doctor.Introduction,
LastName = doctor.LastName,
Phone = doctor.Phone,
Sex = doctor.Sex,
WeChat = doctor.WeChat,
TitleIds = doctor.DoctorDicList
.Where(t => t.KeyName == StaticData.Title).Select(t => t.DictionaryId).ToList()
});
var doctorBasicInfo = doctorQueryable.FirstOrDefault();
return doctorBasicInfo;
}
}
//[ProtoContract]
//[System.Serializable]
public class Demo
{
//[ProtoMember(1)]
public int Id { get; set; }
//[ProtoMember(2)]
public string Name { get; set; }
//[ProtoMember(3)]
public System.DateTime CreateTime { get; set; }
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Application.ViewModels
{
public class DicViewModelDTO
{
public Guid Id { get; set; }
public string KeyName { get; set; }
public string Value { get; set; }
public int ShowOrder { get; set; }
public string Type { get; set; }
}
public class DicQueryDTO : PageInput
{
public string KeyName { get; set; }
}
public class KeyNameType
{
public Guid KeyId { get; set; }
public string KeyName { get; set; }
public string Type { get; set; }
}
public class DicResultDTO
{
public Dictionary<string, Dictionary<Guid, string>> DicList = new Dictionary<string, Dictionary<Guid, string>>();
}
}

View File

@ -0,0 +1,17 @@
using IRaCIS.Core.Domain.Share;
using System;
namespace IRaCIS.Application.ViewModels
{
public class UploadFileInfoDTO
{
public Guid Id { get; set; }
public string FilePath { get; set; }
public string FullFilePath => SystemConfig.RootUrl + FilePath;
}
}

View File

@ -0,0 +1,11 @@
namespace IRaCIS.Application.ViewModels
{
public class MessageViewModel
{
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace IRaCIS.Application.ViewModels
{
public class SysMessageDTO
{
public int Id { get; set; }
public int ToDoctorId { get; set; }
public int FromUserId { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public string MessageTime { get; set; }
public bool HasRead { get; set; }
public string Memo { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,29 @@
using System;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Application.ViewModels
{
public class SystemLogDTO
{
public Guid Id { get; set; }
public string ApiPath { get; set; } = string.Empty;
public string Params { get; set; } = string.Empty;
public string Result { get; set; } = string.Empty;
public DateTime RequestTime { get; set; } = DateTime.Now;
public long ElapsedMilliseconds { get; set; } = 0;
public Guid OptUserId { get; set; } = Guid.Empty;
public string OptUserName { get; set; } = string.Empty;
public string ClientIP { get; set; } = string.Empty;
public bool Status { get; set; } = true;
public string Message { get; set; } = string.Empty;
public string LogCategory { get; set; } = string.Empty;
}
public class QueryLogQueryDTO : PageInput
{
public string Keyword { get; set; } = string.Empty;
public string LogCategory { get; set; } = string.Empty;
public DateTime BeginTime { get; set; } = DateTime.Now;
public DateTime EndTime { get; set; } = DateTime.Now;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using EasyCaching.Core.Interceptor;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Application.Interfaces
{
public interface IDictionaryService
{
IEnumerable<string> GetDicSelect();
PageOutput<DicViewModelDTO> GetDicSelectList(DicQueryDTO dicSearchModel);
IResponseOutput DeleteDictionary(Guid id);
DicResultDTO GetDictionaryResult(string[] searchArray);
DicResultDTO GetAllDictionary();
IResponseOutput AddOrUpdateDictionary(DicViewModelDTO viewModel);
[EasyCachingAble(Expiration = 10)]
List<DictionaryTreeNode> GetDicTree();
DicViewModelDTO GetDetailById(Guid Id);
}
}

View File

@ -0,0 +1,17 @@
using System;
namespace IRaCIS.Application.Interfaces
{
public interface IFileService
{
//IResponseOutput<UploadFileInfo> DownloadOfficialResume(Guid[] doctorIds);
string CreateOfficialResumeZip(Guid[] doctorIds);
string CreateDoctorsAllAttachmentZip(Guid[] doctorIds);
string CreateZipPackageByAttachment(Guid doctorId, Guid[] attachmentIds);
}
}

View File

@ -0,0 +1,12 @@
using IRaCIS.Application.ViewModels;
using System.Collections.Generic;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Application.Interfaces
{
public interface ILogService
{
IResponseOutput SaveLog2Db(SystemLogDTO viewModel);
PageOutput<SystemLogDTO> GetLogList(QueryLogQueryDTO param);
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.ViewModels;
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
namespace IRaCIS.Application.Interfaces
{
public interface IMessageService
{
int GetUnReadMessageCount(Guid doctorId);
IResponseOutput DeleteSysMessage(Guid messageId);
IResponseOutput MarkedAsRead(Guid messageId);
PageOutput<SysMessageDTO> GetMessageList(Guid doctorId, int pageSize, int pageIndex);
}
}

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public sealed class DicomArchiveResult
{
public int ReceivedFileCount { get; set; }
public ICollection<string> ErrorFiles { get; set; }
public ICollection<DicomStudyDTO> ArchivedDicomStudies { get; set; }
public DicomArchiveResult()
{
ReceivedFileCount = 0;
ErrorFiles = new List<string>();
ArchivedDicomStudies = new List<DicomStudyDTO>();
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class DicomInstanceDTO
{
public Guid Id { get; set;}
public Guid StudyId { get; set; }
public Guid SeriesId { get; set; }
public string StudyInstanceUid { get; set; }
public string SeriesInstanceUid { get; set; }
public string SopInstanceUid { get; set; }
public int InstanceNumber { get; set; }
public DateTime InstanceTime { get; set; }
public bool CPIStatus { get; set; }
public int ImageRows { get; set; }
public int ImageColumns { get; set; }
public int SliceLocation { get; set; }
public Guid TrialId { get; set; }
public Guid SiteId { get; set; }
public Guid SubjectId { get; set; }
public Guid SubjectVisitId { get; set; }
public Guid CreateUserId { get; set; }
public DateTime CreateTime { get; set; }
public Guid UpdateUserId { get; set; }
public DateTime UpdateTime { get; set; }
}
public class DicomTrialSiteSubjectInfo
{
public string SiteCode { get; set; }
public string SiteName { get; set; }
public string SubjectCode { get; set; }
public string SubjectName { get; set; }
public int SubjectAge { get; set; }
public string SubjectSex { get; set; }
public string TrialCode { get; set; }
public string ReviewMode { get; set; }
public bool IsDoubleReview { get; set; }
public string TrialIndication { get; set; }
public decimal SubjectVisitNum { get; set; }
public string SubjectVisitSVUPDES { get; set; }
public string SubjectVisitVisitName { get; set; }
public string Sponsor { get; set; }
public string Comment { get; set; }=String.Empty;
public Guid TrialId { get; set; }
public Guid SiteId { get; set; }
public Guid SubjectId { get; set; }
public Guid SubjectVisitId { get; set; }
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class DicomSeriesDTO
{
public Guid Id { get; set; }
public Guid StudyId { get; set; }
public string StudyInstanceUid { get; set; }
public string SeriesInstanceUid { get; set; }
public int SeriesNumber { get; set; }
public DateTime SeriesTime { get; set; }
public string Modality { get; set; }
public string Description { get; set; }
public int InstanceCount { get; set; }
public string SliceThickness { get; set; }
public Guid TrialId { get; set; }
public Guid SiteId { get; set; }
public Guid SubjectId { get; set; }
public Guid SubjectVisitId { get; set; }
public List<Guid> InstanceList { get; set; } = new List<Guid>();
public Guid CreateUserId { get; set; }
public DateTime CreateTime { get; set; }
public Guid UpdateUserId { get; set; }
public DateTime UpdateTime { get; set; }
}
public class DicomSeriesWithLabelDTO : DicomSeriesDTO
{
public bool HasLabel { get; set; } = false;
public bool KeySeries { get; set; } = false;
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class DicomStudyDTO
{
public Guid Id { get; set; }
public Guid TrialId { get; set; }
public Guid SiteId { get; set; }
public Guid SubjectId { get; set; }
public Guid SubjectVisitId { get; set; }
public string StudyCode { get; set; } = string.Empty;
public int Status { get; set; } = 1;
public string StudyInstanceUid { get; set; } = string.Empty;
public DateTime? StudyTime { get; set; }
public string Modalities { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public int SeriesCount { get; set; } = 0;
public int InstanceCount { get; set; } = 0;
public bool SoftDelete { get; set; } = false;
public string InstitutionName { get; set; } = string.Empty;
public string PatientId { get; set; } = string.Empty;
public string PatientName { get; set; } = string.Empty;
public string PatientAge { get; set; } = string.Empty;
public string PatientSex { get; set; } = string.Empty;
public Guid UpdateUserId { get; set; }
public DateTime UpdateTime { get; set; }
public Guid CreateUserId { get; set; }
public DateTime CreateTime { get; set; }
}
public class RelationVisitDTO
{
public string VisitName { get; set; }
public string TpCode { get; set; }
public Guid StudyId { get; set; }
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class ImageLabelDTO
{
public Guid Id { get; set; } = Guid.Empty;
public string TpCode { get; set; } = string.Empty;
public Guid StudyId { get; set; } = Guid.Empty;
public Guid SeriesId { get; set; } = Guid.Empty;
public Guid InstanceId { get; set; } = Guid.Empty;
public string LabelValue { get; set; } = string.Empty;
}
public class ImageLabelInfo
{
public Guid StudyId { get; set; } = Guid.Empty;
public Guid SeriesId { get; set; } = Guid.Empty;
public Guid InstanceId { get; set; } = Guid.Empty;
public string LabelValue { get; set; } = string.Empty;
}
public class ImageLabelCommand
{
public string TpCode { get; set; } = string.Empty;
public List<ImageLabelInfo> ImageLabelList { get; set; } = new List<ImageLabelInfo>();
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using IRaCIS.Application.ViewModels;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class StudyReviewerDTO
{
public Guid Id { get; set; }
public Guid StudyId { get; set; }
public Guid ReviewerId { get; set; }
}
public class StudyDistributeInfo
{
public Guid StudyId { get; set; }
public int Status { get; set; }
//public int ReviewerCount { get; set; }
}
public class StudyReviewerCommand
{
public List<StudyDistributeInfo> StudyList { get; set; } = new List<StudyDistributeInfo>();
//public List<Guid> StudyIdList { get; set; }
public Guid ReviewerId { get; set; }
//public int WorkloadType { get; set; }
public Guid TrialId { get; set; }
//public bool IsDoubleReview { get; set; }
}
public class StudyReviewerEditCommand
{
public Guid TrialId { get; set; }
public Guid StudyId { get; set; }
public bool IsDoubleReview { get; set; }
public Guid? ReviewerId1 { get; set; }
public Guid? ReviewerId2 { get; set; }
public Guid? ReviewerIdForAD { get; set; }
}
public class ReviewerDistributionDTO
{
public Guid ReviewerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Code { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System;
namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
{
public class StudyStatusDetailDTO
{
public Guid Id { get; set; }
public Guid StudyId { get; set; }
public int Status { get; set; }
public string OptUserName { get; set; }
public DateTime OptTime { get; set; }
public string Note { get; set; } = string.Empty;
}
public class StudyStatusDetailCommand
{
public Guid StudyId { get; set; }
public int Status { get; set; }
public string Note { get; set; } = string.Empty;
public string QAComment { get; set; } = string.Empty;
}
}

Some files were not shown because too many files have changed in this diff Show More