Compare commits
455 Commits
Temp_Uat_I
...
Test_IRC_N
| Author | SHA1 | Date |
|---|---|---|
|
|
64ea537dae | |
|
|
990cf0ec41 | |
|
|
9cdd70f491 | |
|
|
a8623ade44 | |
|
|
c0e19eaab4 | |
|
|
43241709af | |
|
|
292263a60c | |
|
|
760f75061e | |
|
|
e11ca4a244 | |
|
|
0266072c6a | |
|
|
99b76704d3 | |
|
|
b39edee3eb | |
|
|
9e426308d0 | |
|
|
416d76e03a | |
|
|
ae867ae230 | |
|
|
e83dc93dca | |
|
|
da220a3f5a | |
|
|
8141c64f87 | |
|
|
5aaedffe20 | |
|
|
9ec53e39ec | |
|
|
c93807d67f | |
|
|
6430f11188 | |
|
|
bc4c523d88 | |
|
|
b7aaeee13e | |
|
|
504304c341 | |
|
|
941bddb771 | |
|
|
1990cebd58 | |
|
|
041d6724e2 | |
|
|
0086ed4723 | |
|
|
b83dd29b20 | |
|
|
aa01c68887 | |
|
|
00f5fa993a | |
|
|
6b98e23e50 | |
|
|
3810b33c9e | |
|
|
e58b0e5315 | |
|
|
a2548c4f95 | |
|
|
0151305ca3 | |
|
|
fbdac497fa | |
|
|
052ac1ff8d | |
|
|
e113bc9fe1 | |
|
|
03b7f00bcd | |
|
|
3bedea2aba | |
|
|
90a7e20be4 | |
|
|
4a02ae2e98 | |
|
|
9852cacb01 | |
|
|
eda79fd455 | |
|
|
45af1d7ba6 | |
|
|
7a4520086f | |
|
|
a252142cef | |
|
|
12a0f7ad82 | |
|
|
3ef3586bf7 | |
|
|
4aecfb3bed | |
|
|
9a31e04fad | |
|
|
af333e72f5 | |
|
|
26f1a2b8ee | |
|
|
497d91f4a4 | |
|
|
bd2d698d9f | |
|
|
b4c884a367 | |
|
|
337dec37b8 | |
|
|
c12ecfdcf0 | |
|
|
919e2bcdd7 | |
|
|
943dbb28a6 | |
|
|
0926da24f7 | |
|
|
6ad80f540d | |
|
|
77b9b14cb6 | |
|
|
b9c55871b8 | |
|
|
848581452a | |
|
|
2e53cdf29b | |
|
|
d9bc12c8d4 | |
|
|
234f8b074b | |
|
|
079c11a7e3 | |
|
|
9d9d65e381 | |
|
|
2517c57778 | |
|
|
5d15ae6fe3 | |
|
|
f9fbb59c53 | |
|
|
c55f7a427c | |
|
|
70b8c23e41 | |
|
|
2591a794bf | |
|
|
1c4be1012a | |
|
|
030eeb663b | |
|
|
4b3180bdfe | |
|
|
28b7cdb187 | |
|
|
f57f6bb389 | |
|
|
673abdfec2 | |
|
|
1d4d068e08 | |
|
|
72d83e9cfd | |
|
|
883783250f | |
|
|
cc1ae55480 | |
|
|
1bc3e77c1a | |
|
|
e24d865ce3 | |
|
|
2762c83d84 | |
|
|
c58ad6142f | |
|
|
c45f5ca083 | |
|
|
fc5c792328 | |
|
|
1b00209c55 | |
|
|
f199d18c4b | |
|
|
3f1d07727b | |
|
|
64d70269f9 | |
|
|
f0a71f8e70 | |
|
|
8901479dd5 | |
|
|
389456c46b | |
|
|
40483dd4ee | |
|
|
fe1d7724bc | |
|
|
9204183add | |
|
|
db9895077c | |
|
|
36c086136f | |
|
|
f3c78c1892 | |
|
|
6d538bf250 | |
|
|
7a84eebf98 | |
|
|
064101b155 | |
|
|
91e7d04e4d | |
|
|
711fa5a2b8 | |
|
|
9f7bc4be75 | |
|
|
df7022b2e3 | |
|
|
6ee51a7f43 | |
|
|
aed8a77e13 | |
|
|
bcfa22a818 | |
|
|
0840d57689 | |
|
|
deb7e77263 | |
|
|
aba477a49c | |
|
|
a9e5a7754e | |
|
|
a2d4d100d3 | |
|
|
7f4f5e9d08 | |
|
|
55a2301bb5 | |
|
|
14ac852eee | |
|
|
d2e53c7b8c | |
|
|
4a335d2a28 | |
|
|
999fde1f5c | |
|
|
024e62103a | |
|
|
73889c51ae | |
|
|
7a0b29bda6 | |
|
|
a592a39fae | |
|
|
aa96ef66c6 | |
|
|
2b24ce723e | |
|
|
867ee32f91 | |
|
|
662001accd | |
|
|
334b2fe440 | |
|
|
2f728629f3 | |
|
|
eb8628da5b | |
|
|
1427940224 | |
|
|
06f10e38f5 | |
|
|
5092f5204f | |
|
|
13f4420e42 | |
|
|
e0e6e60ae0 | |
|
|
9cac49d539 | |
|
|
97d9aefbeb | |
|
|
340119f697 | |
|
|
a075eb34cd | |
|
|
53913d3777 | |
|
|
c1d79a7e9f | |
|
|
3ee6f0ceaa | |
|
|
1821d82ded | |
|
|
476ca95aa3 | |
|
|
d8b799f057 | |
|
|
4c4807c22e | |
|
|
8a9afc2d9a | |
|
|
6fcb670a89 | |
|
|
d224b519f7 | |
|
|
b382595767 | |
|
|
64ff6f73d4 | |
|
|
e1632b58ac | |
|
|
7e39692cc4 | |
|
|
8de44fb7b3 | |
|
|
647aee010a | |
|
|
296459d38a | |
|
|
7941328a29 | |
|
|
38d9a21a5d | |
|
|
7d88f49e68 | |
|
|
3c46215a3c | |
|
|
137ed07b2b | |
|
|
6f05850fbc | |
|
|
80447f5c7a | |
|
|
971d94495a | |
|
|
77790a1cb2 | |
|
|
ecfadcb5a3 | |
|
|
d9e3b642a5 | |
|
|
e56e269f2e | |
|
|
98f7ab8c02 | |
|
|
5d33bd03a7 | |
|
|
55882aa0ba | |
|
|
43d1a94f22 | |
|
|
53b2b9156f | |
|
|
fafc075735 | |
|
|
09ee238e50 | |
|
|
7be3813527 | |
|
|
e6491a6203 | |
|
|
4955a24d6f | |
|
|
425f53b74c | |
|
|
2ed9595186 | |
|
|
4d1e3beda6 | |
|
|
8b0e1b8988 | |
|
|
c77682a9ad | |
|
|
8e0ff1f2b2 | |
|
|
b5e027a553 | |
|
|
ef712949ad | |
|
|
b429b2cf8c | |
|
|
9fb95c3030 | |
|
|
6883d47508 | |
|
|
dae44745ca | |
|
|
24b7d2e1b9 | |
|
|
21ac6850d2 | |
|
|
8b69a07b93 | |
|
|
f92bf347e3 | |
|
|
78669051de | |
|
|
ea90b2b38b | |
|
|
bd61a0f2e9 | |
|
|
888ad8897e | |
|
|
eb18021988 | |
|
|
7b243a9615 | |
|
|
5716c4169a | |
|
|
abb9f47646 | |
|
|
9a5221ef7d | |
|
|
d9eaa06de3 | |
|
|
4f91874b82 | |
|
|
139438133d | |
|
|
6705cf0fc0 | |
|
|
00255e902c | |
|
|
71e867156f | |
|
|
658f437f73 | |
|
|
95bf613263 | |
|
|
03d61347ca | |
|
|
050a0875fe | |
|
|
d9c46acb03 | |
|
|
f19fc0e92f | |
|
|
3bc4b86749 | |
|
|
43455da7bc | |
|
|
0030eac22e | |
|
|
671c071a45 | |
|
|
3419015542 | |
|
|
3eea6cf8b7 | |
|
|
2c407c6e4e | |
|
|
ab90591e7c | |
|
|
33a2b7f373 | |
|
|
9158f28998 | |
|
|
680a6cb437 | |
|
|
21c19f4b6d | |
|
|
8c03167f7e | |
|
|
b629b2eec4 | |
|
|
01af8f72d3 | |
|
|
4d10db054c | |
|
|
a019a542b0 | |
|
|
b42325337e | |
|
|
a3152bb6e1 | |
|
|
4ec0441d28 | |
|
|
9adc8a93b1 | |
|
|
3f3d1a562b | |
|
|
1b6ba91240 | |
|
|
c406976a6d | |
|
|
d213fa7a99 | |
|
|
60707150a6 | |
|
|
008906d245 | |
|
|
762b8b7425 | |
|
|
24228428fa | |
|
|
9148651556 | |
|
|
1c9c3eb893 | |
|
|
17e0517e5b | |
|
|
7662880352 | |
|
|
c3c433244e | |
|
|
df65d592ad | |
|
|
7873523c1b | |
|
|
8b5800b32e | |
|
|
2e46791466 | |
|
|
fc0ef2e89f | |
|
|
1de687cbf3 | |
|
|
3a017dbfa3 | |
|
|
1f828b403b | |
|
|
f75fafaa42 | |
|
|
7c561a4656 | |
|
|
033b849bdc | |
|
|
8ae0b0d621 | |
|
|
b6bad061b7 | |
|
|
1dd8515ac2 | |
|
|
9f3bb29004 | |
|
|
52dd676cf9 | |
|
|
342b567e2c | |
|
|
35ee76be0b | |
|
|
b4d40a4770 | |
|
|
84bfcb4d3e | |
|
|
f030ed9b66 | |
|
|
c6920a1995 | |
|
|
2d681ce6bc | |
|
|
3981f2cd50 | |
|
|
2b961c7985 | |
|
|
fb2fdd2c27 | |
|
|
f6bcefd1e8 | |
|
|
1d7b28e7f9 | |
|
|
3ea2bdfc92 | |
|
|
4aa0161c41 | |
|
|
ff4ab39025 | |
|
|
bb35ae1b9a | |
|
|
0e0ce59d74 | |
|
|
82d3157e2a | |
|
|
12cb53b167 | |
|
|
5fc53a1999 | |
|
|
b712abd1d5 | |
|
|
a1c13b5850 | |
|
|
a0fe7be308 | |
|
|
bbfa966b57 | |
|
|
6d11fc68b4 | |
|
|
eef764dd90 | |
|
|
8423b00bec | |
|
|
dbaac006c7 | |
|
|
510c73dd24 | |
|
|
41486798d2 | |
|
|
f40faa5519 | |
|
|
eecfe6dcae | |
|
|
8a004ef35f | |
|
|
369805e6c6 | |
|
|
93b93f6a3a | |
|
|
9fbee7e0c9 | |
|
|
46704d5299 | |
|
|
4225014cdd | |
|
|
ae36d4680a | |
|
|
d48f736392 | |
|
|
b0d8a49929 | |
|
|
e45791c676 | |
|
|
ca425c602b | |
|
|
44e7ffaeeb | |
|
|
cf42b2e57f | |
|
|
840de08e69 | |
|
|
929903aa1b | |
|
|
5eafcc9c8c | |
|
|
a1657f5827 | |
|
|
dff2e712ad | |
|
|
a5f3430965 | |
|
|
5059d66aa1 | |
|
|
668af5ee0b | |
|
|
a70caefe01 | |
|
|
64bd6a5604 | |
|
|
b68deafa82 | |
|
|
d29c150081 | |
|
|
4d3ecd05dc | |
|
|
143d7f0c4b | |
|
|
4d2f04b30e | |
|
|
955ca4a1a6 | |
|
|
6e92895043 | |
|
|
6102309828 | |
|
|
8f34644d45 | |
|
|
f347b34f59 | |
|
|
dc7e71dc74 | |
|
|
749bf95761 | |
|
|
a67472c9b4 | |
|
|
32c8d70179 | |
|
|
510dfcac30 | |
|
|
9b59a55423 | |
|
|
0bd269f93e | |
|
|
e55a13cfb1 | |
|
|
1617de2fc1 | |
|
|
40c3ea65ff | |
|
|
541e000183 | |
|
|
0e93894ed8 | |
|
|
7f1621915f | |
|
|
70e4829f32 | |
|
|
c77b3d74c8 | |
|
|
1f4ea09bc6 | |
|
|
c45020f24f | |
|
|
ca679057c4 | |
|
|
456793293b | |
|
|
75d3908911 | |
|
|
a7fbd00530 | |
|
|
785d5ec869 | |
|
|
c5feb98ed8 | |
|
|
121b1d4eb4 | |
|
|
8e2b99333c | |
|
|
5bd055c77d | |
|
|
5ea9d63cb9 | |
|
|
0134d6c723 | |
|
|
a9c80a670b | |
|
|
998b92aa79 | |
|
|
60ce8c45b2 | |
|
|
a66d25f564 | |
|
|
91b66660a6 | |
|
|
1031222e47 | |
|
|
2005eacaa9 | |
|
|
b581afebe6 | |
|
|
1532ac4a7e | |
|
|
231b3f71c5 | |
|
|
308f5140a1 | |
|
|
ef673fc44b | |
|
|
f347b0cace | |
|
|
102cf5f6dc | |
|
|
d9ca71009f | |
|
|
114ee50273 | |
|
|
54bb66f738 | |
|
|
19f52bc133 | |
|
|
2439dec9fb | |
|
|
fb0fd7d91f | |
|
|
3765b390a6 | |
|
|
f6be3186e7 | |
|
|
7399568e36 | |
|
|
37d798627a | |
|
|
fe2a375b4e | |
|
|
70443b7b8d | |
|
|
7a37c01b7f | |
|
|
7215c75f5a | |
|
|
a34c47dc3c | |
|
|
6fdad9a482 | |
|
|
08e62e4500 | |
|
|
3cfb4556f3 | |
|
|
b8e3e83b80 | |
|
|
7e9bf65f9f | |
|
|
5197e49c1f | |
|
|
7880836f39 | |
|
|
487eb9dca8 | |
|
|
473cee0e30 | |
|
|
817cdcc8f7 | |
|
|
bf03430958 | |
|
|
58321c4c82 | |
|
|
8cabc8c96a | |
|
|
7f050a1dd6 | |
|
|
e5e2a0394b | |
|
|
a56ab0680b | |
|
|
ee13d0ae2e | |
|
|
ee2c66c8fb | |
|
|
f1fb2068de | |
|
|
95e0239e42 | |
|
|
0b28ef5461 | |
|
|
68fe2b75dc | |
|
|
ecfeee1693 | |
|
|
9cda4360ca | |
|
|
18b9c08101 | |
|
|
d4e89aec20 | |
|
|
01a3a9057b | |
|
|
2107a42e37 | |
|
|
d96e746db7 | |
|
|
be034d4d8b | |
|
|
ca44b4786a | |
|
|
74056167d6 | |
|
|
e6aec6b559 | |
|
|
9a488610da | |
|
|
f82420b7ef | |
|
|
fbeaec2820 | |
|
|
b4907bfe9b | |
|
|
6e75e45942 | |
|
|
3292b9f978 | |
|
|
1959045ab2 | |
|
|
6a99e3104a | |
|
|
ab91d360b1 | |
|
|
50a4a82819 | |
|
|
498c02431b | |
|
|
fd54d64ae3 | |
|
|
ac80e3a455 | |
|
|
c6a55949b3 | |
|
|
18547cdec1 | |
|
|
d29707c8ee | |
|
|
c7e29116dd | |
|
|
a85cc1236c | |
|
|
7b4c603fa6 | |
|
|
67c93e654e | |
|
|
9b0c874314 | |
|
|
d172e48c79 | |
|
|
2a2419af90 | |
|
|
7e39094b13 | |
|
|
8936e9db99 | |
|
|
bd92d48232 |
|
|
@ -14,9 +14,9 @@
|
|||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
|
||||
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
|
||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
||||
<PackageReference Include="fo-dicom" Version="5.2.1" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
|
||||
<PackageReference Include="fo-dicom" Version="5.2.4" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.4" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="Minio" Version="6.0.3" />
|
||||
|
|
|
|||
|
|
@ -220,6 +220,12 @@ namespace IRaCIS.Core.SCP.Service
|
|||
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
||||
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
||||
|
||||
Manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty),
|
||||
ManufacturerModelName = dataset.GetSingleValueOrDefault(DicomTag.ManufacturerModelName, string.Empty),
|
||||
DeviceSerialNumber = dataset.GetSingleValueOrDefault(DicomTag.DeviceSerialNumber, string.Empty),
|
||||
DeviceUID = dataset.GetSingleValueOrDefault(DicomTag.DeviceUID, string.Empty),
|
||||
SoftwareVersions = dataset.GetSingleValueOrDefault(DicomTag.SoftwareVersions, string.Empty),
|
||||
PatientWeight = dataset.GetSingleValueOrDefault(DicomTag.PatientWeight, string.Empty),
|
||||
|
||||
|
||||
//IsDoubleReview = addtionalInfo.IsDoubleReview,
|
||||
|
|
@ -281,6 +287,9 @@ namespace IRaCIS.Core.SCP.Service
|
|||
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
||||
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
||||
|
||||
RadiopharmaceuticalInformationSequence = dataset.GetSingleValueOrDefault(DicomTag.RadiopharmaceuticalInformationSequence, string.Empty),
|
||||
AcquisitionDate = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionDate, string.Empty),
|
||||
|
||||
|
||||
InstanceCount = 0
|
||||
};
|
||||
|
|
@ -332,6 +341,21 @@ namespace IRaCIS.Core.SCP.Service
|
|||
WindowCenter = dataset.GetSingleValueOrDefault(DicomTag.WindowCenter, string.Empty),
|
||||
WindowWidth = dataset.GetSingleValueOrDefault(DicomTag.WindowWidth, string.Empty),
|
||||
|
||||
PhotometricInterpretation = dataset.GetSingleValueOrDefault(DicomTag.PhotometricInterpretation, string.Empty),
|
||||
BitsAllocated = dataset.GetSingleValueOrDefault(DicomTag.BitsAllocated, 0),
|
||||
PixelRepresentation = dataset.GetSingleValueOrDefault(DicomTag.PixelRepresentation, string.Empty),
|
||||
RescaleIntercept = dataset.GetSingleValueOrDefault(DicomTag.RescaleIntercept, string.Empty),
|
||||
RescaleSlope = dataset.GetSingleValueOrDefault(DicomTag.RescaleSlope, string.Empty),
|
||||
ImagePositionPatient = dataset.GetSingleValueOrDefault(DicomTag.ImagePositionPatient, string.Empty),
|
||||
ImageOrientationPatient = dataset.GetSingleValueOrDefault(DicomTag.ImageOrientationPatient, string.Empty),
|
||||
SequenceOfUltrasoundRegions = dataset.GetSingleValueOrDefault(DicomTag.SequenceOfUltrasoundRegions, string.Empty),
|
||||
FrameTime = dataset.GetSingleValueOrDefault(DicomTag.FrameTime, string.Empty),
|
||||
CorrectedImage = dataset.GetSingleValueOrDefault(DicomTag.CorrectedImage, string.Empty),
|
||||
Units = dataset.GetSingleValueOrDefault(DicomTag.Units, string.Empty),
|
||||
DecayCorrection = dataset.GetSingleValueOrDefault(DicomTag.DecayCorrection, string.Empty),
|
||||
EncapsulatedDocument = dataset.GetSingleValueOrDefault(DicomTag.EncapsulatedDocument, string.Empty),
|
||||
|
||||
|
||||
Path = fileRelativePath,
|
||||
|
||||
FileSize= fileSize,
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ namespace IRaCIS.Api.Controllers
|
|||
var token = _tokenService.GetToken(new UserTokenInfo()
|
||||
{
|
||||
IdentityUserId = Guid.NewGuid(),
|
||||
UserName = "Share001",
|
||||
UserName = "ImageShare",
|
||||
UserTypeEnum = UserTypeEnum.ShareImage,
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
public List<OSSFileDTO> UploadedFileList { get; set; } = new List<OSSFileDTO>();
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
|
||||
public class OSSFileDTO
|
||||
{
|
||||
|
|
@ -521,7 +522,17 @@ namespace IRaCIS.Core.API.Controllers
|
|||
}
|
||||
else
|
||||
{
|
||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
|
||||
if (incommand.IsImageSegmentLabel == true)
|
||||
{
|
||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, ImageLabelNoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
await _noneDicomStudyFileRepository.AddAsync(new NoneDicomStudyFile() { FileName = item.FileName, Path = item.FilePath, NoneDicomStudyId = noneDicomStudyId.Value, FileType = item.FileType, FileSize = item.FileFize });
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -557,6 +568,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||
/// 一致性核查 excel上传 支持三种格式
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="isFullCheck"></param>
|
||||
/// <param name="oSSService"></param>
|
||||
/// <param name="_inspectionFileRepository"></param>
|
||||
/// <returns></returns>
|
||||
|
|
@ -564,12 +576,14 @@ namespace IRaCIS.Core.API.Controllers
|
|||
[HttpPost("QCOperation/UploadVisitCheckExcel/{trialId:guid}")]
|
||||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||||
|
||||
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
|
||||
public async Task<IResponseOutput> UploadVisitCheckExcel(Guid trialId, bool isFullCheck, [FromServices] IOSSService oSSService, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
|
||||
{
|
||||
|
||||
var fileName = string.Empty;
|
||||
var templateFileStream = new MemoryStream();
|
||||
|
||||
var inspectionFileId = Guid.Empty;
|
||||
|
||||
await FileUploadToOSSAsync(async (realFileName, fileStream) =>
|
||||
{
|
||||
fileName = realFileName;
|
||||
|
|
@ -586,7 +600,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", realFileName);
|
||||
|
||||
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
||||
var addEntity = await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
||||
|
||||
inspectionFileId = addEntity.Id;
|
||||
|
||||
return ossRelativePath;
|
||||
|
||||
|
|
@ -732,8 +748,11 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
if (etcCheckList == null || etcCheckList.Count == 0)
|
||||
{
|
||||
await _inspectionFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == inspectionFileId, u => new InspectionFile() { CheckState = EDCCheckState.Failed });
|
||||
|
||||
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
|
||||
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -753,6 +772,8 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
if (etcCheckList.Count == 0)
|
||||
{
|
||||
await _inspectionFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == inspectionFileId, u => new InspectionFile() { CheckState = EDCCheckState.Failed });
|
||||
|
||||
//---请保证上传数据符合模板文件中的样式,且存在有效数据。
|
||||
return ResponseOutput.NotOk(_localizer["UploadDownLoad_InvalidData"]);
|
||||
}
|
||||
|
|
@ -764,8 +785,19 @@ namespace IRaCIS.Core.API.Controllers
|
|||
//var client = _mediator.CreateRequestClient<ConsistenCheckCommand>();
|
||||
//await client.GetResponse<ConsistenCheckResult>(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
|
||||
|
||||
//不获取结果,不用定义返回类型
|
||||
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
|
||||
if (isFullCheck)
|
||||
{
|
||||
await _mediator.Send(new ConsistenFullCheckCommand() { ETCList = etcCheckList, TrialId = trialId, InspectionFileId = inspectionFileId });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//不获取结果,不用定义返回类型
|
||||
await _mediator.Send(new ConsistenCheckCommand() { ETCList = etcCheckList, TrialId = trialId });
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
|
@ -972,7 +1004,11 @@ namespace IRaCIS.Core.API.Controllers
|
|||
|
||||
EmailBodyHtml = 4,
|
||||
|
||||
Other = 5
|
||||
ReadKeyFile = 5,
|
||||
|
||||
Other = 6,
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1004,6 +1040,9 @@ namespace IRaCIS.Core.API.Controllers
|
|||
case UploadFileType.EmailBodyHtml:
|
||||
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.EmailTemplate, fileName));
|
||||
break;
|
||||
case UploadFileType.ReadKeyFile:
|
||||
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.ReadKetFile, fileName));
|
||||
break;
|
||||
|
||||
default:
|
||||
result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetOtherFileUploadPath(_hostEnvironment, StaticData.Folder.TempFile, fileName));
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class HangfireHostService(IRecurringMessageScheduler _recurringMessageSch
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 项目手动选择,周期性邮件
|
||||
var taskInfoList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend)
|
||||
.Select(t => new { t.Id, t.Code, TrialCode = t.Trial.TrialCode, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
||||
.ToListAsync();
|
||||
|
|
|
|||
|
|
@ -318,11 +318,12 @@
|
|||
<param name="_noneDicomStudyFileRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.InspectionFile})">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,System.Boolean,IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.InspectionFile})">
|
||||
<summary>
|
||||
一致性核查 excel上传 支持三种格式
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="isFullCheck"></param>
|
||||
<param name="oSSService"></param>
|
||||
<param name="_inspectionFileRepository"></param>
|
||||
<returns></returns>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using IRaCIS.Core.API;
|
||||
using IRaCIS.Core.API.HostService;
|
||||
using IRaCIS.Core.Application.BusinessFilter;
|
||||
using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
|
|
@ -100,6 +101,7 @@ builder.Services.AddControllers(options =>
|
|||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
options.Filters.Add<TrialGlobalLimitActionFilter>();
|
||||
options.Filters.Add<RequestDuplicationFilter>();
|
||||
|
||||
})
|
||||
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@ public static class ServiceCollectionSetup
|
|||
services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||
services.AddOptions().Configure<IRCEncreptOption>(_configuration.GetSection("EncrypteResponseConfig"));
|
||||
services.AddOptions().Configure<RequestDuplicationOptions>(_configuration.GetSection("RequestDuplicationOptions"));
|
||||
services.AddOptions().Configure<SystemPacsConfig>(_configuration.GetSection("SystemPacsConfig"));
|
||||
services.Configure<IRaCISBasicConfigOption>(_configuration.GetSection("IRaCISBasicConfig"));
|
||||
|
||||
services.Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
|
||||
//转发头设置 获取真实IP
|
||||
//ת<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȡ<EFBFBD><C8A1>ʵIP
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
|
|
@ -51,7 +52,7 @@ public static class ServiceCollectionSetup
|
|||
|
||||
services.AddScoped<IObtainTaskAutoCancelJob, ObtainTaskAutoCancelJob>();
|
||||
|
||||
// 注册以Service 结尾的服务
|
||||
// ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Service <20><>β<EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>
|
||||
services.Scan(scan => scan
|
||||
.FromAssemblies(typeof(BaseService).Assembly)
|
||||
.AddClasses(classes => classes.Where(t => t.Name.Contains("Service")))
|
||||
|
|
@ -70,23 +71,23 @@ public static class ServiceCollectionSetup
|
|||
#endregion
|
||||
|
||||
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
// MediatR <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD> <20>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD><EFBFBD> ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>handler<65><72>Ӧ<EFBFBD><D3A6>ϵ
|
||||
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||
|
||||
|
||||
|
||||
#region 历史废弃配置
|
||||
#region <EFBFBD><EFBFBD>ʷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//builder.Services.AddMemoryCache();
|
||||
////上传限制 配置
|
||||
////<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
//builder.Services.Configure<FormOptions>(options =>
|
||||
//{
|
||||
// options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
// options.ValueCountLimit = int.MaxValue;
|
||||
// options.ValueLengthLimit = int.MaxValue;
|
||||
//});
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//IP <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD>
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
// <EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -94,25 +95,25 @@ public static class ServiceCollectionSetup
|
|||
|
||||
}
|
||||
|
||||
#region Autofac 废弃
|
||||
#region Autofac <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
//public class AutofacModuleSetup : Autofac.Module
|
||||
//{
|
||||
// protected override void Load(ContainerBuilder containerBuilder)
|
||||
// {
|
||||
|
||||
// #region byzhouhang 20210917 此处注册泛型仓储 可以减少Domain层 和Infra.EFcore 两层 空的仓储接口定义和 仓储文件定义
|
||||
// #region byzhouhang 20210917 <EFBFBD>˴<EFBFBD>ע<EFBFBD>᷺<EFBFBD>Ͳִ<EFBFBD> <20><><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>Domain<69><6E> <20><>Infra.EFcore <20><><EFBFBD><EFBFBD> <20>յIJִ<C4B2><D6B4>ӿڶ<D3BF><DAB6><EFBFBD><EFBFBD> <20>ִ<EFBFBD><D6B4>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
// containerBuilder.RegisterGeneric(typeof(Repository<>))
|
||||
// .As(typeof(IRepository<>)).InstancePerLifetimeScope();//注册泛型仓储
|
||||
// .As(typeof(IRepository<>)).InstancePerLifetimeScope();//ע<EFBFBD>᷺<EFBFBD>Ͳִ<EFBFBD>
|
||||
|
||||
// containerBuilder.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
|
||||
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region 指定控制器也由autofac 来进行实例获取 https://www.cnblogs.com/xwhqwer/p/15320838.html
|
||||
// #region ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>autofac <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ȡ https://www.cnblogs.com/xwhqwer/p/15320838.html
|
||||
|
||||
// //获取所有控制器类型并使用属性注入
|
||||
// //<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
|
||||
// containerBuilder.RegisterAssemblyTypes(typeof(BaseService).Assembly)
|
||||
// .Where(type => typeof(IDynamicWebApi).IsAssignableFrom(type))
|
||||
// .PropertiesAutowired();
|
||||
|
|
@ -128,7 +129,7 @@ public static class ServiceCollectionSetup
|
|||
// //containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
||||
|
||||
|
||||
// //注册hangfire任务 依赖注入
|
||||
// //ע<EFBFBD><EFBFBD>hangfire<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
|
||||
// containerBuilder.RegisterType<ObtainTaskAutoCancelJob>().As<IObtainTaskAutoCancelJob>().InstancePerDependency();
|
||||
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@
|
|||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
|
@ -55,11 +56,15 @@
|
|||
"ChangePassWordDays": 90,
|
||||
|
||||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 2
|
||||
"TemplateType": 2,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
|
|
@ -69,7 +74,13 @@
|
|||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗",
|
||||
"IsEnv_US": false
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@
|
|||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
|
|
@ -53,19 +54,23 @@
|
|||
"IsNeedChangePassWord": true,
|
||||
"ChangePassWordDays": 90,
|
||||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 2
|
||||
"TemplateType": 2,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "irc@extimaging.com",
|
||||
"FromName": "IRC Imaging System",
|
||||
"AuthorizationCode": "ExtImg@2022",
|
||||
"SiteUrl": "http://irc.extimaging.com/login",
|
||||
"SystemShortName": "IRC",
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"OrganizationName": "ExtImaging",
|
||||
"OrganizationNameCN": "ExtImaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
|
|
@ -78,6 +83,12 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "101.132.193.237"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@
|
|||
},
|
||||
// 系统配置
|
||||
"BasicSystemConfig": {
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
// 打开用户复杂密码
|
||||
"OpenUserComplexPassword": false,
|
||||
// 是否在开始工作前强制签署电子知情同意书
|
||||
|
|
@ -115,7 +117,9 @@
|
|||
// 是否打开项目关联删除
|
||||
"OpenTrialRelationDelete": true,
|
||||
// 转换PDF服务配置
|
||||
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf"
|
||||
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf",
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyMinutes": 1440
|
||||
},
|
||||
// 邮件服务配置(用于系统通知、找回密码、错误报警等)
|
||||
"SystemEmailSendConfig": {
|
||||
|
|
@ -123,6 +127,10 @@
|
|||
"Port": 465,
|
||||
// 企业邮箱SMTP服务器地址
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
|
||||
"ImapPort": 993,
|
||||
// 发件人邮箱地址
|
||||
"FromEmail": "test@extimaging.com",
|
||||
// 发件人显示名称
|
||||
|
|
@ -134,9 +142,9 @@
|
|||
// 系统简称
|
||||
"SystemShortName": "IRC",
|
||||
// 组织英文名称
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationName": "ExtImaging",
|
||||
// 组织中文名称
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"OrganizationNameCN": "ExtImaging",
|
||||
// 公司英文全称
|
||||
"CompanyName": "Extensive Imaging",
|
||||
// 公司中文全称
|
||||
|
|
@ -160,5 +168,16 @@
|
|||
"Port": "11113",
|
||||
// PACS服务器IP地址
|
||||
"IP": "106.14.89.110"
|
||||
},
|
||||
// 重复请求配置
|
||||
"RequestDuplicationOptions": {
|
||||
// 是否启用重复请求检测
|
||||
"IsEnabled": true,
|
||||
// 重复请求时间窗口(毫秒)
|
||||
"DuplicationWindowMs": 200,
|
||||
// 缓存请求时间(秒)
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@
|
|||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
|
@ -75,13 +76,15 @@
|
|||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
||||
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"OrganizationName": "ExtImaging",
|
||||
"OrganizationNameCN": "ExtImaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
|
|
@ -91,5 +94,12 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "106.14.89.110"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
|
|
@ -57,13 +58,17 @@
|
|||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 1,
|
||||
|
||||
"OpenTrialRelationDelete": false
|
||||
"OpenTrialRelationDelete": false,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"Imap": "imap-mail.outlook.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi System",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
|
@ -85,6 +90,13 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "44.210.231.169"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@
|
|||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
|
@ -66,12 +67,16 @@
|
|||
"ChangePassWordDays": 90,
|
||||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 1,
|
||||
"OpenLoginMFA": true
|
||||
"OpenLoginMFA": true,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"Imap": "imap-mail.outlook.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi System",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
|
@ -92,6 +97,13 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "3.226.182.187"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@
|
|||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
|
|
@ -65,12 +66,16 @@
|
|||
"IsNeedChangePassWord": true,
|
||||
"ChangePassWordDays": 90,
|
||||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 1
|
||||
"TemplateType": 1,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 587,
|
||||
"Host": "smtp-mail.outlook.com",
|
||||
"Imap": "imap-mail.outlook.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "donotreply@elevateimaging.ai",
|
||||
"FromName": "LiLi System",
|
||||
"AuthorizationCode": "Q#669869497420ul",
|
||||
|
|
@ -92,6 +97,12 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "104",
|
||||
"IP": "3.226.182.187"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@
|
|||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
// 启用质控风险控制功能
|
||||
"QCRiskControl": true,
|
||||
"OpenUserComplexPassword": true,
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
|
|
@ -72,20 +73,24 @@
|
|||
"IsNeedChangePassWord": true,
|
||||
"ChangePassWordDays": 90,
|
||||
// 模板类型 1 Elevate 2 Extensive
|
||||
"TemplateType": 2
|
||||
"TemplateType": 2,
|
||||
//MFA免验证发送天数
|
||||
"UserMFAVerifyDays": 1
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"Imap": "imap.qiye.aliyun.com",
|
||||
"ImapPort": 993,
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "Uat IRC Imaging System",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||
|
||||
"SystemShortName": "IRC",
|
||||
"OrganizationName": "Extlmaging",
|
||||
"OrganizationNameCN": "Extlmaging",
|
||||
"OrganizationName": "ExtImaging",
|
||||
"OrganizationNameCN": "ExtImaging",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
|
|
@ -99,6 +104,13 @@
|
|||
"SystemPacsConfig": {
|
||||
"Port": "11113",
|
||||
"IP": "101.132.253.119"
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,5 +74,12 @@
|
|||
"redirect_uri": "https://oauthlogin.net/oauth/githubcallback",
|
||||
"scope": "repo"
|
||||
}
|
||||
},
|
||||
"RequestDuplicationOptions": {
|
||||
"IsEnabled": true,
|
||||
"DuplicationWindowMs": 200,
|
||||
"CacheTimeSeconds": 5,
|
||||
"ExcludedPaths": [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>%(DocumentTitle)</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
|
||||
<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" />
|
||||
|
|
|
|||
|
|
@ -505,8 +505,8 @@ var abp = abp || {};
|
|||
|
||||
//Inputs
|
||||
createInput(modalUxContent, 'tenancyName', 'Tenancy Name (Leave empty for Host)');
|
||||
createInput(modalUxContent, 'userName', 'Username or email address', 'text', 'cyldev');
|
||||
createInput(modalUxContent, 'password', 'Password', 'password', '123456');
|
||||
createInput(modalUxContent, 'userName', 'Username or email address', 'text', 'user1wj');
|
||||
createInput(modalUxContent, 'password', 'Password', 'password', '1');
|
||||
createInput(modalUxContent, 'pwdMd5', 'PwdMd5', 'text', '');
|
||||
createSelect(modalUxContent, 'roleSelect', 'role', [])
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
||||
{
|
||||
using Database.Api;
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
using IRaCIS.Core.Application.Service.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Components.Endpoints;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Minio.Helper;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Database.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求拦截 请求前后的操作
|
||||
/// </summary>
|
||||
/// <param name="logger">logger</param>
|
||||
/// <param name="accessor">loggerHelper</param>
|
||||
public class RequestDuplicationFilter(ILogger<RequestDuplicationFilter> logger, IHttpContextAccessor accessor, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<RequestDuplicationOptions> RequestDuplicationOptionsMonitor) : ExceptionFilterAttribute, IAsyncActionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 传入的参数
|
||||
/// </summary>
|
||||
public string Intoparam { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 这个是正常记录(请求刚进入的时候)
|
||||
/// </summary>
|
||||
/// <param name="context">context</param>
|
||||
/// <param name="next">next</param>
|
||||
/// <returns>返回的对象</returns>
|
||||
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
if (RequestDuplicationOptionsMonitor.CurrentValue.IsEnabled)
|
||||
{
|
||||
Dictionary<string, object?> dic = new Dictionary<string, object?>();
|
||||
var desc = context.ActionDescriptor as ControllerActionDescriptor;
|
||||
foreach (var p in desc.Parameters)
|
||||
{
|
||||
// 关键判断:绑定源是否是 Services
|
||||
if (p.BindingInfo?.BindingSource == BindingSource.Services) continue;
|
||||
// 普通参数,取值
|
||||
if (context.ActionArguments.TryGetValue(p.Name, out var value) && value != null)
|
||||
{
|
||||
dic.Add(p.Name, value);
|
||||
}
|
||||
}
|
||||
|
||||
this.Intoparam = JsonConvert.SerializeObject(dic);
|
||||
try
|
||||
{
|
||||
this.RequestDuplication();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var resultContext = await next();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private void RequestDuplication()
|
||||
{
|
||||
var requestPath = accessor?.HttpContext?.Request?.Path.ToString() ?? string.Empty;
|
||||
|
||||
// 验证请求频繁情况
|
||||
if (
|
||||
!requestPath
|
||||
.Split("/", StringSplitOptions.RemoveEmptyEntries)
|
||||
.Any(segment => segment.StartsWith("get", StringComparison.OrdinalIgnoreCase)) &&
|
||||
_userInfo.UserRoleId != default(Guid)&&
|
||||
RequestDuplicationOptionsMonitor.CurrentValue.IsEnabled &&
|
||||
!RequestDuplicationOptionsMonitor.CurrentValue.ExcludePaths.Contains(requestPath))
|
||||
{
|
||||
RequestInfo requestInfo = new RequestInfo
|
||||
{
|
||||
UserRoleId = _userInfo.UserRoleId,
|
||||
RequestPath = requestPath,
|
||||
ParameterHash = GenerateParameterHash(this.Intoparam),
|
||||
RequestTime = DateTime.Now
|
||||
};
|
||||
|
||||
IRCSystemInfo.RequestRecordList= IRCSystemInfo.RequestRecordList.Where(x => x.RequestTime >= DateTime.Now.AddSeconds(-RequestDuplicationOptionsMonitor.CurrentValue.CacheTimeSeconds)).ToList();
|
||||
|
||||
|
||||
var requestsTimes = IRCSystemInfo.RequestRecordList.Any(x=>
|
||||
x.RequestTime>= requestInfo.RequestTime.AddMilliseconds(-RequestDuplicationOptionsMonitor.CurrentValue.DuplicationWindowMs)&&
|
||||
x.RequestKey== requestInfo.RequestKey);
|
||||
if (requestsTimes)
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["RequestDuplicationFilter_RequestDuplication"], ApiResponseCodeEnum.BusinessValidationFailed);
|
||||
}
|
||||
IRCSystemInfo.RequestRecordList.Add(requestInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public string GenerateParameterHash(string parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return string.Empty;
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(parameters));
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ namespace IRaCIS.Core.Domain.Share;
|
|||
[Description("多环境 配置环境实体")]
|
||||
public class ServiceVerifyConfigOption
|
||||
{
|
||||
public bool QCRiskControl { get; set; }
|
||||
public bool OpenUserComplexPassword { get; set; }
|
||||
|
||||
public bool OpenSignDocumentBeforeWork { get; set; }
|
||||
|
|
@ -38,6 +39,8 @@ public class ServiceVerifyConfigOption
|
|||
|
||||
public string ThirdPdfUrl { get; set; }
|
||||
|
||||
public int UserMFAVerifyMinutes { get; set; } = 1440;
|
||||
|
||||
}
|
||||
|
||||
public class SystemEmailSendConfig
|
||||
|
|
@ -45,6 +48,10 @@ public class SystemEmailSendConfig
|
|||
public int Port { get; set; }
|
||||
|
||||
public string Host { get; set; } = string.Empty;
|
||||
|
||||
public string Imap { get; set; } = string.Empty;
|
||||
|
||||
public int ImapPort { get; set; }
|
||||
public string FromEmail { get; set; } = string.Empty;
|
||||
|
||||
public string FromName { get; set; } = string.Empty;
|
||||
|
|
@ -53,7 +60,7 @@ public class SystemEmailSendConfig
|
|||
|
||||
public string SiteUrl { get; set; } = string.Empty;
|
||||
|
||||
public string SystemShortName { get; set; } = string.Empty;
|
||||
public string SystemShortName { get; set; } = string.Empty;
|
||||
|
||||
public string OrganizationName { get; set; } = string.Empty;
|
||||
public string OrganizationNameCN { get; set; } = string.Empty;
|
||||
|
|
@ -72,12 +79,12 @@ public class SystemEmailSendConfig
|
|||
|
||||
public string EmailRegexStr { get; set; }
|
||||
|
||||
public List<string> ErrorNoticeEmailList { get; set; } =new List<string>();
|
||||
public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
public class SystemEmailSendConfigView
|
||||
{
|
||||
public string SystemShortName { get; set; } = string.Empty;
|
||||
public string SystemShortName { get; set; } = string.Empty;
|
||||
public string CompanyName { get; set; } = string.Empty;
|
||||
|
||||
public string CompanyNameCN { get; set; } = string.Empty;
|
||||
|
|
@ -105,6 +112,54 @@ public class IRCEncreptOption
|
|||
public List<string> ApiPathList { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 请求缓存配置
|
||||
/// </summary>
|
||||
public class RequestDuplicationOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存时间(秒),默认5秒
|
||||
/// </summary>
|
||||
public int CacheTimeSeconds { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 重复请求检测时间窗口(毫秒),默认500毫秒
|
||||
/// </summary>
|
||||
public int DuplicationWindowMs { get; set; } = 500;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用防重复请求
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 需要排除的路径(不进行重复检测)
|
||||
/// </summary>
|
||||
public List<string> ExcludePaths { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
public static class IRCSystemInfo
|
||||
{
|
||||
public static List<RequestInfo> RequestRecordList { get; set; } = new List<RequestInfo>();
|
||||
}
|
||||
|
||||
public class RequestInfo
|
||||
{
|
||||
public Guid UserRoleId { get; set; }
|
||||
|
||||
public string RequestPath { get; set; } = string.Empty;
|
||||
|
||||
public string ParameterHash { get; set; } = string.Empty;
|
||||
|
||||
public DateTime RequestTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 请求的唯一标识
|
||||
/// </summary>
|
||||
public string RequestKey => $"{UserRoleId}_{RequestPath}_{ParameterHash}";
|
||||
}
|
||||
|
||||
public class IRaCISBasicConfigOption
|
||||
{
|
||||
public string DoctorCodePrefix { get; set; }
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ public static class CacheKeys
|
|||
/// <returns></returns>
|
||||
public static string StartRestTime(Guid userId) => $"{userId}StartRestTime";
|
||||
|
||||
//每个用户 每个浏览器独立时间
|
||||
public static string UserMFAVerifyPass(Guid userId,string browserFingerprint) => $"UserMFAVerifyPass:{userId}:{browserFingerprint}";
|
||||
|
||||
}
|
||||
|
||||
public static class CacheHelper
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||
|
||||
public class StudyDIRInfo
|
||||
{
|
||||
public Guid SubjectId { get; set; }
|
||||
public bool IsTaskStudy { get; set; }
|
||||
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
// Study
|
||||
public Guid DicomStudyId { get; set; }
|
||||
|
|
@ -97,11 +100,11 @@ namespace IRaCIS.Core.Application.Helper
|
|||
var dicomFile = new DicomFile(dataset);
|
||||
|
||||
// 文件名递增格式:IM_00001, IM_00002, ...
|
||||
string filename = $@"IMAGE/IM_{index:D5}"; // :D5 表示补足5位
|
||||
string filename = $@"IMAGE\IM_{index:D5}"; // :D5 表示补足5位
|
||||
|
||||
mappings.Add($"{filename} => {item.InstanceId}");
|
||||
|
||||
dic.Add(item.InstanceId.ToString(), Path.GetFileName(filename));
|
||||
dic.Add(item.InstanceId.ToString(), filename.TrimEnd('/', '\\').Split('/', '\\').Last());
|
||||
|
||||
dicomDir.AddFile(dicomFile, filename);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using MailKit;
|
||||
using MailKit.Security;
|
||||
using MimeKit;
|
||||
using Org.BouncyCastle.Tls;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
|
@ -9,12 +10,15 @@ namespace IRaCIS.Core.Application.Helper;
|
|||
public static class SendEmailHelper
|
||||
{
|
||||
|
||||
public static async Task SendEmailAsync(MimeMessage messageToSend, SystemEmailSendConfig _systemEmailConfig, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
public static async Task<string> SendEmailAsync(MimeMessage messageToSend, SystemEmailSendConfig _systemEmailConfig, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
{
|
||||
string result = string.Empty;
|
||||
result = messageToSend.MessageId;
|
||||
|
||||
//没有收件人 那么不发送
|
||||
if (messageToSend.To.Count == 0)
|
||||
{
|
||||
return;
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -42,6 +46,7 @@ public static class SendEmailHelper
|
|||
|
||||
await smtp.DisconnectAsync(true);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -51,7 +56,76 @@ public static class SendEmailHelper
|
|||
throw new Exception(I18n.T("SendEmail_SendFail"), new Exception(ex.Message));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static async Task<string> SendEmailAsync(MimeMessage messageToSend, Trial trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
{
|
||||
|
||||
// 项目的需要重设 发件地址与邮件地址
|
||||
var fromAddress = messageToSend.From.Mailboxes.FirstOrDefault();
|
||||
if (fromAddress != null)
|
||||
{
|
||||
messageToSend.From.Clear();
|
||||
messageToSend.From.Add(new MailboxAddress(trial.EmailFromName, trial.EmailFromEmail));
|
||||
}
|
||||
|
||||
|
||||
string result = string.Empty;
|
||||
result = messageToSend.MessageId;
|
||||
|
||||
//没有收件人 那么不发送
|
||||
if (messageToSend.To.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
|
||||
{
|
||||
if (messageSentSuccess != null)
|
||||
{
|
||||
smtp.MessageSent += messageSentSuccess;
|
||||
}
|
||||
|
||||
|
||||
smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;
|
||||
|
||||
//await smtp.ConnectAsync("smtp.qq.com", 465, SecureSocketOptions.SslOnConnect);
|
||||
|
||||
//await smtp.AuthenticateAsync("zhou941003@qq.com", "sqfhlpfdvnexbcab");
|
||||
|
||||
|
||||
//await smtp.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.Auto);
|
||||
|
||||
//await smtp.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
||||
|
||||
|
||||
await smtp.ConnectAsync(trial.EmailSMTPServerAddress, trial.EmailSMTPServerPort, SecureSocketOptions.Auto);
|
||||
|
||||
await smtp.AuthenticateAsync(trial.EmailFromEmail, trial.EmailAuthorizationCode);
|
||||
|
||||
|
||||
await smtp.SendAsync(messageToSend);
|
||||
|
||||
await smtp.DisconnectAsync(true);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
|
||||
throw new Exception(I18n.T("SendEmail_SendFail"), new Exception(ex.Message));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
||||
|
|
@ -73,7 +147,7 @@ public static class SendEmailHelper
|
|||
return true;
|
||||
}
|
||||
|
||||
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig,Trial? trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
{
|
||||
var messageToSend = new MimeMessage();
|
||||
|
||||
|
|
@ -143,7 +217,7 @@ public static class SendEmailHelper
|
|||
|
||||
await smtp.ConnectAsync(sMTPEmailConfig.Host, sMTPEmailConfig.Port, SecureSocketOptions.Auto);
|
||||
|
||||
await smtp.AuthenticateAsync(sMTPEmailConfig.UserName, sMTPEmailConfig.AuthorizationCode);
|
||||
await smtp.AuthenticateAsync(trial.EmailFromEmail, trial.EmailAuthorizationCode);
|
||||
|
||||
await smtp.SendAsync(messageToSend);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,4 +60,16 @@ namespace IRaCIS.Core.Application.Helper
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
|
||||
public class DateTimeTranaslateAttribute : Attribute
|
||||
{
|
||||
public string Formart { get; set; }
|
||||
|
||||
public DateTimeTranaslateAttribute(string formart)
|
||||
{
|
||||
Formart = formart;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using FellowOakDicom.Imaging.LUT;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore.Migrations;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using MiniExcelLibs;
|
||||
using MiniExcelLibs.OpenXml;
|
||||
using Newtonsoft.Json;
|
||||
using NPOI.HSSF.UserModel;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using NPOI.SS.UserModel;
|
||||
|
|
@ -681,13 +685,61 @@ public static class ExcelExportHelper
|
|||
if (itemDicName.IsNotNullOrEmpty())
|
||||
{
|
||||
|
||||
var translatedItemData = dynamicTranslateDataList[itemDicName].Where(t => t.Code.ToLower() == itemValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
var optionTypeEnumStr = iteObjDic.ContainsKey("OptionTypeEnum") ? iteObjDic["OptionTypeEnum"]?.ToString() : "0";
|
||||
|
||||
var translatedItemData = "";
|
||||
//多选
|
||||
if (optionTypeEnumStr == "1")
|
||||
{
|
||||
int[] enumValues = new int[0];
|
||||
// 1. 反序列化 JSON 数组 (字符串枚举)
|
||||
if (!itemValue.StartsWith("[") || !itemValue.EndsWith("]"))
|
||||
{
|
||||
enumValues = new int[1] { int.Parse(itemValue) };
|
||||
}
|
||||
else
|
||||
{
|
||||
enumValues = JsonConvert.DeserializeObject<int[]>(itemValue) ?? new int[0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 2. 翻译每一项并输出逗号拼接字符串
|
||||
translatedItemData = string.Join(",",
|
||||
enumValues.Select(code =>
|
||||
dynamicTranslateDataList[itemDicName]
|
||||
.FirstOrDefault(t =>
|
||||
string.Equals(code.ToString(), t.Code, StringComparison.OrdinalIgnoreCase)
|
||||
) is var r && r != null
|
||||
? (isEn_US ? r.Value : r.ValueCN)
|
||||
: string.Empty
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
translatedItemData = dynamicTranslateDataList[itemDicName].Where(t => t.Code.ToLower() == itemValue?.ToLower()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
|
||||
}
|
||||
|
||||
row.GetCell(writeIndex).SetCellValue(translatedItemData);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
row.GetCell(writeIndex).SetCellValue(itemValue);
|
||||
var unit = iteObjDic.ContainsKey("Unit") ? iteObjDic["Unit"]?.ToString() : null;
|
||||
|
||||
if (unit.IsNotNullOrEmpty() && unit == "9")
|
||||
{
|
||||
row.GetCell(writeIndex).SetCellValue(itemValue + "%");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
row.GetCell(writeIndex).SetCellValue(itemValue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1038,6 +1090,34 @@ public static class ExcelExportHelper
|
|||
|
||||
|
||||
|
||||
public static async Task<IActionResult> MutiSheetDataExportAsync(string code, object data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
|
||||
var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
||||
|
||||
|
||||
//模板路径
|
||||
var tplPath = physicalPath;
|
||||
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
|
||||
var config = new OpenXmlConfiguration()
|
||||
{
|
||||
IgnoreTemplateParameterMissing = true,
|
||||
};
|
||||
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, data, config);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
|
||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
{
|
||||
FileDownloadName = $"{(string.IsNullOrEmpty(exportFileNamePrefix) ? "" : exportFileNamePrefix + "_")}{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出文件模板
|
||||
/// </summary>
|
||||
|
|
@ -1119,4 +1199,7 @@ public static class ExcelExportHelper
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ public enum ObjectStoreUse
|
|||
public interface IOSSService
|
||||
{
|
||||
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
|
||||
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true);
|
||||
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false);
|
||||
|
||||
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
||||
|
||||
|
|
@ -322,9 +322,10 @@ public class OSSService : IOSSService
|
|||
/// <param name="localFilePath"></param>
|
||||
/// <param name="oosFolderPath"></param>
|
||||
/// <param name="isFileNameAddGuid"></param>
|
||||
/// <param name="randomFileName">随机文件名</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
|
||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false)
|
||||
{
|
||||
BackBatchGetToken();
|
||||
|
||||
|
|
@ -332,6 +333,11 @@ public class OSSService : IOSSService
|
|||
|
||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
||||
|
||||
if (randomFileName)
|
||||
{
|
||||
var fileExtension = localFileName.Split(".").LastOrDefault();
|
||||
ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}.{fileExtension}";
|
||||
}
|
||||
|
||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||
{
|
||||
|
|
@ -498,11 +504,14 @@ public class OSSService : IOSSService
|
|||
|
||||
var result = _ossClient.GetObject(aliConfig.BucketName, ossRelativePath);
|
||||
|
||||
// 将OSS返回的流复制到内存流中并返回
|
||||
var memoryStream = new MemoryStream();
|
||||
await result.Content.CopyToAsync(memoryStream);
|
||||
memoryStream.Position = 0; // 重置位置以便读取
|
||||
return memoryStream;
|
||||
// 直接返回流
|
||||
return result.Content;
|
||||
|
||||
//// 将OSS返回的流复制到内存流中并返回
|
||||
//var memoryStream = new MemoryStream();
|
||||
//await result.Content.CopyToAsync(memoryStream);
|
||||
//memoryStream.Position = 0; // 重置位置以便读取
|
||||
//return memoryStream;
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
|
|
@ -513,17 +522,31 @@ public class OSSService : IOSSService
|
|||
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey)
|
||||
.WithSSL(minIOConfig.UseSSL)
|
||||
.Build();
|
||||
|
||||
var pipe = new System.IO.Pipelines.Pipe();
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var args = new GetObjectArgs()
|
||||
.WithBucket(minIOConfig.BucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithCallbackStream(stream =>
|
||||
{
|
||||
stream.CopyTo(pipe.Writer.AsStream());
|
||||
});
|
||||
|
||||
var getObjectArgs = new GetObjectArgs()
|
||||
.WithBucket(minIOConfig.BucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithCallbackStream(stream => stream.CopyToAsync(memoryStream));
|
||||
await minioClient.GetObjectAsync(args);
|
||||
await pipe.Writer.CompleteAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await pipe.Writer.CompleteAsync(ex);
|
||||
}
|
||||
});
|
||||
|
||||
await minioClient.GetObjectAsync(getObjectArgs);
|
||||
memoryStream.Position = 0;
|
||||
return memoryStream;
|
||||
return pipe.Reader.AsStream();
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
|
|
@ -551,10 +574,13 @@ public class OSSService : IOSSService
|
|||
|
||||
var response = await amazonS3Client.GetObjectAsync(getObjectRequest);
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
await response.ResponseStream.CopyToAsync(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
return memoryStream;
|
||||
// ⭐ 直接返回流
|
||||
return response.ResponseStream;
|
||||
|
||||
//var memoryStream = new MemoryStream();
|
||||
//await response.ResponseStream.CopyToAsync(memoryStream);
|
||||
//memoryStream.Position = 0;
|
||||
//return memoryStream;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -892,7 +918,7 @@ public class OSSService : IOSSService
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除某个目录的文件
|
||||
/// 删除某个目录的文件 (包含单个文件,oss单个文件需要去除前缀/)
|
||||
/// </summary>
|
||||
/// <param name="prefix"></param>
|
||||
/// <returns></returns>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@
|
|||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -75,4 +74,8 @@
|
|||
<Folder Include="Service\MinimalApiService\CodeTemplate\FrontTemplate\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Service\TrialSiteUser\TrialStatService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,21 @@
|
|||
using MiniExcelLibs.Attributes;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using MiniExcelLibs.Attributes;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IRaCIS.Core.Application.MassTransit.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// 全量一致性核查
|
||||
/// </summary>
|
||||
public record ConsistenFullCheckCommand
|
||||
{
|
||||
public List<CheckViewModel> ETCList { get; set; } = new List<CheckViewModel>();
|
||||
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid InspectionFileId { get; set; }
|
||||
}
|
||||
|
||||
public record ConsistenCheckCommand
|
||||
{
|
||||
public List<CheckViewModel> ETCList { get; set; } = new List<CheckViewModel>();
|
||||
|
|
@ -17,13 +30,24 @@ namespace IRaCIS.Core.Application.MassTransit.Command
|
|||
|
||||
public class CheckDBModel : CheckViewModel
|
||||
{
|
||||
|
||||
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
|
||||
public Guid StudyId { get; set; }
|
||||
}
|
||||
|
||||
public class FullCheckResult: CheckViewModel
|
||||
{
|
||||
public string LatestScanDateStr { get; set; } = string.Empty;
|
||||
public string Modalitys { get; set; } = string.Empty;
|
||||
public DateTime CheckTime { get; set; }
|
||||
|
||||
public string CheckResult { get; set; }
|
||||
|
||||
|
||||
[DictionaryTranslateAttribute("CheckState")]
|
||||
public CheckStateEnum CheckState { get; set; }
|
||||
}
|
||||
|
||||
|
||||
//[ExcelImporter(/*ImportResultFilter = typeof(ImportResultFilteTest),*/ IsLabelingError = true)]
|
||||
|
|
@ -62,8 +86,13 @@ namespace IRaCIS.Core.Application.MassTransit.Command
|
|||
[ExcelColumnName("Modality")]
|
||||
public string Modality { get; set; } = string.Empty;
|
||||
|
||||
#region 全量一致性核查加入
|
||||
[DictionaryTranslateAttribute("Subject_Visit_Status")]
|
||||
public SubjectStatus SubjectStatus { get; set; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,53 +1,49 @@
|
|||
using AutoMapper;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts.DTO;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace IRaCIS.Core.Application.MassTransit.Consumer
|
||||
{
|
||||
public class ConsistencyCheckConsumer : IConsumer<ConsistenCheckCommand>
|
||||
public class ConsistencyCheckConsumer(
|
||||
IRepository<DicomStudy> _studyRepository,
|
||||
IUserInfo _userInfo,
|
||||
IRepository<Subject> _subjectRepository,
|
||||
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
|
||||
IRepository<SubjectVisit> _subjectVisitRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IOSSService _oSSService,
|
||||
IMapper _mapper,
|
||||
IDictionaryService _dictionaryService,
|
||||
IRepository<CommonDocument> _commonDocumentRepository,
|
||||
IStringLocalizer _localizer,
|
||||
IWebHostEnvironment _hostEnvironment,
|
||||
IRepository<InspectionFile> _inspectionFileRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> _systemEmailSendConfig
|
||||
) : IConsumer<ConsistenCheckCommand>, IConsumer<ConsistenFullCheckCommand>
|
||||
{
|
||||
|
||||
private readonly IRepository<DicomStudy> _studyRepository;
|
||||
private readonly IUserInfo _userInfo;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||||
private readonly IRepository<TrialSite> _trialSiteRepository;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
|
||||
public IStringLocalizer _localizer { get; set; }
|
||||
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig;
|
||||
|
||||
private readonly IRepository<Dictionary> _dictionaryRepository;
|
||||
/// <summary>
|
||||
/// 构造函数注入
|
||||
/// </summary>
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = _systemEmailSendConfig.CurrentValue;
|
||||
|
||||
|
||||
public ConsistencyCheckConsumer(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
|
||||
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
|
||||
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
|
||||
IMapper mapper, IStringLocalizer localizer, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IRepository<Dictionary> dictionaryRepository)
|
||||
{
|
||||
_noneDicomStudyRepository = noneDicomStudyRepository;
|
||||
_studyRepository = studyRepository;
|
||||
_userInfo = userInfo;
|
||||
_subjectRepository = subjectRepository;
|
||||
_subjectVisitRepository = subjectVisitRepository;
|
||||
_trialSiteRepository = trialSiteRepository;
|
||||
_mapper = mapper;
|
||||
_localizer = localizer;
|
||||
|
||||
_systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
_dictionaryRepository = dictionaryRepository;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -67,8 +63,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||
|
||||
//subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
||||
|
||||
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == trialId && x.Subject.IsSubjectQuit == false &&
|
||||
(x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
|
||||
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == trialId && x.Subject.IsSubjectQuit == false && x.AuditState == AuditStateEnum.QCPassed &&
|
||||
(x.CheckState == CheckStateEnum.ToCheck || x.CheckState == CheckStateEnum.CVIng);
|
||||
|
||||
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
|
||||
|
|
@ -86,7 +82,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||
|
||||
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
|
||||
join noneDicomStudy in _noneDicomStudyRepository.AsQueryable() on sv.Id equals noneDicomStudy.SubjectVisitId
|
||||
join noneDicomStudy in _noneDicomStudyRepository.Where(t => t.FileCount > 0) on sv.Id equals noneDicomStudy.SubjectVisitId
|
||||
select new CheckDBModel()
|
||||
{
|
||||
SubjectVisitId = sv.Id,
|
||||
|
|
@ -117,7 +113,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||
foreach (var sv in svExcelGroup)
|
||||
{
|
||||
|
||||
//Excel 的数据 在IRC 中可以找到该访视
|
||||
//Excel 的数据 在IRC 中可以找到该访视(一致性核查中,或者待核查)
|
||||
if (dbCheckList.Any(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName))
|
||||
{
|
||||
|
||||
|
|
@ -201,7 +197,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||
var dbExceptExcel = dbVisitStudyList.Except(etcVisitStudyList);
|
||||
|
||||
// excel 存在
|
||||
var excelExceptDB = etcVisitStudyList.Except(dbCheckList);
|
||||
var excelExceptDB = etcVisitStudyList.Except(dbVisitStudyList);
|
||||
|
||||
//ETC 和系统的完全一致 两者没有差别
|
||||
if (dbExceptExcel.Count() == 0 && excelExceptDB.Count() == 0)
|
||||
|
|
@ -301,12 +297,169 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||
}
|
||||
await _subjectVisitRepository.SaveChangesAsync();
|
||||
|
||||
//await context.RespondAsync<ConsistenCheckResult>(new
|
||||
//{
|
||||
|
||||
//});
|
||||
}
|
||||
|
||||
public async Task Consume(ConsumeContext<ConsistenFullCheckCommand> context)
|
||||
{
|
||||
var inspectionFileId = context.Message.InspectionFileId;
|
||||
var trialId = context.Message.TrialId;
|
||||
|
||||
//系统定义MRI 到底是MR 还是MRI
|
||||
var mriModality = await _dictionaryRepository.Where(t => t.Parent.Code == "Modality").Where(t => t.Code == "MRI").Select(t => t.Value).FirstNotNullAsync();
|
||||
|
||||
//处理Excel大小写
|
||||
context.Message.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
|
||||
var etcList = context.Message.ETCList;
|
||||
|
||||
|
||||
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == trialId /*&& x.Subject.IsSubjectQuit == false*/ && x.AuditState == AuditStateEnum.QCPassed;
|
||||
|
||||
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
|
||||
join study in _studyRepository.AsQueryable() on sv.Id equals study.SubjectVisitId
|
||||
select new CheckDBModel()
|
||||
{
|
||||
SubjectStatus = sv.Subject.Status,
|
||||
SubjectVisitId = sv.Id,
|
||||
SiteCode = sv.TrialSite.TrialSiteCode,
|
||||
StudyDate = study.StudyTime == null ? string.Empty : ((DateTime)study.StudyTime).ToString("yyyy-MM-dd"),
|
||||
StudyId = study.Id,
|
||||
Modality = study.ModalityForEdit,
|
||||
SubjectCode = subject.Code,
|
||||
VisitName = sv.VisitName,
|
||||
};
|
||||
|
||||
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
|
||||
join noneDicomStudy in _noneDicomStudyRepository.Where(t => t.FileCount > 0) on sv.Id equals noneDicomStudy.SubjectVisitId
|
||||
select new CheckDBModel()
|
||||
{
|
||||
SubjectStatus = sv.Subject.Status,
|
||||
SubjectVisitId = sv.Id,
|
||||
SiteCode = sv.TrialSite.TrialSiteCode,
|
||||
StudyDate = noneDicomStudy.ImageDate.ToString("yyyy-MM-dd"),
|
||||
StudyId = noneDicomStudy.Id,
|
||||
Modality = noneDicomStudy.Modality,
|
||||
SubjectCode = subject.Code,
|
||||
VisitName = sv.VisitName,
|
||||
};
|
||||
|
||||
var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();
|
||||
|
||||
//处理数据库 大小写
|
||||
dbList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
|
||||
|
||||
var dbCheckList = _mapper.Map<List<CheckViewModel>>(dbList);
|
||||
|
||||
|
||||
//按照Excel数据访视分组 按照数据库的数据 一个个的访视对比
|
||||
var svExcelGroup = etcList.GroupBy(t => new { t.SiteCode, t.SubjectCode, t.VisitName })
|
||||
.Select(g => new { g.Key.SubjectCode, g.Key.VisitName, g.Key.SiteCode, ExcelStudyList = g.ToList() }).ToList();
|
||||
|
||||
var fullCheckResultList = new List<FullCheckResult>();
|
||||
|
||||
|
||||
foreach (var sv in svExcelGroup)
|
||||
{
|
||||
|
||||
//Excel 的数据 在IRC 中可以找到该访视(一致性核查中,或者待核查)
|
||||
if (dbCheckList.Any(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName))
|
||||
{
|
||||
|
||||
var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
||||
|
||||
//找到etc 当前visit site 和subject 一致的检查列表
|
||||
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
||||
|
||||
|
||||
//以我们系统数据库为准 ,判断是MR 还是MRI, 把Excel 里的MR 或者MRI 处理成一致,MR MRI 是一致的
|
||||
foreach (var item in etcVisitStudyList)
|
||||
{
|
||||
if (item.Modality == "MR" || item.Modality == "MRI")
|
||||
{
|
||||
item.Modality = mriModality;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//etc 和数据库 并集
|
||||
var unionList = dbVisitStudyList.Union(etcVisitStudyList);
|
||||
// 数据库存在
|
||||
var dbExceptExcel = dbVisitStudyList.Except(etcVisitStudyList);
|
||||
|
||||
// excel 存在
|
||||
var excelExceptDB = etcVisitStudyList.Except(dbVisitStudyList);
|
||||
|
||||
var dbCurrentVisitFirst = dbVisitStudyList.First();
|
||||
|
||||
//ETC 和系统的完全一致 两者没有差别
|
||||
if (dbExceptExcel.Count() == 0 && excelExceptDB.Count() == 0)
|
||||
{
|
||||
|
||||
|
||||
//每个受试者每个访视加一条记录
|
||||
fullCheckResultList.Add(new FullCheckResult()
|
||||
{
|
||||
SubjectStatus = dbCurrentVisitFirst.SubjectStatus,
|
||||
CheckTime = DateTime.Now,
|
||||
CheckState=CheckStateEnum.CVPassed,
|
||||
SiteCode = dbCurrentVisitFirst.SiteCode,
|
||||
SubjectCode = dbCurrentVisitFirst.SubjectCode,
|
||||
VisitName = dbCurrentVisitFirst.VisitName,
|
||||
Modalitys = string.Join('、', dbVisitStudyList.Select(t => t.Modality)),
|
||||
LatestScanDateStr = dbVisitStudyList.Select(t => t.StudyDate).MaxBy(d => DateTime.Parse(d)) ?? ""
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var checkResult =
|
||||
String.Join(" | ", dbExceptExcel.Select(t => $"{_localizer["ConsistencyVerification_EdcL", t.StudyDate, t.Modality/*, _systemEmailConfig.SystemShortName*/]}")) + " | "
|
||||
+ String.Join(" | ", excelExceptDB.Select(t => $"{_localizer["ConsistencyVerification_IrcLi", t.StudyDate, t.Modality, _systemEmailConfig.SystemShortName]}"));
|
||||
|
||||
//每个受试者每个访视加一条记录
|
||||
fullCheckResultList.Add(new FullCheckResult()
|
||||
{
|
||||
SubjectStatus = dbCurrentVisitFirst.SubjectStatus,
|
||||
CheckState = CheckStateEnum.None,
|
||||
CheckTime = DateTime.Now,
|
||||
SiteCode = dbCurrentVisitFirst.SiteCode,
|
||||
SubjectCode = dbCurrentVisitFirst.SubjectCode,
|
||||
VisitName = dbCurrentVisitFirst.VisitName,
|
||||
Modalitys = string.Join('、', dbVisitStudyList.Select(t => t.Modality)),
|
||||
LatestScanDateStr = dbVisitStudyList.Select(t => t.StudyDate).MaxBy(d => DateTime.Parse(d)) ?? "",
|
||||
CheckResult = checkResult
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//导到Excel 上传oss 回更记录状态
|
||||
|
||||
var list = fullCheckResultList;
|
||||
|
||||
var exportInfo = new ExcelExportInfo();
|
||||
|
||||
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||
|
||||
var fileStreamResult = (FileStreamResult)await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialConsistentFUllCheckList_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(FullCheckResult));
|
||||
|
||||
var ossRelativePath = await _oSSService.UploadToOSSAsync(fileStreamResult.FileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", "DataReconciliation");
|
||||
|
||||
|
||||
//var add = await _inspectionFileRepository.FindAsync(inspectionFileId);
|
||||
//add.CheckState = EDCCheckState.Success;
|
||||
//add.ResultPath = ossRelativePath;
|
||||
|
||||
//更新
|
||||
await _inspectionFileRepository.BatchUpdateNoTrackingAsync(t => t.Id == inspectionFileId, u => new InspectionFile() { CheckState = EDCCheckState.Success, ResultPath = ossRelativePath });
|
||||
|
||||
await _subjectVisitRepository.SaveChangesAsync();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,12 +339,12 @@ public class ImageConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
// 发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
// 添加抄送
|
||||
foreach (var ccUser in ccUserList)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
||||
}
|
||||
// 格式化邮件内容
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
|
|
@ -365,9 +365,11 @@ public class ImageConsumer(
|
|||
return (topicStr, htmlBodyStr);
|
||||
};
|
||||
|
||||
|
||||
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,12 +474,12 @@ public class ImageConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
// 发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
// 添加抄送
|
||||
foreach (var ccUser in ccUserList)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
||||
}
|
||||
|
||||
// 格式化邮件内容
|
||||
|
|
@ -500,7 +502,7 @@ public class ImageConsumer(
|
|||
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -128,7 +128,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -236,7 +236,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||
};
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -308,7 +308,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -353,8 +353,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||
};
|
||||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -419,7 +418,7 @@ public class UrgentIRApplyedReReadingConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -463,7 +462,7 @@ public class UrgentIRApplyedReReadingConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Vml;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.MassTransit.Command;
|
||||
|
|
@ -122,7 +123,7 @@ public class UserSiteSurveySubmitedEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -205,7 +206,7 @@ public class SiteSurveySPMSubmitedEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ public class SiteSurverRejectedEventConsumer(
|
|||
{
|
||||
//没有SPM PM驳回到CRC
|
||||
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, siteSurveyInfo.Email));
|
||||
messageToSend.To.Add(new MailboxAddress(siteSurveyInfo.UserName, siteSurveyInfo.Email));
|
||||
}
|
||||
|
||||
//发件地址
|
||||
|
|
@ -319,7 +320,7 @@ public class SiteSurverRejectedEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -89,14 +89,14 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
|
|||
|
||||
foreach (var userinfo in userinfoList)
|
||||
{
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
}
|
||||
|
||||
var userNames = userinfoList.Select(x => x.FullName).ToList();
|
||||
|
||||
foreach (var pm in pmandAPm)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(pm.FullName, pm.EMail));
|
||||
}
|
||||
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -122,7 +122,7 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -181,11 +181,11 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
foreach (var pm in pmandAPm)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(pm.FullName, pm.EMail));
|
||||
}
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||
};
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -307,10 +307,10 @@ public class QCRepliedQCChallengeEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
if (craInfo != null)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail));
|
||||
}
|
||||
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -339,7 +339,7 @@ public class QCRepliedQCChallengeEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -439,7 +439,7 @@ public class CRCRepliedCheckChallengeEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -517,10 +517,10 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
if (craInfo != null)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, craInfo.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail));
|
||||
}
|
||||
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -549,7 +549,7 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -620,7 +620,7 @@ public class CheckStateChangedToAuditEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
|
@ -648,7 +648,7 @@ public class CheckStateChangedToAuditEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -707,11 +707,11 @@ public class QCClaimTaskEventConsumer(
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
foreach (var pm in pmandAPm)
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(String.Empty, pm.EMail));
|
||||
messageToSend.Cc.Add(new MailboxAddress(pm.FullName, pm.EMail));
|
||||
}
|
||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
|
|
@ -757,7 +757,7 @@ public class QCClaimTaskEventConsumer(
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Contracts;
|
|||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using MassTransit;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
|
|
@ -26,6 +27,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
public class UrgentIRUnReadTaskRecurringEventConsumer(
|
||||
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<Trial> _trialRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigrepository,
|
||||
|
|
@ -38,6 +40,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||
var trialId = context.Message.TrialId;
|
||||
|
||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||
var scenario = EmailBusinessScenario.ExpeditedReading;
|
||||
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||
|
||||
|
|
@ -161,7 +164,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
|
||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
|
||||
//处理标记已通知的任务
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public static class OldRecurringEmailHelper
|
|||
var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true)
|
||||
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
|
||||
|
||||
var trialInfo=await _trialRepository.Where(t=>t.Id== trialId).FirstOrDefaultAsync();
|
||||
|
||||
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable == false)
|
||||
{
|
||||
|
|
@ -162,7 +163,7 @@ public static class OldRecurringEmailHelper
|
|||
if (sendEmailConfig != null)
|
||||
{
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig, trialInfo);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ using System.Threading.Tasks;
|
|||
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||
|
||||
|
||||
|
||||
//项目手动选择 周期性邮件
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -25,9 +25,11 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
|
|||
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository,
|
||||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IRepository<TrialSiteUserRole> _trialSiteUserRoleRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<QCImageQuestionRecurringEvent>
|
||||
{
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
public async Task Consume(ConsumeContext<QCImageQuestionRecurringEvent> context)
|
||||
{
|
||||
var trialId = context.Message.TrialId;
|
||||
|
|
@ -64,8 +66,9 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
|
|||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||
{
|
||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||
user.FullName, DateTime.Now, sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
|
||||
return (topicStr, htmlBodyStr, isEn_us, userId);
|
||||
};
|
||||
|
|
@ -91,8 +94,10 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
|
|||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<TrialSiteUserRole> _trialSiteUserRoleRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<CRCImageQuestionRecurringEvent>
|
||||
{
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
public async Task Consume(ConsumeContext<CRCImageQuestionRecurringEvent> context)
|
||||
{
|
||||
var trialId = context.Message.TrialId;
|
||||
|
|
@ -131,9 +136,10 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
|
|||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||
{
|
||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
||||
|
||||
user.FullName, DateTime.Now, sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
|
||||
|
||||
return (topicStr, htmlBodyStr, false, userId);
|
||||
|
|
@ -158,8 +164,11 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
|||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<TrialSiteUserRole> _trialSiteUserRoleRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig) : IConsumer<ImageQCRecurringEvent>
|
||||
{
|
||||
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context)
|
||||
{
|
||||
var trialId=context.Message.TrialId;
|
||||
|
|
@ -199,9 +208,12 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
|||
|
||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||
{
|
||||
|
||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
|
||||
user.FullName, DateTime.Now, sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
|
||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||
|
||||
return (topicStr, htmlBodyStr, false, userId);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
if (emailConfig != null)
|
||||
{
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Reactive.Joins;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
|
@ -112,7 +113,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
|
||||
|
||||
|
|
@ -137,7 +138,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
if (emailConfig != null)
|
||||
{
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +163,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<TrialDocument> _trialDocumentRepository,
|
||||
IRepository<IdentityUser> _identityUserRepository,
|
||||
IRepository<Trial> _trialRepository,
|
||||
IRepository<TrialIdentityUser> _trialIdentityUserRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
|
|
@ -198,6 +200,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
{
|
||||
IsSystemDoc = true,
|
||||
Id = trialDoc.Id,
|
||||
TrialId= trialDoc.TrialId,
|
||||
CreateTime = trialDoc.CreateTime,
|
||||
IsDeleted = trialDoc.IsDeleted,
|
||||
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
||||
|
|
@ -219,7 +222,9 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
||||
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
||||
join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
||||
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
||||
|
||||
join trial in _trialRepository.AsQueryable(false) on trialDoc.TrialId equals trial.Id
|
||||
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
||||
on trialIdentityUser.IdentityUserId equals identityUser.Id
|
||||
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
||||
|
||||
|
|
@ -228,6 +233,8 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
{
|
||||
IsSystemDoc = false,
|
||||
Id = trialDoc.Id,
|
||||
TrialId = trialDoc.TrialId,
|
||||
EmailFromName =trial.EmailFromName,
|
||||
CreateTime = trialDoc.CreateTime,
|
||||
IsDeleted = trialDoc.IsDeleted,
|
||||
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
||||
|
|
@ -242,6 +249,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
FullFilePath = trialDoc.Path
|
||||
};
|
||||
}
|
||||
|
||||
var datalist = await systemDocQuery.IgnoreQueryFilters().ToListAsync();
|
||||
|
||||
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
||||
|
|
@ -257,7 +265,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||
|
||||
|
||||
|
||||
|
|
@ -283,7 +291,12 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||
{
|
||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
var trial = datalist.Where(x => x.ConfirmUserId == userinfo.Id).FirstOrDefault();
|
||||
|
||||
var trialInfo = await _trialRepository.Where(x=>x.Id==trial.TrialId).FirstNotNullAsync();
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
msg += "发送成功";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -490,6 +490,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
|
||||
public int? RandomOrder { get; set; }
|
||||
public bool? IsRandomOrderList { get; set; }
|
||||
|
||||
public CriterionType? CriterionType { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1027,8 +1027,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
//满足前序访视不存在 需要签署但是未签署 sql 相当复杂 同时想查询所有未读的统计数字 就无法统计 byzhouhang
|
||||
//但是加字段 IsFrontTaskNeedSignButNotSign 那么签名临床数据的时候,要对该subject 该标准的有效的任务 这个字段需要在签名的时候维护 采取这种方式 统计数字灵活
|
||||
//.Where(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(visitTaskLambda).Any(c => c.IsNeedClinicalDataSign == true && c.IsClinicalDataSign == false && c.VisitTaskNum < t.VisitTaskNum))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate));
|
||||
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode!) && t.IsAnalysisCreate))
|
||||
;
|
||||
|
||||
var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
|
||||
|
||||
|
|
@ -1171,7 +1171,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == trialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect)
|
||||
.WhereIf(inQuery.SubjectId != null, x => x.SubjectId == inQuery.SubjectId)
|
||||
.WhereIf(!string.IsNullOrEmpty(subjectCode), t => (t.Subject.Code.Contains(subjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(subjectCode!) && t.IsAnalysisCreate));
|
||||
.WhereIf(!string.IsNullOrEmpty(subjectCode), t => (t.Subject.Code.Contains(subjectCode!) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(subjectCode!) && t.IsAnalysisCreate))
|
||||
.WhereIf(critrion.CriterionType == CriterionType.OCT, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t=>t.Modality=="OCT").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true)
|
||||
.WhereIf(critrion.CriterionType == CriterionType.IVUS, t => t.ReadingCategory == ReadingCategory.Visit ? t.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.Modality == "IVUS").SelectMany(t => t.ImageLabelNoneDicomFileList).Any() : true);
|
||||
|
||||
var visitGroupQuery = visitQuery.GroupBy(x => new { x.SubjectId, x.Subject.Code, x.BlindSubjectCode });
|
||||
|
||||
|
|
@ -2081,7 +2083,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
{
|
||||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
||||
{
|
||||
CopyForms(newTask, origenalTask);
|
||||
newTask.IsCopyLesionAnswer = true;
|
||||
|
||||
//CopyForms(newTask, origenalTask);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2179,7 +2183,6 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
||||
{
|
||||
CopyForms(newTask, origenalTask);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2189,7 +2192,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
{
|
||||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
||||
{
|
||||
CopyForms(newTask, origenalTask);
|
||||
newTask.IsCopyLesionAnswer = true;
|
||||
//CopyForms(newTask, origenalTask);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2214,7 +2218,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
private void CopyForms(VisitTask newTask, VisitTask origenalTask)
|
||||
{
|
||||
|
||||
newTask.IsCopyLesionAnswer = true;
|
||||
//自定义
|
||||
//var readingCustomTagList = _readingCustomTagRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||
|
||||
|
|
@ -2256,7 +2260,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
|
||||
//ReadingTableAnswerRowInfo ReadingTableQuestionAnswer 一起加
|
||||
var readingTableAnswerRowInfoList = _readingTableAnswerRowInfoRepository.Where(t => t.VisitTaskId == origenalTask.Id).Include(t => t.LesionAnswerList).ToList();
|
||||
|
||||
Dictionary<Guid, Guid> lesionRelationship = new Dictionary<Guid, Guid>() { };
|
||||
foreach (var item in readingTableAnswerRowInfoList)
|
||||
{
|
||||
|
||||
|
|
@ -2264,7 +2268,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
var originalFristAddTaskId = item.FristAddTaskId;
|
||||
|
||||
var newRowId = NewId.NextSequentialGuid();
|
||||
|
||||
lesionRelationship.Add(item.Id, newRowId);
|
||||
foreach (var mark in readingTaskQuestionMarkList)
|
||||
{
|
||||
mark.RowId = mark.RowId == item.Id ? newRowId : mark.RowId;
|
||||
|
|
@ -2286,6 +2290,19 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var item in readingTableAnswerRowInfoList)
|
||||
{
|
||||
if (item.SplitRowId!=null&&lesionRelationship.ContainsKey(item.SplitRowId.Value))
|
||||
{
|
||||
item.SplitRowId = lesionRelationship[item.SplitRowId.Value];
|
||||
}
|
||||
|
||||
if (item.MergeRowId!=null&&lesionRelationship.ContainsKey(item.MergeRowId.Value))
|
||||
{
|
||||
item.MergeRowId = lesionRelationship[item.MergeRowId.Value];
|
||||
}
|
||||
}
|
||||
|
||||
_ = _readingTaskQuestionMarkRepository.AddRangeAsync(readingTaskQuestionMarkList).Result;
|
||||
_ = _readingTableAnswerRowInfoRepository.AddRangeAsync(readingTableAnswerRowInfoList).Result;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-28 06:22:47Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
namespace IRaCIS.Core.Application.ViewModel;
|
||||
|
||||
|
||||
public class GetReSendEmailInDto : PageInput
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
|
||||
public DateTime? EmailStartDate { get; set; }
|
||||
|
||||
public DateTime? EmailEndDate { get; set; }
|
||||
|
||||
public EmailState? EmailStateEnum { get; set; }
|
||||
|
||||
public string ToRecipientName { get; set; } = string.Empty;
|
||||
|
||||
public string CcRecipientName { get; set; } = string.Empty;
|
||||
}
|
||||
public class EmailLogView : EmailLogAddOrEdit
|
||||
{
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
public List<EmailRecipientLogView> RecipientList { get; set; }
|
||||
|
||||
public List<EmaliAttachmentInfo> AttachmentList { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class EmaliAttachmentInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 附件名称
|
||||
/// </summary>
|
||||
public string AttachmentName { get; set; }
|
||||
/// <summary>
|
||||
/// 附件路径
|
||||
/// </summary>
|
||||
public string AttachmentPath { get; set; }
|
||||
}
|
||||
|
||||
public class EmailRecipientLogView
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮件Id
|
||||
/// </summary>
|
||||
public Guid EmailLogId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 收件人姓名
|
||||
/// </summary>
|
||||
public string RecipientName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 收件人地址
|
||||
/// </summary>
|
||||
public string RecipientAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 收件人类型
|
||||
/// </summary>
|
||||
public RecipientType RecipientTypeEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
public int Sort { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class EmailLogAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮件Id
|
||||
/// </summary>
|
||||
public string MessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 唯一Id
|
||||
/// </summary>
|
||||
public string UniqueId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮件主题
|
||||
/// </summary>
|
||||
public string EmailSubject { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 日期
|
||||
/// </summary>
|
||||
public DateTime? EmailDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
public string ErrorInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发件人地址
|
||||
/// </summary>
|
||||
public string SenderAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发件人姓名
|
||||
/// </summary>
|
||||
public string SenderName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮件内容
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邮件状态
|
||||
/// </summary>
|
||||
public EmailState EmailStateEnum { get; set; }
|
||||
}
|
||||
|
||||
public class GetEmailInfoOutDto:EmailLogView
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class GetEmailInfoInDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid? TrialId { get; set; }
|
||||
}
|
||||
|
||||
public class SynchronizationEmailInDto
|
||||
{
|
||||
public Guid? TrialId { get; set; }
|
||||
}
|
||||
|
||||
public class ResendEmailInDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid? TrialId { get; set; }
|
||||
}
|
||||
|
||||
public class EmailAuthorization
|
||||
{
|
||||
public string FromEmail { get; set; } = string.Empty;
|
||||
|
||||
public string AuthorizationCode { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class EmailLogQuery:PageInput
|
||||
{
|
||||
|
||||
public Guid? TrialId { get; set; }
|
||||
|
||||
public DateTime? EmailStartDate { get; set; }
|
||||
|
||||
public DateTime? EmailEndDate { get; set; }
|
||||
|
||||
public EmailState? EmailStateEnum { get; set; }
|
||||
|
||||
public string ToRecipientName { get; set; } = string.Empty;
|
||||
|
||||
public string CcRecipientName { get; set; } = string.Empty;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -159,6 +159,12 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
public class FrontAuditConfigAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适用的标准
|
||||
/// </summary>
|
||||
public List<CriterionType> ApplyCriterionList { get; set; } = new List<CriterionType>() { };
|
||||
|
||||
public string Value { get; set; } = string.Empty;
|
||||
public string ValueCN { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.Common.DTO
|
||||
{
|
||||
//public class MailModel
|
||||
//{
|
||||
//}
|
||||
}
|
||||
|
|
@ -0,0 +1,747 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-28 06:22:42Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using IdentityModel.Client;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using MailKit;
|
||||
using MailKit.Net.Imap;
|
||||
using MailKit.Search;
|
||||
using MailKit.Security;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
using Panda.DynamicWebApi.Attributes;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Threading.Tasks;
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件日志
|
||||
/// </summary>
|
||||
/// <param name="_emailLogRepository"></param>
|
||||
/// <param name="systemEmailConfig"></param>
|
||||
/// <param name="_mapper"></param>
|
||||
/// <param name="_userInfo"></param>
|
||||
/// <param name="_localizer"></param>
|
||||
[ApiExplorerSettings(GroupName = "Common")]
|
||||
public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
||||
IRepository<Trial> _trialRepository,
|
||||
IRepository<EmailAttachmentLog> _emailAttachmentLogRepository,
|
||||
IOSSService oSSService,
|
||||
IRepository<EmailReSendLog> _emailReSendLog,
|
||||
|
||||
IRepository<EmailRecipientLog> _emailRecipientLogRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService, IEmailLogService
|
||||
{
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
|
||||
/// <summary>
|
||||
/// 获取邮件日志列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<EmailLogView>> GetEmailLogList(EmailLogQuery inDto)
|
||||
{
|
||||
var emailFromName = await _trialRepository.Where(x=>x.Id==inDto.TrialId).Select(x=>x.EmailFromName).FirstOrDefaultAsync();
|
||||
|
||||
if (emailFromName.IsNullOrEmpty())
|
||||
{
|
||||
emailFromName = _systemEmailConfig.FromName;
|
||||
}
|
||||
var emailLogQueryable = _emailLogRepository
|
||||
.Where(x=>x.SenderName== emailFromName)
|
||||
.WhereIf(inDto.EmailStartDate.HasValue, x => x.EmailDate >= inDto.EmailStartDate.Value)
|
||||
.WhereIf(inDto.EmailEndDate.HasValue, x => x.EmailDate <= inDto.EmailEndDate.Value)
|
||||
.WhereIf(inDto.EmailStateEnum.HasValue, x => x.EmailStateEnum == inDto.EmailStateEnum.Value)
|
||||
.WhereIf(inDto.CcRecipientName.IsNotNullOrEmpty(),x=>x.EmailRecipientLogList.Any(x=>x.RecipientTypeEnum==RecipientType.Cc&&x.RecipientName.Contains(inDto.CcRecipientName)))
|
||||
.WhereIf(inDto.ToRecipientName.IsNotNullOrEmpty(), x => x.EmailRecipientLogList.Any(x => x.RecipientTypeEnum == RecipientType.To && x.RecipientName.Contains(inDto.ToRecipientName)))
|
||||
.ProjectTo<EmailLogView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var defalutSortArray = new string[] { nameof(EmailLogView.EmailDate) + " desc" };
|
||||
var pageList = await emailLogQueryable.ToPagedListAsync(inDto, defalutSortArray);
|
||||
|
||||
return pageList;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取重发信息
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<EmailLogView>> GetReSendEmail(GetReSendEmailInDto inDto)
|
||||
{
|
||||
var messageId = await _emailLogRepository.Where(x => x.Id == inDto.Id).Select(x => x.MessageId).FirstOrDefaultAsync();
|
||||
|
||||
var reSendMessagelist = await _emailReSendLog.Where(x => x.MainMailMessageId == messageId).Select(x => x.ReMailMessageId).ToListAsync();
|
||||
var emailLogQueryable = _emailLogRepository
|
||||
|
||||
.Where(x => reSendMessagelist.Contains(x.MessageId))
|
||||
.WhereIf(inDto.EmailStartDate.HasValue, x => x.EmailDate >= inDto.EmailStartDate.Value)
|
||||
.WhereIf(inDto.EmailEndDate.HasValue, x => x.EmailDate <= inDto.EmailEndDate.Value)
|
||||
.WhereIf(inDto.EmailStateEnum.HasValue, x => x.EmailStateEnum == inDto.EmailStateEnum.Value)
|
||||
.WhereIf(inDto.CcRecipientName.IsNotNullOrEmpty(), x => x.EmailRecipientLogList.Any(x => x.RecipientTypeEnum == RecipientType.Cc && x.RecipientName.Contains(inDto.CcRecipientName)))
|
||||
.WhereIf(inDto.ToRecipientName.IsNotNullOrEmpty(), x => x.EmailRecipientLogList.Any(x => x.RecipientTypeEnum == RecipientType.To && x.RecipientName.Contains(inDto.ToRecipientName)))
|
||||
.ProjectTo<EmailLogView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var defalutSortArray = new string[] { nameof(EmailLogView.EmailDate) + " desc" };
|
||||
var pageList = await emailLogQueryable.ToPagedListAsync(inDto, defalutSortArray);
|
||||
|
||||
return pageList;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取单条邮件日志详情
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<GetEmailInfoOutDto> GetEmailInfo(GetEmailInfoInDto inDto)
|
||||
{
|
||||
|
||||
var emailInfo=await _emailLogRepository
|
||||
.Where(x => x.Id == inDto.Id).Include(x=>x.EmailRecipientLogList)
|
||||
.ProjectTo<GetEmailInfoOutDto>(_mapper.ConfigurationProvider).AsNoTracking()
|
||||
.FirstNotNullAsync();
|
||||
|
||||
if (emailInfo.UniqueId.IsNotNullOrEmpty())
|
||||
{
|
||||
using (var client = new ImapClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
await AuthenticateImap(client,inDto.TrialId);
|
||||
var sentFolder = OpenSentFolder(client);
|
||||
var uid = new UniqueId(uint.Parse(emailInfo.UniqueId));
|
||||
var message = sentFolder.GetMessage(uid);
|
||||
emailInfo.Content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
||||
|
||||
|
||||
if (emailInfo.AttachmentList.Count == 0)
|
||||
{
|
||||
List< EmaliAttachmentInfo > attachmentInfos = new List<EmaliAttachmentInfo>();
|
||||
foreach (var att in message.Attachments)
|
||||
{
|
||||
EmaliAttachmentInfo emaliAttachmentInfo = new EmaliAttachmentInfo();
|
||||
emaliAttachmentInfo.AttachmentName = att.ContentDisposition?.FileName ?? att.ContentType.Name ?? "unknown";
|
||||
|
||||
// 2. 解码后的流直接上传,不落盘
|
||||
if (att is MimePart part)
|
||||
{
|
||||
// 重要:每次上传新建一个独立流,否则迭代过程中流位置会乱
|
||||
await using var decodeStream = new MemoryStream();
|
||||
await part.Content.DecodeToAsync(decodeStream);
|
||||
decodeStream.Position = 0;
|
||||
|
||||
|
||||
emaliAttachmentInfo.AttachmentPath = await oSSService.UploadToOSSAsync(
|
||||
fileStream: decodeStream,
|
||||
oosFolderPath: $"EmailAttachment/{emailInfo.Id}", // OSS 虚拟目录
|
||||
fileRealName: emaliAttachmentInfo.AttachmentName,
|
||||
isFileNameAddGuid: true); // 让方法自己在文件名前加 Guid
|
||||
|
||||
attachmentInfos.Add(emaliAttachmentInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<EmailAttachmentLog> emailAttachmentLog = attachmentInfos.Select(x => new EmailAttachmentLog()
|
||||
{
|
||||
EmailLogId = emailInfo.Id.Value,
|
||||
AttachmentName = x.AttachmentName,
|
||||
AttachmentPath = x.AttachmentPath,
|
||||
}).ToList();
|
||||
|
||||
await _emailAttachmentLogRepository.AddRangeAsync(emailAttachmentLog);
|
||||
await _emailAttachmentLogRepository.SaveChangesAsync();
|
||||
|
||||
emailInfo.AttachmentList = attachmentInfos;
|
||||
}
|
||||
|
||||
|
||||
sentFolder.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.Disconnect(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", realFileName);
|
||||
|
||||
return emailInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重发邮件
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> ResendEmail(ResendEmailInDto inDto)
|
||||
{
|
||||
var emailInfo = await _emailLogRepository
|
||||
.Where(x => x.Id == inDto.Id)
|
||||
.ProjectTo<GetEmailInfoOutDto>(_mapper.ConfigurationProvider)
|
||||
.FirstNotNullAsync();
|
||||
|
||||
if (emailInfo.UniqueId.IsNotNullOrEmpty())
|
||||
{
|
||||
using (var client = new ImapClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
await AuthenticateImap(client,inDto.TrialId);
|
||||
var sentFolder = OpenSentFolder(client);
|
||||
var uid = new UniqueId(uint.Parse(emailInfo.UniqueId));
|
||||
var message = sentFolder.GetMessage(uid);
|
||||
emailInfo.Content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
||||
sentFolder.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.Disconnect(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var messageToSend = new MimeMessage();
|
||||
// 发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(emailInfo.SenderName, emailInfo.SenderAddress));
|
||||
|
||||
foreach (var item in emailInfo.RecipientList.Where(x => x.RecipientTypeEnum == RecipientType.To))
|
||||
{
|
||||
messageToSend.To.Add(new MailboxAddress(item.RecipientName, item.RecipientAddress));
|
||||
}
|
||||
foreach (var item in emailInfo.RecipientList.Where(x => x.RecipientTypeEnum == RecipientType.Cc))
|
||||
{
|
||||
messageToSend.Cc.Add(new MailboxAddress(item.RecipientName, item.RecipientAddress));
|
||||
}
|
||||
|
||||
|
||||
messageToSend.Subject = emailInfo.EmailSubject;
|
||||
|
||||
var builder = new BodyBuilder();
|
||||
|
||||
builder.HtmlBody = emailInfo.Content;
|
||||
|
||||
messageToSend.Body = builder.ToMessageBody();
|
||||
|
||||
var msgid= await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
|
||||
|
||||
await _emailReSendLog.AddAsync(new EmailReSendLog()
|
||||
{
|
||||
MainMailMessageId= emailInfo.MessageId,
|
||||
ReMailMessageId= msgid
|
||||
});
|
||||
|
||||
await _emailReSendLog.SaveChangesAsync();
|
||||
|
||||
await SynchronizationEmail(new SynchronizationEmailInDto() {
|
||||
|
||||
TrialId= inDto.TrialId
|
||||
});
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步邮件
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> SynchronizationEmail(SynchronizationEmailInDto inDto)
|
||||
{
|
||||
|
||||
var fromEmail = _systemEmailConfig.FromEmail;
|
||||
|
||||
|
||||
if (inDto.TrialId != null)
|
||||
{
|
||||
fromEmail= await _trialRepository.Where(x => x.Id == inDto.TrialId.Value).Select(x => x.EmailFromEmail).FirstNotNullAsync();
|
||||
|
||||
}
|
||||
|
||||
var maxTime = await _emailLogRepository.Where(x=>x.SenderAddress== fromEmail).MaxAsync(t => t.EmailDate);
|
||||
var startDate = maxTime ?? DateTime.MinValue;
|
||||
List<EmailLog> emailList = new List<EmailLog>();
|
||||
List<EmailRecipientLog> EmailRecipientLogList = new List<EmailRecipientLog>();
|
||||
|
||||
// 第一步:同步发件箱邮件
|
||||
using (var client = new ImapClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
await AuthenticateImap(client, inDto.TrialId);
|
||||
var sentFolder = OpenSentFolder(client);
|
||||
|
||||
var searchQuery = SearchQuery.All.And(SearchQuery.DeliveredAfter(startDate));
|
||||
var uids = sentFolder.Search(searchQuery).ToList();
|
||||
|
||||
foreach (var uid in uids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = sentFolder.GetMessage(uid);
|
||||
if (message.Date.DateTime <= startDate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var emaillog = new EmailLog
|
||||
{
|
||||
Id = NewId.NextGuid(),
|
||||
UniqueId = uid.ToString(),
|
||||
MessageId = message.MessageId ?? string.Empty,
|
||||
EmailSubject = message.Subject ?? string.Empty,
|
||||
EmailDate = message.Date.DateTime,
|
||||
EmailStateEnum = EmailState.Success,
|
||||
};
|
||||
|
||||
var fromMailbox = message.From.Mailboxes.FirstOrDefault();
|
||||
if (fromMailbox != null)
|
||||
{
|
||||
emaillog.SenderAddress = fromMailbox.Address;
|
||||
emaillog.SenderName = fromMailbox.Name ?? string.Empty;
|
||||
}
|
||||
|
||||
List<EmailRecipientLog> recipientLogs = new List<EmailRecipientLog>();
|
||||
|
||||
int sort = 0;
|
||||
message.To.Mailboxes.ForEach(x =>
|
||||
{
|
||||
recipientLogs.Add(new EmailRecipientLog()
|
||||
{
|
||||
RecipientName = x.Name ?? string.Empty,
|
||||
RecipientAddress = x.Address,
|
||||
EmailLogId = emaillog.Id,
|
||||
RecipientTypeEnum = RecipientType.To,
|
||||
Sort = sort++,
|
||||
});
|
||||
});
|
||||
sort = 0;
|
||||
message.Cc.Mailboxes.ForEach(x =>
|
||||
{
|
||||
recipientLogs.Add(new EmailRecipientLog()
|
||||
{
|
||||
RecipientName = x.Name ?? string.Empty,
|
||||
RecipientAddress = x.Address,
|
||||
EmailLogId = emaillog.Id,
|
||||
RecipientTypeEnum = RecipientType.Cc,
|
||||
Sort = sort++,
|
||||
});
|
||||
});
|
||||
emailList.Add(emaillog);
|
||||
EmailRecipientLogList.AddRange(recipientLogs);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"处理邮件 {uid} 失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
sentFolder.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"同步发件箱邮件时出错: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.Disconnect(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存同步的发件箱邮件
|
||||
await _emailLogRepository.AddRangeAsync(emailList);
|
||||
await _emailRecipientLogRepository.AddRangeAsync(EmailRecipientLogList);
|
||||
await _emailLogRepository.SaveChangesAsync();
|
||||
|
||||
// 第二步:处理收件箱中的邮件发送失败通知
|
||||
try
|
||||
{
|
||||
await ProcessInboxFailureNotifications(startDate,inDto.TrialId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"处理收件箱失败通知邮件时出错: {ex.Message}");
|
||||
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
|
||||
// 即使处理失败通知邮件出错,也不影响整体同步操作的成功
|
||||
// 记录警告但不中断主流程
|
||||
}
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
private IMailFolder OpenSentFolder(ImapClient client)
|
||||
{
|
||||
IMailFolder folder = null;
|
||||
try
|
||||
{
|
||||
folder = client.GetFolder(SpecialFolder.Sent);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
var candidates = new[] { "已发送", "已发送邮件", "Sent", "Sent Items", "[Gmail]/Sent Mail" };
|
||||
foreach (var name in candidates)
|
||||
{
|
||||
try
|
||||
{
|
||||
var f = client.GetFolder(name);
|
||||
if (f != null)
|
||||
{
|
||||
folder = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var personal = client.GetFolder(client.PersonalNamespaces.FirstOrDefault());
|
||||
if (personal != null)
|
||||
{
|
||||
foreach (var sub in personal.GetSubfolders(false))
|
||||
{
|
||||
if (string.Equals(sub.FullName, "Sent", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(sub.FullName, "Sent Items", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
folder = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("未找到已发送文件夹");
|
||||
|
||||
folder.Open(FolderAccess.ReadOnly);
|
||||
return folder;
|
||||
}
|
||||
|
||||
private IMailFolder OpenInboxFolder(ImapClient client)
|
||||
{
|
||||
IMailFolder folder = null;
|
||||
try
|
||||
{
|
||||
folder = client.GetFolder(SpecialFolder.All);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
var candidates = new[] { "收件箱", "Inbox" };
|
||||
foreach (var name in candidates)
|
||||
{
|
||||
try
|
||||
{
|
||||
var f = client.GetFolder(name);
|
||||
if (f != null)
|
||||
{
|
||||
folder = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var personal = client.GetFolder(client.PersonalNamespaces.FirstOrDefault());
|
||||
if (personal != null)
|
||||
{
|
||||
foreach (var sub in personal.GetSubfolders(false))
|
||||
{
|
||||
if (string.Equals(sub.FullName, "Inbox", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
folder = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("未找到收件箱文件夹");
|
||||
|
||||
folder.Open(FolderAccess.ReadOnly);
|
||||
return folder;
|
||||
}
|
||||
|
||||
private async Task AuthenticateImap(ImapClient client, Guid? trialId)
|
||||
{
|
||||
try
|
||||
{
|
||||
EmailAuthorization authorization = new EmailAuthorization()
|
||||
{
|
||||
FromEmail = _systemEmailConfig.FromEmail,
|
||||
AuthorizationCode = _systemEmailConfig.AuthorizationCode,
|
||||
};
|
||||
|
||||
if (trialId != null)
|
||||
{
|
||||
authorization = await _trialRepository.Where(x => x.Id == trialId.Value).Select(x => new EmailAuthorization()
|
||||
{
|
||||
AuthorizationCode = x.EmailAuthorizationCode,
|
||||
FromEmail = x.EmailFromEmail
|
||||
}).FirstNotNullAsync();
|
||||
}
|
||||
|
||||
client.Connect(_systemEmailConfig.Imap, _systemEmailConfig.ImapPort, SecureSocketOptions.SslOnConnect);
|
||||
client.Authenticate(authorization.FromEmail, authorization.AuthorizationCode);
|
||||
}
|
||||
catch (AuthenticationException)
|
||||
{
|
||||
//if (_systemEmailConfig.UseOAuth2 && _systemEmailConfig.OAuth2AccessToken.IsNotNullOrEmpty())
|
||||
//{
|
||||
// var sasl = new SaslMechanismOAuth2(_systemEmailConfig.FromEmail, _systemEmailConfig.OAuth2AccessToken);
|
||||
// client.Authenticate(sasl);
|
||||
// return;
|
||||
//}
|
||||
//if (_systemEmailConfig.OAuth2AccessToken.IsNullOrEmpty())
|
||||
//{
|
||||
// var token = AcquireOAuth2TokenByPassword();
|
||||
// if (token.IsNotNullOrEmpty())
|
||||
// {
|
||||
// _systemEmailConfig.OAuth2AccessToken = token;
|
||||
// var sasl = new SaslMechanismOAuth2(_systemEmailConfig.FromEmail, token);
|
||||
// client.Authenticate(sasl);
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理收件箱中的邮件发送失败通知
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task ProcessInboxFailureNotifications(DateTime startTime, Guid? trialId)
|
||||
{
|
||||
using (var client = new ImapClient())
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
await AuthenticateImap(client, trialId);
|
||||
var inboxFolder = OpenInboxFolder(client);
|
||||
|
||||
// 搜索可能包含失败通知的邮件
|
||||
// 通常失败通知邮件会包含"失败"、"错误"、"undeliverable"、"delivery failed"等关键词
|
||||
var searchQuery = SearchQuery.All.Or(SearchQuery.SubjectContains("失败"))
|
||||
.Or(SearchQuery.SubjectContains("错误"))
|
||||
.Or(SearchQuery.SubjectContains("undeliverable"))
|
||||
.Or(SearchQuery.SubjectContains("delivery failed"))
|
||||
.Or(SearchQuery.SubjectContains("Delivery Status Notification"))
|
||||
.Or(SearchQuery.BodyContains("失败"))
|
||||
.Or(SearchQuery.BodyContains("错误"))
|
||||
.Or(SearchQuery.BodyContains("undeliverable"))
|
||||
.Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(startTime));
|
||||
|
||||
var uids = inboxFolder.Search(searchQuery).ToList();
|
||||
var processedCount = 0;
|
||||
var updatedCount = 0;
|
||||
|
||||
foreach (var uid in uids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = inboxFolder.GetMessage(uid);
|
||||
|
||||
// 尝试从邮件内容中提取原始邮件的Message-Id或相关信息
|
||||
var originalMessageId = ExtractOriginalMessageId(message);
|
||||
if (!string.IsNullOrEmpty(originalMessageId))
|
||||
{
|
||||
// 查找对应的EmailLog记录
|
||||
var emailLog = await _emailLogRepository
|
||||
.Where(x => x.MessageId == originalMessageId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
await _emailLogRepository.BatchUpdateNoTrackingAsync(x => x.MessageId == originalMessageId, x => new EmailLog()
|
||||
{
|
||||
EmailStateEnum = EmailState.Error,
|
||||
ErrorInfo = message.TextBody
|
||||
|
||||
});
|
||||
|
||||
updatedCount++;
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inboxFolder.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"连接收件箱处理失败通知邮件时出错: {ex.Message}");
|
||||
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
client.Disconnect(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"断开IMAP客户端连接时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从失败通知邮件中提取原始邮件的Message-Id
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
private string ExtractOriginalMessageId(MimeMessage message)
|
||||
{
|
||||
// 首先检查邮件头中是否有原始Message-Id
|
||||
var originalMessageId = message.Headers["Original-Message-ID"] ??
|
||||
message.Headers["X-Original-Message-ID"] ??
|
||||
message.Headers["In-Reply-To"];
|
||||
|
||||
if (!string.IsNullOrEmpty(originalMessageId))
|
||||
{
|
||||
// 清理Message-Id格式(移除尖括号)
|
||||
originalMessageId = originalMessageId.Trim('<', '>');
|
||||
return originalMessageId;
|
||||
}
|
||||
|
||||
// 检查邮件附件中是否包含.eml文件(这是最常见的失败通知格式)
|
||||
foreach (var attachment in message.Attachments)
|
||||
{
|
||||
if (attachment is MessagePart messagePart)
|
||||
{
|
||||
// 直接获取嵌入的邮件消息
|
||||
var originalMessageIdFromAttachment = messagePart.Message?.MessageId;
|
||||
if (!string.IsNullOrEmpty(originalMessageIdFromAttachment))
|
||||
{
|
||||
return originalMessageIdFromAttachment.Trim('<', '>');
|
||||
}
|
||||
}
|
||||
else if (attachment is MimePart mimePart)
|
||||
{
|
||||
// 检查文件扩展名是否为.eml
|
||||
var fileName = mimePart.FileName ?? mimePart.ContentType.Name;
|
||||
if (!string.IsNullOrEmpty(fileName) &&
|
||||
(fileName.EndsWith(".eml", StringComparison.OrdinalIgnoreCase) ||
|
||||
mimePart.ContentType.MimeType.Equals("message/rfc822", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
try
|
||||
{
|
||||
// 解析.eml附件内容
|
||||
using var memoryStream = new MemoryStream();
|
||||
mimePart.Content.DecodeTo(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
|
||||
var originalMessage = MimeMessage.Load(memoryStream);
|
||||
if (!string.IsNullOrEmpty(originalMessage?.MessageId))
|
||||
{
|
||||
return originalMessage.MessageId.Trim('<', '>');
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"解析.eml附件时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果邮件头和附件中都没有,尝试从邮件正文中提取
|
||||
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
|
||||
|
||||
// 尝试匹配常见的Message-Id格式
|
||||
var messageIdPattern = @"(?:Message-ID|Message-Id|message-id):\s*<?([^>\s]+)>?";
|
||||
var match = System.Text.RegularExpressions.Regex.Match(content, messageIdPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
|
||||
// 尝试从邮件引用部分提取
|
||||
var referencePattern = @"^>.*Message-ID:\s*<?([^>\s]+)>?";
|
||||
var matches = System.Text.RegularExpressions.Regex.Matches(content, referencePattern, System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase);
|
||||
if (matches.Count > 0)
|
||||
{
|
||||
return matches[0].Groups[1].Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<IResponseOutput> AddOrUpdateEmailLog(EmailLogAddOrEdit addOrEditEmailLog)
|
||||
{
|
||||
|
||||
|
||||
|
||||
var entity = await _emailLogRepository.InsertOrUpdateAsync(addOrEditEmailLog, true);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("{emailLogId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteEmailLog(Guid emailLogId)
|
||||
{
|
||||
var success = await _emailLogRepository.DeleteFromQueryAsync(t => t.Id == emailLogId,true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -4,9 +4,18 @@
|
|||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MailKit;
|
||||
using MailKit.Net.Imap;
|
||||
using MailKit.Search;
|
||||
using MailKit.Security;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
|
@ -17,8 +26,75 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "Common")]
|
||||
public class EmailNoticeConfigService(IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
|
||||
IRepository<EmailNoticeUserType> _emailNoticeUserTypeRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IEmailNoticeConfigService
|
||||
IRepository<EmailNoticeUserType> _emailNoticeUserTypeRepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IEmailNoticeConfigService
|
||||
{
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
|
||||
/// <summary>
|
||||
/// 获取邮件列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<object> GetEmailList()
|
||||
{
|
||||
|
||||
List<IMessageSummary> emailList = new List<IMessageSummary>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using (var client = new ImapClient())
|
||||
{
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// 连接阿里邮箱 IMAP 服务器(使用 SSL)
|
||||
client.Connect(_systemEmailConfig.Imap, 993, SecureSocketOptions.SslOnConnect);
|
||||
|
||||
// 登录
|
||||
client.Authenticate(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
||||
|
||||
// 3. 获取发件箱文件夹 - 使用你找到的“已发送”
|
||||
var sentFolder = client.GetFolder("已发送");
|
||||
sentFolder.Open(FolderAccess.ReadOnly);
|
||||
|
||||
// 4. 搜索所有邮件(你可以在这里添加更精确的搜索条件)
|
||||
var uids = sentFolder.Search(SearchQuery.All);
|
||||
Console.WriteLine($"找到 {uids.Count} 封已发送邮件");
|
||||
|
||||
// 5. 遍历并处理邮件(示例中处理前10封)
|
||||
foreach (var uid in uids.Take(10))
|
||||
{
|
||||
var message = sentFolder.GetMessage(uid);
|
||||
|
||||
// 输出邮件基本信息
|
||||
Console.WriteLine($"主题: {message.Subject}");
|
||||
Console.WriteLine($"收件人: {string.Join(", ", message.To.Mailboxes.Select(m => m.Address))}");
|
||||
Console.WriteLine($"日期: {message.Date.LocalDateTime:yyyy-MM-dd HH:mm:ss}");
|
||||
Console.WriteLine($"发件人: {message.From}");
|
||||
Console.WriteLine("----------------------------------");
|
||||
}
|
||||
|
||||
sentFolder.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"操作失败: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.Disconnect(true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<EmailNoticeConfigView>> GetEmailNoticeConfigList(EmailNoticeConfigQuery inQuery)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ using System.ComponentModel.Design;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using static IRaCIS.Core.Application.Service.ExcelExportHelper;
|
||||
using IDictionaryService = IRaCIS.Application.Interfaces.IDictionaryService;
|
||||
using TrialIdentityUser = IRaCIS.Core.Domain.Models.TrialIdentityUser;
|
||||
|
|
@ -32,6 +34,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
[ApiExplorerSettings(GroupName = "Common")]
|
||||
public class ExcelExportService(IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IRepository<Internationalization> _internationalizationRepository,
|
||||
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
||||
IRepository<SystemDocNeedConfirmedUserType> _systemDocNeedConfirmedUserTypeRepository,
|
||||
IRepository<DicomStudy> _dicomStudyRepository,
|
||||
|
|
@ -1619,6 +1623,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||
|
||||
|
||||
if (inQuery.IsRandomOrderList == true)
|
||||
{
|
||||
list = list.OrderBy(t => t.RandomOrder).ToList();
|
||||
|
|
@ -1757,6 +1762,80 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
var list = taskMedicalReviewQueryable.OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitTaskNum).ToList();
|
||||
|
||||
|
||||
#region 处理翻译对话 by he wen tao
|
||||
|
||||
Dictionary<string, string> i18NKeys = new Dictionary<string, string>()
|
||||
{
|
||||
{ "Msg1","trials:medicalFeedback:message:msg1"},
|
||||
{ "Msg2","trials:medicalFeedback:message:msg2"},
|
||||
{ "Msg3","trials:medicalFeedback:message:msg3"},
|
||||
{ "Msg4", "trials:medicalFeedback:message:msg4"},
|
||||
{ "Msg5", "trials:medicalFeedback:message:msg5"},
|
||||
{ "CloseReasonEnum", "trials:medicalFeedback:title:closeReasonEnum"},
|
||||
{ "IsEndorse", "trials:medicalFeedback:title:isEndorse"},
|
||||
{ "Reason", "trials:medicalFeedback:title:reason"},
|
||||
{ "IsRequestReread", "trials:medicalFeedback:title:isRequestReread"},
|
||||
};
|
||||
|
||||
var i18Values = i18NKeys.Select(x => x.Value).ToList();
|
||||
var i18nList = await _internationalizationRepository.Where(x => i18Values.Contains(x.Code))
|
||||
.Select(x => new
|
||||
{
|
||||
Code = x.Code,
|
||||
Value = _userInfo.IsEn_Us ? x.Value : x.ValueCN
|
||||
}).ToListAsync();
|
||||
|
||||
List<string> dictionaryCodeList = new List<string>()
|
||||
{
|
||||
"AuditAdvice",
|
||||
"MedicalDialogCloseEnum",
|
||||
"MedicalReviewDoctorUserIdea",
|
||||
"YesOrNo",
|
||||
};
|
||||
|
||||
var dictionadParents = await _dictionaryRepository.Where(x => dictionaryCodeList.Contains(x.Parent.Code))
|
||||
.Select(x => new
|
||||
{
|
||||
ParentCode = x.Parent.Code,
|
||||
Code = x.Code,
|
||||
Value = _userInfo.IsEn_Us ? x.Value : x.ValueCN
|
||||
}).ToListAsync();
|
||||
|
||||
JointMedicalReviewI18n i18N = new JointMedicalReviewI18n() { };
|
||||
foreach (var kv in i18NKeys)
|
||||
{
|
||||
PropertyInfo? pi = i18N.GetType().GetProperty(kv.Key);
|
||||
if (pi != null && pi.CanWrite)
|
||||
{
|
||||
var value = i18nList.Where(x => x.Code == kv.Value).Select(x => x.Value).FirstOrDefault() ?? string.Empty;
|
||||
object safeValue = Convert.ChangeType(value, pi.PropertyType);
|
||||
pi.SetValue(i18N, safeValue);
|
||||
}
|
||||
}
|
||||
foreach (var item in dictionaryCodeList)
|
||||
{
|
||||
PropertyInfo? pi = i18N.GetType().GetProperty(item);
|
||||
if (pi != null && pi.CanWrite)
|
||||
{
|
||||
var value = dictionadParents.Where(x => x.ParentCode == item).ToDictionary(x => x.Code, x => x.Value);
|
||||
object safeValue = Convert.ChangeType(value, pi.PropertyType);
|
||||
pi.SetValue(i18N, safeValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
foreach (var dialog in item.DialogList)
|
||||
{
|
||||
dialog.ResultContent = JointMedicalReviewDialog(dialog, i18N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||
|
|
@ -1766,6 +1845,88 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialMedicalReviewList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TaskMedicalReviewExportDto));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取医学审核对话拼接内容
|
||||
/// </summary>
|
||||
/// <param name="record"></param>
|
||||
/// <param name="i18NAndDic"></param>
|
||||
/// <returns></returns>
|
||||
private string JointMedicalReviewDialog(GetMedicalReviewDialogOutDto record, JointMedicalReviewI18n i18NAndDic)
|
||||
{
|
||||
StringBuilder str = new StringBuilder() { };
|
||||
var userTypes = new List<int>() { 14, 30 };
|
||||
|
||||
// 这里userTypes.Contains(record.UserTypeEnumInt) 可以提出来 但是还是按照前端写吧 免得不好对照
|
||||
|
||||
// v-if="[14, 30].includes(record.UserTypeEnumInt) && record.Questioning
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.Questioning.IsNotNullOrEmpty())
|
||||
{
|
||||
// <!-- 您好,根据医学审核反馈,该阅片任务的评估有如下问题需要您确认或澄清: -->
|
||||
str.AppendLine(i18NAndDic.Msg1);
|
||||
|
||||
str.AppendLine(record.Questioning);
|
||||
|
||||
if (record.FileList.Count() > 0)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.Msg2);
|
||||
record.FileList.ForEach(x =>
|
||||
{
|
||||
str.AppendLine(x.FileName);
|
||||
});
|
||||
}
|
||||
|
||||
str.AppendLine(i18NAndDic.Msg3);
|
||||
|
||||
str.AppendLine(i18NAndDic.AuditAdvice[record.AuditAdviceEnum.GetEnumInt()]);
|
||||
|
||||
str.AppendLine(i18NAndDic.Msg4);
|
||||
}
|
||||
|
||||
//v-if="[14, 30].includes(record.UserTypeEnumInt) && record.MedicalDialogCloseEnum!== null"
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.MedicalDialogCloseEnum != null)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.CloseReasonEnum + i18NAndDic.MedicalDialogCloseEnum[record.MedicalDialogCloseEnum.Value.GetEnumInt()]);
|
||||
}
|
||||
|
||||
// v-if="[14, 30].includes(record.UserTypeEnumInt) && record.Content
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.Content.IsNotNullOrEmpty())
|
||||
{
|
||||
str.AppendLine(record.Content);
|
||||
}
|
||||
|
||||
// v-if="[13].includes(record.UserTypeEnumInt)"
|
||||
|
||||
if (13 == record.UserTypeEnumInt)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.IsEndorse + i18NAndDic.MedicalReviewDoctorUserIdea[record.DoctorUserIdeaEnum.GetEnumInt()]);
|
||||
|
||||
// v-if="record.DoctorUserIdeaEnum===2"
|
||||
if ((int)record.DoctorUserIdeaEnum == 2)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.Reason + record.DisagreeReason);
|
||||
}
|
||||
|
||||
// record.MedicalDialogCloseEnum!== null
|
||||
|
||||
if (record.MedicalDialogCloseEnum != null)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.IsRequestReread + i18NAndDic.YesOrNo[record.IsApplyHeavyReading.ToString()]);
|
||||
}
|
||||
|
||||
// v-if="record.FileList && record.FileList.length > 0"
|
||||
|
||||
if (record.FileList.Count() > 0)
|
||||
{
|
||||
record.FileList.ForEach(x =>
|
||||
{
|
||||
str.AppendLine(x.FileName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 影像下载记录表
|
||||
|
|
@ -2310,8 +2471,263 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
#region 通用阅片结果导出
|
||||
|
||||
/// <summary>
|
||||
/// 一致性分析结果导出 7 8 分别是自身 和组件一致性
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <param name="_commonDocumentRepository"></param>
|
||||
/// <param name="_dictionaryService"></param>
|
||||
/// <param name="_trialRepository"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetAnalysisTaskList_Export(VisitTaskQuery inQuery,
|
||||
[FromServices] IRepository<CommonDocument> _commonDocumentRepository,
|
||||
[FromServices] IDictionaryService _dictionaryService,
|
||||
[FromServices] IRepository<Trial> _trialRepository)
|
||||
{
|
||||
//每次查询必须是单标准的
|
||||
var criterion = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.CriterionType, t.CriterionName, t.ArbitrationRule }).FirstNotNullAsync();
|
||||
|
||||
|
||||
var query = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.TaskAllocationState == TaskAllocationState.Allocated && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
|
||||
|
||||
//一致性分析
|
||||
.WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults, t => t.IsSelfAnalysis == true || t.IsSelfAnalysis == null)
|
||||
.WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults, t => t.IsSelfAnalysis == null ? t.Subject.SubjectVisitTaskList.Any(u => u.IsSelfAnalysis == true && u.VisitTaskNum == t.VisitTaskNum && u.DoctorUserId == t.DoctorUserId && u.TrialReadingCriterionId == t.TrialReadingCriterionId) : true)
|
||||
.WhereIf(inQuery.ReadingExportType == ExportResult.DetailedTableOfInterReaderAnalysisResults, t => t.IsSelfAnalysis == false || t.IsSelfAnalysis == null)
|
||||
|
||||
//访视和全局查询已签名完成的,裁判可以是未签名,未完成的
|
||||
.Where(t => (t.ReadingTaskState == ReadingTaskState.HaveSigned && (t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global)) || t.ReadingCategory == ReadingCategory.Judge)
|
||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||
|
||||
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
|
||||
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
|
||||
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
|
||||
//.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
|
||||
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
|
||||
.WhereIf(inQuery.ArmEnum != null, t => t.ArmEnum == inQuery.ArmEnum)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode))
|
||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
|
||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate);
|
||||
|
||||
var list = await query.ProjectTo<AnalysisDynamicCommonExport>(_mapper.ConfigurationProvider,
|
||||
new
|
||||
{
|
||||
readingExportType = inQuery.ReadingExportType,
|
||||
criterionType = criterion.CriterionType,
|
||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||
isEn_Us = _userInfo.IsEn_Us
|
||||
}).ToListAsync();
|
||||
|
||||
list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList();
|
||||
|
||||
|
||||
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
exportInfo.CriterionName = criterion.CriterionName;
|
||||
|
||||
#region 处理系统标准存在疾病和整体肿瘤合并
|
||||
|
||||
//如果是以合并后的找翻译字典,会少,所以必须放在前面
|
||||
var translateDicNameList = list.SelectMany(t => t.QuestionAnswerList).Where(t => t.TranslateDicName.IsNotNullOrEmpty()).Select(t => t.TranslateDicName).Distinct().ToList();
|
||||
|
||||
//针对1.1 整体肿瘤评估 有的两列要合并一列
|
||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1)
|
||||
{
|
||||
foreach (var item in list)
|
||||
{
|
||||
//处理合并表头
|
||||
|
||||
var questionType = item.IsBaseline == true ? QuestionType.ExistDisease : QuestionType.Tumor;
|
||||
|
||||
var findItem = item.QuestionAnswerList.Where(t => t.QuestionType == questionType).FirstOrDefault();
|
||||
|
||||
if (findItem != null)
|
||||
{
|
||||
findItem.QuestionName = _userInfo.IsEn_Us ? "Overall Response" : "整体肿瘤评估";
|
||||
}
|
||||
|
||||
|
||||
if (item.IsBaseline == true)
|
||||
{
|
||||
item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.Tumor).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ExistDisease).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET)
|
||||
{
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
//处理合并表头
|
||||
|
||||
var questionType = item.IsBaseline == true ? QuestionType.ExistDisease : QuestionType.ImgOncology;
|
||||
|
||||
var findItem = item.QuestionAnswerList.Where(t => t.QuestionType == questionType).FirstOrDefault();
|
||||
|
||||
if (findItem != null)
|
||||
{
|
||||
findItem.QuestionName = _userInfo.IsEn_Us ? "Overall Response" : "整体肿瘤评估";
|
||||
}
|
||||
|
||||
if (item.IsBaseline == true)
|
||||
{
|
||||
item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ImgOncology).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.QuestionAnswerList = item.QuestionAnswerList.Where(t => t.QuestionType != QuestionType.ExistDisease).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (criterion.CriterionType == CriterionType.PCWG3)
|
||||
{
|
||||
|
||||
}
|
||||
else if (criterion.CriterionType == CriterionType.SelfDefine)
|
||||
{
|
||||
//自定义的又问题名称重复 所以统一加上组名
|
||||
|
||||
//有重复的就加,没有重复的就不加
|
||||
if (list.Any(t => t.QuestionAnswerList.Select(t => t.QuestionName).Count() != t.QuestionAnswerList.Select(t => t.QuestionName).Distinct().Count()))
|
||||
{
|
||||
foreach (var item in list)
|
||||
{
|
||||
foreach (var qs in item.QuestionAnswerList)
|
||||
{
|
||||
qs.QuestionName = qs.Group + "_" + qs.QuestionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
var export_Template = StaticData.Export.TrialSelfAnalysisList_Export;
|
||||
|
||||
#region 自身一致性分析和组间一致性分析
|
||||
|
||||
if (inQuery.ReadingExportType == ExportResult.DetailedTableOfIntraReaderAnalysisResults)
|
||||
{
|
||||
//找到非一致性分析的任务
|
||||
var selfExportList = list.Where(t => t.IsSelfAnalysis == null).ToList();
|
||||
|
||||
//处理一致性分析结果是否和原始阅片是否一致
|
||||
foreach (var item in selfExportList)
|
||||
{
|
||||
//找到一致性分析的结果
|
||||
var selfAnalysisTask = list.Where(t => t.IsSelfAnalysis == true && t.SubjectCode == item.SubjectCode && t.VisitTaskNum == item.VisitTaskNum && t.TaskName == t.TaskName && t.UserName == item.UserName).FirstOrDefault();
|
||||
|
||||
//将自身一致性分析的字段 赋值到访视任务这个字段
|
||||
item.IsAnalysisDiffToOriginalData = selfAnalysisTask?.IsAnalysisDiffToOriginalData;
|
||||
|
||||
//处理再次阅片人的结果
|
||||
if (selfAnalysisTask != null)
|
||||
{
|
||||
var cloneQuestionAnswerList = selfAnalysisTask.QuestionAnswerList.Clone();
|
||||
|
||||
foreach (var qItem in cloneQuestionAnswerList)
|
||||
{
|
||||
qItem.QuestionName = qItem.QuestionName + $"{(_userInfo.IsEn_Us ? "(Again)" : "(再次)")}";
|
||||
}
|
||||
|
||||
item.QuestionAnswerList = item.QuestionAnswerList.Union(cloneQuestionAnswerList).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
list = selfExportList;
|
||||
}
|
||||
else
|
||||
{
|
||||
export_Template = StaticData.Export.TrialGroupAnalysisList_Export;
|
||||
|
||||
var newList = new List<AnalysisDynamicCommonExport>();
|
||||
|
||||
foreach (var group in list.GroupBy(t => new { t.SubjectCode, t.VisitTaskNum, t.TaskName }).OrderBy(g => g.Key.SubjectCode).ThenBy(g => g.Key.VisitTaskNum))
|
||||
{
|
||||
var subjectVisitGroupList = group.ToList();
|
||||
|
||||
|
||||
//找到当前访视组间一致性分析的任务结果
|
||||
|
||||
var groupOtherTaskList = subjectVisitGroupList.Where(t => t.IsSelfAnalysis == false).ToList();
|
||||
|
||||
foreach (var subjectVisitTaskArm in subjectVisitGroupList.Where(t => t.IsSelfAnalysis == null).OrderBy(t => t.ArmEnum))
|
||||
{
|
||||
foreach (var otherTask in groupOtherTaskList)
|
||||
{
|
||||
//非一致性分析任务
|
||||
var cloneObj = subjectVisitTaskArm.Clone();
|
||||
|
||||
var otherTaskQuestionAnserList = otherTask.QuestionAnswerList.Clone();
|
||||
|
||||
foreach (var qItem in otherTaskQuestionAnserList)
|
||||
{
|
||||
qItem.QuestionName = qItem.QuestionName + $"{(_userInfo.IsEn_Us ? "(Again)" : "(再次)")}";
|
||||
}
|
||||
|
||||
//处理 再次阅片人,再次阅片人角色 两列
|
||||
var addQuestionList = new List<CommonQuesionInfo>();
|
||||
|
||||
addQuestionList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Reviwer(Again)" : "阅片人(再次)", QuestionValue = otherTask.UserName });
|
||||
addQuestionList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Reviwer Role(Again)" : "阅片人角色(再次)", QuestionValue = ((int)otherTask.ArmEnum).ToString(), TranslateDicName = "ArmEnum" });
|
||||
|
||||
|
||||
cloneObj.QuestionAnswerList = cloneObj.QuestionAnswerList.Union(addQuestionList).Union(otherTaskQuestionAnserList).ToList();
|
||||
|
||||
|
||||
cloneObj.IsGroupAnalysisDiffToOriginalData = cloneObj.ArmEnum == Arm.DoubleReadingArm1 ? otherTask.IsGroupDiffArm1 : otherTask.IsGroupDiffArm2;
|
||||
|
||||
newList.Add(cloneObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
translateDicNameList.Add("ArmEnum");
|
||||
|
||||
list = newList;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
var columNameList = list.SelectMany(t => t.QuestionAnswerList).Where(t => t.QuestionName.IsNotNullOrEmpty()).Select(t => t.QuestionName).Distinct().ToList();
|
||||
|
||||
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list.Where(t => t.ReadingCategory != ReadingCategory.Global).ToList(), _userInfo.TimeZoneId);
|
||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||
|
||||
var dynamicColumnConfig = new DynamicColumnConfig()
|
||||
{
|
||||
//可读的列表名行索引,不是{{}} 模板行索引
|
||||
AutoColumnTitleRowIndex = 2,
|
||||
AutoColumnStartIndex = 5,
|
||||
TempalteLastColumnIndex = 4,
|
||||
DynamicItemDicName = "TranslateDicName",
|
||||
DynamicItemValueName = "QuestionValue",
|
||||
DynamicItemTitleName = "QuestionName",
|
||||
DynamicListName = "QuestionAnswerList",
|
||||
RemoveColunmIndexList = new List<int>() { },
|
||||
ColumnIdNameList = columNameList.Select(t => new DynamicColumnConfig.ColumItem() { Id = Guid.Empty, Name = t }).ToList(),
|
||||
TranslateDicNameList = translateDicNameList ?? new List<string>()
|
||||
};
|
||||
|
||||
|
||||
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig);
|
||||
|
||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
{
|
||||
FileDownloadName = $"{exportInfo.ResearchProgramNo}_{exportInfo.CriterionName}_{fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取阅片标准可以导出的列表
|
||||
|
|
@ -2341,13 +2757,23 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.ReadingLession_Export, ExportCatogory = ExportResult.DetailedTableOfLesions });
|
||||
}
|
||||
|
||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.Lugano2014)
|
||||
{
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.TumorCDISC_Export, ExportCatogory = ExportResult.TumorCDISC_Export });
|
||||
}
|
||||
|
||||
if (criterion.CriterionType == CriterionType.OCT)
|
||||
{
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_CDISC_Export, ExportCatogory = ExportResult.OCT_CDISC_Export });
|
||||
}
|
||||
//else if (criterion.CriterionType == CriterionType.SelfDefine)
|
||||
if (criterion.CriterionType == CriterionType.IVUS)
|
||||
{
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.CDISC_Reading_Export, ExportCatogory = ExportResult.CDISC });
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.IVUS_CDISC_Export, ExportCatogory = ExportResult.IVUS_CDISC_Export });
|
||||
}
|
||||
if (criterion.CriterionGroup != CriterionGroup.Tumor && criterion.CriterionType != CriterionType.OCT && criterion.CriterionType != CriterionType.IVUS)
|
||||
{
|
||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.CDISC_Reading_Export, ExportCatogory = ExportResult.NoneTumorCDISC });
|
||||
}
|
||||
|
||||
switch (criterion.ArbitrationRule)
|
||||
|
|
@ -2474,7 +2900,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
//阅片结果表
|
||||
export_Template = StaticData.Export.CommonReading_Export;
|
||||
}
|
||||
|
||||
//斑块表
|
||||
else if (inQuery.ReadingExportType == ExportResult.OCT_ReadingLession_Export)
|
||||
{
|
||||
//OCT
|
||||
|
|
@ -2528,7 +2954,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
}
|
||||
// 非肿瘤标准 包括自定义,以及系统非肿瘤 会配置到表格层级 问题名称是 表格名称_表格子问题名
|
||||
else if (
|
||||
criterion.CriterionGroup == CriterionGroup.Nontumorous && inQuery.ReadingExportType != ExportResult.CDISC
|
||||
criterion.CriterionGroup == CriterionGroup.Nontumorous && inQuery.ReadingExportType != ExportResult.NoneTumorCDISC
|
||||
)
|
||||
{
|
||||
|
||||
|
|
@ -2545,7 +2971,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
}
|
||||
// CDISC 导出 只管到 外层问题层级 和阅片结果表是保持一致
|
||||
else if (inQuery.ReadingExportType == ExportResult.CDISC)
|
||||
else if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC)
|
||||
{
|
||||
|
||||
if (criterion.CriterionGroup == CriterionGroup.Tumor)
|
||||
|
|
@ -2613,7 +3039,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
#endregion
|
||||
|
||||
|
||||
if (inQuery.ReadingExportType != ExportResult.CDISC)
|
||||
if (inQuery.ReadingExportType != ExportResult.NoneTumorCDISC)
|
||||
{
|
||||
//最终EXCEL 列
|
||||
var configCoumNameList = new List<DynamicColumnConfig.ColumItem>();
|
||||
|
|
@ -2741,7 +3167,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion Type" : "病灶类型", QuestionValue = lession.LessionType, TranslateDicName = "LesionType" });
|
||||
}
|
||||
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName });
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, OptionTypeEnum = t.OptionTypeEnum, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName ,Unit=t.Unit});
|
||||
|
||||
//有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题
|
||||
var dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList();
|
||||
|
|
@ -2769,7 +3195,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
#endregion
|
||||
|
||||
#region 不管是list 还是taskList 最终处理的数据都是list 处理好数据后合并
|
||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
|
||||
if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB
|
||||
|| criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.mRECISTHCC)
|
||||
{
|
||||
//针对1.1 整体肿瘤评估 有的两列要合并一列
|
||||
|
|
@ -2889,14 +3315,14 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionId = Guid.Empty, QuestionName = _userInfo.IsEn_Us ? "Table Name" : "表格名称", QuestionValue = firstLessionAnser.TableName });
|
||||
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, QuestionName = t.TableName + "_" + t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode });
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, OptionTypeEnum = t.OptionTypeEnum, QuestionName = t.TableName + "_" + t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
|
||||
|
||||
//有三部分组成 外层问题+ 固定列表格名称 + 动态的表格问题
|
||||
dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode });
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, OptionTypeEnum = t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
|
||||
|
||||
//两部分组成 外层问题+ 动态的表格问题
|
||||
dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList();
|
||||
|
|
@ -2943,7 +3369,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
TranslateDicNameList = translateDicNameList
|
||||
};
|
||||
|
||||
if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export)
|
||||
if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export || export_Template== StaticData.Export.OCT_ReadingLession_Export)
|
||||
{
|
||||
dynamicColumnConfig.TempalteLastColumnIndex = 8;
|
||||
}
|
||||
|
|
@ -2962,7 +3388,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
var trialConfigTableQuestionList = _trialReadingTableQuestionRepository.Where(t => t.TrialId == trialId && t.TrialCriterionId == trialReadingCriterionId).Where(t => t.ExportResultStr.Contains(((int)inQuery.ReadingExportType).ToString()))
|
||||
.Select(t => new ExportQuestionBasicInfo()
|
||||
{
|
||||
QuestionId = t.Id,
|
||||
QuestionId = t.Id,
|
||||
TableName = _userInfo.IsEn_Us ? t.ReadingQuestionTrial.QuestionEnName : t.ReadingQuestionTrial.QuestionName,
|
||||
QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName,
|
||||
CDISCCode = t.CDISCCode,
|
||||
|
|
@ -3006,7 +3432,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
var dynamicLessionInfoList = new List<CommonQuesionInfo>();
|
||||
|
||||
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode });
|
||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId,OptionTypeEnum=t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
|
||||
|
||||
//两部分组成 外层问题+ 动态的表格问题
|
||||
dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList();
|
||||
|
|
@ -3219,7 +3645,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||
|
||||
string fileName = "";
|
||||
|
||||
if (inQuery.ReadingExportType == ExportResult.CDISC)
|
||||
if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC)
|
||||
{
|
||||
(memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,533 @@
|
|||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.Common;
|
||||
|
||||
public class TumorCommonQustionInfo
|
||||
{
|
||||
//问题标识,肿瘤评估用于区分是什么问题
|
||||
public QuestionType? QuestionType { get; set; }
|
||||
|
||||
public OptionType OptionTypeEnum { get; set; }
|
||||
|
||||
public Guid QuestionId { get; set; }
|
||||
public string QuestionName { get; set; }
|
||||
|
||||
public string QuestionValue { get; set; }
|
||||
|
||||
public string TranslateDicName { get; set; }
|
||||
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
public ValueOfType? ValueType { get; set; }
|
||||
}
|
||||
|
||||
public class TumorLessionInfo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid? OrganInfoId { get; set; }
|
||||
//病灶编号
|
||||
public string LessionCode { get; set; }
|
||||
|
||||
public LesionType? LessionType { get; set; }
|
||||
|
||||
public Guid? SplitRowId { get; set; }
|
||||
|
||||
public string? DicomModality { get; set; }
|
||||
|
||||
public string? NoneDicomModality { get; set; }
|
||||
|
||||
//病灶答案
|
||||
public List<TumorLessionAnswerInfo> LessionAnswerList { get; set; }
|
||||
}
|
||||
|
||||
public class TumorLessionAnswerInfo
|
||||
{
|
||||
public QuestionMark? QuestionMark { get; set; }
|
||||
|
||||
public OptionType OptionTypeEnum { get; set; }
|
||||
|
||||
//病灶Id
|
||||
public Guid RowId { get; set; }
|
||||
|
||||
//如果是4 就取CustomUnit 否则就是字典翻译
|
||||
[Comment("单位")]
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
|
||||
public int ShowOrder { get; set; }
|
||||
|
||||
public Guid TableQuesionId { get; set; }
|
||||
|
||||
public string QuestionName { get; set; }
|
||||
|
||||
public string QuestionValue { get; set; }
|
||||
|
||||
public string TranslateDicName { get; set; }
|
||||
}
|
||||
|
||||
public class TumorGlobalQuestionAnserInfo
|
||||
{
|
||||
[Comment("原任务ID")]
|
||||
public Guid TaskId { get; set; }
|
||||
|
||||
public GlobalAnswerType GlobalAnswerType { get; set; }
|
||||
|
||||
[Comment("问题答案")]
|
||||
public string Answer { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class TumorExportBaseModel : TU_TR_RSBaseModel
|
||||
{
|
||||
public List<TumorLessionInfo> LesionList { get; set; } = new List<TumorLessionInfo>();
|
||||
|
||||
public List<TumorCommonQustionInfo> QuestionAnswerList { get; set; }
|
||||
|
||||
public List<TumorGlobalQuestionAnserInfo> GlobalResultList { get; set; }
|
||||
|
||||
#region 后续处理额外添加字段
|
||||
|
||||
|
||||
|
||||
public DateTime? JudgeSignTime { get; set; }
|
||||
|
||||
public Guid? SourceSubjectVisitId { get; set; }
|
||||
|
||||
public List<decimal> SubjectCriterionReadingPeriodVisitNumList { get; set; }
|
||||
|
||||
public decimal VisitTaskNum { get; set; }
|
||||
|
||||
public ReadingTaskState ReadingTaskState { get; set; }
|
||||
|
||||
public ReadingCategory ReadingCategory { get; set; }
|
||||
|
||||
//裁判结果选择的访视或者全局任务Id
|
||||
public Arm? JudgeArmEnum { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
//在当前访视触发裁判,或者在截止日期小于等于当前访视的阅片期触发裁判
|
||||
[DictionaryTranslateAttribute("YesOrNoAudit")]
|
||||
public bool? IsTrigerJudge { get; set; }
|
||||
|
||||
//(如果是访视点裁判,则仅在所选阅片人对应访视 显示;如果是阅片期裁判,则在所选阅片人 阅片期内的所有访视 显示此原因)
|
||||
public string JudgeNote { get; set; } = string.Empty;
|
||||
|
||||
public string VisitNote { get; set; }
|
||||
#endregion
|
||||
|
||||
#region 肿瘤学结果
|
||||
|
||||
|
||||
public List<OncologyExportInfo> OncologyResultList { get; set; }
|
||||
|
||||
//public string OncologyUserName { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class OncologyExportInfo
|
||||
{
|
||||
public decimal? VisitTaskNum { get; set; }
|
||||
public string VisitName { get; set; }
|
||||
public string OncologyResult { get; set; } = string.Empty;
|
||||
|
||||
public string OncologyReason { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public class TU_TR_RSBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 方案编号 STUDYID
|
||||
/// </summary>
|
||||
public string ResearchProgramNo { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 域 DOMAIN TU TR RS
|
||||
/// </summary>
|
||||
public string Domain { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 取值类型 TUSPID TRSPID RSSPID
|
||||
/// </summary>
|
||||
public string ValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 受试者编号 USUBJID 实际展示TrialSiteSubjectCode
|
||||
/// </summary>
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 供应商 TUNAM (Extensive Imaging)
|
||||
/// </summary>
|
||||
public string Vendor { get; set; } = "Extensive Imaging";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 阅片人 TUEVAL TREVAL RSEVAL
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片人标识 TUEVALID TREVALID RSEVALID
|
||||
/// </summary>
|
||||
public Arm ArmEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访视编号 VISITNUM
|
||||
/// </summary>
|
||||
public decimal? VisitNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访视名称 VISIT
|
||||
/// </summary>
|
||||
public string? VisitName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 拍片日期 TUDTC TRDTC RSDTC
|
||||
/// </summary>
|
||||
public DateTime? LatestScanDate { get; set; }
|
||||
|
||||
public DateTime? EarliestScanDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// eCRF标识 TUREFID TRREFID RSREFID
|
||||
/// </summary>
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
|
||||
#region 移动位置
|
||||
|
||||
/// <summary>
|
||||
/// RSCAT 阅片标准
|
||||
/// </summary>
|
||||
public string CriterionName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RSACPTFL 裁定标记 TUACPTFL
|
||||
/// </summary>
|
||||
//裁判选择标记
|
||||
//根据裁判的任务结果 设置访视任务的这个字段 该字段表示 裁判认同该任务的结果
|
||||
public bool? IsJudgeSelect { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public DateTime? SignTime { get; set; }
|
||||
|
||||
public string TaskName { get; set; }
|
||||
|
||||
#region 额外翻译字段
|
||||
|
||||
|
||||
|
||||
public string IsJudgeSelectStr => IsJudgeSelect == true ? "Y" : "";
|
||||
|
||||
public bool IsTargetPD { get; set; } = false;
|
||||
|
||||
public bool IsOverallResponsePD { get; set; } = false;
|
||||
|
||||
//TR表 靶病灶PD了,访视层级的都是最早拍片日期 RS表 整体肿瘤评估PD了,那么疗效评估的拍片日期都给最早的
|
||||
public bool IsPD => Domain == "TR" ? IsTargetPD : IsOverallResponsePD;
|
||||
|
||||
public string ArmEnumStr { get; set; }
|
||||
public string LatestScanDateStr
|
||||
{
|
||||
get
|
||||
{
|
||||
var date = IsPD ? EarliestScanDate : LatestScanDate;
|
||||
return date?.ToString("yyyy-MM-dd") ?? "";
|
||||
}
|
||||
}
|
||||
public string TrialSiteSubjectCode => ResearchProgramNo + SubjectCode;
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
public class TU_Export : TU_TR_RSBaseModel
|
||||
{
|
||||
|
||||
///// <summary>
|
||||
///// 取值类型 TUSPID
|
||||
///// </summary>
|
||||
//public string TUValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 序号 TUSEQ (同一个访视,所有阅片人选择病灶给个顺序号)
|
||||
/// </summary>
|
||||
public int No { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 链接ID TULNKID (阅片人角色_病灶编号)不同访视可以重复
|
||||
/// </summary>
|
||||
public string ARM_TumorNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤识别简称 TUTESTCD
|
||||
/// </summary>
|
||||
public string TumorIdentificationSimple { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤识别全称 TUTEST
|
||||
/// </summary>
|
||||
public string TumorIdentificationFullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤鉴定结果 TUORRES
|
||||
/// </summary>
|
||||
public string TumorIdentificationResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤识别结果类型 TUSTRESC
|
||||
/// </summary>
|
||||
public string TumorIdentificationResultType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 部位 TULOC (对应病灶表的部位,需要国际化)
|
||||
/// </summary>
|
||||
public string BodyPart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 鉴定方法 TUMETHOD (Modality?)
|
||||
/// </summary>
|
||||
public string IdentificationMethod { get; set; }
|
||||
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 裁定标记 TUACPTFL
|
||||
///// </summary>
|
||||
//public bool? IsJudgeSelect { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 部位描述 LOCTEXT
|
||||
/// </summary>
|
||||
public string BodyPartDes { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class TR_Export : TU_TR_RSBaseModel
|
||||
{
|
||||
|
||||
///// <summary>
|
||||
///// 取值类型 TRSPID
|
||||
///// </summary>
|
||||
//public string TRValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 每个subject 按照顺序编号 TRSEQ
|
||||
/// </summary>
|
||||
public int TRSEQ { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
///TRGRPID 组ID 对应TU表肿瘤鉴定结果 TumorIdentificationResult
|
||||
/// </summary>
|
||||
public string TRGRPID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TRLNKID 链接ID 对应TU表的链接ID TumorNo(阅片人角色_病灶编号)
|
||||
/// </summary>
|
||||
public string ARM_TumorNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///TRLNKGRP 链接组 ARM-任务名(访视名) 对应RS的链接组
|
||||
/// </summary>
|
||||
public string ARM_VisitName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤评估简称 TRTESTCD
|
||||
/// </summary>
|
||||
public string TumorAssessmentSimpleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 肿瘤评估全称 TRTEST
|
||||
/// </summary>
|
||||
public string TumorAssessmentFullName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 原始测量 TRORRES
|
||||
/// </summary>
|
||||
public string OriginalMeasurements { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原始单位 TRORRESU
|
||||
/// </summary>
|
||||
public string OriginalUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标准结果(字符) TRSTRESC
|
||||
/// </summary>
|
||||
public string StandardResult_Character => OriginalMeasurements;
|
||||
|
||||
/// <summary>
|
||||
/// 标准结果(数值) TRORRESU
|
||||
/// </summary>
|
||||
public string StandardResult_Numeric => double.TryParse(OriginalMeasurements, out _) ||
|
||||
(OriginalMeasurements?.EndsWith("%") == true &&
|
||||
double.TryParse(OriginalMeasurements.TrimEnd('%'), out _))
|
||||
? OriginalMeasurements
|
||||
: "";
|
||||
|
||||
/// <summary>
|
||||
/// 标准单位 TRSTRESU
|
||||
/// </summary>
|
||||
public string StandardUnit => OriginalUnit;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 完成状态 TRSTAT
|
||||
/// </summary>
|
||||
public string CompletionStatus { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 完成状态 TRMETHOD
|
||||
/// </summary>
|
||||
public string IdentificationMethod { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 无法测量原因 TRREASND
|
||||
/// </summary>
|
||||
public string NotMeasuredReason { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class RS_Export : TU_TR_RSBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// RSSEQ 按照subject 的数据顺序编号
|
||||
/// </summary>
|
||||
public int RSSEQ { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RSLNKGRP 链接组 ARM_任务名(访视名)
|
||||
/// </summary>
|
||||
public string ARM_VisitName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RSTESTCD 疗效评估简称
|
||||
/// </summary>
|
||||
public string EfficacyEvaluationSimpleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RSTEST 疗效评估全称
|
||||
/// </summary>
|
||||
public string EfficacyEvaluationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RSORRES 响应评估原始结果
|
||||
/// </summary>
|
||||
public string RespondEfficacyAssessment { get; set; }
|
||||
/// <summary>
|
||||
/// RSSTRESC 标准疗效评估
|
||||
/// </summary>
|
||||
public string StandardEfficacyAssessment => RespondEfficacyAssessment;
|
||||
|
||||
/// <summary>
|
||||
/// RSSTAT 完成状态
|
||||
/// </summary>
|
||||
public string CompletionStatus { get; set; }
|
||||
/// <summary>
|
||||
/// RSREASND 无法评估原因
|
||||
/// </summary>
|
||||
public string NotAssessmentReason { get; set; }
|
||||
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 裁定标记 RSACPTFL
|
||||
///// </summary>
|
||||
//public bool? IsJudgeSelect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// REASASM 评估原因
|
||||
/// </summary>
|
||||
public string AssessmentReason { get; set; }
|
||||
/// <summary>
|
||||
/// REASOVR 重新评估原因
|
||||
/// </summary>
|
||||
public string ReAssessmentReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// REASUPD 更新评估原因
|
||||
/// </summary>
|
||||
public string UpdateAssessmentReason { get; set; }
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
public bool? IsOveralResponse { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class CO_Export : TU_TR_RSBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 关联域 RS:(访视点备注) 空:裁判选择原因
|
||||
/// </summary>
|
||||
public string RDOMAIN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COSEQ 序号
|
||||
/// </summary>
|
||||
public int COSEQ { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// IDVAR 标识变量 RSSEQ 空:裁判选择原因
|
||||
/// </summary>
|
||||
public string IdentificationVariable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标识 IDVARVAL RSSEQ具体的值 空:裁判选择原因
|
||||
/// </summary>
|
||||
public string Identification { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// COREF 备注引用
|
||||
/// </summary>
|
||||
public string RemarksQuote { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注 COVAL
|
||||
/// </summary>
|
||||
public string Remarks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁决日期 CODTC
|
||||
/// </summary>
|
||||
public string CODTC { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-28 06:22:47Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
namespace IRaCIS.Core.Application.Interfaces;
|
||||
|
||||
public interface IEmailLogService
|
||||
{
|
||||
|
||||
Task<PageOutput<EmailLogView>> GetEmailLogList(EmailLogQuery inQuery);
|
||||
|
||||
Task<IResponseOutput> AddOrUpdateEmailLog(EmailLogAddOrEdit addOrEditEmailLog);
|
||||
|
||||
Task<IResponseOutput> DeleteEmailLog(Guid emailLogId);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -5,11 +5,16 @@ using IRaCIS.Core.Domain.Models;
|
|||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using MailKit;
|
||||
using MailKit.Net.Imap;
|
||||
using MailKit.Search;
|
||||
using MailKit.Security;
|
||||
using Medallion.Threading;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MimeKit;
|
||||
using System.Net.Mail;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
|
|
@ -70,8 +75,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
Task<(Guid identityUserId, Guid userRoleId)> DoctorJoinTrialEmail(Guid trialId, Guid doctorId, string baseUrl, string rootUrl);
|
||||
|
||||
Task UserFeedBackMail(Guid feedBackId);
|
||||
}
|
||||
|
||||
Task AfterUserModifyPasswordSendEmailAsync(Guid userId);
|
||||
|
||||
Task SiteSuervyCheckUser(Guid trialId, string email, string name);
|
||||
|
||||
Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url);
|
||||
}
|
||||
[ApiExplorerSettings(GroupName = "Common")]
|
||||
public class MailVerificationService(IRepository<VerificationCode> _verificationCodeRepository,
|
||||
IRepository<SystemBasicData> _systemBasicDatarepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
|
|
@ -86,12 +97,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
IRepository<UserType> _userTypeRepository,
|
||||
IRepository<Doctor> _doctorTypeRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
|
||||
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
|
||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig,
|
||||
IDistributedLockProvider _distributedLockProvider, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IMailVerificationService
|
||||
{
|
||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
|
||||
|
||||
|
||||
private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
|
||||
|
|
@ -330,7 +343,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||
|
||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||
|
||||
|
||||
|
||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
|
|
@ -520,8 +533,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -580,8 +592,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -710,8 +721,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc);
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig, null);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null);
|
||||
|
||||
//创建账号 和创建角色 一条,更新的时候才记录更新角色
|
||||
if (isNeedCreateNewUser == false)
|
||||
|
|
@ -874,5 +884,111 @@ namespace IRaCIS.Core.Application.Service
|
|||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//用户修改密码发送邮件
|
||||
public async Task AfterUserModifyPasswordSendEmailAsync(Guid userId)
|
||||
{
|
||||
|
||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
//收件地址
|
||||
messageToSend.To.Add(new MailboxAddress(sysUserInfo.FullName, sysUserInfo.EMail));
|
||||
//主题
|
||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||
|
||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
var topicStr = string.Format(input.topicStr, companyName);
|
||||
|
||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||
|
||||
sysUserInfo.FullName
|
||||
);
|
||||
|
||||
return (topicStr, htmlBodyStr);
|
||||
};
|
||||
|
||||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IdentityUser_ModifyPassword, messageToSend, emailConfigFunc);
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||
}
|
||||
|
||||
//中心调研核对人员提醒
|
||||
public async Task SiteSuervyCheckUser(Guid trialId, string email, string name)
|
||||
{
|
||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync();
|
||||
|
||||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
//收件地址
|
||||
messageToSend.To.Add(new MailboxAddress(name, email));
|
||||
//主题
|
||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||
|
||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
|
||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||
|
||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||
name,
|
||||
trialInfo.TrialCode,
|
||||
trialInfo.ResearchProgramNo
|
||||
);
|
||||
|
||||
return (topicStr, htmlBodyStr);
|
||||
};
|
||||
|
||||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_CheckUser, messageToSend, emailConfigFunc);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
public async Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url)
|
||||
{
|
||||
var siteInfo = await _trialSiteRepository.Where(t => t.Id == trialSiteId).Include(x=>x.Trial).FirstOrDefaultAsync();
|
||||
|
||||
var trialInfo = siteInfo.Trial;
|
||||
var messageToSend = new MimeMessage();
|
||||
//发件地址
|
||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||
//收件地址
|
||||
messageToSend.To.Add(new MailboxAddress(name, email));
|
||||
//主题
|
||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||
|
||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||
|
||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||
{
|
||||
|
||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||
|
||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
||||
name,
|
||||
trialInfo.TrialCode,
|
||||
siteInfo.TrialSiteCode,
|
||||
siteInfo.TrialSiteName,
|
||||
url
|
||||
);
|
||||
|
||||
return (topicStr, htmlBodyStr);
|
||||
};
|
||||
|
||||
|
||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_UpdateUser, messageToSend, emailConfigFunc);
|
||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service.Common;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
|
|
@ -10,7 +11,18 @@ namespace IRaCIS.Core.Application.Service
|
|||
{
|
||||
public CommonConfig()
|
||||
{
|
||||
// 在此处拷贝automapper 映射
|
||||
CreateMap<EmailAttachmentLog, EmaliAttachmentInfo>();
|
||||
CreateMap<EmailRecipientLog, EmailRecipientLogView>();
|
||||
CreateMap<EmailLog, EmailLogView>()
|
||||
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList))
|
||||
.ForMember(t => t.AttachmentList, u => u.MapFrom(c => c.AttachmentList));
|
||||
|
||||
CreateMap<EmailLog, GetEmailInfoOutDto>()
|
||||
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList))
|
||||
.ForMember(t => t.AttachmentList, u => u.MapFrom(c => c.AttachmentList));
|
||||
|
||||
CreateMap<EmailLog, EmailLogAddOrEdit>().ReverseMap();
|
||||
|
||||
CreateMap<FrontAuditConfig, FrontAuditConfigAddOrEdit>().ReverseMap();
|
||||
|
||||
|
|
@ -104,6 +116,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.Subject.TrialSite.TrialSiteCode));
|
||||
|
||||
|
||||
CreateMap<TumorExportBaseModel , TU_Export>();
|
||||
CreateMap<TumorExportBaseModel, TR_Export>();
|
||||
CreateMap<TumorExportBaseModel, RS_Export>();
|
||||
CreateMap<TumorExportBaseModel, CO_Export>();
|
||||
|
||||
CreateMap<IVUS_OCTBaseDto, IvusExportDto>();
|
||||
CreateMap<IVUS_OCTBaseDto, OctExportDto>();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
|
|||
.WhereIf(inQuery.IdentityUserName.IsNotNullOrEmpty(), t => t.AuditRecordIdentityUserList.Any(c => c.IdentityUser.UserName.Contains(inQuery.IdentityUserName) || c.IdentityUser.FullName.Contains(inQuery.IdentityUserName)))
|
||||
.WhereIf(inQuery.CompanyName.IsNotNullOrEmpty(), t => t.CompanyName.Contains(inQuery.CompanyName))
|
||||
.WhereIf(inQuery.AuditContent.IsNotNullOrEmpty(), t => t.AuditContent.Contains(inQuery.AuditContent))
|
||||
.WhereIf(inQuery.IsViewTrainingRecord != null, t => t.IsViewTrainingRecord == inQuery.IsViewTrainingRecord)
|
||||
.ProjectTo<AuditRecordView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var pageList = await auditRecordQueryable.ToPagedListAsync(inQuery);
|
||||
|
|
@ -667,7 +668,7 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
|
|||
#endregion
|
||||
|
||||
|
||||
// 不能自动到自己父类这个文件夹
|
||||
// 不能移动到自己父类这个文件夹
|
||||
if (await _auditDocumentRepository.AnyAsync(x => x.ParentId == inDto.ParentId && inDto.Ids.Contains(x.Id)))
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["AuditDocument_CanNotMoveToParent"]);
|
||||
|
|
@ -693,7 +694,7 @@ public class AuditDocumentService(IRepository<AuditDocument> _auditDocumentRepos
|
|||
public async Task<IResponseOutput> CopyFileOrFolder(MovieFileOrFolderInDto inDto)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
foreach (var item in inDto.Ids)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ public class AuditRecordAddOrEdit
|
|||
|
||||
public AuditType AuditType { get; set; }
|
||||
|
||||
public bool IsViewTrainingRecord { get; set; }
|
||||
|
||||
//public List<Guid> IdnetityUserIdList { get; set; }
|
||||
}
|
||||
|
||||
|
|
@ -85,6 +87,8 @@ public class AuditRecordQuery : PageInput
|
|||
public DateTime? EndCreateTime { get; set; }
|
||||
|
||||
public string? IdentityUserName { get; set; }
|
||||
|
||||
public bool? IsViewTrainingRecord { get; set; }
|
||||
}
|
||||
|
||||
public class SetAuditRecordPermissionCommand
|
||||
|
|
|
|||
|
|
@ -92,11 +92,12 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public class UnionDocumentWithConfirmInfoView : UnionDocumentView
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public bool IsNeedSendEmial { get; set; }
|
||||
public DateTime UserCreateTime { get; set; }
|
||||
|
||||
|
||||
public string EmailFromName { get; set; }
|
||||
|
||||
public DateTime? ConfirmTime { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public bool? IsPublish { get; set; }
|
||||
|
||||
public string? FileTypeCode { get; set; }
|
||||
|
||||
}
|
||||
|
||||
///<summary> TrialDocumentAddOrEdit 列表查询参数模型</summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-20 06:17:15Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
namespace IRaCIS.Core.Application.Service.DTO;
|
||||
|
||||
public class UserAgreementView : UserAgreementAddOrEdit
|
||||
{
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class UserAgreementAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public DateTime EffectiveDate { get; set; }
|
||||
|
||||
public string FileContent { get; set; }
|
||||
|
||||
public string FileEnContent { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
public string FileVersion { get; set; }
|
||||
|
||||
public bool IsCurrentVersion { get; set; }
|
||||
|
||||
public DateTime UpdateDate { get; set; }
|
||||
|
||||
public UserAgreementType UserAgreementTypeEnum { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class SetUserAgreementCurrentVersionInDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
|
||||
public class GetUserAgreementByIdInDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
|
||||
public class UserAgreementQuery:PageInput
|
||||
{
|
||||
public DateTime? StartEffectiveDate { get; set; }
|
||||
|
||||
public DateTime? EndEffectiveDate { get; set; }
|
||||
|
||||
public string? FileContent { get; set; }
|
||||
|
||||
public string? FileName { get; set; }
|
||||
|
||||
public string? FileVersion { get; set; }
|
||||
|
||||
public bool? IsCurrentVersion { get; set; }
|
||||
|
||||
public DateTime? StartUpdateDate { get; set; }
|
||||
|
||||
public DateTime? EndUpdateDate { get; set; }
|
||||
|
||||
public UserAgreementType? UserAgreementTypeEnum { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -29,6 +29,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
//入组确认/PD确认
|
||||
|
||||
|
||||
public async Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm)
|
||||
{
|
||||
EmailBusinessScenario businessScenarioEnum;
|
||||
|
|
@ -109,8 +110,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
if (sendEmailConfig != null)
|
||||
{
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
|
||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync();
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig, trialInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-20 06:17:15Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Application.Service.DTO;
|
||||
namespace IRaCIS.Core.Application.Service.Interface;
|
||||
|
||||
public interface IUserAgreementService
|
||||
{
|
||||
|
||||
Task<PageOutput<UserAgreementView>> GetUserAgreementList(UserAgreementQuery inQuery);
|
||||
|
||||
Task<IResponseOutput> AddOrUpdateUserAgreement(UserAgreementAddOrEdit addOrEditUserAgreement);
|
||||
|
||||
Task<IResponseOutput> DeleteUserAgreement(Guid userAgreementId);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -286,7 +286,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
var isInternal = _userInfo.IsZhiZhun;
|
||||
|
||||
var query = from sysDoc in _systemDocumentRepository.AsQueryable(true)
|
||||
var query = from sysDoc in _systemDocumentRepository.Where(t=>t.IsPublish)
|
||||
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
|
||||
//外部人员 只签署 外部需要签署的
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class TrialDocumentService(IRepository<TrialDocument> _trialDocumentRepository,
|
||||
IRepository<Trial> _trialRepository,
|
||||
IRepository<AuditRecord> _auditRecordRepository,
|
||||
IRepository<TrialDocumentAttachment> _trialDocumentAttachmentRepository,
|
||||
ISystemDocumentService _systemDocumentService,
|
||||
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
|
||||
|
|
@ -53,9 +54,9 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
var trialDocumentAttachmentQueryable = _trialDocumentAttachmentRepository
|
||||
.WhereIf(inQuery.TrialDocumentId != null, x => x.TrialDocumentId == inQuery.TrialDocumentId)
|
||||
.WhereIf(inQuery.Name != null, x => x.Name.Contains(inQuery.Name))
|
||||
.WhereIf(inQuery.FileFormat != null, x => x.FileFormat == inQuery.FileFormat)
|
||||
.ProjectTo<TrialDocumentAttachmentView>(_mapper.ConfigurationProvider);
|
||||
.WhereIf(inQuery.Name != null, x => x.Name.Contains(inQuery.Name))
|
||||
.WhereIf(inQuery.FileFormat != null, x => x.FileFormat == inQuery.FileFormat)
|
||||
.ProjectTo<TrialDocumentAttachmentView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var pageList = await trialDocumentAttachmentQueryable.ToPagedListAsync(inQuery);
|
||||
|
||||
|
|
@ -101,7 +102,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
{
|
||||
IsPublish = true,
|
||||
IsDeleted = false,
|
||||
});
|
||||
},false,true);
|
||||
await _trialDocumentRepository.SaveChangesAsync();
|
||||
Console.WriteLine("开始 发布项目文档");
|
||||
|
||||
|
|
@ -121,7 +122,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试定时发送
|
||||
/// 测试邮件定时发送
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<IResponseOutput> TestPush()
|
||||
|
|
@ -139,6 +140,22 @@ namespace IRaCIS.Core.Application.Services
|
|||
return ResponseOutput.Result(true);
|
||||
}
|
||||
|
||||
|
||||
public async Task<IResponseOutput> TestSendEmail()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
// 创建独立作用域
|
||||
using (var scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
// 从新作用域解析服务
|
||||
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
|
||||
await mediator.Publish(new ImageQCRecurringEvent { TrialId= Guid.Parse("08de2254-5d7d-581a-0242-0a0001000000") });
|
||||
}
|
||||
});
|
||||
return ResponseOutput.Result(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting 界面的 项目所有文档列表
|
||||
/// </summary>
|
||||
|
|
@ -151,8 +168,10 @@ namespace IRaCIS.Core.Application.Services
|
|||
var trialDocumentQueryable = _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == inQuery.TrialId)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.Name), t => t.Name.Contains(inQuery.Name))
|
||||
.WhereIf(inQuery.FileTypeId != null, t => t.FileTypeId == inQuery.FileTypeId)
|
||||
.WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId))
|
||||
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
|
||||
.WhereIf(inQuery.UserTypeId != null, t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId))
|
||||
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
|
||||
.WhereIf(inQuery.IsPublish != null, t => t.IsPublish == inQuery.IsPublish)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.FileTypeCode), t => t.FileType.Code== inQuery.FileTypeCode)
|
||||
.ProjectTo<TrialDocumentView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken, isEn_Us = _userInfo.IsEn_Us });
|
||||
|
||||
return await trialDocumentQueryable.ToPagedListAsync(inQuery);
|
||||
|
|
@ -161,7 +180,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
[HttpPost]
|
||||
public async Task<PageOutput<TrialSignDocView>> GetTrialSignDocumentList(TrialDocQuery inQuery)
|
||||
{
|
||||
var trialDocQueryable = from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
||||
var trialDocQueryable = from trialDoc in _trialDocumentRepository.Where(t=>t.IsPublish)
|
||||
.WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId)
|
||||
.Where(t => t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
|
||||
|
|
@ -334,7 +353,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
#region 统一用户修改
|
||||
|
||||
var systemDocQuery =
|
||||
from sysDoc in _systemDocumentRepository.AsQueryable(true).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
from sysDoc in _systemDocumentRepository.Where(t=>t.IsPublish).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
//外部人员 只签署 外部需要签署的
|
||||
.WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter)
|
||||
from trialUser in _trialIdentityUserRepository.AsQueryable(false)
|
||||
|
|
@ -373,7 +392,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
//项目文档查询
|
||||
var trialDocQuery =
|
||||
from trialDoc in _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == inQuery.TrialId).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
from trialDoc in _trialDocumentRepository.Where(t=>t.IsPublish).Where(t => t.TrialId == inQuery.TrialId).Where(t => t.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId && t.IdentityUserId == _userInfo.IdentityUserId
|
||||
&& t.TrialUserRoleList.Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId)))
|
||||
|
||||
|
|
@ -563,13 +582,14 @@ namespace IRaCIS.Core.Application.Services
|
|||
#endregion
|
||||
|
||||
|
||||
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped)
|
||||
var needSignTrialDocCount = await _trialDocumentRepository.AsQueryable(true).Where(t=>t.IsPublish)
|
||||
.Where(t => t.TrialId == inQuery.TrialId && t.Trial.TrialStatusStr != StaticData.TrialState.TrialStopped)
|
||||
.Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
|
||||
.Where(t => t.IsDeleted == false && !t.TrialDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
.CountAsync();
|
||||
|
||||
|
||||
var needSignSystemDocCount = await _systemDocumentRepository.AsQueryable(true)
|
||||
var needSignSystemDocCount = await _systemDocumentRepository.AsQueryable(true).Where(t => t.IsPublish)
|
||||
.WhereIf(isInternal == false, t => t.DocUserSignType == DocUserSignType.InnerAndOuter)
|
||||
.Where(t => t.IsDeleted == false && !t.SystemDocConfirmedUserList.Any(t => t.ConfirmUserId == _userInfo.IdentityUserId && t.ConfirmTime != null) && t.NeedConfirmedUserTypeList.Any(u => u.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||||
.CountAsync();
|
||||
|
|
@ -602,7 +622,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
var trialInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId, ignoreQueryFilters: true).Select(t => new { t.TrialFinishedTime, t.TrialStatusStr }).FirstNotNullAsync());
|
||||
|
||||
var trialDocQuery =
|
||||
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId)
|
||||
from trialDoc in _trialDocumentRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsPublish)
|
||||
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
|
||||
from trialUser in _trialIdentityUserRepository.AsQueryable(false).Where(t => t.TrialId == inQuery.TrialId
|
||||
&& t.TrialUserRoleList.AsQueryable().Any(t => trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == t.UserRole.UserTypeId))
|
||||
|
|
@ -903,6 +923,12 @@ namespace IRaCIS.Core.Application.Services
|
|||
//EA 只能查看内部人员文档
|
||||
var isEA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.EA;
|
||||
|
||||
//EA 但是没有在进行的培训记录查看权限,那么返回空数据
|
||||
if (isEA && !_auditRecordRepository.Any(t => t.IsViewTrainingRecord && t.AuditState == AuditState.Ongoing && t.AuditRecordIdentityUserList.Any(c => c.IdentityUserId == _userInfo.IdentityUserId)))
|
||||
{
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
var list = _systemDocConfirmedUserRepository.Where(t => t.ConfirmTime != null)
|
||||
.WhereIf(isEA, t => t.ConfirmUser.IsZhiZhun == true)
|
||||
.Select(t => new { t.ConfirmUserId, t.ConfirmUser.UserName, t.ConfirmUser.FullName }).Distinct().ToList();
|
||||
|
|
@ -918,6 +944,12 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
var isEA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.EA;
|
||||
|
||||
//EA 但是没有在进行的培训记录查看权限,那么返回空数据
|
||||
if (isEA && !_auditRecordRepository.Any(t => t.IsViewTrainingRecord && t.AuditState == AuditState.Ongoing && t.AuditRecordIdentityUserList.Any(c=>c.IdentityUserId==_userInfo.IdentityUserId)))
|
||||
{
|
||||
return ResponseOutput.Ok(new PageOutput<UnionDocumentWithConfirmInfoView>());
|
||||
}
|
||||
|
||||
var systemDocQuery =
|
||||
from sysDoc in _systemDocumentRepository.AsQueryable(false)
|
||||
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
|
||||
|
|
@ -1060,6 +1092,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
return ResponseOutput.NotOk(_localizer["TrialD_DuplicateFileInProject"]);
|
||||
}
|
||||
|
||||
entity.IsDeleted = true;
|
||||
//entity.Id = NewId.NextGuid();
|
||||
await _trialDocumentRepository.AddAsync(entity, true);
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
|
@ -1080,6 +1113,7 @@ namespace IRaCIS.Core.Application.Services
|
|||
|
||||
_mapper.Map(addOrEditTrialDocument, document);
|
||||
document.UpdateTime = DateTime.Now;
|
||||
|
||||
#region 不区分路径了
|
||||
|
||||
//if (document.FileTypeId != addOrEditTrialDocument.FileTypeId)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ using IRaCIS.Core.Application.Interfaces;
|
|||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Domain.Share.Common;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
|
|
@ -617,8 +618,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
FileStream = File.OpenRead(phyPath),
|
||||
});
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
|
||||
var trialInfo = await _trialRepository.Where(t => t.Id == taskInfo.TrialId).FirstOrDefaultAsync();
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig, trialInfo);
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
|
@ -733,8 +734,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
FileStream = pdfMemoryStream
|
||||
});
|
||||
|
||||
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
|
||||
var trialInfo = await _trialRepository.Where(t => t.Id == taskInfo.TrialId).FirstOrDefaultAsync();
|
||||
await SendEmailHelper.SendEmailAsync(sendEmailConfig, trialInfo);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1763,22 +1764,22 @@ x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && x.Readi
|
|||
|
||||
await _trialEmailNoticeConfigRepository.SaveChangesAsync();
|
||||
|
||||
var cronInfo = await _trialEmailNoticeConfigRepository.Where(t => t.Id == addOrEditTrialEmailNoticeConfig.Id)
|
||||
.Select(t => new { t.Id, t.Code, TrialCode = t.Trial.TrialCode, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
||||
.FirstAsync();
|
||||
// var cronInfo = await _trialEmailNoticeConfigRepository.Where(t => t.Id == addOrEditTrialEmailNoticeConfig.Id)
|
||||
//.Select(t => new { t.Id, t.Code, TrialCode = t.Trial.TrialCode, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
||||
//.FirstAsync();
|
||||
|
||||
var jobId = $"{cronInfo.TrialId}({cronInfo.TrialCode})_({cronInfo.BusinessScenarioEnum})";
|
||||
// var jobId = $"{cronInfo.TrialId}({cronInfo.TrialCode})_({cronInfo.BusinessScenarioEnum})";
|
||||
|
||||
|
||||
if (addOrEditTrialEmailNoticeConfig.IsAutoSend)
|
||||
{
|
||||
HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, addOrEditTrialEmailNoticeConfig.TrialId, addOrEditTrialEmailNoticeConfig.BusinessScenarioEnum, addOrEditTrialEmailNoticeConfig.EmailCron);
|
||||
// if (addOrEditTrialEmailNoticeConfig.IsAutoSend)
|
||||
// {
|
||||
// HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, addOrEditTrialEmailNoticeConfig.TrialId, addOrEditTrialEmailNoticeConfig.BusinessScenarioEnum, addOrEditTrialEmailNoticeConfig.EmailCron);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
HangfireJobHelper.RemoveCronJob(jobId);
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// HangfireJobHelper.RemoveCronJob(jobId);
|
||||
// }
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-10-20 06:17:11Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Service.Interface;
|
||||
using IRaCIS.Core.Application.Service.DTO;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 用户协议和隐私采集服务
|
||||
/// </summary>
|
||||
/// <param name="_userAgreementRepository"></param>
|
||||
/// <param name="_mapper"></param>
|
||||
/// <param name="_userInfo"></param>
|
||||
/// <param name="_localizer"></param>
|
||||
[ApiExplorerSettings(GroupName = "FileRecord")]
|
||||
public class UserAgreementService(IRepository<UserAgreement> _userAgreementRepository,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService, IUserAgreementService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户协议和隐私采集列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<UserAgreementView>> GetUserAgreementList(UserAgreementQuery inQuery)
|
||||
{
|
||||
var userAgreementQueryable =_userAgreementRepository
|
||||
.WhereIf(inQuery.StartEffectiveDate.HasValue, t => t.EffectiveDate >= inQuery.StartEffectiveDate.Value)
|
||||
.WhereIf(inQuery.EndEffectiveDate.HasValue, t => t.EffectiveDate <= inQuery.EndEffectiveDate.Value)
|
||||
.WhereIf(inQuery.FileContent != null, t => t.FileContent.Contains(inQuery.FileContent))
|
||||
.WhereIf(inQuery.FileName != null, t => t.FileName.Contains(inQuery.FileName))
|
||||
.WhereIf(inQuery.FileVersion != null, t => t.FileVersion.Contains(inQuery.FileVersion))
|
||||
.WhereIf(inQuery.IsCurrentVersion != null, t => t.IsCurrentVersion==inQuery.IsCurrentVersion)
|
||||
.WhereIf(inQuery.UserAgreementTypeEnum != null, t => t.UserAgreementTypeEnum == inQuery.UserAgreementTypeEnum)
|
||||
.WhereIf(inQuery.StartUpdateDate.HasValue, t => t.UpdateDate >= inQuery.StartUpdateDate.Value)
|
||||
.WhereIf(inQuery.EndUpdateDate.HasValue, t => t.UpdateDate <= inQuery.EndUpdateDate.Value)
|
||||
.ProjectTo<UserAgreementView>(_mapper.ConfigurationProvider);
|
||||
var pageList= await userAgreementQueryable.ToPagedListAsync(inQuery);
|
||||
|
||||
return pageList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前版本的用户协议和隐私采集
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
public async Task<List<UserAgreementView>> GetCurrentVersionUserAgreements()
|
||||
{
|
||||
var userAgreementList = await _userAgreementRepository.Where(x=>x.IsCurrentVersion)
|
||||
.ProjectTo<UserAgreementView>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
return userAgreementList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据Id获取用户协议和隐私采集
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
public async Task<UserAgreementView> GetUserAgreementById(GetUserAgreementByIdInDto inDto)
|
||||
{
|
||||
var userAgreement = await _userAgreementRepository.Where(x => x.Id == inDto.Id)
|
||||
.ProjectTo<UserAgreementView>(_mapper.ConfigurationProvider)
|
||||
.FirstNotNullAsync();
|
||||
return userAgreement;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置为当前版本
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> SetCurrentVersion(SetUserAgreementCurrentVersionInDto inDto)
|
||||
{
|
||||
var userAgreement=await _userAgreementRepository.Where(x=>x.Id==inDto.Id).FirstNotNullAsync();
|
||||
await _userAgreementRepository.UpdatePartialFromQueryAsync(
|
||||
x => x.UserAgreementTypeEnum== userAgreement.UserAgreementTypeEnum&&x.IsCurrentVersion,
|
||||
x => new UserAgreement { IsCurrentVersion = false },true);
|
||||
|
||||
await _userAgreementRepository.UpdatePartialFromQueryAsync(
|
||||
inDto.Id,
|
||||
x => new UserAgreement { IsCurrentVersion = true },true);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增或者修改用户协议和隐私采集
|
||||
/// </summary>
|
||||
/// <param name="addOrEditUserAgreement"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> AddOrUpdateUserAgreement(UserAgreementAddOrEdit addOrEditUserAgreement)
|
||||
{
|
||||
var entity = await _userAgreementRepository.InsertOrUpdateAsync(addOrEditUserAgreement, true);
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除用户协议和隐私采集
|
||||
/// </summary>
|
||||
/// <param name="userAgreementId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{userAgreementId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteUserAgreement(Guid userAgreementId)
|
||||
{
|
||||
var success = await _userAgreementRepository.DeleteFromQueryAsync(t => t.Id == userAgreementId,true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -16,6 +16,11 @@ namespace IRaCIS.Core.Application.Service
|
|||
var userId = Guid.Empty;
|
||||
var isEn_Us = false;
|
||||
|
||||
// 在此处拷贝automapper 映射
|
||||
|
||||
CreateMap<UserAgreement, UserAgreementView>();
|
||||
CreateMap<UserAgreement, UserAgreementAddOrEdit>().ReverseMap();
|
||||
|
||||
// 在此处拷贝automapper 映射
|
||||
CreateMap<TrialDocumentAttachment, TrialDocumentAttachmentView>();
|
||||
CreateMap<TrialDocumentAttachment, TrialDocumentAttachmentAddOrEdit>().ReverseMap();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using IRaCIS.Core.Domain.Share;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
|
||||
{
|
||||
|
|
@ -27,6 +28,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
|
|||
|
||||
public List<StudyBasicInfo> UploadStudyList { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<StudyBasicInfo> OriginalTaskStudyList { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -116,6 +120,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
|
|||
public int ReadingSeriesCount { get; set; }
|
||||
|
||||
public int ReadingInstanceCount { get; set; }
|
||||
|
||||
public Guid? SubjectVisitId { get; set; }
|
||||
}
|
||||
|
||||
public class NoneDicomStudyBasicInfo
|
||||
|
|
@ -140,5 +146,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
|
|||
public int ReadingFileCount { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ImageMarkNoneDicomStudyBasicInfo: NoneDicomStudyBasicInfo
|
||||
{
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public Guid SubjectVisitId { get; set; }
|
||||
|
||||
public int FileCount { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class PreArchiveDicomStudyCommand
|
||||
|
|
@ -237,6 +238,9 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class TaskStudyArchiveConfirmResult
|
||||
|
|
@ -265,8 +269,9 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public AddOrUpdateStudyDto Study { get; set; }
|
||||
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
}
|
||||
|
||||
public class NewArchiveStudyCommand
|
||||
|
|
@ -324,13 +329,26 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string BodyPartExamined { get; set; } = string.Empty;
|
||||
|
||||
public string DicomStudyDate { get; set; }
|
||||
public string DicomStudyDate { get; set; } = string.Empty;
|
||||
|
||||
public string DicomStudyTime { get; set; }
|
||||
public string DicomStudyTime { get; set; } = string.Empty;
|
||||
|
||||
public List<AddOrUpdateSeriesDto> SeriesList { get; set; }
|
||||
|
||||
#region 模态支持增加字段
|
||||
|
||||
public string Manufacturer { get; set; } = string.Empty;
|
||||
|
||||
public string ManufacturerModelName { get; set; } = string.Empty;
|
||||
|
||||
public string DeviceSerialNumber { get; set; } = string.Empty;
|
||||
public string DeviceUID { get; set; } = string.Empty;
|
||||
|
||||
public string SoftwareVersions { get; set; } = string.Empty;
|
||||
|
||||
public string PatientWeight { get; set; } = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -358,14 +376,22 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string ImageResizePath { get; set; } = string.Empty;
|
||||
|
||||
public string DicomSeriesDate { get; set; }
|
||||
public string DicomSeriesDate { get; set; } = string.Empty;
|
||||
|
||||
public string DicomSeriesTime { get; set; }
|
||||
public string DicomSeriesTime { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public List<AddInstanceDto> InstanceList { get; set; }
|
||||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
#region 模态增加
|
||||
|
||||
public string RadiopharmaceuticalInformationSequence { get; set; } = string.Empty;
|
||||
|
||||
public string AcquisitionDate { get; set; } = string.Empty;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -398,15 +424,46 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public long FileSize { get; set; }
|
||||
|
||||
public string SOPClassUID { get; set; }
|
||||
public string SOPClassUID { get; set; } = string.Empty;
|
||||
|
||||
public string MediaStorageSOPClassUID { get; set; }
|
||||
public string MediaStorageSOPClassUID { get; set; } = string.Empty;
|
||||
|
||||
public string TransferSytaxUID { get; set; }
|
||||
public string TransferSytaxUID { get; set; } = string.Empty;
|
||||
|
||||
public string MediaStorageSOPInstanceUID { get; set; }
|
||||
public string MediaStorageSOPInstanceUID { get; set; } = string.Empty;
|
||||
|
||||
public bool IsEncapsulated => DicomTransferSyntax.Lookup(DicomUID.Parse(TransferSytaxUID)).IsEncapsulated;
|
||||
public bool IsEncapsulated => !string.IsNullOrEmpty(TransferSytaxUID) ? DicomTransferSyntax.Lookup(DicomUID.Parse(TransferSytaxUID)).IsEncapsulated : false;
|
||||
|
||||
#region 模态支持增加字段
|
||||
|
||||
public string PhotometricInterpretation { get; set; } = string.Empty;
|
||||
|
||||
public int BitsAllocated { get; set; }
|
||||
|
||||
public string PixelRepresentation { get; set; } = string.Empty;
|
||||
|
||||
public string RescaleIntercept { get; set; } = string.Empty;
|
||||
|
||||
public string RescaleSlope { get; set; } = string.Empty;
|
||||
|
||||
public string ImagePositionPatient { get; set; } = string.Empty;
|
||||
public string ImageOrientationPatient { get; set; } = string.Empty;
|
||||
|
||||
//可能大
|
||||
public string SequenceOfUltrasoundRegions { get; set; } = string.Empty;
|
||||
|
||||
public string FrameTime { get; set; } = string.Empty;
|
||||
|
||||
public string CorrectedImage { get; set; } = string.Empty;
|
||||
|
||||
public string Units { get; set; } = string.Empty;
|
||||
public string DecayCorrection { get; set; } = string.Empty;
|
||||
|
||||
public string EncapsulatedDocument { get; set; } = string.Empty;
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -440,12 +497,17 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public string? SubjectCode { get; set; }
|
||||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
|
||||
public Guid? SubjectVisitId { get; set; }
|
||||
}
|
||||
|
||||
public class IRTaskUploadedDicomStudyQuery
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public Guid? SubjectVisitId { get; set; }
|
||||
}
|
||||
|
||||
public class IRUploadTaskDicomStudyDto : DicomStudyBasicInfo
|
||||
|
|
@ -519,6 +581,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public string TaskBlindName { get; set; }
|
||||
|
||||
public string TaskName { get; set; }
|
||||
|
||||
public string VisitName { get; set; }
|
||||
public Guid? SourceSubjectVisitId { get; set; }
|
||||
|
||||
public ReadingTaskState ReadingTaskState { get; set; }
|
||||
|
|
@ -536,11 +600,15 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string TaskBlindName { get; set; }
|
||||
|
||||
|
||||
|
||||
public Guid VisitId { get; set; }
|
||||
|
||||
public List<DownloadDicomStudyDto> StudyList { get; set; }
|
||||
public List<DownloadNoneDicomStudyDto> NoneDicomStudyList { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<DownloadDicomStudyDto> TaskStudyList { get; set; }
|
||||
|
||||
public List<DownloadNoneDicomStudyDto> NoneDicomStudyList { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadDicomStudyDto
|
||||
|
|
@ -551,14 +619,14 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public string StudyInstanceUid { get; set; }
|
||||
public string StudyDIRPath { get; set; }
|
||||
|
||||
public List<DownloadDicomSeriesDto> SeriesList { get; set; }
|
||||
public List<DownloadDicomSeriesDto> SeriesList { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadDicomSeriesDto
|
||||
{
|
||||
public string Modality { get; set; }
|
||||
|
||||
public List<DownloadDicomInstanceDto> InstanceList { get; set; }
|
||||
public List<DownloadDicomInstanceDto> InstanceList { get; set; }
|
||||
}
|
||||
|
||||
public class DownloadDicomInstanceDto
|
||||
|
|
@ -609,6 +677,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public string? SubjectCode { get; set; }
|
||||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -629,6 +699,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public List<Guid> NoneDicomStudyIdList { get; set; }
|
||||
|
||||
public bool? IsImageSegmentLabel { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class TrialKeyImageExportDTO
|
||||
|
|
@ -735,7 +807,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
? $"{TotalReadingImageSize.Value / 1024d / 1024d:F3} MB"
|
||||
: "0.000 MB";
|
||||
|
||||
public string ImageTypeStr => $"{(IsHaveDicom ? "DICOM" : "")}{(IsHaveNoneDicom&&IsHaveDicom?" , ":"")}{(IsHaveNoneDicom ? "Non-DICOM" : "")}";
|
||||
public string ImageTypeStr => $"{(IsHaveDicom ? "DICOM" : "")}{(IsHaveNoneDicom && IsHaveDicom ? " , " : "")}{(IsHaveNoneDicom ? "Non-DICOM" : "")}";
|
||||
|
||||
public bool IsHaveDicom { get; set; }
|
||||
|
||||
|
|
@ -878,4 +950,90 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public Guid TaskId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class SubjectVisitMarkQuery:PageInput
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
|
||||
public string? SubjectCode { get; set; }
|
||||
|
||||
public bool? IsUrgent { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class SubjectVisitMarkDTO
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public bool IsUrgent { get; set; }
|
||||
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
public int? VisitCount { get; set; }
|
||||
|
||||
|
||||
public int? MarkIVUSVisitCount { get; set; }
|
||||
|
||||
public int? MarkOCTVisitCount { get; set; }
|
||||
|
||||
|
||||
public int? DicomStudyCount { get; set; }
|
||||
|
||||
public int? MarkDicomStudyCount { get; set; }
|
||||
|
||||
public int? NoneDicomStudyCount { get; set; }
|
||||
|
||||
public int? MarkNoneDicomStudyCount { get; set; }
|
||||
}
|
||||
|
||||
public class SubjectVisitMarkStudyDto
|
||||
{
|
||||
public bool IsDicom => DicomStudyList.Count() > 0;
|
||||
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
public string VisitName { get; set; }
|
||||
|
||||
public Guid SourceSubjectVisitId { get; set; }
|
||||
|
||||
|
||||
public List<DicomStudyBasicInfo> DicomStudyList { get; set; } = new List<DicomStudyBasicInfo>();
|
||||
|
||||
public List<NoneDicomStudyBasicInfo> NoneDicomStudyList { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class SubjectVisitMarkUploadDto
|
||||
{
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public Guid SubejctId { get; set; }
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
public string VisitName { get; set; }
|
||||
|
||||
public Guid? SourceSubjectVisitId => SubjectVisitId;
|
||||
|
||||
//防止前端null 故意返回
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public List<StudyBasicInfo> OrginalStudyList { get; set; }
|
||||
|
||||
public List<StudyBasicInfo> UploadStudyList { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -3,7 +3,9 @@
|
|||
// 生成时间 2021-12-06 10:54:55
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using DocumentFormat.OpenXml.EMMA;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Medallion.Threading;
|
||||
|
|
@ -34,7 +36,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
[FromQuery] Guid? nonedicomStudyId,
|
||||
[FromQuery] bool isFilterZip,
|
||||
[FromQuery] Guid? visitTaskId,
|
||||
[FromQuery] bool isReading)
|
||||
[FromQuery] bool isReading,
|
||||
[FromQuery] bool? isImageSegmentLabel)
|
||||
{
|
||||
var qcAuditState = await _subjectVisitRepository.Where(s => s.Id == subjectVisitId).Select(t => t.AuditState).FirstOrDefaultAsync();
|
||||
|
||||
|
|
@ -44,33 +47,74 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
//质控过程中并且不是IQC时,可以看到删除的(不需要忽略过滤器) 质控中iqc 也需要看到删除的
|
||||
var isViewDelete = !isQCFinished;
|
||||
|
||||
var isFilterIVUSNoneDicom = false;
|
||||
|
||||
CriterionType? criterionType = null;
|
||||
|
||||
IQueryable<NoneDicomStudyView> noneDicomStudyQueryable = default;
|
||||
if (visitTaskId == null)
|
||||
if (visitTaskId == null || visitTaskId == Guid.Empty)
|
||||
{
|
||||
//质控过程中,需要忽略过滤质控设置删除的检查,以及设置删除的文件,质控通过后才
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId, ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
if (visitTaskId == null)
|
||||
{
|
||||
|
||||
//质控过程中,需要忽略过滤质控设置删除的检查,以及设置删除的文件,质控通过后才
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId, ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
.ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, isReading = isReading });
|
||||
}
|
||||
else
|
||||
{
|
||||
//靶段标注上传后查看影像
|
||||
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId, ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.ProjectTo<ImageLabelNoneDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, isReading = isReading });
|
||||
|
||||
}
|
||||
|
||||
|
||||
.ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, isReading = isReading });
|
||||
//ivus-在访视的时候visitTaskId==null 需要过滤掉空检查 ,但是在靶段标注的查看访视级别的时候不能过滤
|
||||
if (_subjectVisitRepository.Where(t => t.Id == subjectVisitId).SelectMany(t => t.Trial.TrialReadingCriterionList)
|
||||
.Where(t => t.CriterionType == CriterionType.IVUS || t.CriterionType == CriterionType.OCT).Distinct().Count() == 2
|
||||
&& visitTaskId == null)
|
||||
{
|
||||
isFilterIVUSNoneDicom = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(t => new { t.BlindSubjectCode, t.TrialReadingCriterionId, t.TrialReadingCriterion.IsImageFilter, t.TrialReadingCriterion.CriterionModalitys }).FirstNotNullAsync();
|
||||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(t => new { t.BlindSubjectCode, t.TrialReadingCriterionId, t.TrialReadingCriterion.CriterionType, t.TrialReadingCriterion.IsImageFilter, t.TrialReadingCriterion.CriterionModalitys }).FirstNotNullAsync();
|
||||
criterionType = taskinfo.CriterionType;
|
||||
|
||||
if ((taskinfo.CriterionType == CriterionType.IVUS || taskinfo.CriterionType == CriterionType.OCT) && isImageSegmentLabel == false)
|
||||
{
|
||||
//后处理原始影像预览
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.SubjectVisitId == subjectVisitId, ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.Where(t => taskinfo.IsImageFilter ? ("|" + taskinfo.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
|
||||
.ProjectTo<ImageLabelNoneDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, visiTaskId = visitTaskId, isReading = isReading });
|
||||
}
|
||||
else
|
||||
{
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.TaskNoneDicomFileList.Any(t => t.VisitTaskId == visitTaskId), ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
.Where(t => taskinfo.IsImageFilter ? ("|" + taskinfo.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.ProjectTo<TaskDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, visiTaskId = visitTaskId, isReading = isReading });
|
||||
}
|
||||
|
||||
|
||||
noneDicomStudyQueryable = _noneDicomStudyRepository.Where(t => t.TaskNoneDicomFileList.Any(t => t.VisitTaskId == visitTaskId), ignoreQueryFilters: isViewDelete)
|
||||
.WhereIf(isReading, t => t.IsReading && t.IsDeleted == false)
|
||||
.Where(t => taskinfo.IsImageFilter ? ("|" + taskinfo.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
|
||||
.WhereIf(nonedicomStudyId != null, t => t.Id == nonedicomStudyId)
|
||||
.ProjectTo<TaskDicomStudyView>(_mapper.ConfigurationProvider, new { isFilterZip = isFilterZip, visiTaskId = visitTaskId, isReading = isReading });
|
||||
}
|
||||
|
||||
|
||||
var list = await noneDicomStudyQueryable.OrderBy(x => x.ImageDate).ThenBy(x => x.CreateTime).ToListAsync();
|
||||
|
||||
var config = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { t.Trial.ImageFormatList, t.Trial.StudyNameList, t.Trial.IsShowStudyName, AuditState = qcAuditState }).FirstOrDefaultAsync();
|
||||
var list = await noneDicomStudyQueryable.Where(t => isFilterIVUSNoneDicom ? t.Modality != "IVUS" : true)
|
||||
.OrderBy(x => x.ImageDate).ThenBy(x => x.CreateTime).ToListAsync();
|
||||
|
||||
var config = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => new { t.Trial.ImageFormatList, t.Trial.StudyNameList, t.Trial.IsShowStudyName, AuditState = qcAuditState, CriterionType=criterionType }).FirstOrDefaultAsync();
|
||||
return ResponseOutput.Ok(list, config);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
CreateMap<DicomStudy, DicomStudyDTO>();
|
||||
CreateMap<DicomSeries, DicomSeriesDTO>()
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.SubjectVisit.Subject.Code))
|
||||
.ForMember(o => o.VisitName, t => t.MapFrom(u => u.SubjectVisit.VisitName));
|
||||
.ForMember(o => o.VisitName, t => t.MapFrom(u => u.SubjectVisit.VisitName));
|
||||
CreateMap<SCPSeries, DicomSeriesDTO>();
|
||||
|
||||
|
||||
|
|
@ -136,6 +136,11 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(d => d.ReadingSeriesCount, u => u.MapFrom(s => s.SeriesList.Where(t => t.IsReading).Count()))
|
||||
.ForMember(d => d.ReadingInstanceCount, u => u.MapFrom(s => s.InstanceList.Where(t => t.IsReading && t.DicomSerie.IsReading).Count()));
|
||||
|
||||
CreateMap<TaskStudy, DicomStudyBasicInfo>()
|
||||
//.ForMember(d => d.SubjectVisitId, u => u.MapFrom(s => s.SubjectVisitId))
|
||||
.ForMember(d => d.ReadingSeriesCount, u => u.MapFrom(s => s.SeriesCount))
|
||||
.ForMember(d => d.ReadingInstanceCount, u => u.MapFrom(s => s.InstanceCount));
|
||||
|
||||
CreateMap<NoneDicomStudy, NoneDicomStudyBasicInfo>()
|
||||
.ForMember(d => d.ReadingFileCount, u => u.MapFrom(s => s.NoneDicomFileList.Where(t => t.IsReading).Count()));
|
||||
|
||||
|
|
@ -145,7 +150,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys))
|
||||
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
|
||||
.ForMember(d => d.DicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.StudyList))
|
||||
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.IsReading)));
|
||||
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.IsReading)));
|
||||
|
||||
CreateMap<TrialImageDownload, TrialImageDownloadView>()
|
||||
.ForMember(d => d.UserFullName, u => u.MapFrom(s => s.CreateUserRole.FullName))
|
||||
|
|
@ -158,7 +163,25 @@ namespace IRaCIS.Core.Application.Service
|
|||
CreateMap<SCPSeries, DicomSeriesDTO>();
|
||||
|
||||
CreateMap<NoneDicomEdit, NoneDicomStudy>();
|
||||
|
||||
|
||||
|
||||
CreateMap<SubjectVisit, SubjectVisitMarkStudyDto>()
|
||||
.ForMember(d => d.SourceSubjectVisitId, u => u.MapFrom(u => u.Id))
|
||||
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.Subject.Code))
|
||||
.ForMember(d => d.DicomStudyList, u => u.MapFrom(s => s.StudyList))
|
||||
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.NoneDicomStudyList.Where(t => t.IsReading)));
|
||||
|
||||
|
||||
|
||||
CreateMap<NoneDicomStudy, ImageMarkNoneDicomStudyBasicInfo>()
|
||||
.ForMember(d => d.SubjectVisitId, u => u.MapFrom(s => s.SubjectVisitId))
|
||||
.ForMember(d => d.FileCount, u => u.MapFrom(s => s.ImageLabelNoneDicomFileList.Count()))
|
||||
.ForMember(d => d.ReadingFileCount, u => u.MapFrom(s => s.ImageLabelNoneDicomFileList.Count()));
|
||||
|
||||
CreateMap<ImageMarkNoneDicomStudyBasicInfo, NoneDicomStudyBasicInfo>();
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,10 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
|
|||
public string ModuleTypeName { get; set; } = string.Empty;
|
||||
public string ModuleTypeNameCN { get; set; } = string.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 标准枚举
|
||||
/// </summary>
|
||||
public CriterionType? CriterionType { get; set; }
|
||||
public string SignText { get; set; } = string.Empty;
|
||||
|
||||
public decimal? VisitNum { get; set; }
|
||||
|
|
|
|||
|
|
@ -846,10 +846,26 @@ namespace IRaCIS.Core.Application.Service
|
|||
if (jsonObject["DictionaryCode"] != null && jsonObject["DictionaryCode"].ToString() != string.Empty)
|
||||
{
|
||||
|
||||
jsonObject[item.Code] = await _dictionaryRepository.Where(x => x.Code == jsonObject["DictionaryCode"].ToString()).Join(_dictionaryRepository.Where(x => x.Code == jsonObject[item.Code].ToString()), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
|
||||
if (jsonObject[item.Code].ToString().Contains(","))
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).FirstOrDefaultAsync();
|
||||
var data = jsonObject[item.Code].ToString().Split(',').ToList();
|
||||
|
||||
var codeList = await _dictionaryRepository.Where(x => x.Code == jsonObject["DictionaryCode"].ToString()).Join(_dictionaryRepository.Where(x => data.Contains(x.Code)), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).ToListAsync();
|
||||
jsonObject[item.Code] = string.Join(",", codeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonObject[item.Code] = await _dictionaryRepository.Where(x => x.Code == jsonObject["DictionaryCode"].ToString()).Join(_dictionaryRepository.Where(x => x.Code == jsonObject[item.Code].ToString()), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
jsonList.Add(jsonObject);
|
||||
|
|
@ -917,10 +933,25 @@ namespace IRaCIS.Core.Application.Service
|
|||
//通过字典项的code 翻译 枚举或者 bool
|
||||
else
|
||||
{
|
||||
jsonDataDic[item.Key] = await _dictionaryRepository.Where(x => x.Code == item.Code).Join(_dictionaryRepository.Where(x => x.Code == value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
if (value.ToString().Contains(","))
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).FirstOrDefaultAsync();
|
||||
var data = value.ToString().Split(',').ToList();
|
||||
|
||||
var codeList = await _dictionaryRepository.Where(x => x.Code == item.Code).Join(_dictionaryRepository.Where(x => data.Contains(x.Code)), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).ToListAsync();
|
||||
jsonDataDic[item.Key] = string.Join(",", codeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonDataDic[item.Key] = await _dictionaryRepository.Where(x => x.Code == item.Code).Join(_dictionaryRepository.Where(x => x.Code == value.ToString()), a => a.Id, b => b.ParentId, (a, b) => new
|
||||
{
|
||||
value = _userInfo.IsEn_Us ? b.Value : b.ValueCN
|
||||
}).Select(x => x.value).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1232,6 +1263,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
from leftObjectTypeIdtemp in ObjectTypeIdtemp.DefaultIfEmpty()
|
||||
select new FrontAuditConfigView()
|
||||
{
|
||||
ApplyCriterionList=data.ApplyCriterionList,
|
||||
IsShowParent = data.IsShowParent,
|
||||
ChildrenTypeId = data.ChildrenTypeId,
|
||||
Code = data.Code,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||
public class InspectionService(IRepository<DataInspection> _dataInspectionRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IRepository<TrialSign> _trialSignRepository,
|
||||
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
||||
IRepository<IdentityUser> _identityUserRepository,
|
||||
IRepository<TrialAuditShow> _trialAuditShowRepository,
|
||||
IRepository<UserRole> _userRoleRepository,
|
||||
|
|
@ -102,6 +103,9 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||
join trial in _trialRepository.Where().IgnoreQueryFilters() on data.TrialId equals trial.Id into trialtemp
|
||||
from leftrial in trialtemp.DefaultIfEmpty()
|
||||
|
||||
join readingQuestionCriterionTrial in _readingQuestionCriterionTrialRepository.Where().IgnoreQueryFilters() on data.TrialReadingCriterionId equals readingQuestionCriterionTrial.Id into readingQuestionCriterionTrialtemp
|
||||
from leftreadingQuestionCriterionTrial in readingQuestionCriterionTrialtemp.DefaultIfEmpty()
|
||||
|
||||
|
||||
join trialSite in _trialSiteRepository.Where().IgnoreQueryFilters() on data.TrialSiteId equals trialSite.Id into trialSitetemp
|
||||
from lefttrialSite in trialSitetemp.DefaultIfEmpty()
|
||||
|
|
@ -136,6 +140,7 @@ namespace IRaCIS.Core.Application.Service.Inspection
|
|||
{
|
||||
IsShow = lefttrialShow != null ? lefttrialShow.IsShow : leftfrontAuditConfig.IsDefaultChoice,
|
||||
CreateTime = data.CreateTime,
|
||||
CriterionType= leftreadingQuestionCriterionTrial==null? null: leftreadingQuestionCriterionTrial.CriterionType,
|
||||
CreateUserId = data.CreateUserId,
|
||||
ModuleTypeId = leftmoduleTypec.Id,
|
||||
BlindName = data.VisitTask.TaskBlindName,
|
||||
|
|
|
|||
|
|
@ -112,7 +112,15 @@ namespace IRaCIS.Application.Contracts
|
|||
/// </summary>
|
||||
public DateTime? LastChangePassWordTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户协议Id
|
||||
/// </summary>
|
||||
public Guid? UserAgreementId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 隐私政策Id
|
||||
/// </summary>
|
||||
public Guid? PrivacyPolicyId { get; set; }
|
||||
}
|
||||
|
||||
public class MenuFuncTreeNodeView
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
//Task<UserDetailDTO> GetUser(Guid id);
|
||||
//Task<PageOutput<UserListDTO>> GetUserList(UserListQueryDTO param);
|
||||
//Task<IResponseOutput<LoginReturnDTO>> Login(string userName, string password);
|
||||
Task<IResponseOutput> VerifyMFACodeAsync(string Code);
|
||||
Task<IResponseOutput> VerifyMFACodeAsync(string Code,bool isRemember);
|
||||
|
||||
Task<IResponseOutput> SendMFAEmail(SendMfaCommand sendMfa);
|
||||
Task<UserBasicInfo> GetUserBasicInfo(Guid userId, string pwd);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
public class UserService(IRepository<UserRole> _userRoleRepository,
|
||||
IMailVerificationService _mailVerificationService,
|
||||
IRepository<VerificationCode> _verificationCodeRepository,
|
||||
IRepository<UserAgreement> _userAgreementRepository,
|
||||
IRepository<TrialUserRole> _userTrialRepository,
|
||||
IRepository<UserLog> _userLogRepository,
|
||||
IRepository<UserPassWordLog> _userPassWordLogRepository,
|
||||
|
|
@ -40,7 +41,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
IRepository<Doctor> _doctorRepository,
|
||||
ISearcher _searcher, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IUserService
|
||||
{
|
||||
|
||||
private ServiceVerifyConfigOption _serviceVerifyConfigConfig = _verifyConfig.CurrentValue;
|
||||
private SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||
|
||||
private async Task VerifyUserNameAsync(Guid? identityUserId, string userName)
|
||||
|
|
@ -435,6 +436,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = identityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = identityUserId, OptType = UserOptType.UnloginModifyPasswoed }, true);
|
||||
|
||||
await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(identityUserId);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
|
@ -481,6 +483,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.LoginModifyPassword }, true);
|
||||
|
||||
await _mailVerificationService.AfterUserModifyPasswordSendEmailAsync(_userInfo.IdentityUserId);
|
||||
|
||||
return ResponseOutput.Result(success);
|
||||
|
||||
|
||||
|
|
@ -822,9 +826,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
/// 验证MFA 邮件
|
||||
/// </summary>
|
||||
/// <param name="Code"></param>
|
||||
/// <param name="isRemember"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public async Task<IResponseOutput> VerifyMFACodeAsync(string Code)
|
||||
public async Task<IResponseOutput> VerifyMFACodeAsync(string Code, bool isRemember)
|
||||
{
|
||||
var identityUserId = _userInfo.IdentityUserId;
|
||||
|
||||
|
|
@ -854,6 +859,13 @@ namespace IRaCIS.Core.Application.Service
|
|||
}
|
||||
}
|
||||
|
||||
if (isRemember)
|
||||
{
|
||||
await _fusionCache.SetAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), _userInfo.BrowserFingerprint, TimeSpan.FromMinutes(_serviceVerifyConfigConfig.UserMFAVerifyMinutes));
|
||||
|
||||
}
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
|
@ -917,9 +929,19 @@ namespace IRaCIS.Core.Application.Service
|
|||
{
|
||||
await _fusionCache.RemoveAsync(CacheKeys.UserToken(identityUserId));
|
||||
|
||||
var userName = await _userRoleRepository.Where(t => t.Id == userRoleId).Select(t => t.IdentityUser.UserName).FirstOrDefaultAsync();
|
||||
if (_identityUserRepository.Any(t => t.Id == identityUserId))
|
||||
{
|
||||
|
||||
var userName = await _userRoleRepository.Where(t => t.Id == userRoleId).Select(t => t.IdentityUser.UserName).FirstOrDefaultAsync();
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = identityUserId, ActionUserName = userName, OptType = UserOptType.LoginOut }, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = null, ActionUserName = _userInfo.UserName, OptType = UserOptType.LoginOut }, true);
|
||||
}
|
||||
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = identityUserId, ActionUserName = userName, OptType = UserOptType.LoginOut }, true);
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
|
@ -1029,7 +1051,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
var lastLoginIPRegion = await _userLogRepository.Where(t => t.ActionUserName == actionUserName && userOptTypes.Contains(t.OptType))
|
||||
.OrderByDescending(t => t.CreateTime).Select(t => t.IPRegion).FirstOrDefaultAsync();
|
||||
|
||||
if (lastLoginIPRegion != string.Empty)
|
||||
if (lastLoginIPRegion != null && lastLoginIPRegion != string.Empty)
|
||||
{
|
||||
// 与上一次区域不一致
|
||||
//if (SplitAndConcatenate(existUserLoginInfo.LastLoginIP) != SplitAndConcatenate(iPRegion))
|
||||
|
|
@ -1080,6 +1102,53 @@ namespace IRaCIS.Core.Application.Service
|
|||
//登录成功 清除缓存
|
||||
await _fusionCache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes));
|
||||
|
||||
// 记录同意用户协议以及隐私政策
|
||||
#region 记录同意用户协议以及隐私政策
|
||||
|
||||
var userAgreementList = await _userAgreementRepository.Where(t => t.IsCurrentVersion).OrderByDescending(t => t.CreateTime).ToListAsync();
|
||||
|
||||
var userAgreement = userAgreementList.FirstOrDefault(t => t.UserAgreementTypeEnum == UserAgreementType.UserAgreement);
|
||||
|
||||
if (userAgreement != null && loginUser.UserAgreementId != userAgreement.Id)
|
||||
{
|
||||
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.IdentityUserId, x => new IdentityUser()
|
||||
{
|
||||
UserAgreementId = userAgreement.Id,
|
||||
});
|
||||
|
||||
var obj = new
|
||||
{
|
||||
UserAgreementTypeEnum = UserAgreementType.UserAgreement,
|
||||
FileVersion = userAgreement.FileVersion,
|
||||
UserAgreementId = userAgreement.Id,
|
||||
IsEn_Us = _userInfo.IsEn_Us,
|
||||
};
|
||||
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = loginUser.UserName, OptType = UserOptType.AcceptUserAgreement, JsonObj = obj.ToJsonStr() }, true);
|
||||
|
||||
}
|
||||
|
||||
var privacyCollection = userAgreementList.FirstOrDefault(t => t.UserAgreementTypeEnum == UserAgreementType.PrivacyCollection);
|
||||
|
||||
if (privacyCollection != null && loginUser.PrivacyPolicyId != privacyCollection.Id)
|
||||
{
|
||||
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.IdentityUserId, x => new IdentityUser()
|
||||
{
|
||||
PrivacyPolicyId = privacyCollection.Id,
|
||||
});
|
||||
|
||||
var obj = new
|
||||
{
|
||||
UserAgreementTypeEnum = UserAgreementType.PrivacyCollection,
|
||||
FileVersion = privacyCollection.FileVersion,
|
||||
UserAgreementId = privacyCollection.Id
|
||||
};
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = loginUser.UserName, OptType = UserOptType.AcceptPrivacyPolicy, JsonObj = obj.ToJsonStr() }, true);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = loginUser.UserName, OptType = UserOptType.Login, IsLoginUncommonly = isLoginUncommonly }, true);
|
||||
|
||||
|
|
@ -1107,9 +1176,16 @@ namespace IRaCIS.Core.Application.Service
|
|||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
|
||||
//MFA 发送邮件
|
||||
if ((await _fusionCache.GetOrDefaultAsync(CacheKeys.UserMFAVerifyPass(identityUserId, _userInfo.BrowserFingerprint), "")) == _userInfo.BrowserFingerprint)
|
||||
{
|
||||
userLoginReturnModel.IsMFA = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//MFA 发送邮件
|
||||
|
||||
userLoginReturnModel.IsMFA = true;
|
||||
userLoginReturnModel.IsMFA = true;
|
||||
}
|
||||
|
||||
var email = userLoginReturnModel.BasicInfo.EMail;
|
||||
|
||||
|
|
@ -1120,9 +1196,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
//修改密码 || 90天修改密码再mfa 之前
|
||||
if (userLoginReturnModel.BasicInfo.IsFirstAdd || userLoginReturnModel.BasicInfo.NeedChangePassWord)
|
||||
{
|
||||
//移动到上面去了
|
||||
//userLoginReturnModel.JWTStr = _tokenService.GetToken(userLoginReturnModel.BasicInfo);
|
||||
}
|
||||
else
|
||||
else if (userLoginReturnModel.IsMFA == true)
|
||||
{
|
||||
//正常登录才发送邮件
|
||||
await SendMFAEmail(new SendMfaCommand() { IdentityUserId = identityUserId, MFAType = UserMFAType.Login });
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
{
|
||||
}
|
||||
|
||||
public class ImageLabelNoneDicomStudyView : NoneDicomStudyView
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///<summary>NoneDicomStudyQuery 列表查询参数模型</summary>
|
||||
public class NoneDicomStudyQuery
|
||||
{
|
||||
|
|
|
|||
|
|
@ -148,44 +148,25 @@ namespace IRaCIS.Core.Application.Contracts.DTO
|
|||
}
|
||||
|
||||
|
||||
public class GetUserUploadFileDto/*: ConsistencyCheckFile*/
|
||||
public class GetUserUploadFileDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// </summary>
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件路径
|
||||
/// </summary>
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 相对路径
|
||||
/// </summary>
|
||||
public string RelativePath { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建人
|
||||
/// </summary>
|
||||
public Guid CreateUserId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建者名称
|
||||
/// </summary>
|
||||
public string CreateUserName { get; set; }
|
||||
|
||||
#region 一致性核查额外增加字段
|
||||
|
||||
public EDCCheckState? CheckState { get; set; }
|
||||
|
||||
public string ResultPath { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -284,6 +265,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO
|
|||
{
|
||||
public bool ExistsManual { get; set; }
|
||||
public bool IsHaveStudyClinicalData { get; set; }
|
||||
public bool QCRiskControl { get; set; }
|
||||
public SubjectClinicalDataDto SubjectClinicalData { get; set; } = new SubjectClinicalDataDto();
|
||||
|
||||
public List<NoneDicomStudyView> NoneDicomStudyList { get; set; } = new List<NoneDicomStudyView>();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||
using IRaCIS.Core.Application.Contracts.DTO;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MiniExcelLibs.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
|
@ -989,6 +990,13 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
/// </summary>
|
||||
[DictionaryTranslateAttribute("YesOrNo")]
|
||||
public bool IsInvalid { get; set; }
|
||||
|
||||
|
||||
|
||||
public List<GetMedicalReviewDialogOutDto> DialogList { get; set; }
|
||||
|
||||
public string DialogStr => string.Join("\n\n", DialogList.OrderBy(t => t.CreateTime).Select(c => c.CreateUserName + " (" + ExportExcelConverterDate.DateTimeInternationalToString(c.CreateTime) + ") :" + c.ResultContent));
|
||||
|
||||
}
|
||||
|
||||
public class TrialImageDownloadExportDto
|
||||
|
|
@ -1148,7 +1156,9 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public class SelftAnalysisExport : AnalysisExortCommon
|
||||
{
|
||||
//自身一致性分析任务特有
|
||||
//自身
|
||||
//
|
||||
//任务特有
|
||||
|
||||
[DictionaryTranslateAttribute("YesOrNo")]
|
||||
public bool? IsAnalysisDiffToOriginalData { get; set; }
|
||||
|
|
@ -1246,6 +1256,10 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
//问题标识,肿瘤评估用于区分是什么问题
|
||||
public QuestionType? QuestionType { get; set; }
|
||||
|
||||
public OptionType OptionTypeEnum { get; set; }
|
||||
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
|
||||
public Guid QuestionId { get; set; }
|
||||
public string QuestionName { get; set; }
|
||||
|
|
@ -1411,6 +1425,7 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public string TableName { get; set; }
|
||||
#endregion
|
||||
|
||||
public OptionType OptionTypeEnum { get; set; }
|
||||
|
||||
public Guid TableQuesionId { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using IRaCIS.Core.Infrastructure;
|
|||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using MassTransit.Initializers;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using System.Linq;
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
IRepository<DicomSeries> _dicomSeriesRepository,
|
||||
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
|
||||
IRepository<QCChallenge> _qcChallengeRepository,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
|
||||
IRepository<UserRole> _userRoleReposiotry,
|
||||
IReadingImageTaskService _IReadingImageTaskService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IQCListService
|
||||
|
|
@ -456,7 +458,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
return new TrialVisitQADTO
|
||||
{
|
||||
QCQuestionAnswerList = qacheckList,
|
||||
|
||||
QCRiskControl = _verifyConfig.CurrentValue.QCRiskControl,
|
||||
SecondReviewList = secondReviewList,
|
||||
|
||||
IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == sv.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study),
|
||||
|
|
@ -767,12 +769,12 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<GetUserUploadFileDto>> GetConsistencyCheckFile(GetConsistencyCheckFileInDto inQuery, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
|
||||
public async Task<PageOutput<GetUserUploadFileDto>> GetConsistencyCheckFileList(GetConsistencyCheckFileInDto inQuery, [FromServices] IRepository<InspectionFile> _inspectionFileRepository)
|
||||
{
|
||||
var query = _inspectionFileRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
var query = _inspectionFileRepository.Where(t => t.TrialId == inQuery.TrialId && (t.CheckState == EDCCheckState.Success || t.CheckState == EDCCheckState.Failed))
|
||||
.ProjectTo<GetUserUploadFileDto>(_mapper.ConfigurationProvider);
|
||||
|
||||
return await query.ToPagedListAsync(inQuery);
|
||||
return await query.ToPagedListAsync(inQuery,nameof(GetUserUploadFileDto.CreateTime));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1975,6 +1975,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|||
SubjectVisitId = dbSubjectVisit.Id,
|
||||
ModuleName = $"G-{dbSubjectVisit.VisitName}",
|
||||
ModuleType = ModuleTypeEnum.Global,
|
||||
ReadModuleAddTypeEnum= dbSubjectVisit.PDState == PDStateEnum.PDProgress? ReadModuleAddType.PDConfirmation : ReadModuleAddType.FinalVisit,
|
||||
IsUrgent = dbSubjectVisit.IsUrgent,
|
||||
TrialId = dbSubjectVisit.TrialId,
|
||||
SubjectId = dbSubjectVisit.SubjectId
|
||||
|
|
|
|||
|
|
@ -179,13 +179,14 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(o => o.MedicalNo, t => t.MapFrom(u => u.VisitTask.Subject.MedicalNo))
|
||||
.ForMember(o => o.DoctorUserName, t => t.MapFrom(u => u.VisitTask.DoctorUser.UserName))
|
||||
.ForMember(o => o.MedicalManagerUserName, t => t.MapFrom(u => u.MedicalManagerUser.UserName))
|
||||
.ForMember(o => o.QuestionContent, t => t.MapFrom(u => string.Join("\n\n", u.ReadingMedicalReviewDialogList.Where(t => t.IsHaveQuestion).Select(t => t.Questioning))));
|
||||
.ForMember(o => o.QuestionContent, t => t.MapFrom(u => string.Join("\n\n", u.ReadingMedicalReviewDialogList.Where(t => t.IsHaveQuestion).Select(t => t.Questioning))))
|
||||
.ForMember(o => o.DialogList, t => t.MapFrom(u => u.ReadingMedicalReviewDialogList));
|
||||
|
||||
CreateMap<VisitTask, TaskMedicalReviewExportDto>()
|
||||
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.IsSelfAnalysis == true ? u.BlindTrialSiteCode : u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsSelfAnalysis == true ? u.BlindSubjectCode : u.Subject.Code))
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
|
@ -245,6 +246,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
.OrderBy(k => k.ReadingQuestionTrial.ShowOrder)
|
||||
.Select(c => new CommonQuesionInfo()
|
||||
{
|
||||
Unit=c.ReadingQuestionTrial.Unit,
|
||||
OptionTypeEnum=c.ReadingQuestionTrial.OptionTypeEnum,
|
||||
QuestionType = c.ReadingQuestionTrial.QuestionType,
|
||||
QuestionName = isEn_Us ? c.ReadingQuestionTrial.QuestionEnName : c.ReadingQuestionTrial.QuestionName,
|
||||
QuestionValue = c.IsGlobalChange ? c.GlobalChangeAnswer : c.Answer,
|
||||
|
|
@ -284,7 +287,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
.OrderBy(k => k.ReadingQuestionTrial.ShowOrder)
|
||||
.Select(c => new CommonQuesionInfo()
|
||||
{
|
||||
Unit=c.ReadingQuestionTrial.Unit,
|
||||
Group = isEn_Us ? c.ReadingQuestionTrial.GroupEnName : c.ReadingQuestionTrial.GroupName,
|
||||
QuestionType = c.ReadingQuestionTrial.QuestionType,
|
||||
OptionTypeEnum=c.ReadingQuestionTrial.OptionTypeEnum,
|
||||
QuestionId = c.ReadingQuestionTrial.Id,
|
||||
QuestionName = isEn_Us ? c.ReadingQuestionTrial.QuestionEnName : c.ReadingQuestionTrial.QuestionName,
|
||||
QuestionValue = c.IsGlobalChange ? c.GlobalChangeAnswer : c.Answer,
|
||||
|
|
@ -303,9 +309,10 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(o => o.LessionAnswerList, t => t.MapFrom(u => u.LesionAnswerList.Where(c => c.ReadingTableQuestionTrial.ExportResultStr.Contains(((int)readingExportType).ToString()))));
|
||||
|
||||
CreateMap<ReadingTableQuestionAnswer, CommonLessionQuestionAnswerInfo>()
|
||||
//.ForMember(o => o.LessionCode, t => t.MapFrom(u => u.Lesion.RowMark))
|
||||
//.ForMember(o => o.LessionType, t => t.MapFrom(u => (int?)u.ReadingQuestionTrial.LesionType))
|
||||
.ForMember(o => o.ShowOrder, t => t.MapFrom(u => u.ReadingTableQuestionTrial.ShowOrder))
|
||||
//.ForMember(o => o.LessionCode, t => t.MapFrom(u => u.Lesion.RowMark))
|
||||
//.ForMember(o => o.LessionType, t => t.MapFrom(u => (int?)u.ReadingQuestionTrial.LesionType))
|
||||
.ForMember(o => o.OptionTypeEnum, t => t.MapFrom(u => u.ReadingTableQuestionTrial.OptionTypeEnum))
|
||||
.ForMember(o => o.ShowOrder, t => t.MapFrom(u => u.ReadingTableQuestionTrial.ShowOrder))
|
||||
.ForMember(o => o.CustomUnit, t => t.MapFrom(u => u.ReadingTableQuestionTrial.CustomUnit))
|
||||
.ForMember(o => o.Unit, t => t.MapFrom(u => u.ReadingTableQuestionTrial.Unit))
|
||||
.ForMember(o => o.TableQuesionId, t => t.MapFrom(u => u.ReadingTableQuestionTrial.Id))
|
||||
|
|
@ -679,8 +686,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
;
|
||||
|
||||
// 一致性核查文件
|
||||
CreateMap<InspectionFile, GetUserUploadFileDto>()
|
||||
.ForMember(d => d.CreateUserName, u => u.MapFrom(t => t.CreateUserRole.FullName));
|
||||
CreateMap<InspectionFile, GetUserUploadFileDto>();
|
||||
|
||||
|
||||
//CRC 质疑列表
|
||||
|
|
@ -755,6 +761,13 @@ namespace IRaCIS.Core.Application.Service
|
|||
.OrderBy(t => t.CreateTime).ThenBy(t => t.FileName)))
|
||||
.ForMember(d => d.CodeView, u => u.MapFrom(s => s.StudyCode));
|
||||
|
||||
CreateMap<NoneDicomStudy, ImageLabelNoneDicomStudyView>()
|
||||
.ForMember(d => d.NoneDicomStudyFileList, u => u.MapFrom(s =>
|
||||
s.ImageLabelNoneDicomFileList.Where(t => isFilterZip ? !t.FileType.Contains(StaticData.FileType.Zip) : true)
|
||||
.Where(t => isReading ? t.IsReading && t.IsDeleted == false : true)
|
||||
.OrderBy(t => t.CreateTime).ThenBy(t => t.FileName)))
|
||||
.ForMember(d => d.CodeView, u => u.MapFrom(s => s.StudyCode));
|
||||
|
||||
|
||||
CreateMap<SubjectVisitImageBackRecord, ImageBackViewModel>()
|
||||
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.SubjectVisit.Subject.Code))
|
||||
|
|
|
|||
|
|
@ -43,6 +43,87 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
}
|
||||
|
||||
public class GetReadModulePageListInDto : PageInput
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片期名称
|
||||
/// </summary>
|
||||
public string ModuleName { get; set; } = string.Empty;
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
public string VisitName { get; set; }
|
||||
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 阅片配置的类型
|
||||
/// </summary>
|
||||
public ReadingSetType? ReadingSetType { get; set; }
|
||||
|
||||
public ReadModuleAddType? ReadModuleAddTypeEnum { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class GetReadModulePageListOutDto
|
||||
{
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片期类型
|
||||
/// </summary>
|
||||
public ReadingSetType ReadingSetType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片期名称
|
||||
/// </summary>
|
||||
public string ModuleName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 中心编号
|
||||
/// </summary>
|
||||
public string SiteCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 受试者编号
|
||||
/// </summary>
|
||||
|
||||
public string SubjectCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访视名称
|
||||
/// </summary>
|
||||
public string VisitName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 最晚拍片日期
|
||||
/// </summary>
|
||||
public DateTime? LatestScanDate { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 来源
|
||||
/// </summary>
|
||||
public ReadModuleAddType ReadModuleAddTypeEnum { get; set; } = ReadModuleAddType.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// 是否生成任务
|
||||
/// </summary>
|
||||
public bool IsGenerateTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成任务时间
|
||||
/// </summary>
|
||||
public DateTime? GenerateTaskTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class GetSubjectReadVisitsOutDto
|
||||
{
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
|
|
|
|||
|
|
@ -252,21 +252,50 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// <summary>
|
||||
/// 第一次
|
||||
/// </summary>
|
||||
public int FirstData { get; set; }
|
||||
public decimal FirstData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第二次
|
||||
/// </summary>
|
||||
public int SecondData { get; set; }
|
||||
public decimal SecondData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三次
|
||||
/// </summary>
|
||||
public int ThirdData { get; set; }
|
||||
public decimal ThirdData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 巨噬细胞浸润测量
|
||||
/// </summary>
|
||||
public string MacrophageInfiltrationMeasurement { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 巨噬细胞浸润角度测量
|
||||
/// </summary>
|
||||
public decimal? MacrophageInfiltrationAngle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 微通道测量
|
||||
/// </summary>
|
||||
public string MicrochannelMeasurement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 胆固醇结晶测量
|
||||
/// </summary>
|
||||
public string CholesterolCrystalMeasurement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 官腔面积测量
|
||||
/// </summary>
|
||||
public decimal? LumenAreaMeasurement { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public decimal Avg { get {
|
||||
|
||||
return ( FirstData*1m + SecondData * 1m + ThirdData * 1m) / 3;
|
||||
return ( FirstData + SecondData + ThirdData) / 3;
|
||||
} }
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +311,27 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// 值
|
||||
/// </summary>
|
||||
public decimal Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 巨噬细胞浸润测量
|
||||
/// </summary>
|
||||
public string MacrophageInfiltrationMeasurement { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 巨噬细胞浸润角度测量
|
||||
/// </summary>
|
||||
public decimal? MacrophageInfiltrationAngle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 微通道测量
|
||||
/// </summary>
|
||||
public string MicrochannelMeasurement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 胆固醇结晶测量
|
||||
/// </summary>
|
||||
public string CholesterolCrystalMeasurement { get; set; }
|
||||
}
|
||||
|
||||
public class FileToDataTableDto
|
||||
|
|
@ -308,6 +358,43 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public string OverallEfficacy { get; set; }
|
||||
}
|
||||
|
||||
public class FrontGetSiteVisitForTumorEvaluationInDto
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public int NumberOfDaysBetween { get; set; }
|
||||
}
|
||||
|
||||
public class FrontGetSiteVisitForTumorEvaluationOutDto
|
||||
{
|
||||
public List<FrontGetSiteVisitForTumor> ResultList { get; set; }
|
||||
}
|
||||
|
||||
public class FrontGetSiteVisitForTumor
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public string TumorEvaluationResult { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class PCWGSiteVisitForTumor
|
||||
{
|
||||
public bool IsPD { get; set; }
|
||||
|
||||
public string? LastTaskResult { get; set; }
|
||||
|
||||
public Guid? LastTaskId { get; set; }
|
||||
}
|
||||
|
||||
public class SiteVisitForTumorEvaluationByDayOutDto
|
||||
{
|
||||
public string Result { get; set; } = string.Empty;
|
||||
|
||||
public string? LastTaskResult { get; set; }
|
||||
|
||||
public Guid? LastTaskId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 阅片计算Dto
|
||||
/// </summary>
|
||||
|
|
@ -385,6 +472,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public string Answer { get; set; }
|
||||
|
||||
public string? PCWGInterimAnswer { get; set; }
|
||||
/// <summary>
|
||||
/// 问题名称
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public string QuestionName { get; set; }
|
||||
|
||||
public string QuestionEnName { get; set; }
|
||||
|
||||
public bool IsCanEditPosition { get; set; } = false;
|
||||
|
||||
public string BlindName { get; set; }
|
||||
|
|
@ -136,6 +138,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public string? ReportMark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 高亮问题的答案
|
||||
/// </summary>
|
||||
|
|
@ -163,6 +175,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public string Answer { get; set; }
|
||||
|
||||
public bool IsHighlight { get; set; } = false;
|
||||
|
||||
public bool IsGlobalChange { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -192,6 +206,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
}
|
||||
|
||||
public class Globalanswer
|
||||
{
|
||||
public Guid TaskId { get; set; }
|
||||
|
||||
public string Answer { get; set; }
|
||||
|
||||
public decimal VisitTaskNum { get; set; }
|
||||
|
||||
public Guid? QuestionId { get; set; }
|
||||
}
|
||||
|
||||
public class LesionDto
|
||||
{
|
||||
|
|
@ -445,7 +469,46 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public string TaskBlindName { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
public class GetReportsChartDataOutDto
|
||||
{
|
||||
public List<string> VisitTaskNameList { get; set; }
|
||||
|
||||
public List<DateTime?> LatestScanDateList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
public List<ReportChartData> ChartDataList { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ReportChartData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<string> Value { get; set; }
|
||||
}
|
||||
|
||||
public class GetReportsChartDataInDto
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid? QuestionId { get; set; }
|
||||
|
||||
public Guid? TableQuestionId { get; set; }
|
||||
|
||||
public decimal? RowIndex { get; set; }
|
||||
|
||||
public ReportChartType? ReportChartTypeEnum { get; set; }
|
||||
}
|
||||
public class SetReadKeyFileInDto
|
||||
{
|
||||
public Guid TrialCriterionId { get; set; }
|
||||
}
|
||||
public class ViewStudyPartInDto
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
|
@ -898,6 +961,9 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public class CopyTableAnswerRowInfo : ReadingTableAnswerRowInfoBase
|
||||
{
|
||||
|
||||
public Guid? IdentityRowId { get; set; }
|
||||
|
||||
public Guid OriginalId { get; set; }
|
||||
|
||||
public LesionType? LesionType { get; set; }
|
||||
|
|
@ -972,6 +1038,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// 问题分类
|
||||
/// </summary>
|
||||
public QuestionClassify? QuestionClassify { get; set; }
|
||||
|
||||
public bool IsDicomReading { get; set; } = true;
|
||||
}
|
||||
|
||||
public class GetReadingTableQuestionOutDto
|
||||
|
|
@ -989,6 +1057,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public List<CrterionDictionaryGroup> CrterionDictionaryGroup { get; set; }
|
||||
|
||||
public CriterionType CriterionType { get; set; }
|
||||
|
||||
public bool IsPage { get; set; } = false;
|
||||
|
||||
public string Answer { get; set; }
|
||||
|
|
@ -1270,6 +1340,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public string? PicturePath { get; set; }
|
||||
|
||||
public string? Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// NumberOfFrames
|
||||
/// </summary>
|
||||
|
|
@ -1452,6 +1524,19 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public string Answer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数值类型
|
||||
/// </summary>
|
||||
public ValueOfType? ValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自定义单位
|
||||
/// </summary>
|
||||
public string? CustomUnit { get; set; }
|
||||
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 问题类型
|
||||
|
|
@ -1793,6 +1878,13 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public ValueOfType? ValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自定义单位
|
||||
/// </summary>
|
||||
public string? CustomUnit { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
|
|
@ -1941,6 +2033,10 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public bool IsConvertedTask { get; set; } = false;
|
||||
|
||||
public bool IsReadKeyFile { get; set; } = false;
|
||||
|
||||
public bool IsHaveKeyFile { get; set; } = false;
|
||||
|
||||
}
|
||||
|
||||
public class GetReadingImgInDto
|
||||
|
|
@ -2239,6 +2335,17 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自定义单位
|
||||
/// </summary>
|
||||
public string? CustomUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数值类型
|
||||
/// </summary>
|
||||
public ValueOfType? ValueType { get; set; }
|
||||
|
||||
public JudgeReadingQuestionType QuestionType { get; set; } = JudgeReadingQuestionType.Question;
|
||||
|
||||
}
|
||||
|
|
@ -2440,6 +2547,59 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
public class ChangePlottingScaleChangeAnswerInDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 标记id
|
||||
/// </summary>
|
||||
public Guid NoneDicomFileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否移除比例关系
|
||||
/// </summary>
|
||||
public bool IsRemovePlottingScale { get; set; } = false;
|
||||
|
||||
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public string PicturePath { get; set; } = string.Empty;
|
||||
|
||||
public List<PlottingAnswerInfo> AnswerList { get; set; }
|
||||
}
|
||||
|
||||
public class PlottingAnswerInfo
|
||||
{
|
||||
public Guid? QuestionId { get; set; }
|
||||
public Guid? RowId { get; set; }
|
||||
|
||||
public Guid? TableQuestionId { get; set; }
|
||||
|
||||
public string Answer { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class GetNoneDicomMarkAndBindingInDto
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
public class GetNoneDicomMarkAndBindingOutDto
|
||||
{
|
||||
public List<AddNoneDicomMarkInDto> NoneDicomMarkList { get; set; }
|
||||
public List<BindingData> BindingList { get; set; }
|
||||
}
|
||||
|
||||
public class BindingData:BindingInfo
|
||||
{
|
||||
public Guid NoneDicomMarkId { get; set; }
|
||||
|
||||
public Guid? MarkId { get; set; }
|
||||
|
||||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
public class AddNoneDicomMarkInDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
|
@ -2447,14 +2607,68 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public Guid? StudyId { get; set; }
|
||||
|
||||
public string MarkTool { get; set; }
|
||||
|
||||
|
||||
public string OrderMarkName { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 比例
|
||||
///// </summary>
|
||||
//public decimal? Proportion { get; set; }
|
||||
|
||||
public Guid? MarkId { get; set; }
|
||||
public Guid? NoneDicomFileId { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public string PicturePath { get; set; } = string.Empty;
|
||||
|
||||
public string MeasureData { get; set; } = string.Empty;
|
||||
|
||||
}
|
||||
|
||||
public class DeleteBindingInDto
|
||||
{
|
||||
public Guid BindingIdId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class AddNoneDicomMarkAndBinding
|
||||
{
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public Guid? StudyId { get; set; }
|
||||
|
||||
public string MarkTool { get; set; }
|
||||
|
||||
public string OrderMarkName { get; set; }
|
||||
|
||||
public Guid? MarkId { get; set; }
|
||||
public Guid? NoneDicomFileId { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
public string PicturePath { get; set; } = string.Empty;
|
||||
|
||||
public string MeasureData { get; set; } = string.Empty;
|
||||
|
||||
public Guid QuestionId { get; set; }
|
||||
public Guid? RowId { get; set; }
|
||||
|
||||
public Guid? TableQuestionId { get; set; }
|
||||
|
||||
public string Answer { get; set; }
|
||||
}
|
||||
|
||||
public class BindingInfo
|
||||
{
|
||||
public Guid? QuestionId { get; set; }
|
||||
public Guid? RowId { get; set; }
|
||||
|
||||
public Guid? TableQuestionId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -203,6 +203,65 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public Guid TaskMedicalReviewId { get; set; }
|
||||
}
|
||||
|
||||
public class JointMedicalReviewI18n
|
||||
{
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:message:msg1
|
||||
/// </summary>
|
||||
public string Msg1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:message:msg2
|
||||
/// </summary>
|
||||
public string Msg2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:message:msg3
|
||||
/// </summary>
|
||||
public string Msg3 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:message:msg4
|
||||
/// </summary>
|
||||
public string Msg4 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:message:msg5
|
||||
/// </summary>
|
||||
public string Msg5 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:title:closeReasonEnum
|
||||
/// </summary>
|
||||
public string CloseReasonEnum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:title:isEndorse
|
||||
/// </summary>
|
||||
public string IsEndorse { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:title:reason
|
||||
/// </summary>
|
||||
public string Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trials:medicalFeedback:title:isRequestReread
|
||||
/// </summary>
|
||||
public string IsRequestReread { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// AuditAdvice
|
||||
/// </summary>
|
||||
public Dictionary<string, string> AuditAdvice { get; set; }
|
||||
|
||||
public Dictionary<string, string> MedicalDialogCloseEnum { get; set; }
|
||||
|
||||
public Dictionary<string, string> MedicalReviewDoctorUserIdea { get; set; }
|
||||
|
||||
public Dictionary<string, string> YesOrNo { get; set; }
|
||||
}
|
||||
|
||||
public class GetMedicalReviewDialogOutDto
|
||||
{
|
||||
|
|
@ -284,6 +343,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public List<Domain.Models.OSSImageInfo> FileList { get; set; } = new List<Domain.Models.OSSImageInfo>();
|
||||
|
||||
|
||||
//存储最后翻译的内容
|
||||
public string ResultContent { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -572,6 +633,7 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public string TypeValue { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
|
|
@ -697,6 +759,19 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public string Answer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数值类型
|
||||
/// </summary>
|
||||
public ValueOfType? ValueType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自定义单位
|
||||
/// </summary>
|
||||
public string? CustomUnit { get; set; }
|
||||
|
||||
public ValueUnit? Unit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -79,8 +79,73 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public Guid ReadingPeriodSetId { get; set; }
|
||||
}
|
||||
|
||||
public class IsChangeReadingPlanInDto
|
||||
{
|
||||
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片范围
|
||||
/// </summary>
|
||||
public ReadingScopeEnum ReadingScope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 中心ID
|
||||
/// </summary>
|
||||
public List<Guid> SiteIds { get; set; } = new List<Guid>();
|
||||
|
||||
/// <summary>
|
||||
/// 项目ID
|
||||
/// </summary>
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 截止日期
|
||||
/// </summary>
|
||||
public DateTime? ExpirationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 截止访视
|
||||
/// </summary>
|
||||
public decimal? ExpirationVisitNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访视计划ID
|
||||
/// </summary>
|
||||
public Guid? VisitStageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片期名称
|
||||
/// </summary>
|
||||
public string ReadingPeriodName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 类型
|
||||
/// </summary>
|
||||
public ReadingSetType ReadingSetType { get; set; }
|
||||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
}
|
||||
|
||||
public class AddReadingPlanAndGenerateReadModuleInDto
|
||||
{
|
||||
public Guid ReadingPeriodSetId { get; set; }
|
||||
|
||||
public List<Guid> SubjectVisitIdList { get; set; } = new List<Guid>();
|
||||
}
|
||||
|
||||
public class SetBatchAddOrRemoveReadingPlanInDto
|
||||
{
|
||||
public List<Guid> SubjectVisitIdList { get; set; } = new List<Guid>();
|
||||
|
||||
public Guid Id { get; set; }
|
||||
}
|
||||
|
||||
public class PreviewTheReadingListInDto : PageInput
|
||||
{
|
||||
|
||||
public Guid? ReadingPeriodSetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 阅片范围
|
||||
/// </summary>
|
||||
|
|
@ -123,7 +188,25 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 中心Id
|
||||
/// </summary>
|
||||
public Guid? SiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 受试者Code
|
||||
/// </summary>
|
||||
public string SubjectCode { get; set; }=string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否加入阅片计划
|
||||
/// </summary>
|
||||
public bool? IsJoin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否生成阅片计划
|
||||
/// </summary>
|
||||
public bool? IsGenerate { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -185,6 +268,26 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public DateTime? EffectOfTime { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否加入阅片计划
|
||||
/// </summary>
|
||||
public bool? IsJoin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否生成阅片计划
|
||||
/// </summary>
|
||||
public bool? IsGenerate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否生成任务
|
||||
/// </summary>
|
||||
public bool? IsGenerateTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 生成时间
|
||||
/// </summary>
|
||||
public DateTime? GeneratedTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ReadingPeriodSetView
|
||||
|
|
@ -313,6 +416,33 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public ReadingPeriodStatus IsTakeEffect { get; set; }
|
||||
}
|
||||
|
||||
public class AddReadModuleInDto
|
||||
{
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public Guid ReadingPeriodSetId { get; set; }
|
||||
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public string ReadingPeriodName { get; set; }
|
||||
|
||||
public ReadingSetType ReadingSetType { get; set; }
|
||||
|
||||
public List<AddReadModuleVisitInfo> VisitInfoList { get; set; } = new List<AddReadModuleVisitInfo>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class AddReadModuleVisitInfo
|
||||
{
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public Guid? ReadingPeriodPlanId { get; set; }
|
||||
public bool IsUrgent { get; set; }
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ReadingPeriodSetQuery : PageInput
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -431,6 +431,17 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// 数据来源
|
||||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
|
||||
|
|
@ -561,6 +572,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
|
|
@ -1061,10 +1082,6 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public Guid ReadingQuestionCriterionTrialId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否复制病灶
|
||||
/// </summary>
|
||||
public bool IsCopyLesions { get; set; } = false;
|
||||
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
|
|
@ -1245,6 +1262,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 问题英文名称
|
||||
/// </summary>
|
||||
|
|
@ -1356,6 +1383,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
|
|
@ -1821,6 +1858,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
[Comment("数据来源")]
|
||||
public DataSources DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
[Comment("限制编辑")]
|
||||
public LimitEdit LimitEdit { get; set; } = LimitEdit.None;
|
||||
|
||||
|
|
@ -2227,6 +2274,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
|
|
@ -2463,11 +2520,6 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
public Guid? ClassifyQuestionId { get; set; }
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否复制病灶
|
||||
/// </summary>
|
||||
public bool IsCopyLesions { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 全局阅片显示类型
|
||||
/// </summary>
|
||||
|
|
@ -2639,6 +2691,16 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto
|
|||
/// </summary>
|
||||
public DataSources? DataSource { get; set; } = DataSources.ManualEntry;
|
||||
|
||||
/// <summary>
|
||||
/// 显示图表类型
|
||||
/// </summary>
|
||||
public ShowChartType ShowChartTypeEnum { get; set; } = ShowChartType.NotShow;
|
||||
|
||||
/// <summary>
|
||||
/// 选项类型
|
||||
/// </summary>
|
||||
public OptionType OptionTypeEnum { get; set; } = OptionType.Defalut;
|
||||
|
||||
/// <summary>
|
||||
/// 单位
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:46:41Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
namespace IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
|
||||
public class SystemCriterionKeyFileView : SystemCriterionKeyFileAddOrEdit
|
||||
{
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class SystemCriterionKeyFileAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
public string FilePath { get; set; }
|
||||
|
||||
public Guid SystemCriterionId { get; set; }
|
||||
}
|
||||
|
||||
public class SystemCriterionKeyFileQuery:PageInput
|
||||
{
|
||||
public string? FileName { get; set; }
|
||||
|
||||
public string? FilePath { get; set; }
|
||||
|
||||
public Guid SystemCriterionId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:51:58Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
namespace IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
|
||||
public class TrialCriterionKeyFileView : TrialCriterionKeyFileAddOrEdit
|
||||
{
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class TrialCriterionKeyFileAddOrEdit
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
public string FilePath { get; set; }
|
||||
|
||||
public Guid TrialCriterionId { get; set; }
|
||||
}
|
||||
|
||||
public class TrialCriterionKeyFileQuery:PageInput
|
||||
{
|
||||
public string? FileName { get; set; }
|
||||
|
||||
|
||||
public Guid TrialCriterionId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,6 +30,11 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||
public class SetAutoCutNextTaskInDto
|
||||
{
|
||||
public bool AutoCutNextTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否双屏
|
||||
/// </summary>
|
||||
public bool IsDoubleScreen { get; set; } = false;
|
||||
}
|
||||
|
||||
///<summary> UserWLTemplateAddOrEdit 列表查询参数模型</summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:46:41Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
namespace IRaCIS.Core.Application.Service.Reading.Interface;
|
||||
|
||||
public interface ISystemCriterionKeyFileService
|
||||
{
|
||||
|
||||
Task<PageOutput<SystemCriterionKeyFileView>> GetSystemCriterionKeyFileList(SystemCriterionKeyFileQuery inQuery);
|
||||
|
||||
Task<IResponseOutput> AddOrUpdateSystemCriterionKeyFile(SystemCriterionKeyFileAddOrEdit addOrEditSystemCriterionKeyFile);
|
||||
|
||||
Task<IResponseOutput> DeleteSystemCriterionKeyFile(Guid systemCriterionKeyFileId);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:51:58Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using System;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
namespace IRaCIS.Core.Application.Service.Reading.Interface;
|
||||
|
||||
public interface ITrialCriterionKeyFileService
|
||||
{
|
||||
|
||||
Task<PageOutput<TrialCriterionKeyFileView>> GetTrialCriterionKeyFileList(TrialCriterionKeyFileQuery inQuery);
|
||||
|
||||
Task<IResponseOutput> AddOrUpdateTrialCriterionKeyFile(TrialCriterionKeyFileAddOrEdit addOrEditTrialCriterionKeyFile);
|
||||
|
||||
Task<IResponseOutput> DeleteTrialCriterionKeyFile(Guid trialCriterionKeyFileId);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3,12 +3,17 @@ using IRaCIS.Core.Application.Filter;
|
|||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using Panda.DynamicWebApi.Attributes;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
|
|
@ -19,6 +24,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
public class ReadingMedicalReviewService(IRepository<ReadingMedicineTrialQuestion> _readingMedicineTrialQuestionRepository,
|
||||
IRepository<Trial> _trialRepository,
|
||||
IRepository<VisitTask> _visitTaskRepository,
|
||||
IRepository<Dictionary> _dictionaryRepository,
|
||||
IRepository<Internationalization> _internationalizationRepository,
|
||||
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
|
||||
IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository,
|
||||
|
||||
|
|
@ -243,6 +250,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
var visitTaskAnswer = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId) && x.ReadingQuestionTrial.IsJudgeQuestion).Select(x => new JudgeQuestionAnswerInfo
|
||||
{
|
||||
Answer = x.Answer,
|
||||
Unit=x.ReadingQuestionTrial.Unit,
|
||||
ValueType=x.ReadingQuestionTrial.ValueType,
|
||||
CustomUnit=x.ReadingQuestionTrial.CustomUnit,
|
||||
VisitTaskId = x.VisitTaskId,
|
||||
DictionaryCode = x.ReadingQuestionTrial.DictionaryCode,
|
||||
ShowOrder = x.ReadingQuestionTrial.ShowOrder,
|
||||
|
|
@ -331,6 +341,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
ShowOrder = data.ShowOrder,
|
||||
ParentId = data.ParentId,
|
||||
TypeValue = data.TypeValue,
|
||||
|
||||
Answer = leftquestionAnswer.Answer
|
||||
};
|
||||
|
||||
|
|
@ -628,6 +639,167 @@ namespace IRaCIS.Core.Application.Service
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试获取医学审核对话拼接内容
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<string> TestGetJointMedicalReviewDialog(Guid id)
|
||||
{
|
||||
var dialog = await _readingMedicalReviewDialogRepository.Where(x => x.Id == id)
|
||||
.ProjectTo<GetMedicalReviewDialogOutDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||||
|
||||
|
||||
Dictionary<string, string> i18NKeys = new Dictionary<string, string>()
|
||||
{
|
||||
{ "Msg1","trials:medicalFeedback:message:msg1"},
|
||||
{ "Msg2","trials:medicalFeedback:message:msg2"},
|
||||
{ "Msg3","trials:medicalFeedback:message:msg3"},
|
||||
{ "Msg4", "trials:medicalFeedback:message:msg4"},
|
||||
{ "Msg5", "trials:medicalFeedback:message:msg5"},
|
||||
{ "CloseReasonEnum", "trials:medicalFeedback:title:closeReasonEnum"},
|
||||
{ "IsEndorse", "trials:medicalFeedback:title:isEndorse"},
|
||||
{ "Reason", "trials:medicalFeedback:title:reason"},
|
||||
{ "IsRequestReread", "trials:medicalFeedback:title:isRequestReread"},
|
||||
};
|
||||
|
||||
var i18Values = i18NKeys.Select(x => x.Value).ToList();
|
||||
var i18nList=await _internationalizationRepository.Where(x => i18Values.Contains(x.Code))
|
||||
.Select(x => new
|
||||
{
|
||||
Code= x.Code,
|
||||
Value= _userInfo.IsEn_Us?x.Value:x.ValueCN
|
||||
}).ToListAsync();
|
||||
|
||||
List<string> dictionaryCodeList = new List<string>()
|
||||
{
|
||||
"AuditAdvice",
|
||||
"MedicalDialogCloseEnum",
|
||||
"MedicalReviewDoctorUserIdea",
|
||||
"YesOrNo",
|
||||
};
|
||||
|
||||
var dictionadParents=await _dictionaryRepository.Where(x=> dictionaryCodeList.Contains(x.Parent.Code))
|
||||
.Select(x => new
|
||||
{
|
||||
ParentCode = x.Parent.Code,
|
||||
Code=x.Code,
|
||||
Value = _userInfo.IsEn_Us ? x.Value : x.ValueCN
|
||||
}).ToListAsync();
|
||||
|
||||
JointMedicalReviewI18n i18N = new JointMedicalReviewI18n() { };
|
||||
foreach (var kv in i18NKeys)
|
||||
{
|
||||
PropertyInfo? pi = i18N.GetType().GetProperty(kv.Key);
|
||||
if (pi != null && pi.CanWrite)
|
||||
{
|
||||
var value = i18nList.Where(x => x.Code == kv.Value).Select(x => x.Value).FirstOrDefault() ?? string.Empty;
|
||||
object safeValue = Convert.ChangeType(value, pi.PropertyType);
|
||||
pi.SetValue(i18N, safeValue);
|
||||
}
|
||||
}
|
||||
foreach (var item in dictionaryCodeList)
|
||||
{
|
||||
PropertyInfo? pi = i18N.GetType().GetProperty(item);
|
||||
if (pi != null && pi.CanWrite)
|
||||
{
|
||||
var value = dictionadParents.Where(x => x.ParentCode == item).ToDictionary(x => x.Code, x => x.Value);
|
||||
object safeValue = Convert.ChangeType(value, pi.PropertyType);
|
||||
pi.SetValue(i18N, safeValue);
|
||||
}
|
||||
}
|
||||
|
||||
return await JointMedicalReviewDialog(dialog,i18N);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取医学审核对话拼接内容
|
||||
/// </summary>
|
||||
/// <param name="record"></param>
|
||||
/// <param name="i18NAndDic"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> JointMedicalReviewDialog(GetMedicalReviewDialogOutDto record, JointMedicalReviewI18n i18NAndDic)
|
||||
{
|
||||
StringBuilder str = new StringBuilder() { };
|
||||
var userTypes = new List<int>() { 14, 30 };
|
||||
|
||||
// 这里userTypes.Contains(record.UserTypeEnumInt) 可以提出来 但是还是按照前端写吧 免得不好对照
|
||||
|
||||
// v-if="[14, 30].includes(record.UserTypeEnumInt) && record.Questioning
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.Questioning.IsNotNullOrEmpty())
|
||||
{
|
||||
// <!-- 您好,根据医学审核反馈,该阅片任务的评估有如下问题需要您确认或澄清: -->
|
||||
str.AppendLine(i18NAndDic.Msg1);
|
||||
|
||||
str.AppendLine(record.Questioning);
|
||||
|
||||
if (record.FileList.Count() > 0)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.Msg2);
|
||||
record.FileList.ForEach(x =>
|
||||
{
|
||||
str.AppendLine(x.FileName);
|
||||
});
|
||||
}
|
||||
|
||||
str.AppendLine(i18NAndDic.Msg3);
|
||||
|
||||
str.AppendLine(i18NAndDic.AuditAdvice[record.AuditAdviceEnum.GetEnumInt()]);
|
||||
|
||||
str.AppendLine(i18NAndDic.Msg4);
|
||||
}
|
||||
|
||||
//v-if="[14, 30].includes(record.UserTypeEnumInt) && record.MedicalDialogCloseEnum!== null"
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.MedicalDialogCloseEnum != null)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.CloseReasonEnum + i18NAndDic.MedicalDialogCloseEnum[record.MedicalDialogCloseEnum.Value.GetEnumInt()]);
|
||||
}
|
||||
|
||||
// v-if="[14, 30].includes(record.UserTypeEnumInt) && record.Content
|
||||
if (userTypes.Contains(record.UserTypeEnumInt) && record.Content.IsNotNullOrEmpty())
|
||||
{
|
||||
str.AppendLine(record.Content);
|
||||
}
|
||||
|
||||
// v-if="[13].includes(record.UserTypeEnumInt)"
|
||||
|
||||
if (13 == record.UserTypeEnumInt)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.IsEndorse + i18NAndDic.MedicalReviewDoctorUserIdea[record.DoctorUserIdeaEnum.GetEnumInt()]);
|
||||
|
||||
// v-if="record.DoctorUserIdeaEnum===2"
|
||||
if ((int)record.DoctorUserIdeaEnum == 2)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.Reason + record.DisagreeReason);
|
||||
}
|
||||
|
||||
// record.MedicalDialogCloseEnum!== null
|
||||
|
||||
if (record.MedicalDialogCloseEnum != null)
|
||||
{
|
||||
str.AppendLine(i18NAndDic.IsRequestReread + i18NAndDic.YesOrNo[record.IsApplyHeavyReading.ToString()]);
|
||||
}
|
||||
|
||||
// v-if="record.FileList && record.FileList.length > 0"
|
||||
|
||||
if (record.FileList.Count() > 0)
|
||||
{
|
||||
record.FileList.ForEach(x =>
|
||||
{
|
||||
str.AppendLine(x.FileName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 完成医学审核
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
throw new BusinessValidationFailedException(_localizer["ReadingQuestion_CDISCCodeRepeat"]);
|
||||
}
|
||||
|
||||
if(inDto.QuestionList.Any(x=>x.ExportResult.Contains(ExportResult.CDISC)&&x.CDISCCode.IsNullOrEmpty())
|
||||
|| inDto.TableQuestionList.Any(x => x.ExportResult.Contains(ExportResult.CDISC) && x.CDISCCode.IsNullOrEmpty())
|
||||
if(inDto.QuestionList.Any(x=>x.ExportResult.Contains(ExportResult.NoneTumorCDISC)&&x.CDISCCode.IsNullOrEmpty())
|
||||
|| inDto.TableQuestionList.Any(x => x.ExportResult.Contains(ExportResult.NoneTumorCDISC) && x.CDISCCode.IsNullOrEmpty())
|
||||
)
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["ReadingQuestion_CDISCCodeCannotEmpty"]);
|
||||
|
|
@ -565,7 +565,9 @@ namespace IRaCIS.Core.Application.Service
|
|||
{
|
||||
if (indto.Id != null)
|
||||
{
|
||||
if (await _readingQuestionTrialRepository.AnyAsync(x => x.Id == indto.Id && x.IsJudgeQuestion && x.JudgeType != JudgeTypeEnum.None))
|
||||
var isArbitrationReading = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == indto.ReadingQuestionCriterionTrialId).Select(x => x.IsArbitrationReading).FirstOrDefaultAsync();
|
||||
|
||||
if (isArbitrationReading && (await _readingQuestionTrialRepository.AnyAsync(x => x.Id == indto.Id && x.IsJudgeQuestion && x.JudgeType != JudgeTypeEnum.None)))
|
||||
{
|
||||
//---当前问题已经设置了裁判标准了,修改失败
|
||||
throw new BusinessValidationFailedException(_localizer["ReadingQuestion_JudgmentSet"]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:46:38Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Application.Service.Reading.Interface;
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 系统标准阅片关键点文件服务
|
||||
/// </summary>
|
||||
/// <param name="_systemCriterionKeyFileRepository"></param>
|
||||
/// <param name="_mapper"></param>
|
||||
/// <param name="_userInfo"></param>
|
||||
/// <param name="_localizer"></param>
|
||||
[ApiExplorerSettings(GroupName = "Reading")]
|
||||
public class SystemCriterionKeyFileService(IRepository<SystemCriterionKeyFile> _systemCriterionKeyFileRepository,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService, ISystemCriterionKeyFileService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 获取系统标准阅片关键点文件列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<SystemCriterionKeyFileView>> GetSystemCriterionKeyFileList(SystemCriterionKeyFileQuery inQuery)
|
||||
{
|
||||
|
||||
var systemCriterionKeyFileQueryable =_systemCriterionKeyFileRepository
|
||||
.Where(x=>x.SystemCriterionId==inQuery.SystemCriterionId)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.FileName),x=>x.FileName.Contains(inQuery.FileName))
|
||||
.ProjectTo<SystemCriterionKeyFileView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var pageList= await systemCriterionKeyFileQueryable.ToPagedListAsync(inQuery);
|
||||
|
||||
return pageList;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 新增或者修改系统标准阅片关键点文件
|
||||
/// </summary>
|
||||
/// <param name="addOrEditSystemCriterionKeyFile"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IResponseOutput> AddOrUpdateSystemCriterionKeyFile(SystemCriterionKeyFileAddOrEdit addOrEditSystemCriterionKeyFile)
|
||||
{
|
||||
// 在此处拷贝automapper 映射
|
||||
var entity = await _systemCriterionKeyFileRepository.InsertOrUpdateAsync(addOrEditSystemCriterionKeyFile, true);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除系统标准阅片关键点文件
|
||||
/// </summary>
|
||||
/// <param name="systemCriterionKeyFileId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{systemCriterionKeyFileId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteSystemCriterionKeyFile(Guid systemCriterionKeyFileId)
|
||||
{
|
||||
var success = await _systemCriterionKeyFileRepository.DeleteFromQueryAsync(t => t.Id == systemCriterionKeyFileId,true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||
// 生成时间 2025-11-12 06:51:56Z
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System.Threading.Tasks;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Service.Reading.Interface;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 项目标准阅片关键点文件服务
|
||||
/// </summary>
|
||||
/// <param name="_trialCriterionKeyFileRepository"></param>
|
||||
/// <param name="_mapper"></param>
|
||||
/// <param name="_userInfo"></param>
|
||||
/// <param name="_localizer"></param>
|
||||
[ApiExplorerSettings(GroupName = "Reading")]
|
||||
public class TrialCriterionKeyFileService(IRepository<TrialCriterionKeyFile> _trialCriterionKeyFileRepository,
|
||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer): BaseService, ITrialCriterionKeyFileService
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取项目标准阅片关键点文件列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<TrialCriterionKeyFileView>> GetTrialCriterionKeyFileList(TrialCriterionKeyFileQuery inQuery)
|
||||
{
|
||||
|
||||
var trialCriterionKeyFileQueryable =_trialCriterionKeyFileRepository
|
||||
.Where(x=>x.TrialCriterionId==inQuery.TrialCriterionId)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.FileName),x=>x.FileName.Contains(inQuery.FileName))
|
||||
.ProjectTo<TrialCriterionKeyFileView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var pageList= await trialCriterionKeyFileQueryable.ToPagedListAsync(inQuery);
|
||||
|
||||
return pageList;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 新增或者修改项目标准阅片关键点文件
|
||||
/// </summary>
|
||||
/// <param name="addOrEditTrialCriterionKeyFile"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> AddOrUpdateTrialCriterionKeyFile(TrialCriterionKeyFileAddOrEdit addOrEditTrialCriterionKeyFile)
|
||||
{
|
||||
|
||||
|
||||
|
||||
var entity = await _trialCriterionKeyFileRepository.InsertOrUpdateAsync(addOrEditTrialCriterionKeyFile, true);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除项目标准阅片关键点文件
|
||||
/// </summary>
|
||||
/// <param name="trialCriterionKeyFileId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{trialCriterionKeyFileId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteTrialCriterionKeyFile(Guid trialCriterionKeyFileId)
|
||||
{
|
||||
var success = await _trialCriterionKeyFileRepository.DeleteFromQueryAsync(t => t.Id == trialCriterionKeyFileId,true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -269,7 +269,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
ShowOrder = y.ReadingQuestionTrial.ShowOrder,
|
||||
Type = y.ReadingQuestionTrial.Type,
|
||||
TypeValue = y.ReadingQuestionTrial.TypeValue,
|
||||
ValueType = y.ReadingQuestionTrial.ValueType,
|
||||
CustomUnit = y.ReadingQuestionTrial.CustomUnit,
|
||||
Unit = y.ReadingQuestionTrial.Unit,
|
||||
IsJudgeQuestion = y.ReadingQuestionTrial.IsJudgeQuestion,
|
||||
Answer = y.Answer,
|
||||
}).ToList()
|
||||
|
|
@ -313,7 +314,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
ValueType = y.ValueType,
|
||||
IsJudgeQuestion = y.IsJudgeQuestion,
|
||||
Answer = string.Empty,
|
||||
|
||||
CustomUnit = y.CustomUnit,
|
||||
});
|
||||
|
||||
}
|
||||
|
|
@ -399,7 +400,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
JudgeType = lr.question.JudgeType,
|
||||
TypeValue = lr.question.TypeValue,
|
||||
ValueType = lr.question.ValueType,
|
||||
|
||||
CustomUnit = lr.question.CustomUnit,
|
||||
}).ToList();
|
||||
|
||||
|
||||
|
|
@ -524,7 +525,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
ShowOrder = x.Dictionary.ShowOrder,
|
||||
ParentCode = x.Dictionary.Parent.Code,
|
||||
Value = x.Dictionary.Value,
|
||||
ValueCN = x.Dictionary.ValueCN
|
||||
ValueCN = x.Dictionary.ValueCN,
|
||||
}).OrderBy(x => x.ParentCode).ThenBy(x => x.ShowOrder).ToListAsync();
|
||||
result.AssessTypeList = assessTypeList;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue