Compare commits

...

42 Commits

Author SHA1 Message Date
hang e6bd35ae04 url 解码下载修改
continuous-integration/drone/push Build is passing Details
2024-07-17 18:00:17 +08:00
he 102e193ae8 修改
continuous-integration/drone/push Build is passing Details
2024-07-17 10:19:51 +08:00
he 20d557e795 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2024-07-17 10:10:29 +08:00
he 593ab42882 修改 2024-07-17 10:10:28 +08:00
hang b56d256e10 去掉权限,方便前端测试
continuous-integration/drone/push Build is passing Details
2024-07-16 10:59:46 +08:00
he 614a3bd70e 返回值修改
continuous-integration/drone/push Build is passing Details
2024-07-16 10:10:12 +08:00
he 2eb3b04365 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2024-07-16 09:57:34 +08:00
he 1fa3a5a181 加返回参数 2024-07-16 09:57:33 +08:00
hang cd2007c4fd 减少压缩包访视层级,同时处理单个非dicom 特殊情况压缩包处理
continuous-integration/drone/push Build is passing Details
2024-07-15 16:55:21 +08:00
hang 67e710eac0 增加打包下载验证
continuous-integration/drone/push Build is passing Details
2024-07-15 16:28:29 +08:00
hang ef451d82ec 修改ivus影像下载功能
continuous-integration/drone/push Build is passing Details
2024-07-15 15:46:31 +08:00
he 899ebf2a30 跳过阅片修改
continuous-integration/drone/push Build is passing Details
2024-07-15 14:43:49 +08:00
he f233d27f96 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2024-07-15 14:13:14 +08:00
he 9e8ab8acca 跳过阅片修改 2024-07-15 14:13:14 +08:00
hang 2265387f47 Uat 自动打包发布
continuous-integration/drone/push Build is passing Details
2024-07-15 13:12:43 +08:00
he baf8f39bc6 提示语修改
continuous-integration/drone/push Build is passing Details
2024-07-12 10:30:44 +08:00
he 3fa14d92ae 配置文件修改
continuous-integration/drone/push Build is passing Details
2024-07-11 17:29:38 +08:00
he e6c577e68b 阅片时间修改到配置文件
continuous-integration/drone/push Build is passing Details
2024-07-11 17:28:18 +08:00
hang bb111dbbeb 修改发布文件
continuous-integration/drone/push Build is passing Details
2024-07-11 15:26:22 +08:00
hang 0df0b10a72 增加用户机构默认值修改
continuous-integration/drone/push Build is failing Details
2024-07-11 10:14:46 +08:00
hang 0a7ba9f0f5 修改字段名
continuous-integration/drone/push Build is failing Details
2024-07-11 09:42:15 +08:00
hang cd88990c32 spm cpm 返回增加字段 2024-07-11 09:42:03 +08:00
hang d53a1300fc 增加uat irc 自动打包成镜像
continuous-integration/drone/push Build is passing Details
2024-07-10 16:49:59 +08:00
hang 07332ff3e1 修改发送邮件配置 2024-07-09 13:12:59 +08:00
hang 8195a1cf3e 修改发件箱 2024-07-09 09:50:30 +08:00
hang f5e5a47624 修改美国irc uat 数据库名称 2024-07-09 09:40:32 +08:00
hang 28608f3ecb 美国验证增加配置文件 2024-07-08 11:39:30 +08:00
hang bb2da7ca81 修改配置文件 2024-07-05 09:07:57 +08:00
hang 713518a68c 增加美国生产环境配置文件 2024-07-04 14:31:50 +08:00
he bc448da297 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8 2024-07-03 15:15:48 +08:00
he 8447878cb2 代码修改 2024-07-03 15:15:46 +08:00
hang 1b5a9673f6 修改一致性核查颜色 2024-07-02 17:16:46 +08:00
he 27711f4184 关键序列修改 2024-07-02 09:33:42 +08:00
he bb9bac1edf 修改医学审核排序 2024-07-01 16:45:07 +08:00
hang 41ae2febc7 改为阿里云 2024-06-26 15:12:06 +08:00
hang c072c526e2 修改uat 配置文件 2024-06-26 14:36:56 +08:00
hang d6bb98b84f 中心调研修改 2024-06-25 10:57:42 +08:00
hang 42587ee59f 删掉邮件日志组件 2024-06-25 09:17:28 +08:00
hang 62a964a3ea 发送邮件的包降级 2024-06-25 09:01:58 +08:00
hang 72447eb82f 修改 界面控制bug 2024-06-24 16:53:53 +08:00
hang 2f83c27fde 修改筛选条件 2024-06-24 16:39:43 +08:00
hang b219593f61 医生入组,没有spm修改逻辑 2024-06-24 16:39:40 +08:00
31 changed files with 749 additions and 270 deletions

View File

@ -79,7 +79,6 @@
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
<PackageReference Include="Serilog.Sinks.Email" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
</ItemGroup>

View File

@ -54,11 +54,11 @@
},
"applicationUrl": "http://localhost:6100"
},
"IRaCIS.US_IRC": {
"IRaCIS.US_Uat_IRC": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "US_IRC"
"ASPNETCORE_ENVIRONMENT": "US_Uat_IRC"
},
"applicationUrl": "http://localhost:6100"
}

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Email;
//using Serilog.Sinks.Email;
using System;
using System.Net;

View File

@ -42,7 +42,11 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
"Port": 465,

View File

@ -42,9 +42,13 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"AutoLoginOutMinutes": 360,
"OpenLoginMFA": false
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
@ -55,6 +59,8 @@
"FromName": "IRC",
"AuthorizationCode": "ExtImg@2022",
"SiteUrl": "http://irc.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",

View File

@ -62,7 +62,11 @@
"AutoLoginOutMinutes": 1,
"OpenLoginMFA": false
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
@ -74,6 +78,8 @@
"SiteUrl": "http://irc.test.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",

View File

@ -0,0 +1,84 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-prod-mssql-service,1433;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-prod-mssql-service,1433;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=44.210.231.169,1435;Database=US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=44.210.231.169,1435;Database=US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
},
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"AliyunOSS": {
"regionId": "cn-shanghai",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "",
"accessKeySecret": "",
"bucketName": "zy-irc-test-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": {
"endPoint": "44.210.231.169",
"port": "9001",
"useSSL": false,
"accessKey": "e9bT1isTOqSAUxb6wd4n",
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i",
"bucketName": "prod-irc-us",
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/"
},
"AWS": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": true,
"accessKey": "AKIAW3MEAFJX5P32P6NA",
"secretKey": "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",
"bucketName": "ei-med-s3-lili-store",
"viewEndpoint": "https://ei-med-s3-lili-store.s3.amazonaws.com/"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.elevateimaging.ai/login"
}
}

View File

@ -0,0 +1,90 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"AliyunOSS": {
"regionId": "cn-shanghai",
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
"bucketName": "zy-irc-test-store",
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"region": "oss-cn-shanghai"
},
"MinIO": {
//"endPoint": "hir-oss.uat.extimaging.com",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/hir-uat",
"endPoint": "47.117.164.182",
"port": "9001",
"useSSL": false,
"viewEndpoint": "http://47.117.164.182:9001/test-irc-us",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "test-irc-us"
},
"AWS": {
"endPoint": "s3.us-east-1.amazonaws.com",
"useSSL": true,
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
"secretKey": "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",
"bucketName": "ei-irc-test-store",
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
}
},
"BasicSystemConfig": {
"OpenUserComplexPassword": false,
"OpenSignDocumentBeforeWork": false,
"OpenTrialRelationDelete": true,
"OpenLoginLimit": false,
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
}
}

View File

@ -7,8 +7,8 @@
}
},
"ConnectionStrings": {
"RemoteNew": "Server=us-mssql-service,1433;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-service,1433;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
"RemoteNew": "Server=us-mssql-service,1433;Database=US_Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
"Hangfire": "Server=us-mssql-service,1433;Database=US_Uat_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
//"RemoteNew": "Server=44.218.11.19,1435;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
//"Hangfire": "Server=44.218.11.19,1435;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
@ -16,7 +16,7 @@
"ObjectStoreService": {
"ObjectStoreUse": "AWS",
"ObjectStoreUse": "MinIO",
"AliyunOSS": {
"regionId": "cn-shanghai",
@ -30,13 +30,20 @@
},
"MinIO": {
"endPoint": "192.168.3.68",
"port": "8001",
//"endPoint": "hir-oss.us.extimaging.com",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.us.extimaging.com/hir-us",
"endPoint": "44.218.11.19",
"port": "9001",
"useSSL": false,
"accessKey": "IDFkwEpWej0b4DtiuThL",
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
"bucketName": "test",
"viewEndpoint": "http://192.168.3.68:8001/test/"
"viewEndpoint": "http://44.218.11.19:9001/uat-irc-us",
"accessKey": "lH8DkKskLuDqPaiubuSQ",
"secretKey": "pdPdicvvLeH7xAC5yFUrI7odMyBfOXxvVWMvKYV4",
"bucketName": "uat-irc-us"
},
"AWS": {
@ -61,19 +68,27 @@
"LoginMaxFailCount": 5,
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60
"AutoLoginOutMinutes": 60,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
"Port": 465,
"Host": "smtp.qiye.aliyun.com",
"FromEmail": "test@extimaging.com",
"FromName": "Test_IRC",
"AuthorizationCode": "SHzyyl2021",
"CompanyName": "Elevate Imaging",
"Port": 587,
"Host": "smtp-mail.outlook.com",
"FromEmail": "donotreply@elevateimaging.ai",
"FromName": "LiLi",
"AuthorizationCode": "Q#669869497420ul",
"OrganizationName": "Elevate Imaging",
"OrganizationNameCN": "Elevate Imaging",
"CompanyName": "Elevate Imaging Inc.",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Elevate Imaging",
"CompanyShortNameCN": "展影医疗"
"CompanyShortNameCN": "展影医疗",
"SiteUrl": "https://lili.test.elevateimaging.ai/login"
}
}

View File

@ -12,7 +12,7 @@
},
"ObjectStoreService": {
"ObjectStoreUse": "MinIO",
"ObjectStoreUse": "AliyunOSS",
"AliyunOSS": {
"regionId": "cn-shanghai",
@ -27,12 +27,12 @@
"MinIO": {
"endPoint": "hir-oss.uat.extimaging.com",
"port": "80",
"useSSL": false,
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
//"port": "443",
//"useSSL": true,
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
//"port": "80",
//"useSSL": false,
//"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
"port": "443",
"useSSL": true,
"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
"bucketName": "irc-uat"
@ -51,7 +51,11 @@
"LoginFailLockMinutes": 30,
"AutoLoginOutMinutes": 60,
"OpenLoginMFA": false
"OpenLoginMFA": false,
"ContinuousReadingTimeMin": 120,
"ReadingRestTimeMin": 10
},
"SystemEmailSendConfig": {
@ -61,6 +65,8 @@
"FromName": "UAT_IRC",
"AuthorizationCode": "SHzyyl2021",
"SiteUrl": "http://irc.uat.extimaging.com/login",
"OrganizationName": "Extlmaging",
"OrganizationNameCN": "Extlmaging",
"CompanyName": "Extensive Imaging",
"CompanyNameCN": "上海展影医疗科技有限公司",
"CompanyShortName": "Extensive Imaging",

View File

@ -29,7 +29,7 @@ public static class SendEmailHelper
//await smtp.AuthenticateAsync("zhou941003@qq.com", "sqfhlpfdvnexbcab");
await smtp.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.SslOnConnect);
await smtp.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto);
await smtp.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
@ -55,7 +55,7 @@ public static class SendEmailHelper
using (var client = new MailKit.Net.Smtp.SmtpClient())
{
await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.SslOnConnect);
await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto);
await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
@ -133,7 +133,7 @@ public static class SendEmailHelper
smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;
await smtp.ConnectAsync(sMTPEmailConfig.Host, sMTPEmailConfig.Port, SecureSocketOptions.SslOnConnect);
await smtp.ConnectAsync(sMTPEmailConfig.Host, sMTPEmailConfig.Port, SecureSocketOptions.Auto);
await smtp.AuthenticateAsync(sMTPEmailConfig.UserName, sMTPEmailConfig.AuthorizationCode);

View File

@ -78,9 +78,9 @@
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.2" />
<PackageReference Include="fo-dicom.Codecs" Version="5.12.0" />
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="MailKit" Version="4.2.0" />
<PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="MimeKit" Version="4.5.0" />
<PackageReference Include="MimeKit" Version="4.2.0" />
<PackageReference Include="MiniExcel" Version="1.32.0" />
<PackageReference Include="Minio" Version="6.0.2" />
<PackageReference Include="MiniWord" Version="0.8.0" />

View File

@ -13971,6 +13971,13 @@
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.ReadingImageTaskService.ResetReadingTask(IRaCIS.Core.Application.Service.Reading.Dto.ResetReadingTaskInDto)">
<summary>
重置阅片任务
</summary>
<param name="inDto"></param>
<returns></returns>
</member>
<member name="M:IRaCIS.Application.Services.ReadingImageTaskService.VerifyReadingRestTime">
<summary>
验证阅片休息时间

View File

@ -259,7 +259,7 @@ namespace IRaCIS.Core.Application.Service
.ProjectTo<TaskMedicalReviewView>(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(TaskMedicalReviewView.AuditState), nameof(TaskMedicalReviewView.SubjectId), nameof(TaskMedicalReviewView.ArmEnum), nameof(TaskMedicalReviewView.VisitTaskNum) };
var defalutSortArray = new string[] { nameof(TaskMedicalReviewView.SubjectId), nameof(TaskMedicalReviewView.ArmEnum), nameof(TaskMedicalReviewView.VisitTaskNum) };
var pageList = await taskMedicalReviewQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray);
return ResponseOutput.Ok(pageList, new

View File

@ -52,6 +52,19 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
public string ImageResizePath { get; set; }
}
public class StudyInstanceInfo
{
public int ShowOrder { get; set; }
public decimal RowIndex { get; set; }
public Guid? SeriesId { get; set; }
public Guid? StudyId { get; set; }
public Guid? InstanceId { get; set; }
}
public class InstanceBasicInfo
{
public Guid Id { get; set; }

View File

@ -11,6 +11,7 @@ using MassTransit;
using MathNet.Numerics;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
@ -18,12 +19,13 @@ using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
public interface IDownloadAndUploadService
{
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true);
Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true);
}
[ApiExplorerSettings(GroupName = "Trial")]
public class DownloadAndUploadService : BaseService, IDownloadAndUploadService
@ -107,8 +109,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
await SubejctRandomReadingTaskNameDeal(subjectId, trialReadingCriterionId);
var query = _repository.Where<VisitTask>(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.SourceSubjectVisitId != null
&& t.DoctorUserId == _userInfo.Id && t.TaskState==TaskState.Effect)
var query = _repository.Where<VisitTask>(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.SourceSubjectVisitId != null
&& t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect)
.Select(u => new SubjectImageUploadDTO()
{
VisitTaskId = u.Id,
@ -129,7 +131,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
PackState = u.SourceSubjectVisit.PackState,
OrginalStudyList = u.SourceSubjectVisit.StudyList
.Where(t => u.TrialReadingCriterion.IsImageFilter ?("|"+u.TrialReadingCriterion.CriterionModalitys+"|").Contains("|"+t.ModalityForEdit+"|" ) : true)
.Where(t => u.TrialReadingCriterion.IsImageFilter ? ("|" + u.TrialReadingCriterion.CriterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
.Select(t => new StudyBasicInfo()
{
Id = t.Id,
@ -484,24 +486,51 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// </summary>
/// <param name="trialId"></param>
/// <param name="subjectVisitId"></param>
/// <param name="isDicom"></param>
/// <param name="isAnonymize"></param>
/// <returns></returns>
public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
public async Task<IResponseOutput> RequestPackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
{
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
if (subjectVisit.PackState == PackState.WaitPack)
var extralConfig = _repository.Where<Trial>(t => t.Id == trialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(extralConfig) ?? new TrialExtraConfig();
if (config.IsSupportQCDownloadImage == false)
{
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, isAnonymize), TimeSpan.FromSeconds(1));
subjectVisit.PackState = PackState.Packing;
await _subjectVisitRepository.SaveChangesAsync();
throw new BusinessValidationFailedException("该项目不支持QC下载影像");
}
return ResponseOutput.Ok(subjectVisit.VisitImageZipPath);
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
var sujectCode = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.Subject.Code).FirstOrDefaultAsync();
var packState = isDicom ? subjectVisit.PackState : subjectVisit.NoDicomPackState;
if (packState == PackState.WaitPack)
{
if (isDicom)
{
subjectVisit.PackState = PackState.Packing;
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, true, isAnonymize), TimeSpan.FromSeconds(1));
}
else
{
subjectVisit.NoDicomPackState = PackState.Packing;
HangfireJobHelper.NotImmediatelyOnceOnlyJob<IDownloadAndUploadService>(t => t.PackageAndAnonymizImage(trialId, subjectVisitId, false, isAnonymize), TimeSpan.FromSeconds(1));
}
await _subjectVisitRepository.SaveChangesAsync();
}
return ResponseOutput.Ok(isDicom ? subjectVisit.VisitImageZipPath : subjectVisit.VisitNoDicomImageZipPath,
new { FileName = $"{sujectCode}_{subjectVisit.VisitName}_ImageStudy_{(isDicom ? "Dicom" : "NoneDicom")}.zip" });
}
@ -511,9 +540,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// </summary>
/// <param name="trialId"></param>
/// <param name="subjectVisitId"></param>
/// <param name="isDicom"></param>
/// <param name="isAnonymize"></param>
/// <returns></returns>
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isAnonymize = true)
public async Task PackageAndAnonymizImage(Guid trialId, Guid subjectVisitId, bool isDicom, bool isAnonymize = true)
{
var subjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
@ -557,6 +587,20 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
})
})
}),
NoneDicomStudyList = sv.NoneDicomStudyList.Select(nd => new
{
nd.Modality,
nd.StudyCode,
nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new
{
file.FileName,
file.Path,
file.FileType
})
})
};
@ -568,107 +612,146 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
string tempFolderPath = Path.Combine(Directory.GetCurrentDirectory(), $"DownloadTemp_{NewId.NextGuid()}");
Directory.CreateDirectory(tempFolderPath);
// 遍历查询结果
foreach (var studyInfo in info.StudyList)
//dicom 处理
if (isDicom)
{
// 遍历 Series
foreach (var seriesInfo in studyInfo.SeriesList)
// 遍历查询结果
foreach (var studyInfo in info.StudyList)
{
string studyFolderPath = Path.Combine(tempFolderPath, $"{info.SubjectCode}_{info.VisitName}", $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
// 创建 影像 文件夹
Directory.CreateDirectory(studyFolderPath);
// 遍历 InstancePathList
foreach (var instanceInfo in seriesInfo.InstancePathList)
// 遍历 Series
foreach (var seriesInfo in studyInfo.SeriesList)
{
// 复制文件到相应的文件夹
string destinationPath = Path.Combine(studyFolderPath, Path.GetFileName(instanceInfo.Path));
string studyDicomFolderPath = Path.Combine(tempFolderPath, "Dicom",/* $"{info.SubjectCode}_{info.VisitName}",*/ $"{studyInfo.StudyCode}_{studyInfo.StudyTime?.ToString("yyyy-MM-dd")}_{seriesInfo.Modality}");
//下载到当前目录
await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
// 创建 影像 文件夹
Directory.CreateDirectory(studyDicomFolderPath);
#region 匿名化逻辑
if (isAnonymize)
// 遍历 InstancePathList
foreach (var instanceInfo in seriesInfo.InstancePathList)
{
//受试者随机阅片,需要匿名化检查时间
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
DicomDataset dataset = dicomFile.Dataset;
dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
// 复制文件到相应的文件夹
string destinationPath = Path.Combine(studyDicomFolderPath, Path.GetFileName(instanceInfo.Path));
#region 前端已经匿名化不需要做相关tag匿名化
//DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
//下载到当前目录
await _oSSService.DownLoadFromOSSAsync(instanceInfo.Path, destinationPath);
//DicomDataset dataset = dicomFile.Dataset;
#region 匿名化逻辑
//foreach (var item in addOrUpdateFixedFieldList)
//{
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
if (isAnonymize)
{
//受试者随机阅片,需要匿名化检查时间
DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
DicomDataset dataset = dicomFile.Dataset;
dataset.AddOrUpdate(DicomTag.StudyDate, string.Empty);
dataset.AddOrUpdate(DicomTag.StudyTime, string.Empty);
// dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
//}
#region 前端已经匿名化不需要做相关tag匿名化
//DicomFile dicomFile = await DicomFile.OpenAsync(destinationPath, Encoding.Default);
//foreach (var item in ircFieldList)
//{
//DicomDataset dataset = dicomFile.Dataset;
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
//foreach (var item in addOrUpdateFixedFieldList)
//{
// if (dicomTag == DicomTag.ClinicalTrialProtocolID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
// }
// if (dicomTag == DicomTag.ClinicalTrialSiteID)
// {
// //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
// dataset.AddOrUpdate(dicomTag, item.ReplaceValue);
//}
// }
// if (dicomTag == DicomTag.ClinicalTrialSubjectID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
//foreach (var item in ircFieldList)
//{
// }
// if (dicomTag == DicomTag.ClinicalTrialTimePointID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
// var dicomTag = new DicomTag(Convert.ToUInt16(item.Group, 16), Convert.ToUInt16(item.Element, 16));
// }
// if (dicomTag == DicomTag.PatientID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
// if (dicomTag == DicomTag.ClinicalTrialProtocolID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode);
// }
// }
// if (dicomTag == DicomTag.ClinicalTrialSiteID)
// {
// //dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialSiteCode);
//}
// }
// if (dicomTag == DicomTag.ClinicalTrialSubjectID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.SubjectCode);
// }
// if (dicomTag == DicomTag.ClinicalTrialTimePointID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.VisitNum.ToString());
// }
// if (dicomTag == DicomTag.PatientID)
// {
// dataset.AddOrUpdate(dicomTag, subjectAndVisitInfo.TrialCode + "_" + subjectAndVisitInfo.SubjectCode);
// }
//}
#endregion
}
#endregion
}
#endregion
}
}
var zipDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_Dicom.zip");
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "Dicom"), zipDicomPath);
//上传到Oss
var relativeDicomPath = await _oSSService.UploadToOSSAsync(zipDicomPath, $"download_zip", false);
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativeDicomPath });
File.Delete(zipDicomPath);
}
else
{
var relativeNoneDicomPath = string.Empty;
var zipPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy.zip");
if (info.NoneDicomStudyList.Count() == 1 && info.NoneDicomStudyList.SelectMany(t => t.FileList).Count() == 1)
{
relativeNoneDicomPath = info.NoneDicomStudyList.First().FileList.First().Path;
}
else
{
//非dicom 处理
ZipFile.CreateFromDirectory(tempFolderPath, zipPath);
foreach (var noneDicomStudy in info.NoneDicomStudyList)
{
string studyNoneDicomFolderPath = Path.Combine(tempFolderPath, "NoneDicom", /*$"{info.SubjectCode}_{info.VisitName}",*/ $"{noneDicomStudy.StudyCode}_{noneDicomStudy.ImageDate.ToString("yyyy-MM-dd")}_{noneDicomStudy.Modality}");
//上传到Oss
var relativePath = await _oSSService.UploadToOSSAsync(zipPath, $"download_zip", false);
Directory.CreateDirectory(studyNoneDicomFolderPath);
foreach (var file in noneDicomStudy.FileList)
{
string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName));
//下载到当前目录
await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path) , destinationPath);
}
}
var zipNoneDicomPath = Path.Combine(Directory.GetCurrentDirectory(), $"{info.SubjectCode}_{info.VisitName}_ImageStudy_NoneDicom.zip");
ZipFile.CreateFromDirectory(Path.Combine(tempFolderPath, "NoneDicom"), zipNoneDicomPath);
relativeNoneDicomPath = await _oSSService.UploadToOSSAsync(zipNoneDicomPath, $"download_zip", false);
File.Delete(zipNoneDicomPath);
}
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitNoDicomImageZipPath = relativeNoneDicomPath });
//subjectVisit.PackState = PackState.Packed;
//subjectVisit.VisitImageZipPath = relativePath;
//await _subjectVisitRepository.SaveChangesAsync();
await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { PackState = PackState.Packed, VisitImageZipPath = relativePath });
}
//清理文件夹
Directory.Delete(tempFolderPath, true);
File.Delete(zipPath);
}
}

View File

@ -36,7 +36,7 @@ namespace IRaCIS.Application.Services
private readonly IEasyCachingProvider _cache;
private readonly IReadingImageTaskService _readingImageTaskService;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
private readonly SystemEmailSendConfig _systemEmailConfig;
public UserService(IRepository<User> userRepository,
@ -47,6 +47,7 @@ namespace IRaCIS.Application.Services
IReadingImageTaskService readingImageTaskService,
IRepository<TrialUser> userTrialRepository,
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig,
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
IRepository<UserLog> userLogRepository,
IRepository<UserPassWordLog> userPassWordLogRepository
,
@ -64,6 +65,8 @@ namespace IRaCIS.Application.Services
_userTrialRepository = userTrialRepository;
_userLogRepository = userLogRepository;
_distributedLockProvider = distributedLockProvider;
_systemEmailConfig = systemEmailConfig.CurrentValue;
}
@ -589,7 +592,7 @@ namespace IRaCIS.Application.Services
if (user.IsZhiZhun)
{
user.OrganizationName = AppSettings.DefaultInternalOrganizationName;
user.OrganizationName = _userInfo.IsEn_Us? _systemEmailConfig.OrganizationName: _systemEmailConfig.OrganizationNameCN ;
}
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.Id, OptUserId = model.Id, OptType = UserOptType.UpdateUser }, true);

View File

@ -1696,6 +1696,20 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
}
public class ResetReadingTaskOutDto
{
}
public class ResetReadingTaskInDto
{
public Guid VisitTaskId { get; set; }
}
public class SetSkipReadingCacheInDto
{
public Guid VisitTaskId { get; set; }
}
public class GetNextTaskInDto
{

View File

@ -37,7 +37,7 @@ namespace IRaCIS.Core.Application.Contracts
Task<List<GetManualListOutDto>> GetManualList(GetManualListInDto inDto);
Task ResetReadingRestTime(Guid? userId);
Task<bool> ResetReadingRestTime(Guid? userId);
Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto);

View File

@ -21,6 +21,9 @@ using IRaCIS.Core.Application.Service.ReadingCalculate.Interface;
using AutoMapper.QueryableExtensions;
using IRaCIS.Application.Contracts;
using IRaCIS.Core.Domain.Models;
using Microsoft.Extensions.Options;
using System.Linq;
using NPOI.SS.Formula.Functions;
namespace IRaCIS.Application.Services
{
@ -42,6 +45,7 @@ namespace IRaCIS.Application.Services
private readonly IReadingCalculateService _readingCalculateService;
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IRepository<Subject> _subjectRepository;
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
private readonly IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository;
private readonly IRepository<ReadingCriterionPage> _readingCriterionPageRepository;
private readonly IRepository<ReadingTaskRelation> _readingTaskRelationRepository;
@ -84,6 +88,7 @@ namespace IRaCIS.Application.Services
IReadingCalculateService readingCalculateService,
IRepository<SubjectVisit> subjectVisitRepository,
IRepository<Subject> subjectRepository,
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig,
IRepository<ReadingGlobalTaskInfo> readingGlobalTaskInfoRepository,
IRepository<ReadingCriterionPage> readingCriterionPageRepository,
IRepository<ReadingTaskRelation> readingTaskRelationRepository,
@ -125,6 +130,7 @@ namespace IRaCIS.Application.Services
this._readingCalculateService = readingCalculateService;
this._subjectVisitRepository = subjectVisitRepository;
this._subjectRepository = subjectRepository;
this._verifyConfig = verifyConfig;
this._readingGlobalTaskInfoRepository = readingGlobalTaskInfoRepository;
this._readingCriterionPageRepository = readingCriterionPageRepository;
this._readingTaskRelationRepository = readingTaskRelationRepository;
@ -2696,7 +2702,43 @@ namespace IRaCIS.Application.Services
return ResponseOutput.Ok(true);
}
/// <summary>
/// 清除跳过阅片的缓存
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<bool> ClearSkipReadingCache()
{
var clearSkipReadingCacheKey = _userInfo.Id.ToString() + "SkipReadingCache";
_provider.Remove(clearSkipReadingCacheKey);
return true;
}
/// <summary>
/// 设置跳过阅片的缓存
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<bool> SetSkipReadingCache(SetSkipReadingCacheInDto inDto )
{
var clearSkipReadingCacheKey = _userInfo.Id.ToString() + "SkipReadingCache";
var clearSkipReadingCache = _provider.Get<string>(clearSkipReadingCacheKey).Value;
if (clearSkipReadingCache == null|| clearSkipReadingCache==string.Empty)
{
List<Guid> cacheIds = new List<Guid>();
cacheIds.Add(inDto.VisitTaskId);
_provider.Set(clearSkipReadingCacheKey, JsonConvert.SerializeObject(cacheIds), TimeSpan.FromHours(24));
}
else
{
List<Guid>? cacheIds=JsonConvert.DeserializeObject<List<Guid>>(clearSkipReadingCache);
cacheIds.Add(inDto.VisitTaskId);
_provider.Set(clearSkipReadingCacheKey, JsonConvert.SerializeObject(cacheIds), TimeSpan.FromHours(24));
}
return true;
}
/// <summary>
@ -2724,6 +2766,19 @@ namespace IRaCIS.Application.Services
var trialReadingCriterion = await _readingQuestionCriterionTrialRepository.FindAsync(trialReadingCriterionId ?? Guid.Empty);
#region 跳过阅片
var clearSkipReadingCacheKey = _userInfo.Id.ToString() + "SkipReadingCache";
var clearSkipReadingCache = _provider.Get<string>(clearSkipReadingCacheKey).Value;
List<Guid> cacheSkipIds = new List<Guid>();
if (clearSkipReadingCache != null && clearSkipReadingCache != string.Empty)
{
cacheSkipIds = JsonConvert.DeserializeObject<List<Guid>>(clearSkipReadingCache);
}
#endregion
if (inDto.VisitTaskId != null)
{
task = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new GetReadingTaskDto()
@ -2742,6 +2797,7 @@ namespace IRaCIS.Application.Services
trialReadingCriterionId = task.TrialReadingCriterionId;
}
// 有序
else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
@ -2762,14 +2818,20 @@ namespace IRaCIS.Application.Services
var subjectIndex = subjectTaskList.Where(x => x.SubjectId == inDto.SubjectId && x.SubjectCode == inDto.SubjectCode).Select(x => x.Index).FirstOrDefault();
var currentSubject = subjectTaskList.Where(x => x.Index >= subjectIndex && !x.ExistReadingApply).OrderBy(x => x.Index).FirstOrDefault();
var currentSubject = subjectTaskList.Where(x => x.Index >= subjectIndex && !x.ExistReadingApply)
// 排除跳过的
.Where(x=> x.UnReadCanReadTaskList.Select(y => y.Id).Intersect(cacheSkipIds).Count()==0)
.OrderBy(x => x.Index).FirstOrDefault();
if (currentSubject == null)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
task = currentSubject.UnReadCanReadTaskList.Select(x => new GetReadingTaskDto()
task = currentSubject.UnReadCanReadTaskList
.Select(x => new GetReadingTaskDto()
{
ReadingCategory = x.ReadingCategory,
SubjectCode = currentSubject.SubjectCode,
@ -2785,8 +2847,12 @@ namespace IRaCIS.Application.Services
}
// 受试者无序
else if (inDto.SubjectId != null && trialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom)
{
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
@ -2798,12 +2864,25 @@ namespace IRaCIS.Application.Services
})).CurrentPageData;
if (subjectTaskList.Count() == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
var taskList = subjectTaskList.FirstOrDefault()!.UnReadCanReadTaskList;
// 排除跳过的
List<Guid> remainingItems = taskList.Select(x => x.Id).Except(cacheSkipIds).ToList();
taskList = taskList.Where(x => remainingItems.Contains(x.Id)).ToList();
if (taskList.Count() == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
Random random = new Random();
//返回的范围是 0- taskList.Count-1
@ -2825,11 +2904,14 @@ namespace IRaCIS.Application.Services
}).FirstOrDefaultAsync();
}
// 完全随机
else
{
var query = _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.TrialReadingCriterionId == trialReadingCriterionId && x.ReadingTaskState != ReadingTaskState.HaveSigned && x.DoctorUserId == _userInfo.Id
&& x.TrialReadingCriterionId == trialReadingCriterionId
&& x.TaskState == TaskState.Effect);
&& x.TaskState == TaskState.Effect)
// 排除跳过的
.Where(x => !cacheSkipIds.Contains(x.Id));
var count = await query.CountAsync();
if (count == 0)
{
@ -2947,23 +3029,42 @@ namespace IRaCIS.Application.Services
return task;
}
/// <summary>
/// 重置阅片任务
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<ResetReadingTaskOutDto> ResetReadingTask(ResetReadingTaskInDto inDto)
{
await VerifyTaskIsSign(inDto.VisitTaskId);
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
if (taskinfo.ReadingCategory != ReadingCategory.Visit)
{
}
return new ResetReadingTaskOutDto() { };
}
/// <summary>
/// 验证阅片休息时间
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task VerifyReadingRestTime()
public async Task<bool> VerifyReadingRestTime()
{
var userTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt;
var userTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt;
if (userTypeEnum != UserTypeEnum.IndependentReviewer)
{
return;
return true;
}
var startReadingTimeKey = _userInfo.Id.ToString() + "StartReadingTime";
var startRestTimeKey = _userInfo.Id.ToString() + "StartRestTime";
int readingMinute = 120; // 为60整数
int restMinute = 10; //
int readingMinute = _verifyConfig.CurrentValue.ContinuousReadingTimeMin; // 为60整数
int restMinute = _verifyConfig.CurrentValue.ReadingRestTimeMin; //
var startReadingTime = _provider.Get<string>(startReadingTimeKey).Value;
var startRestTime = _provider.Get<string>(startRestTimeKey).Value;
if (startReadingTime == null && startRestTime == null)
@ -2976,7 +3077,7 @@ namespace IRaCIS.Application.Services
int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes;
if (timespanMin <= restMinute)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", readingMinute / 60m, restMinute]);
throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", 2, 10]);
}
else
{
@ -3002,6 +3103,8 @@ namespace IRaCIS.Application.Services
#endregion
}
return true;
}
/// <summary>
@ -3009,7 +3112,7 @@ namespace IRaCIS.Application.Services
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task ResetReadingRestTime(Guid? userID)
public async Task<bool> ResetReadingRestTime(Guid? userID)
{
if (userID == null)
{
@ -3036,6 +3139,7 @@ namespace IRaCIS.Application.Services
{
_provider.Set(startReadingTimeKey, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
}
return true;
}
/// <summary>

View File

@ -72,7 +72,7 @@ namespace IRaCIS.Core.Application.Contracts
public List<TrialSiteUserSurveyView> TrialSiteUserSurveyList { get; set; } = new List<TrialSiteUserSurveyView>();
public SiteSurveyFiledConfig SiteSurveyFiledConfig { get; set; }
public TrialExtraConfig SiteSurveyFiledConfig { get; set; }
}
public class TrialSiteUserSurveyAllDTO : TrialSiteUserSurveyView

View File

@ -391,9 +391,9 @@ namespace IRaCIS.Core.Application.Contracts
var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters()
.ProjectTo<LoginReturnDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException();
var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).Select(t => t.Trial.SiteSurveyConfigJsonStr).FirstOrDefault()??string.Empty;
var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).Select(t => t.Trial.TrialExtraConfigJsonStr).FirstOrDefault()??string.Empty;
result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<SiteSurveyFiledConfig>(siteSurveryConfig) ?? new SiteSurveyFiledConfig();
result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
return result;
}
@ -726,15 +726,15 @@ namespace IRaCIS.Core.Application.Contracts
t.Email,
}).ToListAsync();
var currentUserList = siteUserList.Where(t => t.TrialSiteSurveyId == trialSiteSurveyId).ToList();
//var currentUserList = siteUserList.Where(t => t.TrialSiteSurveyId == trialSiteSurveyId).ToList();
if (!currentUserList.Any(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator))
if (!siteUserList.Any(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA))
{
throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_MissingAccount"]);
}
if (currentUserList.Where(t => t.IsGenerateAccount && t.UserTypeId != null).GroupBy(t => new { t.UserTypeId, t.Email })
if (siteUserList.Where(t => t.IsGenerateAccount && t.UserTypeId != null).GroupBy(t => new { t.UserTypeId, t.Email })
.Any(g => g.Count() > 1))
{
throw new BusinessValidationFailedException(_localizer["TrialSiteSurvey_DuplicateEmail"]);

View File

@ -21,6 +21,7 @@ using DocumentFormat.OpenXml.Office.CustomUI;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Application.Contracts;
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
using Newtonsoft.Json;
namespace IRaCIS.Core.Application
{
@ -604,7 +605,7 @@ namespace IRaCIS.Core.Application
await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{
IsImageFilter=inDto.IsImageFilter,
IsImageFilter = inDto.IsImageFilter,
ImageDownloadEnum = inDto.ImageDownloadEnum,
ImageUploadEnum = inDto.ImageUploadEnum,
CriterionModalitys = inDto.CriterionModalitys,
@ -954,7 +955,7 @@ namespace IRaCIS.Core.Application
trialInfo.UpdateTime = DateTime.Now;
//await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialConfig.TrialId && t.IsSigned == false, u => new ReadingQuestionCriterionTrial() { CriterionModalitys = trialConfig.Modalitys });
//await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialConfig.TrialId && t.IsSigned == false, u => new ReadingQuestionCriterionTrial() { CriterionModalitys = trialConfig.Modalitys });
return ResponseOutput.Ok(await _repository.SaveChangesAsync());
}
@ -1354,5 +1355,13 @@ namespace IRaCIS.Core.Application
return ResponseOutput.Ok(cro.Id.ToString(), ApiResponseCodeEnum.NeedTips);
}
[AllowAnonymous]
public async Task<TrialExtraConfig> GetTrialExtralConfig(Guid trialId)
{
var extralConfig = _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
return JsonConvert.DeserializeObject<TrialExtraConfig>(extralConfig) ?? new TrialExtraConfig();
}
}
}

View File

@ -32,6 +32,7 @@ namespace IRaCIS.Core.Application.Services
private readonly IRepository<DicomInstance> _dicomInstanceRepository;
private readonly IRepository<VisitTask> _visitTaskRepository;
private readonly IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository;
private readonly IRepository<ReadingCustomTag> _readingCustomTagRepository;
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository;
private readonly IRepository<ReadingPeriodPlan> _readingPeriodPlanRepository;
private readonly IRepository<Subject> _subjectRepository;
@ -50,6 +51,7 @@ namespace IRaCIS.Core.Application.Services
IRepository<DicomInstance> dicomInstanceRepository,
IRepository<VisitTask> visitTaskRepository,
IRepository<ReadingTableAnswerRowInfo> readingTableAnswerRowInfoRepository,
IRepository<ReadingCustomTag> readingCustomTagRepository,
IRepository<NoneDicomStudyFile> noneDicomStudyFileRepository,
IRepository<ReadingPeriodPlan> readingPeriodPlanRepository,
IRepository<Subject> subjectRepository,
@ -70,6 +72,7 @@ namespace IRaCIS.Core.Application.Services
this._dicomInstanceRepository = dicomInstanceRepository;
this._visitTaskRepository = visitTaskRepository;
this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository;
this._readingCustomTagRepository = readingCustomTagRepository;
this._noneDicomStudyFileRepository = noneDicomStudyFileRepository;
this._readingPeriodPlanRepository = readingPeriodPlanRepository;
_subjectRepository = subjectRepository;
@ -574,15 +577,28 @@ namespace IRaCIS.Core.Application.Services
//已经签名的任务,加关键序列
if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
{
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == indto.VisitTaskId && x.StudyId != null).OrderBy(x => x.ReadingQuestionTrial.ShowOrder).ThenBy(x => x.RowIndex).Select(x => new
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == indto.VisitTaskId && x.StudyId != null).OrderBy(x => x.ReadingQuestionTrial.ShowOrder).ThenBy(x => x.RowIndex).Select(x => new StudyInstanceInfo()
{
x.ReadingQuestionTrial.ShowOrder,
x.RowIndex,
x.SeriesId,
x.StudyId,
x.InstanceId,
ShowOrder = x.ReadingQuestionTrial.ShowOrder,
RowIndex = x.RowIndex,
SeriesId = x.SeriesId,
StudyId = x.StudyId,
InstanceId = x.InstanceId,
}).ToListAsync();
var customoList = await _readingCustomTagRepository.Where(x => x.VisitTaskId == indto.VisitTaskId && x.StudyId != null).Select(x => new StudyInstanceInfo()
{
ShowOrder = 0,
RowIndex = 0m,
SeriesId = x.SeriesId,
StudyId = x.StudyId,
InstanceId = x.InstanceId,
}).ToListAsync();
rowInfoList.AddRange(customoList);
var thisStudyIds = rowInfoList.OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(x => x.StudyId).Distinct().ToList();
var thisSeriesIdIds = rowInfoList.Where(x => x.SeriesId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(x => x.SeriesId).Distinct().ToList();
if (rowInfoList.Count > 0)
@ -649,7 +665,7 @@ namespace IRaCIS.Core.Application.Services
studyList.Add(thisVisitTaskStudy);
studyList.Insert(0,thisVisitTaskStudy);
}

View File

@ -194,13 +194,14 @@ namespace IRaCIS.Application.Services
var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
var hasSPMOrCPM = await _repository.Where<TrialUser>(t => t.TrialId == trialId).AnyAsync(t=> t.User.UserTypeEnum == UserTypeEnum.SPM || t.User.UserTypeEnum == UserTypeEnum.CPM);
if (trial != null)
{
if (commitState == 1) //确认提交CRO
{
//更新项目状态
trial.TrialEnrollStatus = (int)TrialEnrollStatus.HasCommitCRO;
trial.TrialEnrollStatus = hasSPMOrCPM ? (int)TrialEnrollStatus.HasCommitCRO : (int)TrialEnrollStatus.HasConfirmedDoctorNames;
//添加项目详细记录
var trialDetail = new TrialStatusDetail()
@ -217,17 +218,30 @@ namespace IRaCIS.Application.Services
{
if (doctorIdArray.Contains(intoGroupItem.DoctorId))
{
intoGroupItem.EnrollStatus = EnrollStatus.HasCommittedToCRO;
//_enrollRepository.Update(intoGroupItem);
intoGroupItem.EnrollStatus = hasSPMOrCPM ? EnrollStatus.HasCommittedToCRO : EnrollStatus.InviteIntoGroup;
await _enrollDetailRepository.AddAsync(new EnrollDetail()
{
TrialDetailId = trialDetail.Id,
DoctorId = intoGroupItem.DoctorId,
TrialId = trialId,
EnrollStatus = EnrollStatus.HasCommittedToCRO,
EnrollStatus = hasSPMOrCPM ? EnrollStatus.HasCommittedToCRO : EnrollStatus.InviteIntoGroup,
OptUserType = (int)SystemUserType.AdminUser, //后台用户
});
if (!hasSPMOrCPM)
{
await _enrollDetailRepository.AddAsync(new EnrollDetail()
{
TrialDetailId = trialDetail.Id,
DoctorId = intoGroupItem.DoctorId,
TrialId = trialId,
EnrollStatus = EnrollStatus.HasCommittedToCRO,
OptUserType = (int)SystemUserType.AdminUser, //后台用户
});
}
}
}
@ -257,7 +271,7 @@ namespace IRaCIS.Application.Services
}
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync());
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync(), new {IsHaveSPMOrCPM=hasSPMOrCPM});
}
//$"Cannot find trial {trialId}"
return ResponseOutput.NotOk(_localizer["Enroll_NotFound", trialId]);

View File

@ -213,7 +213,7 @@ namespace IRaCIS.Core.Application.MediatR.Handlers
else
{
//"Problems are as follows:
dialogMsg.AppendLine($"<br/><div style='color: yellow'>{_localizer["ConsistencyVerification_Prob"]}</div>");
dialogMsg.AppendLine($"<br/><div style='color: red'>{_localizer["ConsistencyVerification_Prob"]}</div>");
num = 0;
foreach (var item in dbExceptExcel)

View File

@ -41,11 +41,26 @@ namespace IRaCIS.Core.Domain.Share
}
public class SiteSurveyFiledConfig
public class TrialExtraConfig
{
public List<string> NotShowFieldList { get; set; }=new List<string>();
#region MyRegion
//QC质控
public bool IsSupportQCDownloadImage { get; set; } = false;
#endregion
#region 中心调研
public List<string> NotShowFieldList { get; set; } = new List<string>();
public List<SiteSurveyModifyFiled> ModifyFiledList { get; set; } = new List<SiteSurveyModifyFiled>();
#endregion
public List<SiteSurveyModifyFiled> ModifyFiledList { get; set; }=new List<SiteSurveyModifyFiled>();
}

View File

@ -182,9 +182,8 @@ namespace IRaCIS.Core.Domain.Models
//public List<SiteSurveyFiledConfig>
public string SiteSurveyConfigJsonStr { get; set; } = string.Empty;
public string TrialExtraConfigJsonStr { get; set; } = string.Empty;
public bool VisitPlanConfirmed { get; set; }

View File

@ -248,6 +248,10 @@ namespace IRaCIS.Core.Domain.Models
public string VisitImageZipPath { get; set; } = string.Empty;
public PackState PackState { get; set; }
public PackState NoDicomPackState { get; set; }
public string VisitNoDicomImageZipPath { get; set;} = string.Empty;
}
/// <summary>
/// 影像下载打包状态

View File

@ -24,6 +24,17 @@ namespace IRaCIS.Core.Domain.Share
public int AutoLoginOutMinutes { get; set; }
public bool OpenLoginMFA { get; set; }
/// <summary>
/// 连续阅片时间 (min)
/// </summary>
public int ContinuousReadingTimeMin { get; set; }
/// <summary>
/// 休息时间 (min)
/// </summary>
public int ReadingRestTimeMin { get; set; }
}
public class SystemEmailSendConfig
@ -41,6 +52,9 @@ namespace IRaCIS.Core.Domain.Share
public string SiteUrl { get; set; }
public string OrganizationName { get; set; }
public string OrganizationNameCN { get; set; }
public string CompanyName { get; set; }
public string CompanyNameCN { get; set; }

View File

@ -1,83 +1,31 @@
---
kind: pipeline
type: docker
name: irc-netcore-api
type: ssh
name: ssh-linux-uat-irc-build-image
platform:
os: Linux
arch: 386
clone:
disable: true
server:
host: 47.117.164.182
user: root
password:
from_secret: test_ssh_pwd
steps:
- name: clone-repo
image: alpine/git
pull: if-not-exists
volumes:
- name: irc-test-work
path: /work
- name: build-uat-irc
commands:
- if [ ! -e /work/netcore-repo/.git ]; then
git clone -b Test.IRC http://192.168.3.68:2000/XCKJ/irc-netcore-api.git /work/netcore-repo;
else
cd /work/netcore-repo;
git pull;
fi
- |
if [ ! -e Dockerfile ]; then
echo 'FROM mcr.microsoft.com/dotnet/aspnet:6.0
EXPOSE 80
WORKDIR /app
COPY publish .
ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]' > /work/Dockerfile
fi
- name: restore-publish
image: mcr.microsoft.com/dotnet/sdk:6.0
pull: if-not-exists
depends_on:
- clone-repo
volumes:
- name: nuget-packages
path: /root/.nuget/packages
- name: irc-test-work
path: /work
commands:
- cd /work/netcore-repo/IRaCIS.Core.API
- dotnet restore ./IRaCIS.Core.API.csproj
- rm -rf /work/publish
- cd /work/netcore-repo/IRaCIS.Core.API
- dotnet publish ./IRaCIS.Core.API.csproj -c Release --no-restore -o /work/publish
- name: docker-build
image: docker
pull: if-not-exists
depends_on:
- restore-publish
commands:
- cd /work
- docker build -t test-irc:v${DRONE_BUILD_NUMBER} .
volumes:
- name: irc-test-work
path: /work
- name: dockersock
path: /var/run/docker.sock
volumes:
- name: nuget-packages
host:
path: /opt/cicd/nuget/packages
- name: irc-test-work
host:
path: /opt/cicd/irc-test
- name: dockersock
host:
path: /var/run/docker.sock
- cd /opt/1panel/xc-deploy/Uat_IRC/devops-build-publish/Uat-To-Uat
- sh uat-branch-latest-build-image-publish.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- master
- Uat_IRC_Net8
---
kind: pipeline
type: ssh
name: ssh-linux-test-irc-publish
@ -98,45 +46,13 @@ server:
steps:
- name: publish-test-irc
commands:
- echo start publish test-irc-api
- cd /opt/1panel/hang/devops/test-irc
- sh test-irc.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_IRC/devops-build-publish;sh test-irc-update-or-create-stack.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test_IRC_Net8
---
kind: pipeline
type: ssh
name: test-irc-publish-image-push-aliyun
platform:
os: Linux
arch: 386
clone:
disable: true
server:
host: 192.168.3.68
user: root
password:
from_secret: local_pwd
steps:
- name: build-and-push-image
commands:
- cd /opt/hang/netcore/irc-test
- sh test-irc.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- master
---
kind: pipeline
type: ssh
name: ssh-linux-test-study-publish
@ -146,10 +62,10 @@ platform:
arch: 386
clone:
disable: true
disable: true #禁用默认克隆
server:
host: 123.56.94.154
host: 106.14.89.110
user: root
password:
from_secret: test_ssh_pwd
@ -157,10 +73,68 @@ server:
steps:
- name: publish-test-study
commands:
- echo start publish test-study-api
- cd /opt/1panel/hang/devops/test-study
- cd /opt/1panel/xc-deploy/Test_Study/devops-build-publish
- sh test-study.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test.Study
- Test.Study
---
kind: pipeline
type: ssh
name: ssh-linux-test-scp-publish
platform:
os: Linux
arch: 386
clone:
disable: true #禁用默认克隆
server:
host: 106.14.89.110
user: root
password:
from_secret: test_ssh_pwd
steps:
- name: publish-test-hir-scp
commands:
- cd /opt/1panel/xc-deploy/Test_HIR_SCP/devops-build-publish;sh pull-build-test-hir-scp-image.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_HIR_SCP ;sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test_HIR
---
kind: pipeline
type: ssh
name: ssh-linux-test-hir-publish
platform:
os: Linux
arch: 386
clone:
disable: true #禁用默认克隆
server:
host: 106.14.89.110
user: root
password:
from_secret: test_ssh_pwd
steps:
- name: publish-test-hir
commands:
- cd /opt/1panel/xc-deploy/Test_HIR/devops-build-publish;sh pull-build-test-hir-image.sh v${DRONE_BUILD_NUMBER}
- cd /opt/1panel/xc-deploy/Test_HIR ; sh update-image-if-need-then-pull-aliyun.sh v${DRONE_BUILD_NUMBER}
trigger:
branch:
- Test_HIR