Compare commits
1339 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f6612286d9 | |||
| c21845c60d | |||
| 867ef0ef97 | |||
| f27bee83b7 | |||
| e3b6feb4da | |||
| d727703075 | |||
| c49cf0ed12 | |||
| f324d207dd | |||
| c9bda275f5 | |||
| 62ed1a408d | |||
| 25efb34f1f | |||
| eb0f13c075 | |||
| 7ca92a7675 | |||
| e313f88bca | |||
| 4823eb29d5 | |||
| 43ec332f61 | |||
| cac0652120 | |||
| cc088900b6 | |||
| 824b165723 | |||
| 443b94b332 | |||
| dc116d3a6f | |||
| bbc8859a16 | |||
| 09e388b01a | |||
| e5fcb75b9f | |||
| 8e104e133f | |||
| e2a77537f0 | |||
| a73a79b627 | |||
| e79c3a8f37 | |||
| ca9a2dad18 | |||
| cd03f5f31d | |||
| 33e25de801 | |||
| 9cd60e9575 | |||
| 4da4a4de89 | |||
| ec0a88a5ec | |||
| a52a00e58c | |||
| 0a6ffbba07 | |||
| 8cb5423b0b | |||
| 5a6411c6c3 | |||
| b97a8b5a68 | |||
| 91794266e7 | |||
| 2f86e2dae1 | |||
| fb76c5af6c | |||
| 3f6ec5b7ea | |||
| c95ea8c547 | |||
| facd9e0e5f | |||
| 9d0c3d3fc5 | |||
| 907d0d39a1 | |||
| 4d689100ee | |||
| 818d9d6f62 | |||
| 9a2059726f | |||
| 8bcac405e5 | |||
| 19661c5e82 | |||
| 9875d9622d | |||
| 7573ffe941 | |||
| 47166ab2eb | |||
| 0295b7d919 | |||
| 3653072497 | |||
| 0e7f203a1b | |||
| ab99265c88 | |||
| f774d95f5c | |||
| 9e1e32f16d | |||
| 0accb453e5 | |||
| e2b285c792 | |||
| 935f95fa3b | |||
| a4d20d9f08 | |||
| 0e23719c7b | |||
| eb1f06658d | |||
| 1e177a2530 | |||
| 49031b0e48 | |||
| ca5bbb3064 | |||
| b338188c5f | |||
| 9cbe4cc36e | |||
| 6f5f521803 | |||
| a6db30280b | |||
| 4db3860ade | |||
| 57837cfe1d | |||
| b51fdc5769 | |||
| 5038d7ad53 | |||
| c1d618326b | |||
| db1a0195fe | |||
| 238def8089 | |||
| 59e969c2a8 | |||
| 029a288be2 | |||
| 11e5448acf | |||
| 71577d0346 | |||
| 681e559cb4 | |||
| 862390ae78 | |||
| f210799c4d | |||
| d7700c3c77 | |||
| 44fa4d3fc4 | |||
| f0c57c643b | |||
| 5e48ed1e23 | |||
| a3f12b2a53 | |||
| cc00cce704 | |||
| 9c244c6750 | |||
| ffb5d46ca3 | |||
| 7376732b1a | |||
| 1caf4ff8e6 | |||
| 22147483c1 | |||
| c7dbf7ba92 | |||
| fd3f76d35c | |||
| e10bca6892 | |||
| 4a01960426 | |||
| 318364e70b | |||
| 383064a7b7 | |||
| 78bbfb5f41 | |||
| 9aec1f5f50 | |||
| 66beb43daf | |||
| b02589a957 | |||
| d4a1d83851 | |||
| 53aee1020d | |||
| 010c106879 | |||
| fb43e38c7d | |||
| ca96c67e96 | |||
| 1fbf635582 | |||
| 44d62b187f | |||
| 57600cbad1 | |||
| 311d6507ce | |||
| 8e520ce579 | |||
| 5a97e15885 | |||
| bb36c67159 | |||
| 7a33edc7a6 | |||
| a7d6303da4 | |||
| 704c201c33 | |||
| c69d3eec36 | |||
| 6e5a3a0078 | |||
| ed62de9135 | |||
| a8b218ce95 | |||
| f6d2b1e7f1 | |||
| 85439213b2 | |||
| 2933d100f7 | |||
| ac799688d3 | |||
| a4b9c44cfa | |||
| af282d2bb8 | |||
| a93bbebb61 | |||
| 4552a24caa | |||
| fc22ec0672 | |||
| 963fbcb5e8 | |||
| 3da3b9de45 | |||
| a055d1c668 | |||
| 0b130bbc01 | |||
| 9f9bc9c747 | |||
| 75367ae727 | |||
| bd9d78622f | |||
| 6b807f419b | |||
| f58ee6f63a | |||
| 7510d86a52 | |||
| 65fba6ca41 | |||
| 3e2198b7ba | |||
| 535c0fc419 | |||
| 1c5d30b673 | |||
| 3bf26dbbef | |||
| 329437411d | |||
| 090cdaf2e4 | |||
| 7c257f261c | |||
| 477bc7baf7 | |||
| 32d6ebef9c | |||
| 51e0676ce5 | |||
| 53156e210f | |||
| 84f76c09f7 | |||
| 74e0765d7a | |||
| 51cfadbc77 | |||
| 01e047f639 | |||
| 4050d7e4a3 | |||
| adab66172d | |||
| 7c850c969e | |||
| f55fa98dec | |||
| 7f28c984e1 | |||
| 6220e53d8f | |||
| 5bb0231354 | |||
| 58eec48af7 | |||
| 65545dd3e5 | |||
| 5b92015c98 | |||
| 64c97b22d5 | |||
| 87adbe9bed | |||
| c6ed8b8318 | |||
| 4d2890976a | |||
| 9cfddf1327 | |||
| 84203d5aa2 | |||
| 4d19fffc5f | |||
| 18683390b7 | |||
| fb137ae840 | |||
| c8bc0c4a32 | |||
| 8ded82fa81 | |||
| acd1f47f4a | |||
| 054827bbae | |||
| a5ebe97dc5 | |||
| 02b2d8f754 | |||
| cf5da8f55a | |||
| 40947de05a | |||
| 662648691d | |||
| 29836a9c62 | |||
| a2b1a0d64b | |||
| 87fbd2cb59 | |||
| c91e21c23a | |||
| 0f25c7db0e | |||
| e5b5cbb8d8 | |||
| 9c1af1b8dc | |||
| 0da09da45e | |||
| 87aaefadf6 | |||
| b5b739a5cb | |||
| 1315d5dc29 | |||
| 72b70f5311 | |||
| fd15a62148 | |||
| e9bd625195 | |||
| c37fcf588c | |||
| 3f8d5027c8 | |||
| 972fc32eeb | |||
| 1ba9efe894 | |||
| f85ac8a813 | |||
| 7bf097c127 | |||
| fc579d9cf4 | |||
| b1c0933428 | |||
| bd7dd906fb | |||
| 3a8e400f33 | |||
| c6dd323b80 | |||
| dfb45d8391 | |||
| 0b0df00525 | |||
| 96fc5ae78c | |||
| a4b2d68995 | |||
| 70ababc2d9 | |||
| e57887eba5 | |||
| aef7fded18 | |||
| e0613c1f2d | |||
| f6d323cc31 | |||
| aa85562076 | |||
| 0165688799 | |||
| c2aefebedc | |||
| 1c5e4454da | |||
| 65e2a45d74 | |||
| 99026d6483 | |||
| 9190783ac4 | |||
| ae8f50dc14 | |||
| 2a51de03b7 | |||
| 2be9daa443 | |||
| 2778b3ea7b | |||
| 4cedb9dbcb | |||
| ed6a6fb844 | |||
| 8daf02246e | |||
| b3178e6f8d | |||
| 00cbde90c7 | |||
| 938175c49f | |||
| 146fc916d1 | |||
| 87776513fb | |||
| 60d462e5f9 | |||
| b39d8dd546 | |||
| b65635c41c | |||
| fe2539afba | |||
| d2ff216396 | |||
| 4c05da8335 | |||
| 6061cf5d93 | |||
| d313b7d8a6 | |||
| 71c21ccc00 | |||
| f415c03daa | |||
| 2bfef364ec | |||
| c822d20d0d | |||
| 3a996212ed | |||
| 5a3b6a5f93 | |||
| 3f7227ce32 | |||
| af0df80874 | |||
| a163d8a785 | |||
| 70fbf8d352 | |||
| d9a8692be8 | |||
| 56fb9c14d1 | |||
| 8bc0cee81f | |||
| dc86767184 | |||
| e1383445e2 | |||
| 0a30107859 | |||
| ba27925409 | |||
| 3a52021cdc | |||
| aba4fc70c2 | |||
| 5b89343192 | |||
| 20f9e90a69 | |||
| 5c58171ac3 | |||
| e98d80eea6 | |||
| c14d5be4ac | |||
| fea108371f | |||
| dd47bf05f8 | |||
| 3a160c1913 | |||
| c42c26d76a | |||
| f7117563f7 | |||
| 39968194b1 | |||
| 0d5f7e5673 | |||
| 7f4e111f7d | |||
| 0c92fcb011 | |||
| 2f4418e3ed | |||
| 75a3d7c80f | |||
| 4605053e50 | |||
| a8da0c0b55 | |||
| ba984f9263 | |||
| 451a311142 | |||
| f86bc219cf | |||
| 06bd63b6d1 | |||
| be088d8ba2 | |||
| c718ec8446 | |||
| 668e1019f0 | |||
| e2f5a7fae1 | |||
| f1a141c018 | |||
| 30a0f428bc | |||
| 7a8346621d | |||
| 6d93054d3d | |||
| 5c53e78aca | |||
| 1eeb832b0e | |||
| c8db9431b2 | |||
| ce8e0e3972 | |||
| ed4192838d | |||
| d900c368e2 | |||
| 6926bb877c | |||
| cb9b54a089 | |||
| 57c5d14f5a | |||
| 4f19d1638d | |||
| ace39a7f94 | |||
| e8e0540cc2 | |||
| a98799daaf | |||
| f2b53cd359 | |||
| 960f479b91 | |||
| d6dacb93dd | |||
| 8823656231 | |||
| 2c859e7186 | |||
| 99828dd82e | |||
| 855242e6fe | |||
| 90a1a920fa | |||
| c73968f490 | |||
| 282368b9e0 | |||
| 726a2be71e | |||
| 510104d0ff | |||
| 12318937f4 | |||
| 8f17d4b110 | |||
| 18496246b2 | |||
| 55f60e897a | |||
| dd2d142340 | |||
| 49a0cf3ece | |||
| f0d4a1c075 | |||
| 5e6db93250 | |||
| 12adf2f3a9 | |||
| b08908b1dc | |||
| 8f08746377 | |||
| 045e9346ad | |||
| 864ab17ff3 | |||
| 700d111011 | |||
| 7168d68997 | |||
| 40ec535e8a | |||
| 4dfaf29f3d | |||
| 702cd361fe | |||
| b776103328 | |||
| 381e7b5046 | |||
| ebdec8dd62 | |||
| 6677f2a01e | |||
| 5aaa9043ff | |||
| 48874adda3 | |||
| 0cf5a88d63 | |||
| 4b92874ca6 | |||
| 2d81b05fba | |||
| 78756aa2f4 | |||
| a15c91ebcb | |||
| 4b389c8293 | |||
| 2313b5e907 | |||
| e22941d947 | |||
| 3efc173056 | |||
| 6389919cfd | |||
| 984b840fa7 | |||
| 2bf01fbf0c | |||
| 116eeb753d | |||
| 82a6237323 | |||
| 6220a96666 | |||
| 259ab2c569 | |||
| efda4e0fdd | |||
| 968264fe9a | |||
| 57911cf567 | |||
| a61d9ae4d1 | |||
| 5735383cd7 | |||
| e3607895b4 | |||
| 16a2e0b53f | |||
| 41e5f9fd78 | |||
| 64b750b06e | |||
| ca90736366 | |||
| 664b308e31 | |||
| 8de0671d31 | |||
| 19d7192842 | |||
| c3ed54f05f | |||
| ef6655a014 | |||
| 234e549b22 | |||
| 903f72989a | |||
| 3e9900cc45 | |||
| 78d0cffd3d | |||
| 658e8d983c | |||
| 8174237a82 | |||
| 39a5e8eade | |||
| 54dea66f5f | |||
| 86fd9ddc0e | |||
| b071d1126b | |||
| 139e9daec0 | |||
| 4eeda2b3e7 | |||
| fa64b42a84 | |||
| ce67f4828f | |||
| 87e3d953d3 | |||
| 5d4668eaee | |||
| cfce8dba1f | |||
| c11e319472 | |||
| 7c7a0cd20b | |||
| a66bb42126 | |||
| 7d63f3f5cb | |||
| b102d23477 | |||
| e19c03412d | |||
| 56cba570bf | |||
| c7abcc153e | |||
| 967a77f371 | |||
| 2060f2c62e | |||
| 193c107539 | |||
| 2fe0851786 | |||
| 46b68ca2c9 | |||
| 396797dc0c | |||
| 5579f543de | |||
| ce31ab3097 | |||
| daa4764aac | |||
| a24c6775e8 | |||
| eb9de1769e | |||
| d675cc50b3 | |||
| 350d089c39 | |||
| 116969f4f2 | |||
| 112d9f9a63 | |||
| 5dae9c5d06 | |||
| c0a63ecfed | |||
| 881a5320a8 | |||
| 22a254890e | |||
| 0912909b68 | |||
| cd7318dd63 | |||
| 21cc610095 | |||
| cc8151caf8 | |||
| 8cce399430 | |||
| 99688df446 | |||
| de0a278cac | |||
| 7031ea1a04 | |||
| 541455a08b | |||
| 814efc4e35 | |||
| f85bbc41c4 | |||
| c00e8eb809 | |||
| 9dd00170af | |||
| fdba16de86 | |||
| 38f319b425 | |||
| d35046b277 | |||
| bdcaf2f2be | |||
| bba622da0e | |||
| 0d4f694fcf | |||
| a41824414e | |||
| c54b0abbd7 | |||
| d772ea527a | |||
| 62b76220d4 | |||
| 6aa8628c0c | |||
| 7d9f4864d0 | |||
| d149d5a5d5 | |||
| 7572bf9fb0 | |||
| 40ab925a4e | |||
| 75a989b4f1 | |||
| f98f89a51d | |||
| 423ea4bc6f | |||
| 3c60dd9ae8 | |||
| f9006be79b | |||
| 0492563838 | |||
| d58089b9ee | |||
| e17a33a16f | |||
| c935599fcf | |||
| efafdc50b8 | |||
| 8846c1d728 | |||
| 9bfd89cb9b | |||
| 35f01818dd | |||
| 875af7e9f7 | |||
| 7dfce2db55 | |||
| cab5772068 | |||
| 6319f1e82d | |||
| d42c8477aa | |||
| b559a7882b | |||
| 30e1d70099 | |||
| 84a8d18519 | |||
| 1fc20e5640 | |||
| d8f0fba8e2 | |||
| 2921404540 | |||
| df79b7b57b | |||
| 0a45638bac | |||
| 4f725af6cd | |||
| 44ae7bde56 | |||
| cd5e0405de | |||
| 5bbf2d3c82 | |||
| 09743f7153 | |||
| f88ef2f3fc | |||
| ef032b548e | |||
| db2f3cc85a | |||
| 7584f4a5b4 | |||
| aac559e221 | |||
| aee5c17591 | |||
| d8248a7973 | |||
| b68d060f85 | |||
| 74399df5eb | |||
| c3b62137d8 | |||
| 352bd23766 | |||
| 398344854b | |||
| e181c3cc82 | |||
| 24e4008b72 | |||
| 50d9ed7e3c | |||
| 9fd113c95f | |||
| 5683ced93d | |||
| 4360f4b2cb | |||
| 43a873defd | |||
| e5d08cdb3e | |||
| c78b80c679 | |||
| 9cd3ba1c67 | |||
| dd22b206dc | |||
| 12b668642c | |||
| 77fa881d69 | |||
| 05dcbfed2e | |||
| 6471041fad | |||
| 69ab56f878 | |||
| 97538333c0 | |||
| a094e1a2b7 | |||
| d0c8df1452 | |||
| 1b6a31e626 | |||
| 2c1cde9f69 | |||
| 1aa5e45694 | |||
| 9fc04193c7 | |||
| b685b9fa13 | |||
| 59f97d0c2d | |||
| 8f94460537 | |||
| 26fe947991 | |||
| 16829f9075 | |||
| 246314561b | |||
| 331a3c4178 | |||
| 35ba7861d1 | |||
| 59cb66331e | |||
| 782bfaa6c4 | |||
| 830af4a164 | |||
| 994cb73104 | |||
| 8e3dc73408 | |||
| 6792f9e916 | |||
| a350c35f49 | |||
| fb498b3723 | |||
| 7b9c90b77c | |||
| f4fd16d8fd | |||
| 5656e66c28 | |||
| 39882e43ce | |||
| e5f2d1cde9 | |||
| 4f978863e4 | |||
| f26aafa8cb | |||
| e444354cf7 | |||
| 0e4ae72016 | |||
| c1121a2d3f | |||
| 1737825506 | |||
| 437c569617 | |||
| 9580d77512 | |||
| f7fb89313c | |||
| 721a7d2341 | |||
| 3529ab6cb6 | |||
| 484bb3ca5b | |||
| 121b2d5df1 | |||
| 472887d627 | |||
| 03f514d5fe | |||
| 36d2203e4c | |||
| 4e11cc7db3 | |||
| f23963896d | |||
| fd2b13b391 | |||
| b90743ded1 | |||
| ee499d9352 | |||
| d12f0bddad | |||
| 9eabd9031b | |||
| 552e7a430d | |||
| b97f9f8f12 | |||
| 8be0cea193 | |||
| bce088bcdf | |||
| 6955c42c8b | |||
| 07b36279cf | |||
| 5c1dc0754b | |||
| 7eaa644028 | |||
| 1b29312bef | |||
| 930412bf21 | |||
| 0e1f4931eb | |||
| 2e2c4b4397 | |||
| 7665cc7f73 | |||
| c743335d13 | |||
| e9aeb1c918 | |||
| c092e9a8d0 | |||
| a55ec01992 | |||
| 302e503e02 | |||
| f82639cdf3 | |||
| 9172d8c5f8 | |||
| 69fd8ec123 | |||
| d9c7a512e9 | |||
| 38383f34ff | |||
| b7585fe022 | |||
| b7d9009ff4 | |||
| 9c26745c2a | |||
| 67f8e57ab6 | |||
| b2ef603729 | |||
| 110ea953c4 | |||
| cef07a5bff | |||
| a5899023b9 | |||
| 61530be208 | |||
| 292bcd7100 | |||
| 8f4a6fcf80 | |||
| dfdb3b5951 | |||
| 0cc7b373b7 | |||
| 7e5cbd92b4 | |||
| 2594ecd27e | |||
| edf8af3e4d | |||
| 5a76275571 | |||
| b147ee1c99 | |||
| 8b7cc8a220 | |||
| 88931a4a56 | |||
| df187bed58 | |||
| 8b86bc6b3f | |||
| f9ac64023a | |||
| 3a710e1e50 | |||
| 1d4f58f362 | |||
| abfd0a0a2e | |||
| 98839b15dc | |||
| 5b885e98cc | |||
| 58e29608e5 | |||
| db71cfd396 | |||
| 0de9cfb240 | |||
| 2a8efb246d | |||
| 071cf4eed8 | |||
| 87a8d8d490 | |||
| d3caa1dda9 | |||
| f832d44f3a | |||
| 103ab700fc | |||
| 6419fa6e61 | |||
| 98cf2adf92 | |||
| 5660d2e83b | |||
| 5e3e242981 | |||
| 65c31fb457 | |||
| 0f891075cc | |||
| 6d898367e4 | |||
| 003e63b7fb | |||
| 73c9e15976 | |||
| 1dc1d673dd | |||
| 46818d9a02 | |||
| d6a585c6cc | |||
| c54fcf920c | |||
| 467c7f77f5 | |||
| 3c51287178 | |||
| 9d8fdcfa12 | |||
| fadd8a7f79 | |||
| f2afb7ab1a | |||
| b52d8785bb | |||
| 70846525bf | |||
| abe77916a3 | |||
| 660846a0d8 | |||
| 8dec77f30a | |||
| 5812c8f939 | |||
| 1c673e11ac | |||
| bf54bcfd9b | |||
| 33a0b8f11f | |||
| 61ffdabc51 | |||
| 2f224047bc | |||
| 2747fa82e3 | |||
| 5dd80c91cf | |||
| 495e602599 | |||
| 545ddd4ec9 | |||
| 9fff53f137 | |||
| 1d38fc0879 | |||
| 48f44b8920 | |||
| e365818ef5 | |||
| c2bb3010cc | |||
| 4ca8003d24 | |||
| 6a212926e0 | |||
| dae5c0440f | |||
| 6b1d083faa | |||
| c8510bea2a | |||
| a00e84018a | |||
| 3435806020 | |||
| 27f0a0fcfa | |||
| 1f4bb0128a | |||
| e686b6b7d4 | |||
| b74d46b425 | |||
| aa08628b72 | |||
| d4b2c48916 | |||
| 152846cfd5 | |||
| 48ef1c8605 | |||
| de72cdb61a | |||
| 4c17101e27 | |||
| 0c1b3b0175 | |||
| 45b51d9bfa | |||
| 127916f03e | |||
| f94e9c98f9 | |||
| e52523f1fa | |||
| 2d36f75660 | |||
| a541423de5 | |||
| 8e98d1710b | |||
| 7b53756753 | |||
| e20d7982f4 | |||
| ff8604f44a | |||
| aaddd8e26f | |||
| 5e7fd398f2 | |||
| 53cc5f129f | |||
| 881e67d3e2 | |||
| 2c385aba12 | |||
| b53616addc | |||
| ff3796b7a0 | |||
| 9aa061e093 | |||
| 9524a31fe6 | |||
| 9c4f2dcf6b | |||
| c70120bcaa | |||
| ea693b3ffc | |||
| 62ec7d91a9 | |||
| 01b6799a31 | |||
| 52f3a88e36 | |||
| 35687c01ec | |||
| ed01407382 | |||
| 3dbe92a667 | |||
| 127ae75b5b | |||
| 3d90eaf32c | |||
| 4bbfacd7de | |||
| 5bb0f30c77 | |||
| b179a2fa49 | |||
| 3d0f0b0f52 | |||
| c11f4a5dc7 | |||
| dcb9d7b7fc | |||
| 87a39fa264 | |||
| 24f64e9d59 | |||
| d7f380fc73 | |||
| a37a1a6b95 | |||
| 33c3fc158f | |||
| 3a6afd6958 | |||
| 378f4e13fb | |||
| f4d7e30b5d | |||
| 088be2f1a5 | |||
| 56cab93554 | |||
| 17734753c8 | |||
| 36fa5e1d73 | |||
| abc364835c | |||
| 061625e474 | |||
| 0888577cde | |||
| 906bf18971 | |||
| 4398afe298 | |||
| 7c14e9e7a3 | |||
| b6798a3466 | |||
| 867c7b1752 | |||
| 0ef8f62a58 | |||
| 03f1f9f157 | |||
| a5e257a2f1 | |||
| f550750e30 | |||
| 6865c7f4a1 | |||
| 9d2bb15ffd | |||
| 336b14a4ce | |||
| 344e8f50ae | |||
| ba0b7f33bc | |||
| 49bc2e1762 | |||
| d3ec067224 | |||
| 267d0494d3 | |||
| 172f6bc29f | |||
| 4f93db928f | |||
| c10ee98076 | |||
| 0820cffd9d | |||
| 7f90d64064 | |||
| c4c98910e8 | |||
| 06f1ca232e | |||
| 90320c2b12 | |||
| f5885f612a | |||
| af74059945 | |||
| 42948185f9 | |||
| 6329778123 | |||
| eadf8f5266 | |||
| c4a0e47a84 | |||
| f9661e3b72 | |||
| 1715d4d056 | |||
| 40fae42a9e | |||
| 19e55c1185 | |||
| 6443a46abb | |||
| 8fb2e4b7f4 | |||
| 0be25fa16a | |||
| 8743c028a3 | |||
| 7174fd056a | |||
| cd188691f6 | |||
| c9586e7320 | |||
| c35da39ba6 | |||
| e2639b8055 | |||
| 558ed48874 | |||
| e38a3e5f53 | |||
| 1175696590 | |||
| 95862906a4 | |||
| 44cc8d883d | |||
| 4c607302f3 | |||
| a37ccac097 | |||
| b8c460e252 | |||
| 4df35ef8c0 | |||
| 397ac4a154 | |||
| 3e6854053d | |||
| e155301b60 | |||
| 197c315f07 | |||
| 5654125091 | |||
| 3768c22aed | |||
| beb43a785e | |||
| 34e10ac41e | |||
| 8e26edabba | |||
| d6cda6337b | |||
| 5b1638ab42 | |||
| 3537ccf3cd | |||
| d15a9945de | |||
| 61fa371fd4 | |||
| 05802ae91c | |||
| b4df799a37 | |||
| 6553bd70c5 | |||
| f3d0c6f28c | |||
| 09e35513b0 | |||
| 381e25cda1 | |||
| c763c174d5 | |||
| d4f3239844 | |||
| 806e9528f0 | |||
| aa59d9ecca | |||
| 1226af6376 | |||
| 596ecba13f | |||
| 57290d6a4b | |||
| 52251d420f | |||
| 95e365fe4f | |||
| 4f37f2fa0a | |||
| 716b7833b0 | |||
| 84d8d33349 | |||
| 132f90b28e | |||
| 7caabad651 | |||
| c4f3b0d653 | |||
| ddb9410c60 | |||
| f8ca73c164 | |||
| 9512846bb0 | |||
| 224097311c | |||
| 903718019e | |||
| a79ae2d6b5 | |||
| 71cc352982 | |||
| 94381dc5c0 | |||
| ac90d678c1 | |||
| c3959bbe63 | |||
| b88b92d884 | |||
| b05356b8e2 | |||
| 37a9315066 | |||
| 7324ec72ed | |||
| 90e8aa234d | |||
| 40669a14fe | |||
| f55c52d99e | |||
| a47b94e1a6 | |||
| 505af40b7b | |||
| 1fef1aa500 | |||
| 3aa63675c1 | |||
| 5825a5cd63 | |||
| 01d5b031a9 | |||
| 30b6aae25b | |||
| 54ebf14f02 | |||
| 2654f85c32 | |||
| fa9573cf54 | |||
| 98ea3d1a92 | |||
| e4b20908dc | |||
| 9b51ca3753 | |||
| 6d4ce03c10 | |||
| 1316dae035 | |||
| 79a6e43e02 | |||
| 625a4819e9 | |||
| 2838b3756f | |||
| 4f9dcfd584 | |||
| 37200b4ced | |||
| 4afbbcde99 | |||
| a05c3725e7 | |||
| 7110844c7c | |||
| 2a205a9634 | |||
| 1fad2c513c | |||
| 1ad4c16d23 | |||
| affc336f7d | |||
| e7f21db79a | |||
| 523dd52567 | |||
| 3191df85e4 | |||
| 2c37915ef7 | |||
| 1a8bd17f01 | |||
| a42907e7c8 | |||
| 1fc5bc8f3b | |||
| afebbc294b | |||
| dd50d9cd12 | |||
| 70f682edd6 | |||
| 48f7cee0c4 | |||
| 91fddff077 | |||
| c09144690e | |||
| 5cd4fde48a | |||
| fe90438f52 | |||
| a227bfe826 | |||
| a5f2e3f2e1 | |||
| 0dead1c4fe | |||
| 2db751bae4 | |||
| 5d6cd6ab9d | |||
| c93655d199 | |||
| 53cb22c474 | |||
| b58ab5e692 | |||
| f98dfb7c52 | |||
| f7c8178a45 | |||
| 336462bc02 | |||
| 7af0b6e6a5 | |||
| d1d22660c8 | |||
| 8afeeefc51 | |||
| 7f49a437ad | |||
| 6f1651dfc5 | |||
| 5372023651 | |||
| 659e92f95b | |||
| fd79df810c | |||
| 3f714dd030 | |||
| f39e013eca | |||
| d0367ddc36 | |||
| 1ce519673a | |||
| 03a96d4fff | |||
| 768eeeba1f | |||
| b068d20dd3 | |||
| 97a61ddfc0 | |||
| 4ed45c8616 | |||
| f4fc3dfab9 | |||
| 4673034737 | |||
| da155bfca3 | |||
| b6676b92bf | |||
| 363e0e11b3 | |||
| 7af5249e9c | |||
| ff663a1a9a | |||
| 860a09f6e8 | |||
| 59262a5c72 | |||
| e10e1f990f | |||
| ce8fe53d4d | |||
| bfad36af3d | |||
| c909dee4aa | |||
| 6775cfe170 | |||
| 995b612537 | |||
| e61b8e9777 | |||
| db0d90c0f0 | |||
| 6edacd4fd4 | |||
| 0df5e56dee | |||
| 16e0bebc29 | |||
| 5be959f4b8 | |||
| ea9a5fa3a0 | |||
| 2e15cfaed5 | |||
| 57d8673bb2 | |||
| bd8a8f744c | |||
| edc0734f9f | |||
| 0ad9da1076 | |||
| 6a8a005951 | |||
| fc8aaea395 | |||
| f469ce0227 | |||
| 1fb1b3d563 | |||
| 1baa31db04 | |||
| 0e4c972b19 | |||
| 8f438ff314 | |||
| 9bb5266d61 | |||
| edbcabace6 | |||
| bcc9e1c761 | |||
| c390997f79 | |||
| adff45de00 | |||
| a9cf555513 | |||
| 7885e4f80c | |||
| 8cccb5da36 | |||
| 1dc6c60de6 | |||
| 8cc9cb8caf | |||
| b718fcf185 | |||
| 495418cac2 | |||
| 3c031a9065 | |||
| 5109e84fcb | |||
| 7616813537 | |||
| 06230bb14b | |||
| a8e0c1691d | |||
| 8e9e2670fd | |||
| 95665f0274 | |||
| 26dbbd8dc9 | |||
| 2c991043ae | |||
| e739925da2 | |||
| 65ca6be4cd | |||
| bddb4eee6d | |||
| 8470a5f2ac | |||
| 2509d9cd9b | |||
| 633c2e5b8b | |||
| 9f5ae6f897 | |||
| 06231fe321 | |||
| 76a9a99762 | |||
| e2f1036ff1 | |||
| acd8e1765b | |||
| 79b97f089c | |||
| 6a6a314718 | |||
| 6be556dad2 | |||
| cee45b87ee | |||
| 9e47c34449 | |||
| ba96432757 | |||
| 7acd7ec8fb | |||
| 333763b3e1 | |||
| 7137064ead | |||
| 9813ab55a7 | |||
| a656b0c7dd | |||
| 9cf8ef47bb | |||
| ae6a0faa03 | |||
| 88a000d1d6 | |||
| 158c3608a0 | |||
| d529d5c52f | |||
| 2e549869af | |||
| 5346a12641 | |||
| c872f46257 | |||
| 56389be6a0 | |||
| 169b76161f | |||
| 2a56a8490b | |||
| 25844c5870 | |||
| 8b68fb319f | |||
| 3dfae86b00 | |||
| d26da8a4a8 | |||
| 0cbb375a49 | |||
| de1d971e44 | |||
| a031752d33 | |||
| b3b3cfff57 | |||
| a730b4485e | |||
| 897ad8c3eb | |||
| 6266146ecb | |||
| 7ed13b2b12 | |||
| 13e8ed7b6e | |||
| d2e2355673 | |||
| 951b4fde90 | |||
| 0b5cf19078 | |||
| 1274eaaec3 | |||
| 638fb12e16 | |||
| aacfbf7178 | |||
| 0f5a1a6335 | |||
| 73cbf96a65 | |||
| bee4a4b22b | |||
| 332e39b0fd | |||
| 7827fa2846 | |||
| 9d7c8f9786 | |||
| fbe02cd287 | |||
| 570fd0a27f | |||
| 7164c183ea | |||
| 094b43e748 | |||
| d16009272d | |||
| 3a3212f96c | |||
| 63b02936b1 | |||
| 2eced17ca9 | |||
| c4f0b0d60d | |||
| ec64533b4b | |||
| 670cee5923 | |||
| 67091fd72f | |||
| a5dee142bf | |||
| ade516d188 | |||
| da746c0e66 | |||
| 14826ee44b | |||
| 767c24dd56 | |||
| 22487c1893 | |||
| e6e2e8a91d | |||
| 4ebe354caa | |||
| 3b9c87c172 | |||
| c36aac0cdf | |||
| ab04db17f3 | |||
| 624cbee901 | |||
| a7891ee323 | |||
| 404c414f76 | |||
| bc55b870cb | |||
| ed282e444d | |||
| 8d3cf31941 | |||
| bec8720a4d | |||
| b9121e1468 | |||
| 55b72a9156 | |||
| 2ce78f333b | |||
| 5834ac7f37 | |||
| 1aaf5e10f4 | |||
| 82212aac16 | |||
| a118cbeb1e | |||
| c7b956344f | |||
| 2fe19dbf0e | |||
| 50e0e3bf98 | |||
| 5be941663b | |||
| 7a7acfa15c | |||
| 15ee30bcdf | |||
| 70362b8f96 | |||
| b217967d9c | |||
| eadf2d2cfa | |||
| ba441a826a | |||
| 7f063cf626 | |||
| bb2de4cca0 | |||
| fae51b4444 | |||
| 45438e09e5 | |||
| 1492d5acbb | |||
| 8f0dae936b | |||
| cd1222d27f | |||
| 71cfaaad63 | |||
| 66682260a0 | |||
| a1fdd5de05 | |||
| 5bcba84acb | |||
| 2cc362edfc | |||
| 8e5e638914 | |||
| 1c689ccfbd | |||
| 7b300a97c6 | |||
| 3199bea647 | |||
| bd31a3a598 | |||
| b3d58c5fa5 | |||
| 3457283220 | |||
| 33fc733f6d | |||
| 07a600c05f | |||
| cf30c49b0e | |||
| e2fd05db81 | |||
| 9d49ed9e61 | |||
| 5d6a44912e | |||
| ad3b0f84c2 | |||
| ceb111eccd | |||
| 53c56f5c0a | |||
| 15834921a8 | |||
| 8a1970bb3d | |||
| 50ce20071a | |||
| a8771052f3 | |||
| c53390beb3 | |||
| 0ec468becb | |||
| 2c45d4f1a5 | |||
| 2036c63a59 | |||
| e56d3dc632 | |||
| 8dedf719e0 | |||
| c04dfb4b77 | |||
| 281d10f3b4 | |||
| e28665fd05 | |||
| cc3b6d7e55 | |||
| 37d1c48f2e | |||
| 28187aea37 | |||
| 963d0d582f | |||
| ce279dda60 | |||
| ba92a90832 | |||
| 624bec0c88 | |||
| 85934de439 | |||
| 6a56132de9 | |||
| 8075684d1d | |||
| 3d3ac28848 | |||
| 5ec879833e | |||
| e8d2b494bf | |||
| c271537878 | |||
| ae2a3ba8a3 | |||
| 72215ad898 | |||
| d36e3c0d91 | |||
| 086ca46218 | |||
| 6c1288823d | |||
| 11c83759d2 | |||
| 9e2268ce72 | |||
| ce2f8ad003 | |||
| af661212b0 | |||
| f26db2b523 | |||
| 0451ef4190 | |||
| 84c5cdeca7 | |||
| ee8014385a | |||
| 27c63202cd | |||
| 9d446a6e29 | |||
| df27d6492f | |||
| 1d12d8e2ff | |||
| 551eb3851b | |||
| cb683b6674 | |||
| 4e5b96b8ea | |||
| 1db7b86f89 | |||
| 7198962847 | |||
| c7b32fd29a | |||
| 4b9ca6ca25 | |||
| f4a502024d | |||
| a9fd1978e1 | |||
| a73f6a4aeb | |||
| e34f13bd6a | |||
| f39ef0d799 | |||
| 66b9f2dd5c | |||
| b9d50179c0 | |||
| 35cac0d7e9 | |||
| 46980e6b50 | |||
| 7fc93a667d | |||
| e8e9105f5c | |||
| e6cd24065c | |||
| 65ae0e06f5 | |||
| 04a702fb0e | |||
| 5934178a5f | |||
| e43b28969e | |||
| a1bd7b4815 | |||
| baaf5af664 | |||
| 1f1500c661 | |||
| 3d92fac1d6 | |||
| 682a5d1c44 | |||
| e5f10d052a | |||
| 91bd2ac69f | |||
| e7ec55eb61 | |||
| c469b5e506 | |||
| e384470705 | |||
| 7c1e91b945 | |||
| 78e9623598 | |||
| a0f756a4cb | |||
| 108be0bc23 | |||
| e772407e38 | |||
| e789c32564 | |||
| 03f7173855 | |||
| 61b5a8295c | |||
| 665c88a681 | |||
| 53402bdda5 | |||
| 56295b3c98 | |||
| 0cbd0f67a1 | |||
| 7cf23668af | |||
| 7465b8b5b9 | |||
| 6019fdbe36 | |||
| 532eb15e3b | |||
| 064abbf8dd | |||
| d88a0412a0 | |||
| 296b510c41 | |||
| 473bb64b42 | |||
| 6df9099707 | |||
| b8c7441c92 | |||
| 79c21b24cd | |||
| b72e90f0b9 | |||
| 658ce479eb | |||
| 2e316c35fe | |||
| 3e9546aa10 | |||
| 21bd781468 | |||
| 2ea9c49b2e | |||
| b926519424 | |||
| 9e82fd124a | |||
| d859def7d6 | |||
| 2d5926913e | |||
| 8bde83bb7b | |||
| 08f592a9cb | |||
| a088071914 | |||
| a313f97736 | |||
| 367a096b8a | |||
| 363411f57c | |||
| 3bedd60b72 | |||
| bed277f899 | |||
| 6131101520 | |||
| b8f5709e65 | |||
| 689e8cf259 | |||
| 4acbe5b560 | |||
| 2c80ca7812 | |||
| 75b5458c02 | |||
| 1f446ac60f | |||
| 0b59b0a2cb | |||
| a13b1d08c4 | |||
| 39f5110464 | |||
| e67bf63bc5 | |||
| 2fffaca696 | |||
| be3dde7657 | |||
| 4d94784e88 | |||
| 7ea39def40 | |||
| 5b202121df | |||
| 1e0278fe72 | |||
| fd70a01803 | |||
| e6a909bba0 | |||
| 7ceb4b264b | |||
| fbaf78d18e | |||
| 7b8189dae2 | |||
| f29bdcab3f | |||
| 45de42fc71 | |||
| b62a1e5d88 | |||
| fbf86ab7e3 | |||
| 5dec67aa32 | |||
| 6e4d038b38 | |||
| 9b25cea893 | |||
| 4a2fd0166e | |||
| dfeab8793f | |||
| a867291b51 | |||
| 0fdf9a3419 | |||
| 796b3cf710 | |||
| 27e9cadf91 | |||
| 89d852f4ed | |||
| 9ad4c96572 | |||
| ed89bc652e | |||
| 746f2ba7e0 | |||
| 09acd12586 | |||
| a1d8e2237c | |||
| 86a486b060 | |||
| 173f899881 | |||
| 8436a319f8 | |||
| a565282a94 | |||
| 5d7beb71e6 | |||
| 3218be613d | |||
| 9ade3a7c39 | |||
| 3de5142a5b | |||
| ba3319d0cd | |||
| 2c82cf525a | |||
| c4e53d5654 | |||
| 7591f19707 | |||
| 7739652e21 | |||
| 40806ffda4 | |||
| 29783e2f3f | |||
| a888ed25ec | |||
| c402878262 | |||
| b8cbec9462 | |||
| 3d60c3af49 | |||
| 551198b6ec | |||
| 11395d8e5f | |||
| 5c89478ecb | |||
| f0a8133b94 | |||
| 83bdcdad1f | |||
| f1b5a457df | |||
| 8d00a6b2a3 | |||
| 8823392846 | |||
| 70f1faa312 | |||
| 61f95bf59b | |||
| 992dfe39fb | |||
| 964a95d934 | |||
| 2f1df92dc3 | |||
| 71d128a325 | |||
| 1c5aa8ce28 | |||
| 5dab6ef30b | |||
| 473dafbb58 | |||
| 6020248afc | |||
| 2c119e900c | |||
| 9f08024514 | |||
| 6e1c6fbc49 | |||
| a8212404ba | |||
| 5399c89d8e | |||
| 52e8e68cfc | |||
| b3e5d2924a | |||
| 2161a5d36d | |||
| 4a482adefe | |||
| 3c23dfd792 | |||
| d644e150ec | |||
| ceda3f8427 | |||
| 6ae2e60b33 | |||
| 56f86b1303 | |||
| e62774bf9a | |||
| c97253cb5f | |||
| 285992d137 | |||
| 67f137927d | |||
| f96025ae38 | |||
| 166b46f6a3 | |||
| 304ad35f29 | |||
| 8d8b41253e | |||
| 46ad5920de | |||
| 03c824a1c9 | |||
| 7f3fae5da7 | |||
| a9a51a76c7 | |||
| d887e9fe6a | |||
| 1a14eeb39e | |||
| c68e1494ac | |||
| ad0b3d4c28 | |||
| 785641cc47 | |||
| ae40f36853 | |||
| 2cada0fcbe | |||
| 1f45a3aa9f | |||
| 2a917ec091 | |||
| bad5f32ffc | |||
| b006fff6ed | |||
| 35f5a362e3 | |||
| 8924b2ca7a | |||
| 46de4000a1 | |||
| aea09998f9 | |||
| 80c001ba9c | |||
| eebf08217c | |||
| 44ca1ebc9a | |||
| 6854f5c8d3 | |||
| a362d5a977 | |||
| d2aef5df04 | |||
| 87992a36e1 | |||
| 2c6ef0dffe | |||
| a94670d6ca |
@@ -0,0 +1,30 @@
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
!**/.gitignore
|
||||
!.git/HEAD
|
||||
!.git/config
|
||||
!.git/packed-refs
|
||||
!.git/refs/heads/**
|
||||
@@ -126,6 +126,15 @@ csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
|
||||
|
||||
dotnet_diagnostic.CS1570.severity = none
|
||||
dotnet_diagnostic.CS1587.severity = none
|
||||
dotnet_diagnostic.CS8619.severity = none
|
||||
dotnet_diagnostic.CS8620.severity = none
|
||||
dotnet_diagnostic.CS8632.severity = none
|
||||
dotnet_diagnostic.CS8604.severity = none
|
||||
dotnet_diagnostic.CS1998.severity = none
|
||||
|
||||
[*.vb]
|
||||
#### 命名样式 ####
|
||||
|
||||
|
||||
@@ -11,25 +11,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Application", "
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Domain.Share", "IRaCIS.Core.Domain.Share\IRaCIS.Core.Domain.Share.csproj", "{7CBC76F5-3817-46B7-8D9D-79253A89B578}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.JWT.RS256", "ZhiZhunAuthenticationCenter\IRaCIS.JWT.RS256.csproj", "{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Test", "IRaCIS.Core.Test\IRaCIS.Core.Test.csproj", "{3292B2B4-6E8A-43AA-84C0-AB4A391E8A2A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infra.EFCore", "IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj", "{6D8115E5-84D6-424B-8F8D-0C2D40347A8C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.Infrastructure", "IRaCIS.Core.Infrastructure\IRaCIS.Core.Infrastructure.csproj", "{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IRaCIS.AuthenticationCenter", "IRaCIS.AuthenticationCenter", "{481329D6-B8A0-491F-A398-1DF66A0FBB62}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.IdentityServer4", "IRaCIS.Core.IdentityServer4\IRaCIS.Core.IdentityServer4.csproj", "{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IRaCIS.Core.IdentityServer4.MVC", "IRaCIS.Core.IdentityServer4.MVC\IRaCIS.Core.IdentityServer4.MVC.csproj", "{F621ADD6-94E8-4A4B-998E-25B8EF15D39C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F852ABFB-88AC-48BE-B876-2228BE2373D6}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -52,10 +39,6 @@ Global
|
||||
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7CBC76F5-3817-46B7-8D9D-79253A89B578}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3292B2B4-6E8A-43AA-84C0-AB4A391E8A2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3292B2B4-6E8A-43AA-84C0-AB4A391E8A2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3292B2B4-6E8A-43AA-84C0-AB4A391E8A2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -68,23 +51,10 @@ Global
|
||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07EED0F8-08E6-46F3-ACBE-17BC1391BD4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F621ADD6-94E8-4A4B-998E-25B8EF15D39C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F621ADD6-94E8-4A4B-998E-25B8EF15D39C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F621ADD6-94E8-4A4B-998E-25B8EF15D39C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F621ADD6-94E8-4A4B-998E-25B8EF15D39C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{3EF210EE-D5D1-4C93-A8FA-E0DB1852BD39} = {481329D6-B8A0-491F-A398-1DF66A0FBB62}
|
||||
{C3DD48CF-B8B3-40F6-9BDB-B7C7F0851674} = {481329D6-B8A0-491F-A398-1DF66A0FBB62}
|
||||
{F621ADD6-94E8-4A4B-998E-25B8EF15D39C} = {481329D6-B8A0-491F-A398-1DF66A0FBB62}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BCC2EB19-3914-489B-B1D7-B7303E0218A3}
|
||||
EndGlobalSection
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
//using Autofac;
|
||||
//using Autofac.Extensions.DependencyInjection;
|
||||
//using IRaCIS.Core.API;
|
||||
//using IRaCIS.Core.Application.Filter;
|
||||
//using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
//using LogDashboard;
|
||||
//using MassTransit;
|
||||
//using MassTransit.NewIdProviders;
|
||||
//using MediatR;
|
||||
//using Microsoft.AspNetCore.Builder;
|
||||
//using Microsoft.AspNetCore.Http.Features;
|
||||
//using Microsoft.AspNetCore.HttpOverrides;
|
||||
//using Microsoft.AspNetCore.SignalR;
|
||||
//using Microsoft.Extensions.Configuration;
|
||||
//using Microsoft.Extensions.DependencyInjection;
|
||||
//using Microsoft.Extensions.Hosting;
|
||||
//using Serilog;
|
||||
//using System;
|
||||
|
||||
//var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
||||
// //以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||
// var config = new ConfigurationBuilder()
|
||||
// .AddEnvironmentVariables()
|
||||
// .Build();
|
||||
|
||||
// var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
// if (string.IsNullOrWhiteSpace(enviromentName))
|
||||
// {
|
||||
|
||||
// var index = Array.IndexOf(args, "--env");
|
||||
// enviromentName = index > -1
|
||||
// ? args[index + 1]
|
||||
// : "Development";
|
||||
// }
|
||||
|
||||
|
||||
// NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
|
||||
|
||||
|
||||
//builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||
// .ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
// {
|
||||
// containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||
// })
|
||||
// .UseWindowsService().UseSerilog();
|
||||
|
||||
|
||||
|
||||
//// Add services to the container.
|
||||
|
||||
////本地化
|
||||
//builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
//// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
//builder.Services.AddControllers(options =>
|
||||
//{
|
||||
// //options.Filters.Add<LogActionFilter>();
|
||||
// options.Filters.Add<ModelActionFilter>();
|
||||
// options.Filters.Add<ProjectExceptionFilter>();
|
||||
// //options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
// //if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
// //{
|
||||
// // options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
|
||||
// //}
|
||||
|
||||
|
||||
//}).AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
|
||||
|
||||
////动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
//builder.Services.AddDynamicWebApiSetup();
|
||||
////AutoMapper
|
||||
//builder.Services.AddAutoMapperSetup();
|
||||
////EF ORM QueryWithNoLock
|
||||
//builder.Services.AddEFSetup(builder.Configuration);
|
||||
////Http 响应压缩
|
||||
//builder.Services.AddResponseCompressionSetup();
|
||||
////Swagger Api 文档
|
||||
//builder.Services.AddSwaggerSetup();
|
||||
////JWT Token 验证
|
||||
//builder.Services.AddJWTAuthSetup(builder.Configuration);
|
||||
//// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
//builder.Services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
|
||||
//// EasyCaching 缓存
|
||||
//builder.Services.AddEasyCachingSetup();
|
||||
|
||||
////services.AddDistributedMemoryCache();
|
||||
|
||||
////// hangfire 定时任务框架 有界面,更友好~
|
||||
//builder.Services.AddhangfireSetup(builder.Configuration);
|
||||
////// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
|
||||
////builder.Services.AddQuartZSetup(_configuration);
|
||||
|
||||
//// 保护上传文件
|
||||
////services.AddStaticFileAuthorizationSetup();
|
||||
|
||||
|
||||
//////HttpReports 暂时废弃
|
||||
////services.AddHttpReports().AddHttpTransport();
|
||||
////Serilog 日志可视化 LogDashboard日志
|
||||
//builder.Services.AddLogDashboardSetup();
|
||||
////上传限制 配置
|
||||
//builder.Services.Configure<FormOptions>(options =>
|
||||
//{
|
||||
// options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
// options.ValueCountLimit = int.MaxValue;
|
||||
// options.ValueLengthLimit = int.MaxValue;
|
||||
//});
|
||||
////IP 限流 可设置白名单 或者黑名单
|
||||
////services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
////用户类型 策略授权
|
||||
//builder.Services.AddAuthorizationPolicySetup(builder.Configuration);
|
||||
|
||||
//builder.Services.AddJsonConfigSetup(builder.Configuration);
|
||||
|
||||
////转发头设置 获取真实IP
|
||||
//builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||
//{
|
||||
// options.ForwardedHeaders =
|
||||
// ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
//});
|
||||
////Dicom影像渲染图片 跨平台
|
||||
//builder.Services.AddDicomSetup();
|
||||
|
||||
//// 实时应用
|
||||
//builder.Services.AddSignalR();
|
||||
|
||||
|
||||
//builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||
|
||||
//builder.Services.AddControllers();
|
||||
//// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
////builder.Services.AddEndpointsApiExplorer();
|
||||
////builder.Services.AddSwaggerGen();
|
||||
|
||||
////SerilogExtension.AddSerilogSetup(enviromentName, builder.Host.confi);
|
||||
|
||||
|
||||
//var app = builder.Build();
|
||||
|
||||
//// Configure the HTTP request pipeline.
|
||||
|
||||
////本地化
|
||||
//app.UseLocalization();
|
||||
|
||||
//app.UseForwardedHeaders();
|
||||
|
||||
|
||||
////不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
//app.UseStaticFiles();
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(app.Environment);
|
||||
|
||||
////LogDashboard
|
||||
//app.UseLogDashboard("/LogDashboard");
|
||||
|
||||
////hangfire
|
||||
////app.UseHangfireConfig(app.Environment);
|
||||
|
||||
//////暂时废弃
|
||||
////app.UseHttpReports();
|
||||
|
||||
//////限流 中间件
|
||||
////app.UseIpRateLimiting();
|
||||
|
||||
////响应压缩
|
||||
//app.UseResponseCompression();
|
||||
|
||||
//if (app.Environment.IsDevelopment())
|
||||
//{
|
||||
// app.UseDeveloperExceptionPage();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
|
||||
// //app.UseHsts();
|
||||
//}
|
||||
|
||||
//SwaggerSetup.Configure(app, app.Environment);
|
||||
|
||||
//Console.WriteLine("当前环境: " + builder.Environment.EnvironmentName);
|
||||
|
||||
////app.UseMiddleware<AuthMiddleware>();
|
||||
|
||||
//// 特殊异常处理 比如 404
|
||||
//app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||
|
||||
|
||||
|
||||
|
||||
//////serilog 记录请求的用户信息
|
||||
//app.UseSerilogConfig(app.Environment);
|
||||
|
||||
//app.UseRouting();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
|
||||
//app.UseAuthentication();
|
||||
////app.UseJwtBearerQueryString();
|
||||
//app.UseAuthorization();
|
||||
|
||||
//////文件伺服 必须带Token 访问
|
||||
//////app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
|
||||
|
||||
////app.UseEndpoints(endpoints =>
|
||||
////{
|
||||
|
||||
|
||||
//// endpoints.MapControllers();
|
||||
|
||||
//// endpoints.MapHub<UploadHub>("/UploadHub")/*.RequireCors(t=>t.WithOrigins(new string[] {"null"}).AllowAnyMethod().AllowAnyHeader().AllowCredentials())*/;
|
||||
////});
|
||||
|
||||
|
||||
|
||||
//app.MapControllers();
|
||||
//app.MapHub<UploadHub>("/UploadHub")/*.RequireCors(t=>t.WithOrigins(new string[] {"null"}).AllowAnyMethod().AllowAnyHeader().AllowCredentials())*/;
|
||||
|
||||
|
||||
//app.Run();
|
||||
|
||||
//测试同步
|
||||
@@ -1,106 +0,0 @@
|
||||
{
|
||||
"needAnonymizeTag": [
|
||||
{ //PatientsName
|
||||
"Group": "0010",
|
||||
"Element": "0010",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientID
|
||||
"Group": "0010",
|
||||
"Element": "0020",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // IssuerOfPatientID
|
||||
"Group": "0010",
|
||||
"Element": "0021",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientsBirthDate
|
||||
"Group": "0010",
|
||||
"Element": "0030",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientsBirthTime
|
||||
"Group": "0010",
|
||||
"Element": "0032",
|
||||
"ReplaceValue": "",
|
||||
"Enable": false
|
||||
},
|
||||
{ // PatientsSex
|
||||
"Group": "0010",
|
||||
"Element": "0040",
|
||||
"ReplaceValue": "",
|
||||
"Enable": false
|
||||
},
|
||||
{ // OtherPatientIDs
|
||||
"Group": "0010",
|
||||
"Element": "1000",
|
||||
"ReplaceValue": "",
|
||||
"Enable": false
|
||||
},
|
||||
{ // OtherPatientNames
|
||||
"Group": "0010",
|
||||
"Element": "1001",
|
||||
"ReplaceValue": "",
|
||||
"Enable": false
|
||||
},
|
||||
{ // OtherPatientNames
|
||||
"Group": "0010",
|
||||
"Element": "1005",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientBirthName
|
||||
"Group": "0010",
|
||||
"Element": "1005",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientsAge
|
||||
"Group": "0010",
|
||||
"Element": "1010",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientsAddress
|
||||
"Group": "0010",
|
||||
"Element": "1040",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{ // PatientsMothersBirthName
|
||||
"Group": "0010",
|
||||
"Element": "1060",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{
|
||||
"Group": "0010",
|
||||
"Element": "2150",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{
|
||||
"Group": "0010",
|
||||
"Element": "2152",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{
|
||||
"Group": "0010",
|
||||
"Element": "2154",
|
||||
"ReplaceValue": "",
|
||||
"Enable": true
|
||||
},
|
||||
{
|
||||
"Group": "0012",
|
||||
"Element": "0040",
|
||||
"ReplaceValue": "XXX",
|
||||
"Enable": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using EasyCaching.Core;
|
||||
using gRPC.ZHiZHUN.AuthServer.protos;
|
||||
using Grpc.Net.Client;
|
||||
using Grpc.Net.Client.Configuration;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Auth;
|
||||
@@ -24,6 +21,17 @@ using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MassTransit;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Aliyun.Acs.Core.Profile;
|
||||
using Aliyun.Acs.Core.Auth.Sts;
|
||||
using Aliyun.Acs.Core;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.Extensions.Options;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
|
||||
namespace IRaCIS.Api.Controllers
|
||||
{
|
||||
@@ -47,9 +55,10 @@ namespace IRaCIS.Api.Controllers
|
||||
/// <param name="doctorId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet, Route("doctor/getDetail/{doctorId:guid}")]
|
||||
|
||||
public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
|
||||
|
||||
public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
|
||||
[FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,
|
||||
|
||||
[FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService, Guid doctorId)
|
||||
{
|
||||
var education = await _educationService.GetEducation(doctorId);
|
||||
@@ -59,7 +68,7 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var doctorDetail = new DoctorDetailDTO
|
||||
{
|
||||
AuditView =await _doctorService.GetAuditState(doctorId),
|
||||
AuditView = await _doctorService.GetAuditState(doctorId),
|
||||
BasicInfoView = await _doctorService.GetBasicInfo(doctorId),
|
||||
EmploymentView = await _doctorService.GetEmploymentInfo(doctorId),
|
||||
AttachmentList = await attachmentService.GetAttachments(doctorId),
|
||||
@@ -70,7 +79,7 @@ namespace IRaCIS.Api.Controllers
|
||||
TrialExperienceView = await _trialExperienceService.GetTrialExperience(doctorId),
|
||||
ResearchPublicationView = await _researchPublicationService.GetResearchPublication(doctorId),
|
||||
|
||||
SpecialtyView =await _doctorService.GetSpecialtyInfo(doctorId),
|
||||
SpecialtyView = await _doctorService.GetSpecialtyInfo(doctorId),
|
||||
InHoliday = (await _vacationService.OnVacation(doctorId)).IsSuccess,
|
||||
IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(doctorId),
|
||||
SowList = sowList,
|
||||
@@ -89,77 +98,31 @@ namespace IRaCIS.Api.Controllers
|
||||
/// <summary> 系统用户登录接口[New] </summary>
|
||||
[HttpPost, Route("user/login")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> Login(UserLoginDTO loginUser, [FromServices] IEasyCachingProvider provider, [FromServices] IUserService _userService,
|
||||
[FromServices] ITokenService _tokenService, [FromServices] IConfiguration configuration)
|
||||
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
|
||||
[FromServices] IEasyCachingProvider provider,
|
||||
[FromServices] IUserService _userService,
|
||||
[FromServices] ITokenService _tokenService,
|
||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||
IMailVerificationService _mailVerificationService)
|
||||
{
|
||||
|
||||
|
||||
var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
|
||||
|
||||
if (returnModel.IsSuccess)
|
||||
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
||||
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
#region GRPC 调用鉴权中心,因为服务器IIS问题 http/2 故而没法使用
|
||||
Guid userId = (Guid)loginUser.UserId;
|
||||
|
||||
////重试策略
|
||||
//var defaultMethodConfig = new MethodConfig
|
||||
//{
|
||||
// Names = { MethodName.Default },
|
||||
// RetryPolicy = new RetryPolicy
|
||||
// {
|
||||
// MaxAttempts = 3,
|
||||
// InitialBackoff = TimeSpan.FromSeconds(1),
|
||||
// MaxBackoff = TimeSpan.FromSeconds(5),
|
||||
// BackoffMultiplier = 1.5,
|
||||
// RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
|
||||
// }
|
||||
//};
|
||||
//验证MFA 编码是否有问题 ,前端要拆开,自己调用验证的逻辑
|
||||
//await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode);
|
||||
|
||||
//#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
|
||||
//var loginUser = await _userRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo<UserBasicInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
|
||||
//var httpHandler = new HttpClientHandler();
|
||||
//// Return `true` to allow certificates that are untrusted/invalid
|
||||
//httpHandler.ServerCertificateCustomValidationCallback =
|
||||
// HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
var basicInfo = await _userService.GetUserBasicInfo(userId, loginUser.Password);
|
||||
|
||||
var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo };
|
||||
|
||||
//////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
|
||||
//AppContext.SetSwitch(
|
||||
// "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||
loginReturn.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(loginReturn.BasicInfo));
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
//var grpcAdress = configuration.GetValue<string>("GrpcAddress");
|
||||
////var grpcAdress = "http://localhost:7200";
|
||||
|
||||
//var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
|
||||
//{
|
||||
// HttpHandler = httpHandler,
|
||||
// ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
|
||||
|
||||
//});
|
||||
////var channel = GrpcChannel.ForAddress(grpcAdress);
|
||||
//var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);
|
||||
|
||||
//var userInfo = returnModel.Data.BasicInfo;
|
||||
|
||||
//var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
|
||||
//{
|
||||
// Id = userInfo.Id.ToString(),
|
||||
// ReviewerCode = userInfo.ReviewerCode,
|
||||
// IsAdmin = userInfo.IsAdmin,
|
||||
// RealName = userInfo.RealName,
|
||||
// UserTypeEnumInt = (int)userInfo.UserTypeEnum,
|
||||
// UserTypeShortName = userInfo.UserTypeShortName,
|
||||
// UserName = userInfo.UserName
|
||||
//});
|
||||
|
||||
//returnModel.Data.JWTStr = tokenResponse.Token;
|
||||
|
||||
#endregion
|
||||
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
|
||||
var option = new CookieOptions
|
||||
@@ -170,19 +133,161 @@ namespace IRaCIS.Api.Controllers
|
||||
Secure = false // 确保 cookie 只能通过 HTTPS 访问
|
||||
};
|
||||
|
||||
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
|
||||
HttpContext.Response.Cookies.Append("access_token", loginReturn.JWTStr, option);
|
||||
|
||||
// 验证阅片休息时间
|
||||
await readingImageTaskService.ResetReadingRestTime(userId);
|
||||
|
||||
await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
||||
|
||||
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||
|
||||
return ResponseOutput.Ok(loginReturn);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
|
||||
|
||||
if (returnModel.IsSuccess)
|
||||
{
|
||||
#region GRPC 调用鉴权中心,因为服务器IIS问题 http/2 故而没法使用
|
||||
|
||||
////重试策略
|
||||
//var defaultMethodConfig = new MethodConfig
|
||||
//{
|
||||
// Names = { MethodName.Default },
|
||||
// RetryPolicy = new RetryPolicy
|
||||
// {
|
||||
// MaxAttempts = 3,
|
||||
// InitialBackoff = TimeSpan.FromSeconds(1),
|
||||
// MaxBackoff = TimeSpan.FromSeconds(5),
|
||||
// BackoffMultiplier = 1.5,
|
||||
// RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
|
||||
// }
|
||||
//};
|
||||
|
||||
//#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
|
||||
|
||||
//var httpHandler = new HttpClientHandler();
|
||||
//// Return `true` to allow certificates that are untrusted/invalid
|
||||
//httpHandler.ServerCertificateCustomValidationCallback =
|
||||
// HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
|
||||
|
||||
//////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
|
||||
//AppContext.SetSwitch(
|
||||
// "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
//var grpcAdress = configuration.GetValue<string>("GrpcAddress");
|
||||
////var grpcAdress = "http://localhost:7200";
|
||||
|
||||
//var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
|
||||
//{
|
||||
// HttpHandler = httpHandler,
|
||||
// ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
|
||||
|
||||
//});
|
||||
////var channel = GrpcChannel.ForAddress(grpcAdress);
|
||||
//var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);
|
||||
|
||||
//var userInfo = returnModel.Data.BasicInfo;
|
||||
|
||||
//var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
|
||||
//{
|
||||
// Id = userInfo.Id.ToString(),
|
||||
// ReviewerCode = userInfo.ReviewerCode,
|
||||
// IsAdmin = userInfo.IsAdmin,
|
||||
// RealName = userInfo.RealName,
|
||||
// UserTypeEnumInt = (int)userInfo.UserTypeEnum,
|
||||
// UserTypeShortName = userInfo.UserTypeShortName,
|
||||
// UserName = userInfo.UserName
|
||||
//});
|
||||
|
||||
//returnModel.Data.JWTStr = tokenResponse.Token;
|
||||
|
||||
#endregion
|
||||
|
||||
var userId = returnModel.Data.BasicInfo.Id;
|
||||
|
||||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
//发版屏蔽
|
||||
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
//MFA 发送邮件
|
||||
|
||||
returnModel.Data.IsMFA = true;
|
||||
|
||||
var email = returnModel.Data.BasicInfo.EMail;
|
||||
|
||||
#region 隐藏Email
|
||||
// 找到 "@" 符号的位置
|
||||
int atIndex = email.IndexOf('@');
|
||||
|
||||
// 替换 "@" 符号前的中间两位为星号
|
||||
string visiblePart = email.Substring(0, atIndex);
|
||||
|
||||
int startIndex = (visiblePart.Length - 2) / 2;
|
||||
|
||||
// 替换中间两位字符为星号
|
||||
string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
|
||||
|
||||
string afterAt = email.Substring(atIndex + 1);
|
||||
|
||||
// 组合隐藏和可见部分
|
||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
||||
#endregion
|
||||
|
||||
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
||||
|
||||
await _userService.SendMFAEmail(userId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
|
||||
var option = new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
|
||||
HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
|
||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
|
||||
Secure = false // 确保 cookie 只能通过 HTTPS 访问
|
||||
};
|
||||
|
||||
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
|
||||
|
||||
|
||||
|
||||
// 验证阅片休息时间
|
||||
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
|
||||
|
||||
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||
|
||||
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||
}
|
||||
|
||||
}
|
||||
return returnModel;
|
||||
|
||||
}
|
||||
|
||||
var userId = returnModel.Data.BasicInfo.Id.ToString();
|
||||
//provider.Set(userId, userId, TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan));
|
||||
|
||||
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||
return returnModel;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpGet, Route("imageShare/ShareImage")]
|
||||
[AllowAnonymous]
|
||||
public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
|
||||
@@ -202,18 +307,117 @@ namespace IRaCIS.Api.Controllers
|
||||
return ResponseOutput.Ok("/showdicom?studyId=f7b67793-8155-0223-2f15-118f2642efb8&type=Share&token=" + token);
|
||||
}
|
||||
|
||||
[HttpGet("user/GetObjectStoreToken")]
|
||||
public IResponseOutput GetObjectStoreToken([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
|
||||
{
|
||||
var serviceOption = options.CurrentValue;
|
||||
|
||||
if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedEnum) && parsedEnum == ObjectStoreUse.AliyunOSS)
|
||||
{
|
||||
|
||||
var ossOptions = serviceOption.AliyunOSS;
|
||||
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS });
|
||||
|
||||
#region 临时token 屏蔽
|
||||
//IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
|
||||
//DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||
|
||||
|
||||
//// 创建一个STS请求
|
||||
//AssumeRoleRequest request = new AssumeRoleRequest
|
||||
//{
|
||||
// RoleArn = ossOptions.RoleArn, // 角色ARN,需要替换为你的角色ARN
|
||||
// RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
|
||||
// DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
|
||||
//};
|
||||
|
||||
|
||||
//AssumeRoleResponse response = client.GetAcsResponse(request);
|
||||
|
||||
//// 返回STS令牌信息给前端
|
||||
//var stsToken = new ObjectStoreDTO()
|
||||
//{
|
||||
// ObjectStoreUse = serviceOption.ObjectStoreUse,
|
||||
// AliyunOSS = new AliyunOSSTempToken()
|
||||
// {
|
||||
// AccessKeyId = response.Credentials.AccessKeyId,
|
||||
// AccessKeySecret = response.Credentials.AccessKeySecret,
|
||||
// SecurityToken = response.Credentials.SecurityToken,
|
||||
// Expiration = response.Credentials.Expiration,
|
||||
|
||||
// Region = ossOptions.Region,
|
||||
// BucketName = ossOptions.BucketName,
|
||||
// ViewEndpoint = ossOptions.ViewEndpoint,
|
||||
|
||||
// },
|
||||
// MinIO = serviceOption.MinIO
|
||||
//};
|
||||
//return ResponseOutput.Ok(stsToken);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
|
||||
{
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpGet("user/GenerateSTS")]
|
||||
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
|
||||
{
|
||||
var ossOptions = options.CurrentValue;
|
||||
|
||||
|
||||
IClientProfile profile = DefaultProfile.GetProfile(ossOptions.regionId, ossOptions.accessKeyId, ossOptions.accessKeySecret);
|
||||
DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||
|
||||
|
||||
// 创建一个STS请求
|
||||
AssumeRoleRequest request = new AssumeRoleRequest
|
||||
{
|
||||
RoleArn = ossOptions.roleArn, // 角色ARN,需要替换为你的角色ARN
|
||||
RoleSessionName = $"session-name-{NewId.NextGuid()}", // 角色会话名称,可自定义
|
||||
DurationSeconds = 900, // 令牌有效期(单位:秒),这里设置为1小时
|
||||
};
|
||||
|
||||
|
||||
AssumeRoleResponse response = client.GetAcsResponse(request);
|
||||
|
||||
// 返回STS令牌信息给前端
|
||||
var stsToken = new
|
||||
{
|
||||
AccessKeyId = response.Credentials.AccessKeyId,
|
||||
AccessKeySecret = response.Credentials.AccessKeySecret,
|
||||
SecurityToken = response.Credentials.SecurityToken,
|
||||
Expiration = response.Credentials.Expiration,
|
||||
|
||||
Region = ossOptions.region,
|
||||
BucketName = ossOptions.bucketName,
|
||||
ViewEndpoint = ossOptions.viewEndpoint,
|
||||
|
||||
};
|
||||
|
||||
return ResponseOutput.Ok(stsToken);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("User/UserRedirect")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> UserRedirect([FromServices] IRepository<User> _userRepository, string url ,[FromServices]ILogger<ExtraController> _logger)
|
||||
public async Task<IActionResult> UserRedirect([FromServices] IRepository<User> _userRepository, string url, [FromServices] ILogger<ExtraController> _logger)
|
||||
{
|
||||
|
||||
var decodeUrl = System.Web.HttpUtility.UrlDecode(url);
|
||||
|
||||
var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length , 36) ;
|
||||
var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length, 36);
|
||||
|
||||
var token = decodeUrl.Substring(decodeUrl.IndexOf("access_token=") + "access_token=".Length);
|
||||
|
||||
@@ -221,12 +425,12 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var domainStrList = decodeUrl.Split("/").ToList().Take(3).ToList();
|
||||
|
||||
var errorUrl = domainStrList[0]+"//"+ domainStrList[2]+ "/error";
|
||||
var errorUrl = domainStrList[0] + "//" + domainStrList[2] + "/error";
|
||||
|
||||
|
||||
if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
|
||||
if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
|
||||
{
|
||||
decodeUrl = errorUrl+ $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang=="zh"? "您的初始化链接已过期": "Error!The initialization link has expired. Return")} ";
|
||||
decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang == "zh" ? "您的初始化链接已过期" : "Error!The initialization link has expired. Return")} ";
|
||||
}
|
||||
|
||||
return Redirect(decodeUrl);
|
||||
|
||||
@@ -419,13 +419,30 @@ namespace IRaCIS.Core.API.Controllers
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重置并同步项目阅片标准
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingCriterion/ResetAndAsyncCriterion")]
|
||||
[UnitOfWork]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
/// <summary>
|
||||
/// CRC RequestToQC 批量提交
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")]
|
||||
public async Task<IResponseOutput> ResetAndAsyncCriterion(DataInspectionDto<ResetAndAsyncCriterionInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _trialConfigService.ResetAndAsyncCriterion(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// CRC RequestToQC 批量提交
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> CRCRequestToQC(DataInspectionDto<CRCRequestToQCCommand> opt)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
// 使用的是proto3版本
|
||||
// 使用的是proto3版本
|
||||
syntax = "proto3";
|
||||
// 定义命名空间,后续生成代码时就会生成对应的命名空间
|
||||
// 定义命名空间,后续生成代码时就会生成对应的命名空间
|
||||
option csharp_namespace = "gRPC.ZHiZHUN.AuthServer.protos";
|
||||
|
||||
/*
|
||||
每一句需要用分号结尾
|
||||
message 用来定义请求和返回数据格式
|
||||
tag message后面的值数字代表是字段的标识(tag),不是赋值,
|
||||
每一句需要用分号结尾
|
||||
message 用来定义请求和返回数据格式
|
||||
tag message后面的值数字代表是字段的标识(tag),不是赋值,
|
||||
*/
|
||||
|
||||
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
message GetTokenReuqest{
|
||||
string id=1;
|
||||
string userName=2;
|
||||
@@ -22,48 +22,48 @@ message GetTokenReuqest{
|
||||
|
||||
}
|
||||
|
||||
// 新增时返回的消息格式
|
||||
// 新增时返回的消息格式
|
||||
message GetTokenResponse {
|
||||
int32 code=1;
|
||||
string token =2;
|
||||
}
|
||||
|
||||
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
service TokenGrpcService{
|
||||
// 获取token
|
||||
// 获取token
|
||||
rpc GetUserToken(GetTokenReuqest) returns (GetTokenResponse);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
message AddUserReuqest{
|
||||
string name=1;
|
||||
int32 age=2;
|
||||
bool isBoy=3;
|
||||
}
|
||||
// 新增时返回的消息格式
|
||||
// 新增时返回的消息格式
|
||||
message ResultResponse {
|
||||
int32 code=1;
|
||||
string msg =2;
|
||||
}
|
||||
//传递的查询条件信息格式,可理解为平时传入的查询条件对象
|
||||
//传递的查询条件信息格式,可理解为平时传入的查询条件对象
|
||||
message QueryUserReuqest{
|
||||
string name=1;
|
||||
}
|
||||
//查询返回的用户信息格式,可理解为返回的类
|
||||
//查询返回的用户信息格式,可理解为返回的类
|
||||
message UserInfoResponse {
|
||||
string name=1;
|
||||
int32 age=2;
|
||||
string gender=3;
|
||||
}
|
||||
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
service UserService{
|
||||
// 新增用户
|
||||
// 新增用户
|
||||
rpc AddUser(AddUserReuqest) returns (ResultResponse);
|
||||
// 查询用户
|
||||
// 查询用户
|
||||
rpc GetAllUser(QueryUserReuqest) returns (UserInfoResponse);
|
||||
}
|
||||
*/
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||
<LangVersion>default</LangVersion>
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>.\IRaCIS.Core.API.xml</DocumentationFile>
|
||||
<NoWarn>1701;1702;1591;</NoWarn>
|
||||
<NoWarn>1701;1702;1591;1570;</NoWarn>
|
||||
<OutputPath>..\bin\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -24,12 +24,7 @@
|
||||
<NoWarn>1701;1702;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="wwwroot\**" />
|
||||
<EmbeddedResource Remove="UploadFile\**" />
|
||||
<EmbeddedResource Remove="wwwroot\**" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="web.config" />
|
||||
@@ -66,33 +61,27 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.7.0" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.7.0" />
|
||||
<PackageReference Include="EntityFrameworkCore.Triggered.Extensions" Version="3.2.1" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.8" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.49.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.50.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Hangfire.Tags.SqlServer" Version="1.8.1" />
|
||||
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.Castle" Version="1.9.2" />
|
||||
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.2">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.12" />
|
||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||
<PackageReference Include="Hangfire.SqlServer" Version="1.8.12" />
|
||||
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
|
||||
<PackageReference Include="LogDashboard" Version="1.4.8" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.10" />
|
||||
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.6.2" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.6.2" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
|
||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="1.2.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.3" />
|
||||
<PackageReference Include="Serilog.Sinks.Email" Version="3.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.4.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -105,9 +94,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="NLog.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -168,7 +154,7 @@
|
||||
<Folder Include="Properties\PublishProfiles\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ProjectExtensions><VisualStudio><UserProperties anonymizetagsetting_1json__JsonSchema="http://json.schemastore.org/jovo-language-model" properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||
<ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<param name="doctorId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Configuration.IConfiguration)">
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,EasyCaching.Core.IEasyCachingProvider,IRaCIS.Application.Services.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Application.Services.IMailVerificationService)">
|
||||
<summary> 系统用户登录接口[New] </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialInspection(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Application.Contracts.TrialCommand})">
|
||||
@@ -208,6 +208,12 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.ResetAndAsyncCriterion(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.ResetAndAsyncCriterionInDto})">
|
||||
<summary>
|
||||
重置并同步项目阅片标准
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.CRCRequestToQC(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Contracts.CRCRequestToQCCommand})">
|
||||
<summary>
|
||||
CRC RequestToQC 批量提交
|
||||
@@ -268,95 +274,49 @@
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{System.Guid},System.Guid,Microsoft.Extensions.Logging.ILogger{IRaCIS.Core.API.Controllers.UploadDownLoadController},EasyCaching.Core.IEasyCachingProvider,IRaCIS.Core.Application.Contracts.IStudyService,Microsoft.AspNetCore.SignalR.IHubContext{IRaCIS.Core.API.UploadHub,IRaCIS.Core.API.IUploadClient},IRaCIS.Core.Application.Contracts.Dicom.IDicomArchiveService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
||||
<summary>Dicom 归档</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitClinicalData(System.Guid)">
|
||||
<summary>
|
||||
上传临床数据 多文件
|
||||
</summary>
|
||||
<param name="subjectVisitId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadClinicalTemplate(System.Nullable{System.Guid})">
|
||||
<summary>
|
||||
上传临床数据模板
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadReadClinicalData(System.Guid,System.Guid,System.Guid)">
|
||||
<summary>
|
||||
上传阅片临床数据
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="subjectId"></param>
|
||||
<param name="readingId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadPrintscreen(System.Guid)">
|
||||
<summary>
|
||||
上传截图
|
||||
</summary>
|
||||
<param name="subjectId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadReadingAnswerImage(System.Guid,System.Guid)">
|
||||
<summary>
|
||||
上传Reading问题的图像
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="visitTaskId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadJudgeTaskImage(System.Guid,System.Guid)">
|
||||
<summary>
|
||||
上传裁判任务的图像
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="visitTaskId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadMedicalReviewImage(System.Guid,System.Guid)">
|
||||
<summary>
|
||||
上传医学审核图片
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="taskMedicalReviewId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(Microsoft.AspNetCore.Http.IFormCollection,System.Guid,System.Guid,System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFile(IRaCIS.Core.API.Controllers.StudyController.UploadNoneDicomFileCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.StudyMonitor})">
|
||||
<summary>
|
||||
上传非Dicom 文件 支持压缩包 多文件上传
|
||||
</summary>
|
||||
<param name="formCollection"></param>
|
||||
<param name="subjectVisitId"></param>
|
||||
<param name="noneDicomStudyId"></param>
|
||||
<param name="studyMonitorId"></param>
|
||||
<param name="incommand"></param>
|
||||
<param name="_noneDicomStudyRepository"></param>
|
||||
<param name="_studyMonitorRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid,IRaCIS.Core.Application.Helper.IOSSService)">
|
||||
<summary>
|
||||
一致性核查 excel上传 支持三种格式
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<param name="oSSService"></param>
|
||||
<returns></returns>
|
||||
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.API.Controllers.FileController">
|
||||
<summary>医生文件上传下载</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.UploadOrdinaryFile(System.String,System.Guid)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.GetOfficialResume(IRaCIS.Core.API.Controllers.GetDoctorPathCommand,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Attachment})">
|
||||
<summary>
|
||||
上传文件[FileUpload]
|
||||
New 医生首页 多选 获取多个医生信息+文件路径列表 医生压缩包名称 doctorCode + "_" + doctorName _(时间戳或者随机的Guid)
|
||||
</summary>
|
||||
<param name="attachmentType">附件类型</param>
|
||||
<param name="doctorId">医生Id</param>
|
||||
<returns>返回文件信息</returns>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.UploadNonDoctorFile(System.String)">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.GetTrialDoctorOfficialResume(IRaCIS.Core.API.Controllers.GetDoctorPathCommand,IRaCIS.Application.Interfaces.IDoctorService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Attachment})">
|
||||
<summary>
|
||||
上传文件( 不是医生个人的文件)[FileUpload]
|
||||
例如:阅片章程等
|
||||
New 项目入组 勾选获取简历路径
|
||||
</summary>
|
||||
<param name="type">文件类型</param>
|
||||
<param name="command"></param>
|
||||
<param name="_doctorService"></param>
|
||||
<param name="_attachmentrepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.GetDoctorAttachment(IRaCIS.Core.API.Controllers.GetDoctoreAttachPathCommand,IRaCIS.Application.Interfaces.IDoctorService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Attachment})">
|
||||
<summary>
|
||||
new 医生详情 勾选或者下载文件路径
|
||||
</summary>
|
||||
<param name="command"></param>
|
||||
<param name="_doctorService"></param>
|
||||
<param name="_attachmentrepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachment(System.Guid[])">
|
||||
@@ -366,14 +326,6 @@
|
||||
<param name="doctorIds"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadOfficialResume(System.Int32,System.Guid[])">
|
||||
<summary>
|
||||
下载医生官方简历
|
||||
</summary>
|
||||
<param name="language"></param>
|
||||
<param name="doctorIds"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachmentById(System.Guid,System.Guid[])">
|
||||
<summary>
|
||||
下载指定医生的指定附件
|
||||
@@ -382,50 +334,35 @@
|
||||
<param name="attachmentIds">要下载的附件Id</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.LocalFilePreview(System.String)">
|
||||
<summary> 缩略图 </summary>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadOfficialResume(System.Int32,System.Guid[])">
|
||||
<summary>
|
||||
下载医生官方简历 首页 区分 中文和英文
|
||||
</summary>
|
||||
<param name="language"></param>
|
||||
<param name="doctorIds"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadResume(System.Int32,System.Guid,System.Guid[])">
|
||||
<summary>
|
||||
入组 项目下载简历
|
||||
</summary>
|
||||
<param name="language"></param>
|
||||
<param name="trialId"></param>
|
||||
<param name="doctorIdArray"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadCommonFile(System.String,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.CommonDocument})">
|
||||
<summary> 通用文件下载 </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadTrialClinicalFile(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet})">
|
||||
<summary>
|
||||
下载项目临床数据文件
|
||||
</summary>
|
||||
<param name="clinicalDataTrialSetId"></param>
|
||||
<param name="_clinicalDataTrialSetRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.DownloadSystemClinicalFile(System.Guid,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataSystemSet})">
|
||||
<summary>
|
||||
下载系统临床数据文件
|
||||
</summary>
|
||||
<param name="clinicalDataSystemSetId"></param>
|
||||
<param name="_clinicalDataSystemSetRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.UploadTrialDoc(System.Guid)">
|
||||
<summary>
|
||||
上传项目签名文档
|
||||
</summary>
|
||||
<param name="trialId"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.UploadSysTemDoc">
|
||||
<summary>
|
||||
上传系统签名文档
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.UploadCommonDoc">
|
||||
<summary>
|
||||
上传通用文档 比如一致性核查的 比如导出的excel 模板
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.UploadSystemNoticeDoc">
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.Upload(IRaCIS.Core.API.Controllers.UploadDownLoadController.UploadFileType)">
|
||||
<summary>
|
||||
上传系统通知文档
|
||||
1:数据上传 2:导出、 3:邮件附件 4:邮件Html 通过 ----new
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
@@ -434,6 +371,11 @@
|
||||
IPLimit限流 启动服务
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.API.JSONTimeZoneConverter">
|
||||
<summary>
|
||||
序列化,反序列化的时候,处理时间 时区转换
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.NullToEmptyStringResolver.CreateProperties(System.Type,Newtonsoft.Json.MemberSerialization)">
|
||||
<summary>
|
||||
创建属性
|
||||
@@ -449,6 +391,11 @@
|
||||
<param name="httpContext"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:TimeZoneAdjustmentMiddleware">
|
||||
<summary>
|
||||
废弃,没用
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
||||
<summary>
|
||||
对称可逆加密
|
||||
@@ -484,113 +431,5 @@
|
||||
<param name="withPrivate"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:gRPC.ZHiZHUN.AuthServer.protos.GrpcTokenReflection">
|
||||
<summary>Holder for reflection information generated from Protos/GrpcToken.proto</summary>
|
||||
</member>
|
||||
<member name="P:gRPC.ZHiZHUN.AuthServer.protos.GrpcTokenReflection.Descriptor">
|
||||
<summary>File descriptor for Protos/GrpcToken.proto</summary>
|
||||
</member>
|
||||
<member name="T:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest">
|
||||
<summary>
|
||||
新增用户时需要传递数据消息, 可理解为一个类
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.IdFieldNumber">
|
||||
<summary>Field number for the "id" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.UserNameFieldNumber">
|
||||
<summary>Field number for the "userName" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.RealNameFieldNumber">
|
||||
<summary>Field number for the "realName" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.ReviewerCodeFieldNumber">
|
||||
<summary>Field number for the "reviewerCode" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.UserTypeEnumIntFieldNumber">
|
||||
<summary>Field number for the "userTypeEnumInt" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.UserTypeShortNameFieldNumber">
|
||||
<summary>Field number for the "userTypeShortName" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest.IsAdminFieldNumber">
|
||||
<summary>Field number for the "isAdmin" field.</summary>
|
||||
</member>
|
||||
<member name="T:gRPC.ZHiZHUN.AuthServer.protos.GetTokenResponse">
|
||||
<summary>
|
||||
新增时返回的消息格式
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenResponse.CodeFieldNumber">
|
||||
<summary>Field number for the "code" field.</summary>
|
||||
</member>
|
||||
<member name="F:gRPC.ZHiZHUN.AuthServer.protos.GetTokenResponse.TokenFieldNumber">
|
||||
<summary>Field number for the "token" field.</summary>
|
||||
</member>
|
||||
<member name="T:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService">
|
||||
<summary>
|
||||
service 用标识定义服务的,里面写对应的方法
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.Descriptor">
|
||||
<summary>Service descriptor</summary>
|
||||
</member>
|
||||
<member name="T:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient">
|
||||
<summary>Client for TokenGrpcService</summary>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.#ctor(Grpc.Core.ChannelBase)">
|
||||
<summary>Creates a new client for TokenGrpcService</summary>
|
||||
<param name="channel">The channel to use to make remote calls.</param>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.#ctor(Grpc.Core.CallInvoker)">
|
||||
<summary>Creates a new client for TokenGrpcService that uses a custom <c>CallInvoker</c>.</summary>
|
||||
<param name="callInvoker">The callInvoker to use to make remote calls.</param>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.#ctor">
|
||||
<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.#ctor(Grpc.Core.ClientBase.ClientBaseConfiguration)">
|
||||
<summary>Protected constructor to allow creation of configured clients.</summary>
|
||||
<param name="configuration">The client configuration.</param>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.GetUserToken(gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest,Grpc.Core.Metadata,System.Nullable{System.DateTime},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
获取token
|
||||
</summary>
|
||||
<param name="request">The request to send to the server.</param>
|
||||
<param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
|
||||
<param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
|
||||
<param name="cancellationToken">An optional token for canceling the call.</param>
|
||||
<returns>The response received from the server.</returns>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.GetUserToken(gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest,Grpc.Core.CallOptions)">
|
||||
<summary>
|
||||
获取token
|
||||
</summary>
|
||||
<param name="request">The request to send to the server.</param>
|
||||
<param name="options">The options for the call.</param>
|
||||
<returns>The response received from the server.</returns>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.GetUserTokenAsync(gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest,Grpc.Core.Metadata,System.Nullable{System.DateTime},System.Threading.CancellationToken)">
|
||||
<summary>
|
||||
获取token
|
||||
</summary>
|
||||
<param name="request">The request to send to the server.</param>
|
||||
<param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
|
||||
<param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
|
||||
<param name="cancellationToken">An optional token for canceling the call.</param>
|
||||
<returns>The call object.</returns>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.GetUserTokenAsync(gRPC.ZHiZHUN.AuthServer.protos.GetTokenReuqest,Grpc.Core.CallOptions)">
|
||||
<summary>
|
||||
获取token
|
||||
</summary>
|
||||
<param name="request">The request to send to the server.</param>
|
||||
<param name="options">The options for the call.</param>
|
||||
<returns>The call object.</returns>
|
||||
</member>
|
||||
<member name="M:gRPC.ZHiZHUN.AuthServer.protos.TokenGrpcService.TokenGrpcServiceClient.NewInstance(Grpc.Core.ClientBase.ClientBaseConfiguration)">
|
||||
<summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// 废弃,没用
|
||||
/// </summary>
|
||||
public class TimeZoneAdjustmentMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public TimeZoneAdjustmentMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
if (string.IsNullOrEmpty(context.Request.ContentType))
|
||||
{
|
||||
// 请求没有内容体,可能是一个没有请求体的请求,比如 GET 请求
|
||||
await _next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var timeZoneId = "Asia/Shanghai"; // 客户端默认时区
|
||||
|
||||
var timeZoneIdHeaderValue = context.Request.Headers["TimeZoneId"];
|
||||
|
||||
if (!string.IsNullOrEmpty(timeZoneIdHeaderValue))
|
||||
{
|
||||
timeZoneId = timeZoneIdHeaderValue;
|
||||
}
|
||||
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||
|
||||
|
||||
|
||||
// 处理 JSON 请求体中的时间字段
|
||||
if (context.Request.ContentType.StartsWith("application/json"))
|
||||
{
|
||||
var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
|
||||
|
||||
// 使用 JSON.NET 或 System.Text.Json 解析 JSON 请求体
|
||||
// 假设请求体中有一个名为 "dateTime" 的时间字段
|
||||
dynamic jsonData = JsonConvert.DeserializeObject(requestBody);
|
||||
|
||||
if (jsonData.dateTime != null)
|
||||
{
|
||||
if (DateTime.TryParse((string)jsonData.dateTime, out DateTime dateTime))
|
||||
{
|
||||
// 将 JSON 请求体中的时间字段转换为服务器时区的时间
|
||||
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||
jsonData.dateTime = serverTime;
|
||||
}
|
||||
}
|
||||
|
||||
// 将修改后的 JSON 请求体重新写入请求流中
|
||||
var jsonBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonData));
|
||||
context.Request.Body = new MemoryStream(jsonBytes);
|
||||
context.Request.ContentLength = jsonBytes.Length;
|
||||
}
|
||||
|
||||
|
||||
// 处理 URL 表单参数
|
||||
var modifiedQuery = new Dictionary<string, StringValues>();
|
||||
|
||||
foreach (var key in context.Request.Query.Keys)
|
||||
{
|
||||
if (DateTime.TryParse(context.Request.Query[key], out DateTime dateTime))
|
||||
{
|
||||
// 将 URL 表单参数中的时间转换为服务器时区的时间
|
||||
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||
modifiedQuery[key] = new StringValues(serverTime.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedQuery[key] = context.Request.Query[key];
|
||||
}
|
||||
}
|
||||
|
||||
context.Request.Query = new QueryCollection(modifiedQuery);
|
||||
|
||||
// 处理Form请求体中的参数
|
||||
if (context.Request.HasFormContentType)
|
||||
{
|
||||
var modifiedForm = new Dictionary<string, StringValues>();
|
||||
|
||||
foreach (var key in context.Request.Form.Keys)
|
||||
{
|
||||
if (DateTime.TryParse(context.Request.Form[key], out DateTime dateTime))
|
||||
{
|
||||
// 将请求体中的时间转换为服务器时区的时间
|
||||
var serverTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);
|
||||
modifiedForm[key] = new StringValues(serverTime.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiedForm[key] = context.Request.Form[key];
|
||||
}
|
||||
}
|
||||
|
||||
var newFormCollection = new FormCollection(modifiedForm);
|
||||
|
||||
// 将新的表单集合设置回请求对象
|
||||
context.Request.Form = newFormCollection;
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
autoReload="true"
|
||||
throwExceptions="false"
|
||||
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
|
||||
<variable name="myvar" value="myvalue"/>
|
||||
|
||||
<targets>
|
||||
|
||||
<target xsi:type="file" name="File" fileName="${basedir}/logs/${shortdate}/${level}.log"
|
||||
layout="${longdate}||${level}||${logger}||${message}||${exception:format=ToString:innerFormat=ToString:maxInnerExceptionLevel=10:separator=\r\n}||end" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="*" minlevel="Debug" writeTo="file" />
|
||||
</rules>
|
||||
</nlog>
|
||||
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using MassTransit;
|
||||
using MassTransit.NewIdProviders;
|
||||
using System.IO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public readonly string environment;
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enviromentName))
|
||||
{
|
||||
|
||||
var index = Array.IndexOf(args, "--env");
|
||||
enviromentName = index > -1
|
||||
? args[index + 1]
|
||||
: "Development";
|
||||
}
|
||||
|
||||
//Dicom 浏览
|
||||
//ImageManager.SetImplementation(WinFormsImageManager.Instance);
|
||||
|
||||
var host = CreateHostBuilder(args)
|
||||
.UseEnvironment(enviromentName) //命令行传入环境
|
||||
.ConfigureAppConfiguration((hostContext, config) =>
|
||||
{
|
||||
|
||||
//Console.WriteLine(hostContext.HostingEnvironment.EnvironmentName);
|
||||
config.AddJsonFile("appsettings.json", false, true)
|
||||
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
||||
})
|
||||
.Build();
|
||||
|
||||
|
||||
//// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, host.Services);
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
|
||||
|
||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
|
||||
//缓存项目的状态 匿名化数据
|
||||
await InitCache(host);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
host.Run();
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.UseWindowsService()
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.ConfigureKestrel((context, options) =>
|
||||
{
|
||||
//设置应用服务器Kestrel请求体最大为1GB // if don't set default value is: 30 MB
|
||||
options.Limits.MaxRequestBodySize = long.MaxValue;
|
||||
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(30);
|
||||
options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);
|
||||
|
||||
});
|
||||
//webBuilder.UseSerilog();//在宿主机启动的时候配置serilog,与微软ILogger进行整合
|
||||
webBuilder.UseStartup<Startup>();
|
||||
}).UseSerilog()
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
|
||||
|
||||
|
||||
private static async Task InitCache(IHost host)
|
||||
{
|
||||
var _repository = host.Services.GetService(typeof(IRepository)) as IRepository;
|
||||
|
||||
//初始化 国际化数据,并且监测国际化文件变更
|
||||
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_repository);
|
||||
|
||||
var _mediator = host.Services.GetService(typeof(IMediator)) as IMediator;
|
||||
|
||||
await _mediator.Send(new AnonymizeCacheRequest());
|
||||
|
||||
await _mediator.Send(new TrialStateCacheRequest());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
using System;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using MassTransit;
|
||||
using MassTransit.NewIdProviders;
|
||||
using System.IO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using IRaCIS.Core.API;
|
||||
using Autofac;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using LogDashboard;
|
||||
using FellowOakDicom.Network;
|
||||
using IRaCIS.Core.Application.Service.ImageAndDoc;
|
||||
using IP2Region.Net.Abstractions;
|
||||
using IP2Region.Net.XDB;
|
||||
|
||||
|
||||
#region 获取环境变量
|
||||
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enviromentName))
|
||||
{
|
||||
|
||||
var index = Array.IndexOf(args, "--env");
|
||||
enviromentName = index > -1
|
||||
? args[index + 1]
|
||||
: "Development";
|
||||
}
|
||||
#endregion
|
||||
|
||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||
{
|
||||
EnvironmentName = enviromentName
|
||||
});
|
||||
|
||||
#region 兼容windows 服务命令行的方式
|
||||
|
||||
//foreach (var arg in args)
|
||||
//{
|
||||
// Console.WriteLine(arg);
|
||||
//}
|
||||
|
||||
int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--urls"));
|
||||
|
||||
if (urlsIndex > -1)
|
||||
{
|
||||
var url = args[urlsIndex].Substring("--urls=".Length);
|
||||
Console.WriteLine(url);
|
||||
builder.WebHost.UseUrls(url);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 主机配置
|
||||
|
||||
|
||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
builder.Configuration.AddJsonFile("appsettings.json", false, true)
|
||||
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
||||
|
||||
builder.Host
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||
})
|
||||
.UseWindowsService().UseSerilog();
|
||||
#endregion
|
||||
|
||||
|
||||
#region 配置服务
|
||||
var _configuration = builder.Configuration;
|
||||
|
||||
//健康检查
|
||||
builder.Services.AddHealthChecks();
|
||||
//本地化
|
||||
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
//options.Filters.Add<LogActionFilter>();
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
{
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
}
|
||||
|
||||
})
|
||||
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
|
||||
|
||||
builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.GetSection("SystemEmailSendConfig"));
|
||||
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||
|
||||
|
||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
builder.Services.AddDynamicWebApiSetup();
|
||||
//AutoMapper
|
||||
builder.Services.AddAutoMapperSetup();
|
||||
//EF ORM QueryWithNoLock
|
||||
builder.Services.AddEFSetup(_configuration);
|
||||
//Http 响应压缩
|
||||
builder.Services.AddResponseCompressionSetup();
|
||||
//Swagger Api 文档
|
||||
builder.Services.AddSwaggerSetup();
|
||||
//JWT Token 验证
|
||||
builder.Services.AddJWTAuthSetup(_configuration);
|
||||
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||
// EasyCaching 缓存
|
||||
builder.Services.AddEasyCachingSetup(_configuration);
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
builder.Services.AddhangfireSetup(_configuration);
|
||||
|
||||
|
||||
//Serilog 日志可视化 LogDashboard日志
|
||||
builder.Services.AddLogDashboardSetup();
|
||||
|
||||
|
||||
builder.Services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
//Dicom影像渲染图片 跨平台
|
||||
builder.Services.AddDicomSetup();
|
||||
|
||||
// 实时应用
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||
|
||||
|
||||
builder.Services.AddSingleton<ISearcher>(new Searcher(CachePolicy.Content, Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources, "ip2region.xdb")));
|
||||
|
||||
|
||||
#region 历史废弃配置
|
||||
//builder.Services.AddMemoryCache();
|
||||
////上传限制 配置
|
||||
//builder.Services.Configure<FormOptions>(options =>
|
||||
//{
|
||||
// options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
// options.ValueCountLimit = int.MaxValue;
|
||||
// options.ValueLengthLimit = int.MaxValue;
|
||||
//});
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
var app = builder.Build();
|
||||
var env = app.Environment;
|
||||
|
||||
#region 配置中间件
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
//本地化
|
||||
app.UseLocalization();
|
||||
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
//响应压缩
|
||||
app.UseResponseCompression();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
|
||||
|
||||
////限流 中间件
|
||||
//app.UseIpRateLimiting();
|
||||
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
//app.UseHsts();
|
||||
}
|
||||
|
||||
// 特殊异常处理 比如 404
|
||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||
|
||||
SwaggerSetup.Configure(app, env);
|
||||
|
||||
|
||||
////serilog 记录请求的用户信息
|
||||
app.UseSerilogConfig(env);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.MapHub<UploadHub>("/UploadHub");
|
||||
app.MapHealthChecks("/health");
|
||||
|
||||
|
||||
// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, app.Services);
|
||||
|
||||
|
||||
var hangfireJobService = app.Services.GetRequiredService<IIRaCISHangfireJob>();
|
||||
|
||||
await hangfireJobService.InitHangfireJobTaskAsync();
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
try
|
||||
{
|
||||
#region 运行环境 部署平台
|
||||
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:windows");
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:linux");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Log.Logger.Warning($"ContentRootPath:{env.ContentRootPath}");
|
||||
|
||||
|
||||
string parentDirectory = Path.GetFullPath(Path.Combine(env.ContentRootPath, ".."));
|
||||
|
||||
|
||||
Log.Logger.Warning($"ContentRootPath——parentDirectory:{parentDirectory}");
|
||||
|
||||
//Log.Logger.Warning($"ContentRootPath——GetParent:{Directory.GetParent(env.ContentRootPath).Parent.FullName}");
|
||||
//Log.Logger.Warning($"ContentRootPath——xx:{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
|
||||
|
||||
|
||||
|
||||
|
||||
var server = DicomServerFactory.Create<CStoreSCPService>(11112,userState: app.Services);
|
||||
|
||||
app.Run();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,54 +13,55 @@
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC"
|
||||
}
|
||||
},
|
||||
"IRaCIS.Development": {
|
||||
"IRaCIS.Test_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Event_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6101"
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true
|
||||
},
|
||||
"IRaCIS.Staging": {
|
||||
"IRaCIS.Uat_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Staging"
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6200"
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Production": {
|
||||
"IRaCIS.Prod_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Production"
|
||||
"ASPNETCORE_ENVIRONMENT": "Prod_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6300"
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.CertificateApply": {
|
||||
"IRaCIS.US_IRC": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "CertificateApply"
|
||||
"ASPNETCORE_ENVIRONMENT": "US_IRC"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6400"
|
||||
},
|
||||
"IRaCIS.CenterImageDev": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "CenterImageDev"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6500"
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
// 使用的是proto3版本
|
||||
// 使用的是proto3版本
|
||||
syntax = "proto3";
|
||||
// 定义命名空间,后续生成代码时就会生成对应的命名空间
|
||||
// 定义命名空间,后续生成代码时就会生成对应的命名空间
|
||||
option csharp_namespace = "gRPC.ZHiZHUN.AuthServer.protos";
|
||||
|
||||
/*
|
||||
每一句需要用分号结尾
|
||||
message 用来定义请求和返回数据格式
|
||||
tag message后面的值数字代表是字段的标识(tag),不是赋值,
|
||||
每一句需要用分号结尾
|
||||
message 用来定义请求和返回数据格式
|
||||
tag message后面的值数字代表是字段的标识(tag),不是赋值,
|
||||
*/
|
||||
|
||||
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
message GetTokenReuqest{
|
||||
string id=1;
|
||||
string userName=2;
|
||||
@@ -22,48 +22,48 @@ message GetTokenReuqest{
|
||||
|
||||
}
|
||||
|
||||
// 新增时返回的消息格式
|
||||
// 新增时返回的消息格式
|
||||
message GetTokenResponse {
|
||||
int32 code=1;
|
||||
string token =2;
|
||||
}
|
||||
|
||||
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
service TokenGrpcService{
|
||||
// 获取token
|
||||
// 获取token
|
||||
rpc GetUserToken(GetTokenReuqest) returns (GetTokenResponse);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
// 新增用户时需要传递数据消息, 可理解为一个类
|
||||
message AddUserReuqest{
|
||||
string name=1;
|
||||
int32 age=2;
|
||||
bool isBoy=3;
|
||||
}
|
||||
// 新增时返回的消息格式
|
||||
// 新增时返回的消息格式
|
||||
message ResultResponse {
|
||||
int32 code=1;
|
||||
string msg =2;
|
||||
}
|
||||
//传递的查询条件信息格式,可理解为平时传入的查询条件对象
|
||||
//传递的查询条件信息格式,可理解为平时传入的查询条件对象
|
||||
message QueryUserReuqest{
|
||||
string name=1;
|
||||
}
|
||||
//查询返回的用户信息格式,可理解为返回的类
|
||||
//查询返回的用户信息格式,可理解为返回的类
|
||||
message UserInfoResponse {
|
||||
string name=1;
|
||||
int32 age=2;
|
||||
string gender=3;
|
||||
}
|
||||
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
// service 用标识定义服务的,里面写对应的方法
|
||||
service UserService{
|
||||
// 新增用户
|
||||
// 新增用户
|
||||
rpc AddUser(AddUserReuqest) returns (ResultResponse);
|
||||
// 查询用户
|
||||
// 查询用户
|
||||
rpc GetAllUser(QueryUserReuqest) returns (UserInfoResponse);
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
using Autofac;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using LogDashboard;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using AspNetCoreRateLimit;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Localization;
|
||||
using Magicodes.ExporterAndImporter.Core.Filters;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using Invio.Extensions.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
public ILogger<Startup> _logger { get; }
|
||||
|
||||
public IConfiguration _configuration { get; }
|
||||
|
||||
//// ConfigureContainer is where you can register things directly
|
||||
//// with Autofac. This runs after ConfigureServices so the things
|
||||
//// here will override registrations made in ConfigureServices.
|
||||
//// Don't build the container; that gets done for you by the factory.
|
||||
// for castle
|
||||
public void ConfigureContainer(ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||
|
||||
#region Test
|
||||
//containerBuilder.RegisterType<ClinicalDataService>().PropertiesAutowired().InstancePerLifetimeScope();//注册仓储
|
||||
|
||||
//var container = containerBuilder.Build();
|
||||
|
||||
//// Now you can resolve services using Autofac. For example,
|
||||
//// this line will execute the lambda expression registered
|
||||
//// to the IConfigReader service.
|
||||
//using (var scope = container.BeginLifetimeScope())
|
||||
//{
|
||||
// var reader = scope.Resolve<BaseService>();
|
||||
|
||||
// var test = scope.Resolve<ClinicalDataService>();
|
||||
// var test2 = scope.Resolve<IClinicalDataService>();
|
||||
|
||||
// var test3 = scope.Resolve<IEFUnitOfWork<IRaCISDBContext>>();
|
||||
//}
|
||||
#endregion
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
//本地化
|
||||
services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
services.AddControllers(options =>
|
||||
{
|
||||
//options.Filters.Add<LogActionFilter>();
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
{
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
|
||||
|
||||
services.AddOptions().Configure<SystemEmailSendConfig>( _configuration.GetSection("SystemEmailSendConfig"));
|
||||
services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
|
||||
|
||||
|
||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
services.AddDynamicWebApiSetup();
|
||||
//AutoMapper
|
||||
services.AddAutoMapperSetup();
|
||||
//EF ORM QueryWithNoLock
|
||||
services.AddEFSetup(_configuration);
|
||||
//Http 响应压缩
|
||||
services.AddResponseCompressionSetup();
|
||||
//Swagger Api 文档
|
||||
services.AddSwaggerSetup();
|
||||
//JWT Token 验证
|
||||
services.AddJWTAuthSetup(_configuration);
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
|
||||
// EasyCaching 缓存
|
||||
services.AddEasyCachingSetup();
|
||||
|
||||
//services.AddDistributedMemoryCache();
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
//services.AddhangfireSetup(_configuration);
|
||||
// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
|
||||
services.AddQuartZSetup(_configuration);
|
||||
|
||||
// 保护上传文件
|
||||
//services.AddStaticFileAuthorizationSetup();
|
||||
|
||||
|
||||
////HttpReports 暂时废弃
|
||||
//services.AddHttpReports().AddHttpTransport();
|
||||
//Serilog 日志可视化 LogDashboard日志
|
||||
services.AddLogDashboardSetup();
|
||||
//上传限制 配置
|
||||
services.Configure<FormOptions>(options =>
|
||||
{
|
||||
options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
options.ValueCountLimit = int.MaxValue;
|
||||
options.ValueLengthLimit = int.MaxValue;
|
||||
});
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
|
||||
services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
//Dicom影像渲染图片 跨平台
|
||||
services.AddDicomSetup();
|
||||
|
||||
// 实时应用
|
||||
services.AddSignalR();
|
||||
|
||||
|
||||
services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||
|
||||
//services.AddSingleton<IImportResultFilter, ImportResultFilteTest>();
|
||||
|
||||
services.AddMemoryCache();
|
||||
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
//本地化
|
||||
app.UseLocalization();
|
||||
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
//响应压缩
|
||||
app.UseResponseCompression();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
|
||||
//hangfire
|
||||
//app.UseHangfireConfig(env);
|
||||
|
||||
////暂时废弃
|
||||
//app.UseHttpReports();
|
||||
|
||||
////限流 中间件
|
||||
//app.UseIpRateLimiting();
|
||||
|
||||
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
//app.UseHsts();
|
||||
}
|
||||
Console.WriteLine("当前环境: " + env.EnvironmentName);
|
||||
|
||||
//app.UseMiddleware<AuthMiddleware>();
|
||||
|
||||
// 特殊异常处理 比如 404
|
||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||
|
||||
SwaggerSetup.Configure(app, env);
|
||||
|
||||
|
||||
|
||||
////serilog 记录请求的用户信息
|
||||
app.UseSerilogConfig(env);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(env);
|
||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
//app.UseJwtBearerQueryString();
|
||||
app.UseAuthorization();
|
||||
|
||||
////文件伺服 必须带Token 访问
|
||||
////app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
|
||||
endpoints.MapHub<UploadHub>("/UploadHub");
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
||||
|
||||
public static class HangfireConfig
|
||||
{
|
||||
|
||||
public static void UseHangfireConfig(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
app.UseHangfireDashboard("/api/hangfire", new DashboardOptions()
|
||||
{
|
||||
//直接访问,没有带token 获取不到用户身份信息,所以这种自定义授权暂时没法使用
|
||||
//Authorization = new[] { new hangfireAuthorizationFilter() }
|
||||
|
||||
//本地请求 才能看
|
||||
Authorization = new[] { new LocalRequestsOnlyAuthorizationFilter() }
|
||||
|
||||
});
|
||||
|
||||
#region hangfire
|
||||
//// 延迟任务执行 1秒之后执行 有时启动没运行 换成添加到队列中
|
||||
//BackgroundJob.Schedule<ICacheTrialStatusJob>(t => t.MemoryCacheTrialStatus(), TimeSpan.FromSeconds(1));
|
||||
////添加到后台任务队列,
|
||||
//BackgroundJob.Enqueue<ICacheTrialStatusJob>(t => t.MemoryCacheTrialStatus());
|
||||
|
||||
//周期性任务,1天执行一次
|
||||
|
||||
RecurringJob.AddOrUpdate<IIRaCISCacheHangfireJob>(t => t.ProjectStartCache(), Cron.Daily);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using Hangfire.Dashboard.BasicAuthorization;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using IRaCIS.Core.API.Filter;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
||||
|
||||
public static class HangfireConfig
|
||||
{
|
||||
|
||||
public static void UseHangfireConfig(this IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
|
||||
|
||||
app.UseHangfireDashboard("/back/hangfire", new DashboardOptions()
|
||||
{
|
||||
|
||||
|
||||
|
||||
Authorization = new IDashboardAuthorizationFilter[] { /*new hangfireAuthorizationFilter(),*/
|
||||
|
||||
new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions(){
|
||||
SslRedirect=false,
|
||||
RequireSsl=false,
|
||||
Users=new BasicAuthAuthorizationUser[]{
|
||||
new BasicAuthAuthorizationUser(){
|
||||
Login="admin",
|
||||
PasswordClear="admin",
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
DashboardTitle ="后台任务管理",
|
||||
|
||||
|
||||
//Authorization = new BasicAuthAuthorizationFilter[] {
|
||||
// new BasicAuthAuthorizationFilter(new BasicAuthAuthorizationFilterOptions(){
|
||||
// SslRedirect=false,
|
||||
// RequireSsl=false,
|
||||
// Users=new BasicAuthAuthorizationUser[]{
|
||||
// new BasicAuthAuthorizationUser(){
|
||||
// Login="admin",
|
||||
// PasswordClear="test",
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// })
|
||||
//}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -1,8 +1,11 @@
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Azure;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders.Physical;
|
||||
@@ -11,6 +14,7 @@ using Microsoft.Extensions.Hosting.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.VisualBasic;
|
||||
using Newtonsoft.Json;
|
||||
using SharpCompress.Common;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -47,7 +51,7 @@ namespace IRaCIS.Core.API
|
||||
var path = context.Request.Path.Value;
|
||||
var isIRacisFile = path.StartsWith($"/{StaticData.Folder.IRaCISDataFolder}");
|
||||
|
||||
var isDicomFile = path.Contains($"{StaticData.Folder.DicomFolder}");
|
||||
var isDicomFile = isIRacisFile && path.Contains($"{StaticData.Folder.DicomFolder}");
|
||||
|
||||
|
||||
|
||||
@@ -147,6 +151,12 @@ namespace IRaCIS.Core.API
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到文件,返回404
|
||||
context.Response.StatusCode = 404;
|
||||
context.Response.ContentType = "application/json";
|
||||
|
||||
await context.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("File not found")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace IRaCIS.Core.API
|
||||
app.UseSerilogRequestLogging(opts
|
||||
=>
|
||||
{
|
||||
opts.MessageTemplate = "{TokenUserRealName} {TokenUserType} {ClientIp} {RequestIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||
opts.MessageTemplate = "{TokenUserRealName} {TokenUserTypeShortName} {ClientIp} {LocalIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||
opts.EnrichDiagnosticContext = SerilogHelper.EnrichFromRequest;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Serilog;
|
||||
using System;
|
||||
@@ -20,7 +21,7 @@ namespace IRaCIS.Core.API
|
||||
diagnosticContext.Set("Host", request.Host);
|
||||
|
||||
//这种获取的Ip不准 配置服务才行
|
||||
diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
|
||||
//diagnosticContext.Set("RequestIP", httpContext.Connection.RemoteIpAddress.ToString());
|
||||
|
||||
//这种方式可以,但是serilog提供了 就不用了
|
||||
//diagnosticContext.Set("TestIP", httpContext.GetUserIp());
|
||||
@@ -41,9 +42,9 @@ namespace IRaCIS.Core.API
|
||||
// Set the content-type of the Response at this point
|
||||
diagnosticContext.Set("ContentType", httpContext.Response.ContentType);
|
||||
|
||||
diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst("realName")?.Value);
|
||||
diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.RealName)?.Value);
|
||||
|
||||
diagnosticContext.Set("TokenUserType", httpContext?.User?.FindFirst("userTypeEnumName")?.Value);
|
||||
diagnosticContext.Set("TokenUserTypeShortName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value);
|
||||
|
||||
// Retrieve the IEndpointFeature selected for the request
|
||||
var endpoint = httpContext.GetEndpoint();
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace IRaCIS.Core.API
|
||||
public IStringLocalizer _localizer;
|
||||
public ApiResponseHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
IStringLocalizer localizer,
|
||||
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder)
|
||||
{
|
||||
_localizer = localizer;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Autofac;
|
||||
using Autofac.Extras.DynamicProxy;
|
||||
using IRaCIS.Core.Application;
|
||||
using IRaCIS.Core.Application.AOP;
|
||||
using IRaCIS.Core.Application.BackGroundJob;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -31,10 +30,6 @@ namespace IRaCIS.Core.API
|
||||
|
||||
containerBuilder.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
|
||||
|
||||
//containerBuilder.RegisterType<Mapper>().As<IMapper>().InstancePerLifetimeScope();
|
||||
|
||||
//containerBuilder.RegisterGeneric(typeof(EFUnitOfWork<>))
|
||||
// .As(typeof(IEFUnitOfWork<>)).InstancePerLifetimeScope();//注册仓储
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -50,8 +45,7 @@ namespace IRaCIS.Core.API
|
||||
#endregion
|
||||
|
||||
|
||||
//containerBuilder.RegisterType<BaseService>().As<IBaseService>().PropertiesAutowired().InstancePerLifetimeScope();
|
||||
//containerBuilder.RegisterType<DictionaryService>().As<IDictionaryService>().InstancePerLifetimeScope();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -59,22 +53,13 @@ namespace IRaCIS.Core.API
|
||||
containerBuilder.RegisterAssemblyTypes(application).Where(t => t.FullName.Contains("Service"))
|
||||
.PropertiesAutowired().AsImplementedInterfaces().EnableClassInterceptors();
|
||||
|
||||
//Assembly infrastructure = Assembly.Load("IRaCIS.Core.Infra.EFCore");
|
||||
//containerBuilder.RegisterAssemblyTypes(infrastructure).AsImplementedInterfaces();
|
||||
|
||||
|
||||
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
|
||||
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
||||
|
||||
|
||||
//containerBuilder.RegisterType<Dictionary>().InstancePerLifetimeScope();
|
||||
//Autofac 注册拦截器 需要注意的是生成api上服务上的动态代理AOP失效 间接掉用不影响
|
||||
//containerBuilder.RegisterType<TrialStatusAutofacAOP>();
|
||||
//containerBuilder.RegisterType<UserAddAOP>();
|
||||
//containerBuilder.RegisterType<QANoticeAOP>();
|
||||
//containerBuilder.RegisterType<LogService>().As<ILogService>().SingleInstance();
|
||||
|
||||
|
||||
//注册hangfire任务 依赖注入
|
||||
//注册hangfire任务 依赖注入
|
||||
containerBuilder.RegisterType<ObtainTaskAutoCancelJob>().As<IObtainTaskAutoCancelJob>().InstancePerDependency();
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using IRaCIS.Core.Application.Triggers;
|
||||
using Hangfire.SqlServer;
|
||||
using IRaCIS.Core.Application.Triggers;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using Medallion.Threading;
|
||||
using Medallion.Threading.SqlServer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -45,8 +49,11 @@ namespace IRaCIS.Core.API
|
||||
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
|
||||
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIbeforeTrigger>();
|
||||
|
||||
triggerOptions.AddTrigger<UserLogTrigger>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +62,13 @@ namespace IRaCIS.Core.API
|
||||
|
||||
});
|
||||
|
||||
//注意区分 easy caching 也有 IDistributedLockProvider
|
||||
services.AddSingleton<IDistributedLockProvider>(sp =>
|
||||
{
|
||||
//var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
|
||||
|
||||
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
|
||||
});
|
||||
|
||||
//services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
using EasyCaching.Core;
|
||||
using EasyCaching.Core.Configurations;
|
||||
using EasyCaching.Interceptor.Castle;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class EasyCachingSetup
|
||||
public static class EasyCachingSetup
|
||||
{
|
||||
public static void AddEasyCachingSetup(this IServiceCollection services)
|
||||
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddEasyCaching(options =>
|
||||
{
|
||||
options.UseInMemory();
|
||||
|
||||
//options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
|
||||
|
||||
|
||||
});
|
||||
|
||||
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
|
||||
|
||||
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
//using System;
|
||||
//using Microsoft.Extensions.DependencyInjection;
|
||||
//using StackExchange.Profiling.Storage;
|
||||
|
||||
//namespace IRaCIS.Core.API
|
||||
//{
|
||||
// public class MiniProfilerConfigure
|
||||
// {
|
||||
// public static void ConfigureMiniProfiler(IServiceCollection services)
|
||||
// {
|
||||
|
||||
// services.AddMiniProfiler(options =>
|
||||
// {
|
||||
// // All of this is optional. You can simply call .AddMiniProfiler() for all defaults
|
||||
|
||||
// // (Optional) Path to use for profiler URLs, default is /mini-profiler-resources
|
||||
// options.RouteBasePath = "/profiler";
|
||||
|
||||
// //// (Optional) Control storage
|
||||
// //// (default is 30 minutes in MemoryCacheStorage)
|
||||
// (options.Storage as MemoryCacheStorage).CacheDuration = TimeSpan.FromMinutes(10);
|
||||
|
||||
// //// (Optional) Control which SQL formatter to use, InlineFormatter is the default
|
||||
// //options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
|
||||
|
||||
// //// (Optional) To control authorization, you can use the Func<HttpRequest, bool> options:
|
||||
// //// (default is everyone can access profilers)
|
||||
// //options.ResultsAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;
|
||||
// //options.ResultsListAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;
|
||||
// //// Or, there are async versions available:
|
||||
// //options.ResultsAuthorizeAsync = async request => (await MyGetUserFunctionAsync(request)).CanSeeMiniProfiler;
|
||||
// //options.ResultsAuthorizeListAsync = async request => (await MyGetUserFunctionAsync(request)).CanSeeMiniProfilerLists;
|
||||
|
||||
// //// (Optional) To control which requests are profiled, use the Func<HttpRequest, bool> option:
|
||||
// //// (default is everything should be profiled)
|
||||
// //options.ShouldProfile = request => MyShouldThisBeProfiledFunction(request);
|
||||
|
||||
// //// (Optional) Profiles are stored under a user ID, function to get it:
|
||||
// //// (default is null, since above methods don't use it by default)
|
||||
// //options.UserIdProvider = request => MyGetUserIdFunction(request);
|
||||
|
||||
// //// (Optional) Swap out the entire profiler provider, if you want
|
||||
// //// (default handles async and works fine for almost all applications)
|
||||
// //options.ProfilerProvider = new MyProfilerProvider();
|
||||
|
||||
// //// (Optional) You can disable "Connection Open()", "Connection Close()" (and async variant) tracking.
|
||||
// //// (defaults to true, and connection opening/closing is tracked)
|
||||
// //options.TrackConnectionOpenClose = true;
|
||||
|
||||
// //// (Optional) Use something other than the "light" color scheme.
|
||||
// //// (defaults to "light")
|
||||
// //options.ColorScheme = StackExchange.Profiling.ColorScheme.Auto;
|
||||
|
||||
// //// The below are newer options, available in .NET Core 3.0 and above:
|
||||
|
||||
// //// (Optional) You can disable MVC filter profiling
|
||||
// //// (defaults to true, and filters are profiled)
|
||||
// //options.EnableMvcFilterProfiling = true;
|
||||
// //// ...or only save filters that take over a certain millisecond duration (including their children)
|
||||
// //// (defaults to null, and all filters are profiled)
|
||||
// //// options.MvcFilterMinimumSaveMs = 1.0m;
|
||||
|
||||
// //// (Optional) You can disable MVC view profiling
|
||||
// //// (defaults to true, and views are profiled)
|
||||
// //options.EnableMvcViewProfiling = true;
|
||||
// //// ...or only save views that take over a certain millisecond duration (including their children)
|
||||
// //// (defaults to null, and all views are profiled)
|
||||
// //// options.MvcViewMinimumSaveMs = 1.0m;
|
||||
|
||||
// //// (Optional) listen to any errors that occur within MiniProfiler itself
|
||||
// //// options.OnInternalError = e => MyExceptionLogger(e);
|
||||
|
||||
// //// (Optional - not recommended) You can enable a heavy debug mode with stacks and tooltips when using memory storage
|
||||
// //// It has a lot of overhead vs. normal profiling and should only be used with that in mind
|
||||
// //// (defaults to false, debug/heavy mode is off)
|
||||
// ////options.EnableDebugMode = true;
|
||||
// });
|
||||
// //.AddEntityFramework();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,46 +0,0 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class JSONCustomDateConverter : DateTimeConverterBase
|
||||
{
|
||||
private TimeZoneInfo _timeZoneInfo;
|
||||
private string _dateFormat;
|
||||
|
||||
private IUserInfo _userInfo;
|
||||
public JSONCustomDateConverter(string dateFormat, TimeZoneInfo timeZoneInfo, IUserInfo userInfo)
|
||||
{
|
||||
_dateFormat = dateFormat;
|
||||
_timeZoneInfo = timeZoneInfo;
|
||||
|
||||
_userInfo = userInfo;
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
var timeZoneId = _userInfo.TimeZoneId;
|
||||
|
||||
var needConvertUtcDateTime = Convert.ToDateTime(value);
|
||||
|
||||
|
||||
var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||
|
||||
|
||||
var dateTimeOffset = new DateTimeOffset(needConvertUtcDateTime);
|
||||
|
||||
var time = TimeZoneInfo.ConvertTimeFromUtc(needConvertUtcDateTime, tz).ToString(_dateFormat);
|
||||
|
||||
writer.WriteValue(time);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化,反序列化的时候,处理时间 时区转换
|
||||
/// </summary>
|
||||
public class JSONTimeZoneConverter : DateTimeConverterBase
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
private readonly TimeZoneInfo _clientTimeZone;
|
||||
public JSONTimeZoneConverter(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
||||
//默认是UTC
|
||||
//var timeZoneId = "Etc/UTC";
|
||||
var timeZoneId = "Asia/Shanghai";
|
||||
|
||||
var timeZoneIdHeader = _httpContextAccessor?.HttpContext?.Request?.Headers["TimeZoneId"];
|
||||
|
||||
if (timeZoneIdHeader is not null && !string.IsNullOrEmpty(timeZoneIdHeader.Value))
|
||||
{
|
||||
timeZoneId = timeZoneIdHeader.Value;
|
||||
}
|
||||
|
||||
_clientTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
// 仅支持 DateTime 类型的转换
|
||||
return objectType == typeof(DateTime)|| objectType == typeof(DateTime?);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.Value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
DateTime dateTime;
|
||||
|
||||
if (reader.ValueType == typeof(DateTime) || reader.ValueType == typeof(DateTime?))
|
||||
{
|
||||
DateTime? nullableDateTime = reader.Value as DateTime?;
|
||||
|
||||
|
||||
if (nullableDateTime != null && nullableDateTime.HasValue)
|
||||
{
|
||||
dateTime = nullableDateTime.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DateTime.TryParse((string)reader.Value, out dateTime) == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 将客户端时间转换为服务器时区的时间
|
||||
var serverZoneTime = TimeZoneInfo.ConvertTime(dateTime, _clientTimeZone, TimeZoneInfo.Local);
|
||||
|
||||
return serverZoneTime;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
DateTime? nullableDateTime = value as DateTime?;
|
||||
|
||||
if (nullableDateTime != null && nullableDateTime.HasValue)
|
||||
{
|
||||
//第一个参数默认使用系统本地时区 也就是应用服务器的时区
|
||||
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
|
||||
writer.WriteValue(clientZoneTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
@@ -8,8 +10,12 @@ namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class NewtonsoftJsonSetup
|
||||
{
|
||||
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder)
|
||||
public static void AddNewtonsoftJsonSetup(this IMvcBuilder builder, IServiceCollection services)
|
||||
{
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddScoped<JSONTimeZoneConverter>();
|
||||
services.AddScoped<CustomStringConverter>();
|
||||
services.AddScoped<IOSSService,OSSService>();
|
||||
|
||||
builder.AddNewtonsoftJson(options =>
|
||||
{
|
||||
@@ -23,8 +29,15 @@ namespace IRaCIS.Core.API
|
||||
// 设置时间格式
|
||||
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
|
||||
|
||||
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
|
||||
|
||||
options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<JSONTimeZoneConverter>());
|
||||
|
||||
//options.SerializerSettings.Converters.Add(services.BuildServiceProvider().GetService<CustomStringConverter>());
|
||||
|
||||
|
||||
//IsoDateTimeConverter
|
||||
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace IRaCIS.Core.API
|
||||
if(_MemberInfo.PropertyType == typeof(string))
|
||||
{
|
||||
//去掉前后空格
|
||||
_MemberInfo.SetValue(target, value==null?string.Empty: value.ToString()==string.Empty? value:value.ToString().Trim());
|
||||
_MemberInfo.SetValue(target, value==null?string.Empty: value.ToString()==string.Empty? value:value/*.ToString().Trim()*/);
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson
|
||||
{
|
||||
public class CustomStringConverter : JsonConverter<string>
|
||||
{
|
||||
//private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IOSSService _oSSService;
|
||||
|
||||
// 构造函数
|
||||
public CustomStringConverter(/*IHttpContextAccessor httpContextAccessor*/ IOSSService oSSService)
|
||||
{
|
||||
//_httpContextAccessor = httpContextAccessor;
|
||||
_oSSService = oSSService;
|
||||
}
|
||||
|
||||
public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.String)
|
||||
{
|
||||
return (string)reader.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
// 在这里对字符串进行处理,例如转换大小写、去除空格等
|
||||
// 这里只是一个示例,您可以根据实际需求进行更改
|
||||
|
||||
// 获取当前正在序列化的属性名
|
||||
string propertyName = writer.Path.Split('.').Last();
|
||||
|
||||
Regex guidRegex = new Regex(@"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (propertyName.IndexOf("Path") > -1 && value.IndexOf('.')>-1 && guidRegex.IsMatch(value))
|
||||
{
|
||||
var tt= _oSSService.GetSignedUrl(value);
|
||||
writer.WriteValue(tt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 将处理后的字符串写入到 JsonWriter 中
|
||||
writer.WriteValue(value);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Quartz;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class QuartZSetup
|
||||
{
|
||||
public static void AddQuartZSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddTransient<CacheTrialStatusQuartZJob>();
|
||||
|
||||
services.AddQuartz(q =>
|
||||
{
|
||||
// base quartz scheduler, job and trigger configuration
|
||||
|
||||
// as of 3.3.2 this also injects scoped services (like EF DbContext) without problems
|
||||
q.UseMicrosoftDependencyInjectionJobFactory();
|
||||
|
||||
// 基本Quartz调度器、作业和触发器配置
|
||||
var jobKey = new JobKey("RegularTrialWork", "regularWorkGroup");
|
||||
q.AddJob<CacheTrialStatusQuartZJob>(jobKey, j => j
|
||||
.WithDescription("Trial regular work")
|
||||
);
|
||||
q.AddTrigger(t => t
|
||||
.WithIdentity("TrialStatusTrigger")
|
||||
.ForJob(jobKey)
|
||||
|
||||
.WithCronSchedule("0 0 * * * ?")
|
||||
.WithDescription("My regular trial work trigger")
|
||||
);
|
||||
});
|
||||
|
||||
// ASP.NET Core hosting
|
||||
services.AddQuartzHostedService(options =>
|
||||
{
|
||||
// when shutting down we want jobs to complete gracefully
|
||||
options.WaitForJobsToComplete = true;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,31 +19,33 @@ namespace IRaCIS.Core.API
|
||||
// Filter out ASP.NET Core infrastructre logs that are Information and below 日志太多了 一个请求 记录好几条
|
||||
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
|
||||
.Enrich.WithClientIp()
|
||||
.Enrich.WithClientAgent()
|
||||
.Enrich.FromLogContext()
|
||||
|
||||
.Filter.ByExcluding(logEvent =>logEvent.Properties.ContainsKey("RequestPath") && logEvent.Properties["RequestPath"].ToString().Contains("/health"))
|
||||
|
||||
//控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型
|
||||
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning,
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} ] {LocalIP} {ClientIp} {TokenUserRealName} {TokenUserType} {Message:lj} {Properties:j}{NewLine} {Exception}")
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
|
||||
|
||||
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day,
|
||||
outputTemplate: "{Timestamp:HH:mm:ss} || {Level} || {SourceContext:l} || {Message} ||{Exception} ||end {NewLine}");
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}");
|
||||
|
||||
//.WriteTo.MSSqlServer("Data Source=DESKTOP-4TU9A6M;Initial Catalog=CoreFrame;User ID=sa;Password=123456", "logs", autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)//从左至右四个参数分别是数据库连接字符串、表名、如果表不存在是否创建、最低等级。Serilog会默认创建一些列。
|
||||
|
||||
if (environment == "Production")
|
||||
{
|
||||
config.WriteTo.Email(new EmailConnectionInfo()
|
||||
{
|
||||
EmailSubject = "系统警告,请速速查看!",//邮件标题
|
||||
FromEmail = "test@extimaging.com",//发件人邮箱
|
||||
MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址
|
||||
NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码
|
||||
Port = 465,//端口号
|
||||
ToEmail = "872297557@qq.com"//收件人
|
||||
}, restrictedToMinimumLevel: LogEventLevel.Error,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})");
|
||||
}
|
||||
//if (environment == "Production")
|
||||
//{
|
||||
// config.WriteTo.Email(new EmailConnectionInfo()
|
||||
// {
|
||||
// EmailSubject = "系统警告,请速速查看!",//邮件标题
|
||||
// FromEmail = "test@extimaging.com",//发件人邮箱
|
||||
// MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址
|
||||
// NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码
|
||||
// Port = 465,//端口号
|
||||
// ToEmail = "872297557@qq.com"//收件人
|
||||
// }, restrictedToMinimumLevel: LogEventLevel.Error,
|
||||
// outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})");
|
||||
//}
|
||||
|
||||
//扩展方法 获取上下文的ip 用户名 用户类型
|
||||
Log.Logger = config.Enrich.WithHttpContextInfo(serviceProvider).CreateLogger();
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class JsonPatchDocumentFilter : IDocumentFilter
|
||||
{
|
||||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
||||
{
|
||||
var schemas = swaggerDoc.Components.Schemas.ToList();
|
||||
foreach (var item in schemas)
|
||||
{
|
||||
if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
|
||||
swaggerDoc.Components.Schemas.Remove(item.Key);
|
||||
}
|
||||
|
||||
swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{ "op", new OpenApiSchema { Type = "string" } },
|
||||
{"value", new OpenApiSchema{ Type = "object", Nullable = true } },
|
||||
{ "path", new OpenApiSchema { Type = "string" } }
|
||||
}
|
||||
});
|
||||
|
||||
swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema
|
||||
{
|
||||
Type = "array",
|
||||
Items = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" }
|
||||
},
|
||||
Description = "Array of operations to perform"
|
||||
});
|
||||
|
||||
foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
|
||||
.Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
|
||||
{
|
||||
foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
|
||||
path.Value.RequestBody.Content.Remove(item.Key);
|
||||
|
||||
var response = path.Value.RequestBody.Content.SingleOrDefault(c => c.Key == "application/json-patch+json");
|
||||
|
||||
response.Value.Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ namespace IRaCIS.Core.API
|
||||
{
|
||||
public static void AddSwaggerSetup(this IServiceCollection services)
|
||||
{
|
||||
services.AddSwaggerExamplesFromAssemblyOf<JsonPatchUserRequestExample>();
|
||||
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
@@ -63,7 +62,6 @@ namespace IRaCIS.Core.API
|
||||
// 在header中添加token,传递到后台
|
||||
options.OperationFilter<SecurityRequirementsOperationFilter>();
|
||||
|
||||
options.DocumentFilter<JsonPatchDocumentFilter>();
|
||||
|
||||
// 添加登录按钮
|
||||
options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Hangfire;
|
||||
using Hangfire.SqlServer;
|
||||
using Hangfire.Tags.SqlServer;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class hangfireSetup
|
||||
public static class hangfireSetup
|
||||
{
|
||||
public static void AddhangfireSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
@@ -15,24 +14,29 @@ namespace IRaCIS.Core.API
|
||||
|
||||
services.AddHangfire(hangFireConfig =>
|
||||
{
|
||||
|
||||
//hangFireConfig.UseInMemoryStorage();
|
||||
|
||||
//指定存储介质
|
||||
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
|
||||
{
|
||||
SchemaName = "hangfire",
|
||||
SchemaName = "dbo",
|
||||
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
|
||||
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
|
||||
QueuePollInterval = TimeSpan.Zero,
|
||||
UseRecommendedIsolationLevel = true,
|
||||
UsePageLocksOnDequeue = true,
|
||||
DisableGlobalLocks = true
|
||||
});
|
||||
|
||||
hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
||||
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
||||
//.UseHangfireHttpJob();
|
||||
|
||||
});
|
||||
|
||||
services.AddHangfireServer();
|
||||
services.AddHangfireServer(option =>
|
||||
{
|
||||
option.Queues = new[] { "immediately_once", "default", "sys_init", "not_immediately_once" };
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=CenterImage_Test;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=IRaCIS_Certificate;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Hangfire_IRaCIS;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true"
|
||||
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.IRC;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Hangfire_IRaCIS;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true"
|
||||
|
||||
},
|
||||
|
||||
"AliyunOSS": {
|
||||
"endpoint": "https://zyypacs-code.oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "mpXG7Nu6zTpsDrI1",
|
||||
"accessKeySecret": "yNINcEb099SkNfF6vYKaoP8TZNI3xZ",
|
||||
"bucketName": "zyypacs-code"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes":1
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Event_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Event_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.event.extimaging.com/login"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
// "RemoteNew": "Server=47.117.165.18,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
// "Hangfire": "Server=47.117.165.18,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "IRC@extimaging.com",
|
||||
"FromName": "IRC",
|
||||
"AuthorizationCode": "ExtImg@2022",
|
||||
"SiteUrl": "http://irc.extimaging.com/login",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
//"RootUrl": "http://123.56.181.144:8060/",
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=101.132.193.237,1433;Database=IRaCIS.Production;User ID=sa;Password=zhanying2021;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=101.132.193.237,1433;Database=Hangfire.IRaCIS.Production;User ID=sa;Password=zhanying2021;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
},
|
||||
//"SystemEmailSendConfig": {
|
||||
// "Port": 465,
|
||||
// "Host": "smtp.163.com",
|
||||
// "FromEmail": "zhou941003@qq.com",
|
||||
// "FromName": "hangZhou",
|
||||
// "AuthorizationCode": "sqfhlpfdvnexbcab"
|
||||
//}
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "IRC@extimaging.com",
|
||||
"FromName": "IRC",
|
||||
"AuthorizationCode": "ExtImg@2022"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=IRaCIS_Verify;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Hangfire_IRaCIS;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
"endPoint": "192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test",
|
||||
"viewEndpoint": "http://192.168.3.68:8001/test/"
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||
"bucketName": "ei-irc-test-store",
|
||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 1,
|
||||
|
||||
"AutoLoginOutMinutes": 1,
|
||||
|
||||
"OpenLoginMFA": false
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
|
||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
||||
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.90.161.85,1433\\MSSQLSERVER;Database=IRaCIS_Demo_US;User ID=sa;Password=zhanying2021;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.90.161.85,1433\\MSSQLSERVER;Database=Hangfire.IRaCIS_Demo_US;User ID=sa;Password=zhanying2021;TrustServerCertificate=true"
|
||||
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=us-mssql-service,1433;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=us-mssql-service,1433;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
|
||||
//"RemoteNew": "Server=44.218.11.19,1435;Database=Prod_US_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
//"Hangfire": "Server=44.218.11.19,1435;Database=Prod_US_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AWS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"endPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-test-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
"endPoint": "192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test",
|
||||
"viewEndpoint": "http://192.168.3.68:8001/test/"
|
||||
},
|
||||
|
||||
"AWS": {
|
||||
"endPoint": "s3.us-east-1.amazonaws.com",
|
||||
"useSSL": true,
|
||||
"accessKey": "AKIAZQ3DRSOHFPJJ6FEU",
|
||||
"secretKey": "l+yjtvV7Z4jiwm/7xCYv30UeUj/SvuqqYzAwjJHf",
|
||||
"bucketName": "ei-irc-test-store",
|
||||
"viewEndpoint": "https://ei-irc-test-store.s3.amazonaws.com/"
|
||||
}
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "test@extimaging.com",
|
||||
"FromName": "Test_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"CompanyName": "Elevate Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Elevate Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Uat_IRC.Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"ObjectStoreService": {
|
||||
|
||||
"ObjectStoreUse": "AliyunOSS",
|
||||
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-irc-uat-store",
|
||||
"roleArn": "acs:ram::1899121822495495:role/oss-upload",
|
||||
"viewEndpoint": "https://zy-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||
"region": "oss-cn-shanghai"
|
||||
},
|
||||
|
||||
"MinIO": {
|
||||
"endpoint": "http://192.168.3.68",
|
||||
"port": "8001",
|
||||
"useSSL": false,
|
||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
||||
"bucketName": "test"
|
||||
}
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30,
|
||||
"AutoLoginOutMinutes": 60
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021",
|
||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||
"CompanyName": "Extensive Imaging",
|
||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||
"CompanyShortName": "Extensive Imaging",
|
||||
"CompanyShortNameCN": "展影医疗"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"JwtSetting": {
|
||||
"SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f",
|
||||
"Issuer": "IRaCIS",
|
||||
"Audience": "ZhiZhun",
|
||||
"SecurityKey": "ShangHaiZhanYing_SecurityKey_SHzyyl@2021",
|
||||
"Issuer": "Extimaging",
|
||||
"Audience": "EICS",
|
||||
"TokenExpireDays": "7"
|
||||
},
|
||||
"IpRateLimiting": {
|
||||
@@ -55,6 +55,26 @@
|
||||
"EnableReadDeepClone": true,
|
||||
"EnableWriteDeepClone": false
|
||||
}
|
||||
},
|
||||
"redis": {
|
||||
"MaxRdSecond": 120,
|
||||
"EnableLogging": false,
|
||||
"LockMs": 5000,
|
||||
"SleepMs": 300,
|
||||
"dbconfig": {
|
||||
"Password": "xc@123456",
|
||||
"IsSsl": false,
|
||||
"SslHost": null,
|
||||
"ConnectionTimeout": 5000,
|
||||
"AllowAdmin": true,
|
||||
"Endpoints": [
|
||||
{
|
||||
"Host": "47.117.164.182",
|
||||
"Port": 6379
|
||||
}
|
||||
],
|
||||
"Database": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"IRaCISImageStore": {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗为您添加了账户,账户信息如下:
|
||||
{company abbreviation}为您添加了账户,账户信息如下:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
<div>
|
||||
首次登陆前,请通过该链接修改您的账户信息:
|
||||
<a href='{3}' style='margin-left:30px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
初始化账号信息
|
||||
</a>
|
||||
</div>
|
||||
@@ -31,8 +31,8 @@
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0} ,
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Extensive Imaging has generated a user account for you. <br>The account information is as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{company abbreviation} has created an account for you. The account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
User ID: {1}
|
||||
</div>
|
||||
@@ -22,17 +22,17 @@
|
||||
Role: {2}
|
||||
</div>
|
||||
<div>
|
||||
Before logging in for the first time, please initialize your account information through this link:
|
||||
<a href='{3}' style='margin-left:30px;font-size:12px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;font-size: 16px'>
|
||||
Initialize Account Information
|
||||
Before logging in for the first time, please modify the account information through this link:
|
||||
<a href='{3}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Initialize account information
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗将您的账户密码已重置,账户信息如下:
|
||||
{company abbreviation}将您的账户密码已重置,账户信息如下:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0} ,
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Extensive Imaging has reset your password.<br>The account information is as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{company abbreviation} has reset your account password, and the account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 12px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
User ID: {1}
|
||||
</div>
|
||||
@@ -27,9 +27,9 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;font-size: 16px'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear Sir or Madam:
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Thank you for using our IRC imaging system.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
Thank you for using {company abbreviation} Cloud System.
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{0}。
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作。
|
||||
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目阅片相关工作。
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -34,14 +34,16 @@
|
||||
角色: {5}
|
||||
</div>
|
||||
<div>
|
||||
系统登录地址:{6}
|
||||
系统登录地址:
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
点击跳转
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the IRC service provider of {1} trial(Protocol ID is {2}), Extensive Imaging invites you to participate in the independent assessment work of this trial.
|
||||
{company abbreviation} invites you to participate in the IRC work of a trial ({1} , {2}).
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Digital workflow is implemented for this trial, and your account information is as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
Your account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
@@ -28,19 +28,23 @@
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {4}
|
||||
User ID: {4}
|
||||
</div>
|
||||
<div>
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Login URL: {6}
|
||||
Login URL:
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Click to login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<div>
|
||||
首次登陆前,请通过该链接修改您的账户信息:
|
||||
<a href='{6}' style='margin-left:30px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
初始化账号信息
|
||||
</a>
|
||||
</div>
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,21 +4,20 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the IRC service provider of {1}trial (Protocol ID is {2}), Extensive Imaging invites you to participate in the independent assessment work of this trial.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Digital workflow is implemented for this trial, and your account information is as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
Your account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
@@ -35,17 +34,17 @@
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Before logging in for the first time, please modify your account information through this link:
|
||||
<a href='{6}' style='margin-left:30px;font-size:16px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Initialize Account Information
|
||||
Before logging in for the first time, please modify the account information through this link:
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Initialize account information
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;font-size: 16px'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
您好, 您填写的中心调研表被驳回,详细信息如下:
|
||||
您填写的中心调研表被驳回,详细信息如下:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
@@ -40,8 +40,8 @@
|
||||
</a>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;font-size: 16px'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6;font-size: 16px'>
|
||||
<div style='padding-top: 20px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0} ,
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
The site survey questionnaire you filled in has been rejected. Details are as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
The site survey form you filled in has been rejected. The details are as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
Trial ID: {1}
|
||||
</div>
|
||||
@@ -28,20 +28,20 @@
|
||||
Site ID: {4}
|
||||
</div>
|
||||
<div>
|
||||
Site Name: {5}
|
||||
Site name: {5}
|
||||
</div>
|
||||
<div>
|
||||
Reason for rejection: {6}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<a href='{7}' style='margin-left:60px;font-size:16px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;font-size: 16px'>
|
||||
Login & View
|
||||
<a href='{7}' style='margin-left:60px;font-size:14px;padding: 10px;text-decoration: none;display:{8} ;height: 40px;width: 140px;background: #00D1B2;color:#fff;border-radius: 5px;line-height: 40px;text-align: center;margin-bottom: 100px;'>
|
||||
Login and view
|
||||
</a>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -34,14 +34,17 @@
|
||||
角色: {5}
|
||||
</div>
|
||||
<div>
|
||||
系统登录地址:{6}
|
||||
系统登录地址:
|
||||
<a href='{6}' style='margin-left:5px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
点击跳转
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;font-size: 16px'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6;font-size: 16px'>
|
||||
<div style='padding-top: 20px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the IRC service provider of {1} trial (Protocol ID is {2}), Extensive Imaging invites you to participate in IRC-related work of this trial.
|
||||
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Digital workflow is implemented for this trial, and your account information is as follows:
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
Your account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
@@ -28,20 +28,23 @@
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {4}
|
||||
User ID: {4}
|
||||
</div>
|
||||
<div>
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Login URL: {6}
|
||||
Login URL:
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Click to login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作。
|
||||
{company abbreviation}作为 [{1} (试验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<div>
|
||||
首次登陆前,请通过该链接修改您的账户信息:
|
||||
<a href='{6}' style='margin-left:30px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
初始化账号信息
|
||||
</a>
|
||||
</div>
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;font-size: 16px'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the IRC service provider of {1} trial (Protocol ID is {2}), Extensive Imaging invites you to participate in IRC-related work of this trial.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{company abbreviation} invites you to participate in the IRC work of a trial ({1}, {2}).
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
Digital workflow is implemented for this trial, and your account information is as follows:
|
||||
Your account information is as follows:
|
||||
</div>
|
||||
<span style="color: #00D1B2"></span>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;font-size: 16px'>
|
||||
<div style='border: 1px solid #eee;box-sizing:border-box;width: 50%;background: #fff;padding: 20px;line-height: 40px;font-size: 14px;border-radius: 5px;margin-left: 60px;margin-bottom: 30px;'>
|
||||
<div>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
@@ -28,23 +28,23 @@
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {4}
|
||||
User ID: {4}
|
||||
</div>
|
||||
<div>
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Before logging in for the first time, please modify your account information through this link:
|
||||
<a href='{6}' style='margin-left:30px;font-size:16px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Initialize Account Information
|
||||
Before logging in for the first time, please modify the account information through this link:
|
||||
<a href='{6}' style='margin-left:1px;font-size:14px;text-decoration: none;display: inline-block;color:#00D1B2;border-radius: 5px;line-height: 40px;text-align: center;'>
|
||||
Initialize the account information
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,18 +8,20 @@
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
亲爱的用户 ,
|
||||
{0}您好,
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
感谢您使用展影云平台。
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{0},验证码是: {1},请在3分钟内输入该验证码,进行后续操作。如非本人操作,请忽略该邮件。
|
||||
{1},验证码是: <span style="font-weight:bold">{2}</span>。
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
请在3分钟内输入该验证码,进行后续操作
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>祝您顺利!/Best Regards</div>
|
||||
<div style="font-size: 14px;">展影医疗</div>
|
||||
<div>祝您顺利!</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,25 +4,25 @@
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body style='font-family: Times New Roman;padding: 0;margin: 0;'>
|
||||
<body style='font-family: 微软雅黑;padding: 0;margin: 0;'>
|
||||
<div style='padding-left: 40px;background: #f6f6f6'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear Sir or Madam:
|
||||
<div style='line-height: 40px;font-size: 18px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Thank you for using our IRC imaging system.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
{1}
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
{0}, the verification code is {1}. Please enter this code within 3 minutes for follow-up operations.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
The verification code is <span style="font-weight:bold">{2}</span>.
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
If you are not the intended person, please ignore this email.
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
This code will expire in 3 minutes.
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;font-size: 16px'>
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
<div style="font-size: 14px;">{company}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Binary file not shown.
@@ -1,97 +0,0 @@
|
||||
using Castle.DynamicProxy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.AOP
|
||||
{
|
||||
public abstract class AsyncInterceptorBase : IInterceptor
|
||||
{
|
||||
public AsyncInterceptorBase()
|
||||
{
|
||||
}
|
||||
|
||||
public void Intercept(IInvocation invocation)
|
||||
{
|
||||
BeforeProceed(invocation);
|
||||
invocation.Proceed();
|
||||
if (IsAsyncMethod(invocation.MethodInvocationTarget))
|
||||
{
|
||||
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, invocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
AfterProceedSync(invocation);
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckMethodReturnTypeIsTaskType(MethodInfo method)
|
||||
{
|
||||
var methodReturnType = method.ReturnType;
|
||||
if (methodReturnType.IsGenericType)
|
||||
{
|
||||
if (methodReturnType.GetGenericTypeDefinition() == typeof(Task<>) ||
|
||||
methodReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (methodReturnType == typeof(Task) ||
|
||||
methodReturnType == typeof(ValueTask))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsAsyncMethod(MethodInfo method)
|
||||
{
|
||||
bool isDefAsync = Attribute.IsDefined(method, typeof(AsyncStateMachineAttribute), false);
|
||||
bool isTaskType = CheckMethodReturnTypeIsTaskType(method);
|
||||
bool isAsync = isDefAsync && isTaskType;
|
||||
|
||||
return isAsync;
|
||||
}
|
||||
|
||||
protected object ProceedAsyncResult { get; set; }
|
||||
|
||||
|
||||
private async Task InterceptAsync(Task task, IInvocation invocation)
|
||||
{
|
||||
await task.ConfigureAwait(false);
|
||||
await AfterProceedAsync(invocation, false);
|
||||
}
|
||||
|
||||
private async Task<TResult> InterceptAsync<TResult>(Task<TResult> task, IInvocation invocation)
|
||||
{
|
||||
ProceedAsyncResult = await task.ConfigureAwait(false);
|
||||
await AfterProceedAsync(invocation, true);
|
||||
return (TResult)ProceedAsyncResult;
|
||||
}
|
||||
|
||||
private async ValueTask InterceptAsync(ValueTask task, IInvocation invocation)
|
||||
{
|
||||
await task.ConfigureAwait(false);
|
||||
await AfterProceedAsync(invocation, false);
|
||||
}
|
||||
|
||||
private async ValueTask<TResult> InterceptAsync<TResult>(ValueTask<TResult> task, IInvocation invocation)
|
||||
{
|
||||
ProceedAsyncResult = await task.ConfigureAwait(false);
|
||||
await AfterProceedAsync(invocation, true);
|
||||
return (TResult)ProceedAsyncResult;
|
||||
}
|
||||
|
||||
protected virtual void BeforeProceed(IInvocation invocation) { }
|
||||
|
||||
protected virtual void AfterProceedSync(IInvocation invocation) { }
|
||||
|
||||
protected virtual Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,499 +0,0 @@
|
||||
//using System;
|
||||
//using Castle.DynamicProxy;
|
||||
//using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||
//using IRaCIS.Core.Infra.EFCore;
|
||||
|
||||
//using System.Linq;
|
||||
//using IRaCIS.Core.Domain.Models;
|
||||
//using IRaCIS.Core.Domain.Share;
|
||||
|
||||
//namespace IRaCIS.Core.API.Utility.AOP
|
||||
//{
|
||||
//#pragma warning disable
|
||||
// public class QANoticeAOP : IInterceptor
|
||||
// {
|
||||
// private readonly IRepository<QANotice> _qaNoticeRepository;
|
||||
|
||||
// private readonly IRepository<DicomStudy> _studyRepository;
|
||||
// private readonly IRepository<TrialUser> _userTrialRepository;
|
||||
// private readonly IRepository<TrialSiteUser> _userTrialSiteRepository;
|
||||
// private readonly IUserInfo _userInfo;
|
||||
|
||||
// public QANoticeAOP(IRepository<QANotice> qaNoticeRepository,
|
||||
// IUserInfo userInfo, IRepository<DicomStudy> studyRepository, IRepository<TrialUser> userTrialRepository, IRepository<TrialSiteUser> userTrialSiteRepository)
|
||||
// {
|
||||
// _qaNoticeRepository = qaNoticeRepository;
|
||||
|
||||
// _studyRepository = studyRepository;
|
||||
// _userTrialRepository = userTrialRepository;
|
||||
// _userTrialSiteRepository = userTrialSiteRepository;
|
||||
// _userInfo = userInfo;
|
||||
// }
|
||||
|
||||
// public void Intercept(IInvocation invocation)
|
||||
// {
|
||||
// //处理拦截的方法
|
||||
// invocation.Proceed();
|
||||
|
||||
// if (invocation.Method.Name == "UpdateStudyStatus")
|
||||
// {
|
||||
// var studyStatus = invocation.Arguments[0] as StudyStatusDetailCommand;
|
||||
|
||||
// var study = _studyRepository.FirstOrDefault(t=>t.Id==studyStatus.StudyId);
|
||||
|
||||
|
||||
// if (study.Status == (int)StudyStatus.Uploaded)
|
||||
// {
|
||||
// _qaNoticeRepository.Add(new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
|
||||
// NoticeTypeEnum = NoticeType.NotNeedNotice,
|
||||
// NeedDeal = false,
|
||||
// StudyStatusStr = "Uploaded",
|
||||
// Message = $"CRC : {_userInfo.RealName} has uploaded {study.StudyCode} ",
|
||||
// SendTime = DateTime.Now,
|
||||
// });
|
||||
// }
|
||||
|
||||
// #region 处理QA通知模块
|
||||
|
||||
// //查询项目的参与者 和 负责site下CRC用户
|
||||
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// // 找到该study 关联Site 下的CRC
|
||||
|
||||
// var crcList = _userTrialSiteRepository.Where(t =>
|
||||
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
|
||||
|
||||
|
||||
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
||||
|
||||
// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager);
|
||||
|
||||
|
||||
|
||||
|
||||
// // CRC =>QA
|
||||
// if (studyStatus.Status == (int)StudyStatus.QARequested)
|
||||
// {
|
||||
// //找出当前操作的CRC
|
||||
// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户
|
||||
// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id);
|
||||
|
||||
// var notice = new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
|
||||
// //FromUser = currentCRC.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentCRC.UserType,
|
||||
// NoticeTypeEnum = NoticeType.CRC_RequestToQA_NoticeQA,
|
||||
// NeedDeal = true,
|
||||
// StudyStatusStr = "QA Requested",
|
||||
// Message =
|
||||
// $"CRC -> QA : {_userInfo.RealName} request QA {study.StudyCode} , Inquiry can be performed! ",
|
||||
// SendTime = DateTime.Now,
|
||||
// };
|
||||
|
||||
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// {
|
||||
// QANoticeId = notice.Id,
|
||||
// SubjectVisitId = study.Id,
|
||||
// ToUser = t.User.LastName + " / " + t.User.FirstName,
|
||||
// ToUserId = t.UserId,
|
||||
// ToUserType = t.User.UserTypeRole.UserTypeShortName
|
||||
// }));
|
||||
|
||||
// _qaNoticeRepository.Add(notice);
|
||||
|
||||
// //DealRequestToQA(study.Id);
|
||||
|
||||
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
|
||||
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA).ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
// }
|
||||
|
||||
// // QA =>CRC 向CRC推送消息影像有问题 同时作为 requestToQA 的边界
|
||||
// else if (studyStatus.Status == (int)StudyStatus.QAing)
|
||||
// {
|
||||
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
|
||||
// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id);
|
||||
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
|
||||
|
||||
// //在项目CRC列表中筛选出 负责该study关联 site的CRC
|
||||
// var siteCRCList = _userTrialSiteRepository.Where(t =>
|
||||
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// //查询项目的参与者 和 负责site下CRC用户
|
||||
|
||||
|
||||
|
||||
// var notice = new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// //FromUser = currentQA.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentQA.UserType,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.QA_InQA_NoticeCRC,
|
||||
// NeedDeal = true,
|
||||
// StudyStatusStr = "In QA",
|
||||
// Message = $"QA -> CRC : {_userInfo.RealName} inquiry {study.StudyCode} ",
|
||||
// SendTime = DateTime.Now,
|
||||
// };
|
||||
|
||||
// siteCRCList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// {
|
||||
// QANoticeId = notice.Id,
|
||||
// SubjectVisitId = study.Id,
|
||||
// ToUser = t.User.LastName + " / " + t.User.FirstName,
|
||||
// ToUserId = t.UserId,
|
||||
// ToUserType = t.UserTypeRole.UserTypeShortName
|
||||
// }));
|
||||
|
||||
// //添加 发送给CRC的消息 消息和CRC是 一对多
|
||||
// _qaNoticeRepository.Add(notice);
|
||||
|
||||
|
||||
// //处理 消息 标记已处理
|
||||
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
|
||||
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
|
||||
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA)).ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
|
||||
|
||||
// }
|
||||
// // QA =>QA 给自己的消息 通知需要匿名化 同时作为 requestToQA 的边界
|
||||
// else if (studyStatus.Status == (int)StudyStatus.QAFinish)
|
||||
// {
|
||||
|
||||
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
|
||||
// //var currentQA = qaList.First(t => t.UserId == _userInfo.Id);
|
||||
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
|
||||
|
||||
// //发送给当前项目QA列表
|
||||
|
||||
// var notice = new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// //FromUser = currentQA.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentQA.UserType,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.QA_QAPass_NoticeQA,
|
||||
// NeedDeal = true,
|
||||
// StudyStatusStr = "QA-Passed",
|
||||
// Message =
|
||||
// $"QA -> QA : {_userInfo.RealName} inquiry {study.StudyCode} finished,Anonymization can be performed!",
|
||||
// SendTime = DateTime.Now,
|
||||
// };
|
||||
|
||||
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// {
|
||||
// QANoticeId = notice.Id,
|
||||
// SubjectVisitId = study.Id,
|
||||
// ToUser = t.User.LastName+" / "+t.User.FirstName,
|
||||
// ToUserId = t.UserId,
|
||||
// ToUserType = t.User.UserTypeRole.UserTypeShortName
|
||||
// }));
|
||||
|
||||
// _qaNoticeRepository.Add(notice);
|
||||
|
||||
// //处理 消息 标记已处理 存在意外情况 qa发给CRC的 但是qa里面设置了 通过或者不通过 此时qa发送的消息也设置为已处理
|
||||
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
|
||||
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
|
||||
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA ||
|
||||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC ||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC ||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
|
||||
|
||||
// }
|
||||
// // QA =>CRC 暂时不用发送消息给CRC 因为CRC 暂时没有入口回复 同时作为 requestToQA 的边界
|
||||
// else if (studyStatus.Status == (int)StudyStatus.QAFInishNotPass)
|
||||
// {
|
||||
|
||||
// _qaNoticeRepository.Add(new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.NotNeedNotice,
|
||||
// NeedDeal = false,
|
||||
// StudyStatusStr = "QA-Failed",
|
||||
// Message = $"QA : {_userInfo.RealName} set {study.StudyCode} QA-Failed !",
|
||||
// SendTime = DateTime.Now,
|
||||
// });
|
||||
|
||||
// //处理 消息 标记已处理
|
||||
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
|
||||
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal &&
|
||||
// (t.NoticeTypeEnum == NoticeType.CRC_RequestToQA_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_ReUpload_NoticeQA ||
|
||||
// t.NoticeTypeEnum == NoticeType.CRC_QARecordDialogPost_NoticeQA ||
|
||||
|
||||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC ||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC ||
|
||||
// t.NoticeTypeEnum == NoticeType.QA_AddQARecord_NoticeCRC)).ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// else if (invocation.Method.Name == "ReUploadSameStudy")
|
||||
// {
|
||||
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
|
||||
|
||||
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
|
||||
// var status = study.Status;
|
||||
|
||||
// //处理CRC 重传时 QA消息
|
||||
|
||||
// if (status == (int)StudyStatus.QAing)
|
||||
// {
|
||||
// //查询项目的参与者 和 负责site下CRC用户
|
||||
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// // 找到该study 关联Site 下的CRC
|
||||
|
||||
// var crcList = _userTrialSiteRepository.Where(t =>
|
||||
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
||||
|
||||
// //CRC =>QA CRC的职能被PM 或者admin代替
|
||||
// //if (_userInfo.UserTypeEnumInt == (int)UserType.ClinicalResearchCoordinator)
|
||||
// {
|
||||
// //PM 或者admin可以代替CRC角色 不能从CRC列表中查询用户
|
||||
// //var currentCRC = trialUserList.First(t => t.UserId == _userInfo.Id);
|
||||
|
||||
// var notice = new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// //FromUser = currentCRC.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentCRC.UserType,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.CRC_ReUpload_NoticeQA,
|
||||
// NeedDeal = true,
|
||||
// Message = $"CRC -> QA :{_userInfo.RealName} has reuploaded {study.StudyCode} , Need to be inquiry again",
|
||||
// SendTime = DateTime.Now
|
||||
// };
|
||||
|
||||
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// {
|
||||
// QANoticeId = notice.Id,
|
||||
// SubjectVisitId = study.Id,
|
||||
// ToUser = t.User.LastName+" / "+t.User.FirstName,
|
||||
// ToUserId = t.UserId,
|
||||
// ToUserType = t.User.UserTypeRole.UserTypeShortName
|
||||
// }));
|
||||
|
||||
// _qaNoticeRepository.Add(notice);
|
||||
|
||||
// //这里作为 QA 设置 Inqa 状态的回复 或者QA和CRC对话的
|
||||
// var needDealNoticeList = _qaNoticeRepository.Where(t => t.SubjectVisitId == study.Id && t.NeedDeal
|
||||
// && (t.NoticeTypeEnum == NoticeType.QA_InQA_NoticeCRC || t.NoticeTypeEnum == NoticeType.QA_QARecordDialogPost_NoticeCRC))
|
||||
// .ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //不是QAing 的重传 不发送qa消息
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// else if (invocation.Method.Name == "DicomAnonymize")
|
||||
// {
|
||||
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
|
||||
|
||||
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
|
||||
|
||||
// #region 处理QA通知 匿名化完毕 通知PM
|
||||
|
||||
// //查询项目的参与者 和 负责site下CRC用户
|
||||
// var trialUserList = _userTrialRepository.Where(t => t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// // 找到该study 关联Site 下的CRC
|
||||
|
||||
// var crcList = _userTrialSiteRepository.Where(t =>
|
||||
// t.SiteId == study.SiteId && t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && t.TrialId == study.TrialId).ToList();
|
||||
|
||||
// var qaList = trialUserList.Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
||||
|
||||
// //
|
||||
// var pm = trialUserList.FirstOrDefault(t => t.User.UserTypeEnum == UserTypeEnum.ProjectManager);
|
||||
|
||||
|
||||
// //找出当前操作的QA 如果是pm 或者admin 代替操作 此时会有问题 所以 谁代替,就以谁的名义执行
|
||||
// //var currentQA = trialUserList.First(t =>
|
||||
// // t.UserTypeEnum == UserType.IQC && t.UserId == _userInfo.Id);
|
||||
// //var currentQA = trialUserList.First(t => t.UserId == _userInfo.Id);
|
||||
|
||||
// var notice = new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// //FromUser = currentQA.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentQA.UserType,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.QA_Anonymized_NoticeQA,
|
||||
// NeedDeal = true,
|
||||
// StudyStatusStr = "Anonymized",
|
||||
// //Message = $"QA -> PM :{_userInfo.RealName} has anonymized {study.StudyCode} ,Forward can be performed!!",
|
||||
// Message = $"QA -> QA :{_userInfo.RealName} has anonymized {study.StudyCode} ,Forward can be performed!!",
|
||||
|
||||
// SendTime = DateTime.Now,
|
||||
|
||||
// };
|
||||
|
||||
// //notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// //{
|
||||
// // QANoticeId = notice.Id,
|
||||
// // StudyId = study.Id,
|
||||
// // ToUser = pm.UserRealName,
|
||||
// // ToUserId = pm.UserId,
|
||||
// // ToUserType = pm.UserType
|
||||
// //});
|
||||
|
||||
// qaList.ForEach(t => notice.QANoticeUserList.Add(new QANoticeUser()
|
||||
// {
|
||||
// QANoticeId = notice.Id,
|
||||
// SubjectVisitId = study.Id,
|
||||
// ToUser = t.User.LastName+" / "+t.User.FirstName,
|
||||
// ToUserId = t.UserId,
|
||||
// ToUserType = t.User.UserTypeRole.UserTypeShortName
|
||||
// }));
|
||||
|
||||
// _qaNoticeRepository.Add(notice);
|
||||
|
||||
// var needDealNoticeList = _qaNoticeRepository.AsQueryable()
|
||||
// .Where(t => t.SubjectVisitId == study.Id && t.NeedDeal && (t.NoticeTypeEnum == NoticeType.QA_QAPass_NoticeQA)).ToList();
|
||||
|
||||
// needDealNoticeList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
|
||||
|
||||
// #endregion
|
||||
// }
|
||||
|
||||
// else if (invocation.Method.Name == "ForwardStudy")
|
||||
// {
|
||||
// var studyId = Guid.Parse(invocation.Arguments[0].ToString());
|
||||
|
||||
// var study = _studyRepository.FirstOrDefault(t => t.Id == studyId);
|
||||
|
||||
// //匿名化操作产生的消息 设置为已经处理
|
||||
// _qaNoticeRepository.Add(new QANotice()
|
||||
// {
|
||||
// TrialId = study.TrialId,
|
||||
// SubjectVisitId = study.Id,
|
||||
// //FromUser = currentQA.UserRealName,
|
||||
// //FromUserId = _userInfo.Id,
|
||||
// //FromUserType = currentQA.UserType,
|
||||
// FromUser = _userInfo.RealName,
|
||||
// FromUserId = _userInfo.Id,
|
||||
// FromUserType = _userInfo.UserTypeShortName,
|
||||
// NoticeTypeEnum = NoticeType.NotNeedNotice,
|
||||
// NeedDeal = false,
|
||||
// StudyStatusStr = "Forwarded",
|
||||
// //Message = $"PM :{_userInfo.RealName} has forwarded {study.StudyCode} !",
|
||||
// Message = $"QA :{_userInfo.RealName} has forwarded {study.StudyCode} !",
|
||||
// SendTime = DateTime.Now,
|
||||
// });
|
||||
|
||||
// var needDealList = _qaNoticeRepository.Where(t =>
|
||||
// t.SubjectVisitId == study.Id && t.NeedDeal && t.NoticeTypeEnum == NoticeType.QA_Anonymized_NoticeQA).ToList();
|
||||
|
||||
// needDealList.ForEach(t =>
|
||||
// {
|
||||
// t.NeedDeal = false;
|
||||
// t.DealTime = DateTime.Now;
|
||||
// _qaNoticeRepository.Update(t);
|
||||
// });
|
||||
// }
|
||||
|
||||
// var success = _qaNoticeRepository.SaveChanges();
|
||||
|
||||
// if (!success)
|
||||
// {
|
||||
// throw new Exception("Send QA message failed");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
//}
|
||||
@@ -1,89 +0,0 @@
|
||||
using Castle.DynamicProxy;
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Core.Application.AOP
|
||||
{
|
||||
public class TrialStatusAutofacAOP : IAsyncInterceptor
|
||||
{
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
|
||||
public TrialStatusAutofacAOP(IEasyCachingProvider provider)
|
||||
{
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void InterceptAsynchronous(IInvocation invocation)
|
||||
{
|
||||
invocation.Proceed();
|
||||
}
|
||||
|
||||
//这里AOP 处理两个方法 分别是 项目的添加和更新、项目状态的变更
|
||||
|
||||
public void InterceptAsynchronous<TResult>(IInvocation invocation)
|
||||
{
|
||||
|
||||
|
||||
//处理拦截的方法
|
||||
invocation.Proceed();
|
||||
|
||||
|
||||
|
||||
dynamic result = invocation.ReturnValue;
|
||||
|
||||
//接口成功了,才修改缓存
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#region 处理项目列表的查询 在前端界面已经在某个界面,但是服务器重置了,此时没有缓存项目信息,接口不能正确返回,因故采用,启动时查询,每天查询一次,缓存一天,然后项目添加、更改状态时,及时更新
|
||||
|
||||
//if (invocation.Method.Name == "GetTrialList")
|
||||
//{
|
||||
// //在此 将当前查询的项目Id 和对应的项目状态进行缓存
|
||||
// dynamic result = invocation.ReturnValue;
|
||||
// foreach (var item in result.CurrentPageData)
|
||||
// {
|
||||
// _provider.Remove(item.Id.ToString());
|
||||
// _provider.Set(item.Id.ToString(), item.TrialStatusStr.ToString(), TimeSpan.FromDays(1));
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
if (invocation.Method.Name == "AddOrUpdateTrial")
|
||||
{
|
||||
//如果是添加 那么将对应的初始状态加进去 更新状态是单独操作的
|
||||
|
||||
var trialModel = (invocation.Arguments[0] as TrialCommand).IfNullThrowConvertException();
|
||||
if (trialModel.Id == null || trialModel.Id == Guid.Empty)
|
||||
{
|
||||
_provider.Set(result.Data.Id.ToString(), StaticData.TrialState.TrialOngoing, TimeSpan.FromDays(1));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// 更新缓存
|
||||
else if (invocation.Method.Name == "UpdateTrialStatus")
|
||||
{
|
||||
//项目状态更新,也需要及时更新
|
||||
_provider.Set(invocation.Arguments[0].ToString(), invocation.Arguments[1].ToString(), TimeSpan.FromDays(1));
|
||||
|
||||
////Test参数是否符合要求
|
||||
//var tt = invocation.Arguments[0].ToString();
|
||||
//var cc = _provider.Get<string>(invocation.Arguments[0].ToString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void InterceptSynchronous(IInvocation invocation)
|
||||
{
|
||||
invocation.Proceed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Domain;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Quartz;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public class CacheTrialStatusQuartZJob: IJob
|
||||
{
|
||||
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<CacheTrialStatusQuartZJob> _logger;
|
||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
||||
|
||||
public CacheTrialStatusQuartZJob(IRepository<Trial> trialRepository, IEasyCachingProvider provider,ILogger<CacheTrialStatusQuartZJob> logger, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
}
|
||||
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
|
||||
{
|
||||
_logger.LogInformation($"开始执行QuartZ定时任务作业");
|
||||
try
|
||||
{
|
||||
await MemoryCacheTrialStatus();
|
||||
|
||||
await MemoryCacheAnonymizeData();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($" 查询和缓存过程出现异常"+e.Message);
|
||||
}
|
||||
_logger.LogInformation("QuartZ定时任务作业结束");
|
||||
}
|
||||
|
||||
|
||||
public async Task MemoryCacheTrialStatus()
|
||||
{
|
||||
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||
.ToListAsync();
|
||||
|
||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||
|
||||
}
|
||||
|
||||
public async Task MemoryCacheAnonymizeData()
|
||||
{
|
||||
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
using EasyCaching.Core;
|
||||
using Hangfire;
|
||||
using Hangfire.Storage;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public interface IIRaCISHangfireJob
|
||||
{
|
||||
|
||||
Task MemoryCacheTrialStatusAsync();
|
||||
|
||||
Task InitHangfireJobTaskAsync();
|
||||
|
||||
}
|
||||
public class IRaCISCHangfireJob : IIRaCISHangfireJob
|
||||
{
|
||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
||||
|
||||
public static FileSystemWatcher FileSystemWatcher_US { get; set; }
|
||||
public static FileSystemWatcher FileSystemWatcher_CN { get; set; }
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<IRaCISCHangfireJob> _logger;
|
||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
||||
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
|
||||
private readonly IRepository<Internationalization> _internationalizationRepository;
|
||||
|
||||
|
||||
|
||||
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
|
||||
_internationalizationRepository = internationalizationRepository;
|
||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
}
|
||||
|
||||
public async Task InitHangfireJobTaskAsync()
|
||||
{
|
||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
||||
|
||||
|
||||
//项目状态 立即加载到缓存中
|
||||
await MemoryCacheTrialStatusAsync();
|
||||
|
||||
await MemoryCacheAnonymizeData();
|
||||
|
||||
|
||||
//创建项目缓存 定时任务
|
||||
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
|
||||
|
||||
//初始化
|
||||
|
||||
await InitInternationlizationDataAndWatchJsonFileAsync();
|
||||
|
||||
//创建邮件定时任务
|
||||
await InitSysAndTrialCronJobAsync();
|
||||
|
||||
|
||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓存项目状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task MemoryCacheTrialStatusAsync()
|
||||
{
|
||||
|
||||
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||
.ToListAsync();
|
||||
|
||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||
|
||||
}
|
||||
|
||||
public async Task MemoryCacheAnonymizeData()
|
||||
{
|
||||
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
}
|
||||
|
||||
|
||||
#region 国际化 初始化
|
||||
|
||||
|
||||
public async Task InitInternationlizationDataAndWatchJsonFileAsync()
|
||||
{
|
||||
//查询数据库的数据
|
||||
var toJsonList = await _internationalizationRepository.Where(t => t.InternationalizationType == 1).Select(t => new
|
||||
{
|
||||
t.Code,
|
||||
t.Value,
|
||||
t.ValueCN
|
||||
}).ToListAsync();
|
||||
|
||||
//组织成json 文件
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//本地静态文件国际化需要
|
||||
foreach (var tojsonItem in toJsonList)
|
||||
{
|
||||
StaticData.En_US_Dic[tojsonItem.Code] = tojsonItem.Value;
|
||||
StaticData.Zh_CN_Dic[tojsonItem.Code] = tojsonItem.ValueCN;
|
||||
}
|
||||
|
||||
File.WriteAllText(usJsonPath, JsonConvert.SerializeObject(StaticData.En_US_Dic));
|
||||
File.WriteAllText(cnJsonPath, JsonConvert.SerializeObject(StaticData.Zh_CN_Dic));
|
||||
|
||||
|
||||
//监测Json文件变更 实时刷新数据
|
||||
|
||||
if (!File.Exists(usJsonPath)|| !File.Exists(cnJsonPath))
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||
}
|
||||
|
||||
FileSystemWatcher_US = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(usJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(usJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
// 添加文件更改事件的处理程序
|
||||
FileSystemWatcher_US.Changed += (sender, e) => LoadJsonFile(usJsonPath);
|
||||
|
||||
|
||||
FileSystemWatcher_CN = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(cnJsonPath)!,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size,
|
||||
Filter = Path.GetFileName(cnJsonPath),
|
||||
EnableRaisingEvents = true,
|
||||
|
||||
};
|
||||
FileSystemWatcher_CN.Changed += (sender, e) => LoadJsonFile(cnJsonPath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void LoadJsonFile(string filePath)
|
||||
{
|
||||
Console.WriteLine("刷新json内存数据");
|
||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath,false,true);
|
||||
|
||||
IConfigurationRoot enConfiguration = builder.Build();
|
||||
|
||||
foreach (IConfigurationSection section in enConfiguration.GetChildren())
|
||||
{
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
StaticData.En_US_Dic[section.Key] = section.Value;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticData.Zh_CN_Dic[section.Key] = section.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task InitSysAndTrialCronJobAsync()
|
||||
{
|
||||
//var deleteJobIdList = await _trialEmailNoticeConfigRepository.Where(t => t.Trial.TrialStatusStr != StaticData.TrialState.TrialOngoing && t.EmailCron != string.Empty && t.IsAutoSend)
|
||||
// .Select(t => t.TrialId + "_" + t.Id)
|
||||
// .ToListAsync();
|
||||
|
||||
//foreach (var jobId in deleteJobIdList)
|
||||
//{
|
||||
// HangfireJobHelper.RemoveCronJob(jobId);
|
||||
//}
|
||||
|
||||
|
||||
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, t.EmailCron, t.BusinessScenarioEnum, t.TrialId })
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var task in taskInfoList)
|
||||
{
|
||||
//利用主键作为任务Id
|
||||
var jobId = $"{task.TrialId}_{task.Id}";
|
||||
|
||||
HangfireJobHelper.AddOrUpdateTrialCronJob(jobId, task.TrialId, task.BusinessScenarioEnum, task.EmailCron);
|
||||
}
|
||||
|
||||
var addOrUpdateJobIdList = taskInfoList.Select(t => $"{t.TrialId}_{t.Id}").ToList();
|
||||
|
||||
var list = JobStorage.Current.GetConnection().GetRecurringJobs().ToList();
|
||||
|
||||
//项目定时任务都在default 队列
|
||||
//var dbJobIdList = JobStorage.Current.GetConnection().GetRecurringJobs().Where(t => t.Queue == "default").Select(t => t.Id).ToList();
|
||||
|
||||
//var deleteList= dbJobIdList.Except(addOrUpdateJobIdList).ToList();
|
||||
|
||||
// foreach (var jobId in deleteList)
|
||||
// {
|
||||
// HangfireJobHelper.RemoveCronJob(jobId);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public interface IIRaCISCacheHangfireJob
|
||||
{
|
||||
|
||||
Task ProjectStartCache();
|
||||
Task MemoryCacheTrialStatus();
|
||||
|
||||
Task MemoryCacheAnonymizeData();
|
||||
|
||||
Task CacheUserTypePermission(Guid? cacheUserTypeId);
|
||||
}
|
||||
public class IRaCISCacheHangfireJob: IIRaCISCacheHangfireJob
|
||||
{
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<IRaCISCacheHangfireJob> _logger;
|
||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
||||
|
||||
private readonly IRepository<UserTypeMenu> _userTypeMenuRepository;
|
||||
|
||||
public IRaCISCacheHangfireJob(IRepository<Trial> trialRepository,
|
||||
IRepository<SystemAnonymization> systemAnonymizationRepository, IRepository<UserTypeMenu> userTypeMenuRepository,
|
||||
IEasyCachingProvider provider,ILogger<IRaCISCacheHangfireJob> logger)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
_userTypeMenuRepository = userTypeMenuRepository;
|
||||
}
|
||||
|
||||
|
||||
public async Task ProjectStartCache()
|
||||
{
|
||||
_logger.LogInformation("hangfire 定时缓存项目状态任务开始~");
|
||||
try
|
||||
{
|
||||
await MemoryCacheTrialStatus();
|
||||
|
||||
await MemoryCacheAnonymizeData();
|
||||
|
||||
await CacheUserTypePermission();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("hangfire 定时任务执行失败" + e.Message);
|
||||
|
||||
}
|
||||
|
||||
_logger.LogInformation("hangfire 定时任务执行结束");
|
||||
}
|
||||
|
||||
public async Task MemoryCacheTrialStatus()
|
||||
{
|
||||
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||
.ToListAsync();
|
||||
|
||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task MemoryCacheAnonymizeData()
|
||||
{
|
||||
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
|
||||
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
|
||||
}
|
||||
|
||||
public async Task CacheUserTypePermission(Guid? cacheUserTypeId=null)
|
||||
{
|
||||
|
||||
var permissionList = await _userTypeMenuRepository.Where(t => t.Menu.MenuType == "F")
|
||||
.WhereIf(cacheUserTypeId != null, t => t.UserTypeId == cacheUserTypeId.Value).Select(t => new { t.UserTypeId, t.Menu.PermissionStr }).ToListAsync();
|
||||
|
||||
foreach (var userTypeGroup in permissionList.GroupBy(t => t.UserTypeId))
|
||||
{
|
||||
_provider.Set($"{StaticData.CacheKey.UserTypeId}_{userTypeGroup.Key}", userTypeGroup.Select(t => t.PermissionStr).ToList(), TimeSpan.FromDays(7));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,8 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
|
||||
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
|
||||
{
|
||||
var minutes = _verifyConfig.CurrentValue.AutoLoginOutMinutes;
|
||||
|
||||
if (_verifyConfig.CurrentValue.OpenLoginLimit)
|
||||
{
|
||||
if (context.ActionDescriptor.EndpointMetadata.Any(item => item is IAllowAnonymous))
|
||||
@@ -58,22 +60,45 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉
|
||||
var cacheUserToken = (await _provider.GetAsync<string>(_userInfo.Id.ToString())).Value;
|
||||
|
||||
|
||||
|
||||
//缓存中没有取到Token
|
||||
if (string.IsNullOrWhiteSpace(cacheUserToken))
|
||||
{
|
||||
cacheUserToken = _userInfo.UserToken;
|
||||
|
||||
//设置当前用户最新Token
|
||||
await _provider.SetAsync(_userInfo.Id.ToString(), _userInfo.UserToken, TimeSpan.FromDays(7));
|
||||
|
||||
cacheUserToken = _userInfo.UserToken;
|
||||
//重启应用程序,所有人续期,不一下子踢出所有人
|
||||
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
||||
|
||||
}
|
||||
//是同一个人
|
||||
else if (cacheUserToken == _userInfo.UserToken)
|
||||
{
|
||||
|
||||
var cacheTime = (await _provider.GetAsync<string>($"{_userInfo.Id.ToString()}_Online")).Value;
|
||||
|
||||
//过期了 需要自动退出
|
||||
if (string.IsNullOrEmpty(cacheTime))
|
||||
{
|
||||
context.HttpContext.Response.ContentType = "application/json";
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountAuto_LoginOut"], ApiResponseCodeEnum.AutoLoginOut));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
await _provider.SetAsync($"{_userInfo.Id.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(minutes));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
//using System.Diagnostics;
|
||||
//using IRaCIS.Application.Interfaces;
|
||||
//using IRaCIS.Application.Contracts;
|
||||
//using IRaCIS.Core.Infra.EFCore;
|
||||
//using IRaCIS.Core.Infrastructure.Extention;
|
||||
//using Microsoft.AspNetCore.Mvc;
|
||||
//using Microsoft.AspNetCore.Mvc.Filters;
|
||||
//using Microsoft.Extensions.Logging;
|
||||
//using Newtonsoft.Json;
|
||||
|
||||
//namespace IRaCIS.Core.Application.Filter
|
||||
//{
|
||||
|
||||
// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
|
||||
// public class LogFilter : Attribute
|
||||
// {
|
||||
// }
|
||||
// public class LogActionFilter : IAsyncActionFilter
|
||||
// {
|
||||
// private readonly ILogService _logService;
|
||||
// private readonly IUserInfo _userInfo;
|
||||
// private readonly ILogger<LogActionFilter> _logger;
|
||||
|
||||
// public LogActionFilter(ILogService logService, IUserInfo userInfo , ILogger<LogActionFilter> logger)
|
||||
// {
|
||||
// _logService = logService;
|
||||
// _userInfo = userInfo;
|
||||
// _logger = logger;
|
||||
// }
|
||||
|
||||
// public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
// {
|
||||
|
||||
// if (context.ActionDescriptor.EndpointMetadata!=null&& context.ActionDescriptor.EndpointMetadata.Any(m => m.GetType() == typeof(LogFilter)))
|
||||
// {
|
||||
// return LogAsync(context, next);
|
||||
// }
|
||||
// return next();
|
||||
// }
|
||||
|
||||
// public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
// {
|
||||
// var sw = new Stopwatch();
|
||||
// sw.Start();
|
||||
|
||||
// dynamic actionResult = (await next()).Result;
|
||||
// sw.Stop();
|
||||
// var args = JsonConvert.SerializeObject(context.ActionArguments);
|
||||
// var result = JsonConvert.SerializeObject(actionResult?.Value);
|
||||
|
||||
// var attr = (ApiExplorerSettingsAttribute)context.ActionDescriptor.EndpointMetadata.FirstOrDefault(m => m.GetType() == typeof(ApiExplorerSettingsAttribute));
|
||||
// var groupName = attr?.GroupName;
|
||||
// var res = actionResult?.Value as IResponseOutput;
|
||||
// var input = new SystemLogDTO
|
||||
// {
|
||||
// ClientIP = string.Empty,
|
||||
// OptUserId = _userInfo.Id,
|
||||
// OptUserName = _userInfo.UserName,
|
||||
// ApiPath = context.ActionDescriptor.AttributeRouteInfo.Template.ToLower(),
|
||||
// Params = args,
|
||||
// Result = result,
|
||||
// RequestTime = DateTime.Now,
|
||||
// ElapsedMilliseconds = sw.ElapsedMilliseconds,
|
||||
// Status =res?.IsSuccess?? false,
|
||||
// Message = res?.ErrorMessage,
|
||||
// LogCategory = groupName
|
||||
// };
|
||||
|
||||
// try
|
||||
// {
|
||||
// _logService.SaveLog2Db(input);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
|
||||
// _logger.LogError(ex.Message);
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -32,7 +32,9 @@ namespace IRaCIS.Core.Application.Filter
|
||||
|
||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message,ApiResponseCodeEnum.BusinessValidationFailed));
|
||||
var error = context.Exception as BusinessValidationFailedException;
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(context.Exception.Message, error!.Code));
|
||||
}
|
||||
else if(context.Exception.GetType() == typeof(QueryBusinessObjectNotExistException))
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,7 @@ namespace IRaCIS.Core.Application.Filter
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA)
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower())
|
||||
{
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
||||
|
||||
//OK
|
||||
var tuple = (dynamic)objectResult.Value;
|
||||
var apiResponse = ResponseOutput.Ok(tuple.Item1, tuple.Item2);
|
||||
var apiResponse = ResponseOutput.Ok(tuple!.Item1, tuple!.Item2);
|
||||
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
|
||||
@@ -5,7 +5,6 @@ using IRaCIS.Application.Contracts;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Magicodes.ExporterAndImporter.Excel;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MiniExcelLibs;
|
||||
@@ -14,7 +13,7 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NPOI.HSSF.UserModel;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using SkiaSharp;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
@@ -51,20 +50,24 @@ public static class ExcelExportHelper
|
||||
var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray());
|
||||
|
||||
|
||||
var dic = JsonConvert.DeserializeObject<IDictionary<string, object>>(data.ToJsonNotIgnoreNull());
|
||||
var dic = data.ConvertToDictionary();
|
||||
|
||||
|
||||
foreach (var key in dic.Keys)
|
||||
{
|
||||
//是数组 那么找到对应的属性 进行翻译
|
||||
if (dic[key].GetType().IsAssignableFrom(typeof(JArray)))
|
||||
if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
{
|
||||
|
||||
var newObjList = new List<object>();
|
||||
var no = 1;
|
||||
|
||||
foreach (var item in dic[key] as JArray)
|
||||
foreach (var item in dic[key] as IList )
|
||||
{
|
||||
var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||
//var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||
|
||||
var itemDic = item.ConvertToDictionary();
|
||||
|
||||
|
||||
|
||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||
@@ -72,7 +75,7 @@ public static class ExcelExportHelper
|
||||
//翻译的属性依赖其他属性
|
||||
if (needTranslateProperty.IsTranslateDenpendOtherProperty)
|
||||
{
|
||||
if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
if (itemDic[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
@@ -146,7 +149,7 @@ public static class ExcelExportHelper
|
||||
}
|
||||
|
||||
var memoryStream2 = new MemoryStream();
|
||||
workbook.Write(memoryStream2);
|
||||
workbook.Write(memoryStream2,true);
|
||||
|
||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
@@ -226,29 +229,30 @@ public static class ExcelExportHelper
|
||||
|
||||
var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray());
|
||||
|
||||
|
||||
var dic = JsonConvert.DeserializeObject<IDictionary<string, object>>(data.ToJsonNotIgnoreNull());
|
||||
var dic = data.ConvertToDictionary();
|
||||
//var dic = (JsonConvert.DeserializeObject<IDictionary<string, object>>(data.ToJsonNotIgnoreNull())).IfNullThrowException();
|
||||
|
||||
foreach (var key in dic.Keys)
|
||||
{
|
||||
//是数组 那么找到对应的属性 进行翻译
|
||||
if (dic[key].GetType().IsAssignableFrom(typeof(JArray)))
|
||||
if (dic[key].GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
//if (dic[key].GetType().IsAssignableFrom(typeof(JArray)))
|
||||
{
|
||||
|
||||
var newObjList = new List<object>();
|
||||
var no = 1;
|
||||
|
||||
foreach (var item in dic[key] as JArray)
|
||||
foreach (var item in dic[key] as IList)
|
||||
//foreach (var item in dic[key] as JArray)
|
||||
{
|
||||
var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||
|
||||
//var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||
var itemDic = item.ConvertToDictionary();
|
||||
|
||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||
{
|
||||
//翻译的属性依赖其他属性
|
||||
if (needTranslateProperty.IsTranslateDenpendOtherProperty)
|
||||
{
|
||||
if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
if (itemDic[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
@@ -316,7 +320,7 @@ public static class ExcelExportHelper
|
||||
}
|
||||
|
||||
var memoryStream2 = new MemoryStream();
|
||||
workbook.Write(memoryStream2);
|
||||
workbook.Write(memoryStream2,true);
|
||||
|
||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
@@ -336,7 +340,7 @@ public static class ExcelExportHelper
|
||||
IgnoreTemplateParameterMissing = true,
|
||||
};
|
||||
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, translateData, config);
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, templateStream.ToArray(), translateData, config);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
{
|
||||
public class FileConvertHelper
|
||||
{
|
||||
|
||||
|
||||
static public void ConvertWordToPdf(string inputWordFilePath, string outputPdfDir)
|
||||
{
|
||||
// 设置 libreoffice 命令行参数
|
||||
string arguments = $"--headless --invisible --convert-to pdf \"{inputWordFilePath}\" --outdir \"{outputPdfDir}\"";
|
||||
|
||||
// 启动 libreoffice 进程
|
||||
using (Process process = new Process())
|
||||
{
|
||||
process.StartInfo.FileName = "libreoffice";
|
||||
process.StartInfo.Arguments = arguments;
|
||||
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
process.Start();
|
||||
|
||||
// 等待进程结束
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using DocumentFormat.OpenXml.Bibliography;
|
||||
using NPOI.XWPF.UserModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
{
|
||||
public class FileFormatConvertHelper
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -14,40 +14,6 @@ namespace IRaCIS.Core.Application.Helper;
|
||||
public static class FileStoreHelper
|
||||
{
|
||||
|
||||
public static string UploadOOS(string filePath,string route)
|
||||
{
|
||||
var endpoint = ConfigurationManager.AppSettings["AliyunOSS:endpoint"];
|
||||
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
|
||||
|
||||
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
|
||||
var accessKeyId = ConfigurationManager.AppSettings["AliyunOSS:accessKeyId"];
|
||||
var accessKeySecret = ConfigurationManager.AppSettings["AliyunOSS:accessKeySecret"];
|
||||
// 填写Bucket名称,例如examplebucket。
|
||||
var bucketName = ConfigurationManager.AppSettings["AliyunOSS:bucketName"];
|
||||
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
|
||||
|
||||
var fileNameList = filePath.Split(',').ToList();
|
||||
var fileName = fileNameList[fileNameList.Count() - 1];
|
||||
|
||||
var objectName = route+ fileName;
|
||||
// 填写本地文件完整路径,例如D:\\localpath\\examplefile.txt。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
|
||||
var localFilename = filePath;
|
||||
// 创建OSSClient实例。
|
||||
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
|
||||
try
|
||||
{
|
||||
// 上传文件。
|
||||
var result = client.PutObject(bucketName, objectName, localFilename);
|
||||
|
||||
return result.ETag;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new BusinessValidationFailedException("上传异常!");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//处理文件名 压缩包,或者目录类的 会带上相对路径
|
||||
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false)
|
||||
{
|
||||
@@ -90,8 +56,9 @@ public static class FileStoreHelper
|
||||
//API vue 部署目录
|
||||
public static string GetIRaCISRootPath(IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
var rootPath = (Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\'))).IfNullThrowException().FullName;
|
||||
return rootPath;
|
||||
string parentDirectory = Path.GetFullPath(Path.Combine(_hostEnvironment.ContentRootPath, ".."));
|
||||
|
||||
return parentDirectory;
|
||||
|
||||
}
|
||||
|
||||
@@ -111,11 +78,56 @@ public static class FileStoreHelper
|
||||
{
|
||||
var rootPath = GetIRaCISRootPath(_hostEnvironment);
|
||||
|
||||
var physicalFilePath = Path.Combine(rootPath, relativePath.Trim('/'));
|
||||
var physicalFilePath = Path.Combine(rootPath, relativePath.TrimStart('/'));
|
||||
|
||||
return physicalFilePath;
|
||||
}
|
||||
|
||||
|
||||
#region 修改后留存
|
||||
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetSystemFileUploadPath(IWebHostEnvironment _hostEnvironment, string templateFolderName, string fileName)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
//文件类型路径处理
|
||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.SystemDataFolder, templateFolderName);
|
||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||||
|
||||
|
||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||||
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.SystemDataFolder}/{templateFolderName}/{trustedFileNameForFileStorage}";
|
||||
|
||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
return (serverFilePath, relativePath);
|
||||
}
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetOtherFileUploadPath(IWebHostEnvironment _hostEnvironment, string templateFolderName, string fileName)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
//文件类型路径处理
|
||||
var uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.OtherDataFolder, templateFolderName);
|
||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||||
|
||||
|
||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||||
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.OtherDataFolder}/{templateFolderName}/{trustedFileNameForFileStorage}";
|
||||
|
||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
return (serverFilePath, relativePath);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -417,7 +429,6 @@ public static class FileStoreHelper
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="siteid"></param>
|
||||
/// <param name="subjectId"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetUploadPrintscreenFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteid, Guid subjectId)
|
||||
{
|
||||
@@ -504,18 +515,18 @@ public static class FileStoreHelper
|
||||
|
||||
// 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径
|
||||
|
||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId,bool isChangeToPdfFormat=false)
|
||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid trialSiteId, Guid subjectId,bool isChangeToPdfFormat=false)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString());
|
||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), trialSiteId.ToString(), subjectId.ToString());
|
||||
|
||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||||
|
||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName, isChangeToPdfFormat);
|
||||
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{trustedFileNameForFileStorage}";
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{trialSiteId}/{subjectId}/{trustedFileNameForFileStorage}";
|
||||
|
||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
@@ -530,7 +541,7 @@ public static class FileStoreHelper
|
||||
return Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder);
|
||||
}
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
||||
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
||||
{
|
||||
#region 切换存储前
|
||||
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
@@ -541,7 +552,7 @@ public static class FileStoreHelper
|
||||
|
||||
//加入访视层级 和Data
|
||||
var path = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(),
|
||||
siteId.ToString(), subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder, studyId.ToString());
|
||||
subjectId.ToString(), subjectVisitId.ToString(), StaticData.Folder.DicomFolder, studyId.ToString());
|
||||
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
@@ -550,7 +561,7 @@ public static class FileStoreHelper
|
||||
|
||||
var physicalPath = Path.Combine(path, instanceId.ToString() );
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{subjectId}/{subjectVisitId}/{StaticData.Folder.DicomFolder}/{studyId}/{instanceId}";
|
||||
|
||||
//var physicalPath = Path.Combine(path, instanceId.ToString() + ".dcm");
|
||||
|
||||
@@ -564,7 +575,7 @@ public static class FileStoreHelper
|
||||
|
||||
var json = File.ReadAllText( Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
JObject jsonObject = (JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load })).IfNullThrowException();
|
||||
|
||||
int switchingRatio = 80;
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
using Hangfire;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
{
|
||||
public static class HangfireJobHelper
|
||||
{
|
||||
|
||||
|
||||
|
||||
//public static void AddOrUpdateCronJob(string jobId, string queueName, Expression<Action> methodCall, string cron)
|
||||
//{
|
||||
// RecurringJob.AddOrUpdate(jobId, queueName, methodCall, cron);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//添加 或者更新定时任务 Id 要唯一标识一个定义任务
|
||||
public static void AddOrUpdateCronJob<T>(string jobId, Expression<Action<T>> methodCall, string cron, string queueName = "default")
|
||||
{
|
||||
RecurringJob.AddOrUpdate<T>(jobId, queueName, methodCall, cron);
|
||||
}
|
||||
|
||||
public static void AddOrUpdateInitCronJob<T>(string jobId, Expression<Action<T>> methodCall, string cron)
|
||||
{
|
||||
RecurringJob.AddOrUpdate<T>(jobId, "sys_init", methodCall, cron);
|
||||
}
|
||||
|
||||
public static void RemoveCronJob(string jobId)
|
||||
{
|
||||
RecurringJob.RemoveIfExists(jobId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void ImmediatelyOnceOnlyJob(Expression<Action> methodCall)
|
||||
{
|
||||
BackgroundJob.Enqueue("immediately_once", methodCall);
|
||||
}
|
||||
|
||||
public static void ImmediatelyOnceOnlyJob<T>(Expression<Action<T>> methodCall)
|
||||
{
|
||||
BackgroundJob.Enqueue<T>("immediately_once", methodCall);
|
||||
}
|
||||
|
||||
public static void NotImmediatelyOnceOnlyJob(Expression<Action> methodCall, TimeSpan timeSpan)
|
||||
{
|
||||
BackgroundJob.Schedule("not_immediately_once", methodCall, timeSpan);
|
||||
}
|
||||
|
||||
public static void NotImmediatelyOnceOnlyJob<T>(Expression<Action<T>> methodCall, TimeSpan timeSpan)
|
||||
{
|
||||
BackgroundJob.Schedule<T>("not_immediately_once", methodCall, timeSpan);
|
||||
}
|
||||
|
||||
|
||||
public static void AddOrUpdateTrialCronJob (string jobId, Guid trialId, EmailBusinessScenario businessScenario, string emailCron)
|
||||
{
|
||||
|
||||
switch (businessScenario)
|
||||
{
|
||||
|
||||
case EmailBusinessScenario.QCTask:
|
||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialImageQCTaskEmailAsync(trialId), emailCron);
|
||||
break;
|
||||
case EmailBusinessScenario.QCQuestion:
|
||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialQCQuestionEmailAsync(trialId), emailCron);
|
||||
break;
|
||||
case EmailBusinessScenario.ImageQuestion:
|
||||
HangfireJobHelper.AddOrUpdateCronJob<IEmailSendService>(jobId, t => t.SendTrialImageQuestionAsync(trialId), emailCron);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NPOI.OpenXmlFormats.Wordprocessing;
|
||||
using NPOI.XWPF.UserModel;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
public static class NpoiWordHelper
|
||||
{
|
||||
public static async Task<IActionResult> TemplateExportWordAsync(string code, object data, IRepository<CommonDocument>? _commonDocumentRepository, IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
//var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
||||
|
||||
var physicalPath = code;
|
||||
|
||||
|
||||
using (FileStream stream = File.OpenRead(physicalPath))
|
||||
{
|
||||
XWPFDocument doc = new XWPFDocument(stream);
|
||||
//遍历段落
|
||||
foreach (var para in doc.Paragraphs)
|
||||
{
|
||||
ReplaceKey(para, data);
|
||||
}
|
||||
//遍历表格
|
||||
var tables = doc.Tables;
|
||||
foreach (var table in tables)
|
||||
{
|
||||
//ReplaceTableKey(table, data, "Data");
|
||||
}
|
||||
|
||||
foreach (var table in tables)
|
||||
{
|
||||
foreach (var row in table.Rows)
|
||||
{
|
||||
foreach (var cell in row.GetTableCells())
|
||||
{
|
||||
foreach (var para in cell.Paragraphs)
|
||||
{
|
||||
ReplaceKey(para, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileStream out1 = new FileStream("table.docx", FileMode.Create);
|
||||
doc.Write(out1);
|
||||
out1.Close();
|
||||
return new FileStreamResult(stream, "application/msword")
|
||||
{
|
||||
FileDownloadName = $"replaced_{DateTime.Now.ToString("yyyyMMddHHmmss")}.docx"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void ReplaceKey(XWPFParagraph para, object model)
|
||||
{
|
||||
string text = para.ParagraphText;
|
||||
|
||||
Type t = model.GetType();
|
||||
PropertyInfo[] pi = t.GetProperties();
|
||||
foreach (PropertyInfo p in pi)
|
||||
{
|
||||
//$$与模板中$$对应,也可以改成其它符号,比如{$name},务必做到唯一
|
||||
if (text.Contains("$" + p.Name + "$"))
|
||||
{
|
||||
text = text.Replace("$" + p.Name + "$", p.GetValue(model)?.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
//var runs = para.Runs;
|
||||
//string styleid = para.Style;
|
||||
//for (int i = 0; i < runs.Count; i++)
|
||||
//{
|
||||
// var run = runs[i];
|
||||
// text = run.ToString();
|
||||
// Type t = model.GetType();
|
||||
// PropertyInfo[] pi = t.GetProperties();
|
||||
// foreach (PropertyInfo p in pi)
|
||||
// {
|
||||
// //$$与模板中$$对应,也可以改成其它符号,比如{$name},务必做到唯一
|
||||
// if (text.Contains("$" + p.Name + "$"))
|
||||
// {
|
||||
// text = text.Replace("$" + p.Name + "$", p.GetValue(model)?.ToString());
|
||||
// }
|
||||
// }
|
||||
// runs[i].SetText(text, 0);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 替换表格Key
|
||||
/// </summary>
|
||||
/// <param name="table"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="field"></param>
|
||||
|
||||
private static void ReplaceTableKey(XWPFTable table, IList list, String field)
|
||||
{
|
||||
List<XWPFParagraph> paras = new List<XWPFParagraph>();
|
||||
// 获取最后一行数据,最后一行设置值
|
||||
Int32 iLastRowIndex = 0;
|
||||
for (int iIndex = 0; iIndex < table.Rows.Count; iIndex++)
|
||||
{
|
||||
if (iIndex == table.Rows.Count - 1)
|
||||
{
|
||||
iLastRowIndex = iIndex;
|
||||
foreach (var cell in table.Rows[iIndex].GetTableCells())
|
||||
{
|
||||
foreach (var para in cell.Paragraphs)
|
||||
{
|
||||
paras.Add(para);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除最后一行
|
||||
table.RemoveRow(iLastRowIndex);
|
||||
|
||||
for (int iIndex = 0; iIndex < list.Count; iIndex++)
|
||||
{
|
||||
object data = list[iIndex];
|
||||
Type t = data.GetType();
|
||||
PropertyInfo[] pi = t.GetProperties();
|
||||
// 表增加行
|
||||
XWPFTableRow m_row = table.CreateRow();
|
||||
CT_Row m_NewRow = new CT_Row();
|
||||
String text = String.Empty;
|
||||
Int32 jIndex = 0;
|
||||
paras.ForEach(para =>
|
||||
{
|
||||
text = para.ParagraphText;
|
||||
foreach (PropertyInfo p in pi)
|
||||
{
|
||||
if (text.Contains("$" + field + "." + p.Name + "$"))
|
||||
{
|
||||
m_row.GetCell(jIndex).SetText(p.GetValue(data, null).ToString());
|
||||
}
|
||||
}
|
||||
jIndex++;
|
||||
});
|
||||
m_row = new XWPFTableRow(m_NewRow, table);
|
||||
table.AddRow(m_row);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
using Aliyun.OSS;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Minio.DataModel.Args;
|
||||
using Minio;
|
||||
using NPOI.HPSF;
|
||||
using SharpCompress.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
{
|
||||
public class MinIOOptions : AWSOptions
|
||||
{
|
||||
public int port { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class AWSOptions
|
||||
{
|
||||
public string endPoint { get; set; }
|
||||
public bool useSSL { get; set; }
|
||||
public string accessKey { get; set; }
|
||||
public string secretKey { get; set; }
|
||||
public string bucketName { get; set; }
|
||||
public string viewEndpoint { get; set; }
|
||||
}
|
||||
|
||||
public class AliyunOSSOptions
|
||||
{
|
||||
public string regionId { get; set; }
|
||||
public string accessKeyId { get; set; }
|
||||
public string accessKeySecret { get; set; }
|
||||
public string endPoint { get; set; }
|
||||
public string bucketName { get; set; }
|
||||
|
||||
public string roleArn { get; set; }
|
||||
|
||||
public string region { get; set; }
|
||||
|
||||
public string viewEndpoint { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ObjectStoreServiceOptions
|
||||
{
|
||||
public string ObjectStoreUse { get; set; }
|
||||
public AliyunOSSOptions AliyunOSS { get; set; }
|
||||
public MinIOOptions MinIO { get; set; }
|
||||
|
||||
public AWSOptions AWS { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ObjectStoreDTO
|
||||
{
|
||||
public string ObjectStoreUse { get; set; }
|
||||
|
||||
public AliyunOSSOptions AliyunOSS { get; set; }
|
||||
|
||||
public MinIOOptions MinIO { get; set; }
|
||||
|
||||
public AWSOptions AWS { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class AliyunOSSTempToken
|
||||
{
|
||||
public string AccessKeyId { get; set; }
|
||||
public string AccessKeySecret { get; set; }
|
||||
public string SecurityToken { get; set; }
|
||||
public string Expiration { get; set; }
|
||||
|
||||
public string Region { get; set; }
|
||||
public string BucketName { get; set; }
|
||||
public string ViewEndpoint { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum ObjectStoreUse
|
||||
{
|
||||
AliyunOSS = 0,
|
||||
MinIO = 1,
|
||||
AWS = 2,
|
||||
}
|
||||
|
||||
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 DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
||||
|
||||
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
|
||||
|
||||
public Task<string> GetSignedUrl(string ossRelativePath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class OSSService : IOSSService
|
||||
{
|
||||
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
|
||||
|
||||
|
||||
public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
|
||||
{
|
||||
ObjectStoreServiceOptions = options.CurrentValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||
/// </summary>
|
||||
/// <param name="fileStream"></param>
|
||||
/// <param name="oosFolderPath"></param>
|
||||
/// <param name="fileRealName"></param>
|
||||
/// <param name="isFileNameAddGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
|
||||
{
|
||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}" : $"{oosFolderPath}/{fileRealName}";
|
||||
//var ossRelativePath = $"{oosFolderPath}/{Guid.NewGuid()}_{fileRealName}";
|
||||
//var ossRelativePath = oosFolderPath + "/" + fileRealName;
|
||||
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
fileStream.CopyTo(memoryStream);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
|
||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||
{
|
||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||
|
||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||
|
||||
|
||||
|
||||
// 上传文件
|
||||
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, memoryStream);
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithStreamData(memoryStream)
|
||||
.WithObjectSize(memoryStream.Length);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithStreamData(memoryStream)
|
||||
.WithObjectSize(memoryStream.Length);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "/" + ossRelativePath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||
/// </summary>
|
||||
/// <param name="localFilePath"></param>
|
||||
/// <param name="oosFolderPath"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true)
|
||||
{
|
||||
var localFileName = Path.GetFileName(localFilePath);
|
||||
|
||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
||||
|
||||
|
||||
//var ossRelativePath = oosFolderPath + "/" + localFileName;
|
||||
|
||||
|
||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||
{
|
||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||
|
||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||
|
||||
// 上传文件
|
||||
var result = _ossClient.PutObject(aliConfig.bucketName, ossRelativePath, localFilePath);
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithFileName(localFilePath);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithFileName(localFilePath);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||
}
|
||||
return "/" + ossRelativePath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath)
|
||||
{
|
||||
|
||||
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||
{
|
||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||
|
||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||
|
||||
// 上传文件
|
||||
var result = _ossClient.GetObject(aliConfig.bucketName, ossRelativePath);
|
||||
|
||||
// 将下载的文件流保存到本地文件
|
||||
using (var fs = File.OpenWrite(localFilePath))
|
||||
{
|
||||
result.Content.CopyTo(fs);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var getObjectArgs = new GetObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithFile(localFilePath);
|
||||
|
||||
await minioClient.GetObjectAsync(getObjectArgs);
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
var getObjectArgs = new GetObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithFile(localFilePath);
|
||||
|
||||
await minioClient.GetObjectAsync(getObjectArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw new BusinessValidationFailedException("oss下载失败!" + ex.Message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async Task<string> GetSignedUrl(string ossRelativePath)
|
||||
{
|
||||
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||
{
|
||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||
|
||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||
|
||||
// 生成签名URL。
|
||||
var req = new GeneratePresignedUriRequest(aliConfig.bucketName, ossRelativePath, SignHttpMethod.Get)
|
||||
{
|
||||
// 设置签名URL过期时间,默认值为3600秒。
|
||||
Expiration = DateTime.Now.AddHours(1),
|
||||
};
|
||||
var uri = _ossClient.GeneratePresignedUri(req);
|
||||
|
||||
return uri.PathAndQuery;
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}:{minIOConfig.port}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
//var reqParams = new Dictionary<string, string>(StringComparer.Ordinal)
|
||||
// {
|
||||
// { "response-content-type", "application/json" }
|
||||
// };
|
||||
|
||||
var args = new PresignedGetObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithExpiry(3600)
|
||||
/*.WithHeaders(reqParams)*/;
|
||||
|
||||
var presignedUrl = await minioClient.PresignedGetObjectAsync(args);
|
||||
|
||||
Uri uri = new Uri(presignedUrl);
|
||||
|
||||
string relativePath = uri.PathAndQuery;
|
||||
|
||||
|
||||
return relativePath;
|
||||
|
||||
}
|
||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||
{
|
||||
var minIOConfig = ObjectStoreServiceOptions.AWS;
|
||||
|
||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.endPoint}")
|
||||
.WithCredentials(minIOConfig.accessKey, minIOConfig.secretKey).WithSSL(minIOConfig.useSSL)
|
||||
.Build();
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw new BusinessValidationFailedException("oss授权url失败!" + ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public static class SendEmailHelper
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception )
|
||||
{
|
||||
|
||||
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>default</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
@@ -63,53 +63,45 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
||||
<PackageReference Include="Hangfire.Core" Version="1.8.12" />
|
||||
<PackageReference Include="BeetleX.BNR" Version="1.0.1" />
|
||||
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.7.0" />
|
||||
<PackageReference Include="EasyCaching.Redis" Version="1.9.2" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
|
||||
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
|
||||
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.1.0">
|
||||
<PackageReference Include="DistributedLock.Redis" Version="1.0.3" />
|
||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.4" />
|
||||
<PackageReference Include="fo-dicom" Version="5.1.2" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.2" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.12.0" />
|
||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
||||
<PackageReference Include="MailKit" Version="4.5.0" />
|
||||
<PackageReference Include="MediatR" Version="12.2.0" />
|
||||
<PackageReference Include="MimeKit" Version="4.5.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.32.0" />
|
||||
<PackageReference Include="Minio" Version="6.0.2" />
|
||||
<PackageReference Include="MiniWord" Version="0.8.0" />
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="fo-dicom.Drawing" Version="4.0.8" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.0.3" />
|
||||
<PackageReference Include="FreeSpire.Doc" Version="10.8.0" />
|
||||
<PackageReference Include="Hangfire" Version="1.7.31">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.2" />
|
||||
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.2">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.2">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.2" />
|
||||
<PackageReference Include="MailKit" Version="3.4.2" />
|
||||
<PackageReference Include="MediatR" Version="11.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MimeKit" Version="3.4.2" />
|
||||
<PackageReference Include="MiniExcel" Version="1.30.1" />
|
||||
<PackageReference Include="MiniWord" Version="0.6.1" />
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.0.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
||||
<PackageReference Include="NPOI" Version="2.6.0" />
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.0" />
|
||||
<PackageReference Include="Quartz" Version="3.5.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
|
||||
<PackageReference Include="WinSCP" Version="5.21.5" />
|
||||
<PackageReference Include="NPOI" Version="2.7.0" />
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
||||
<PackageReference Include="WinSCP" Version="6.3.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IRaCIS.Core.Infra.EFCore\IRaCIS.Core.Infra.EFCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Resources\ip2region.xdb">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,37 +0,0 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service.ViewModel
|
||||
{
|
||||
public class AllocationVisitViewModel
|
||||
{
|
||||
|
||||
public Guid SubjectVisitId { get; set; }
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public string BlindName { get; set; } = string.Empty;
|
||||
|
||||
public decimal VisitNum { get; set; }
|
||||
|
||||
|
||||
public Guid SiteId { get; set; }
|
||||
public String TrialSiteCode { get; set; } = String.Empty;
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public string VisitName { get; set; } = string.Empty;
|
||||
|
||||
public DateTime? CheckPassedTime { get; set; }
|
||||
|
||||
public bool IsUrgent { get; set; }
|
||||
|
||||
|
||||
public ReadingCategory ReadingCategoryEnum { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public int? GeneratedSubjectCount { get; set; }
|
||||
|
||||
public int? MatchSubejctCount { get; set; }
|
||||
|
||||
public int? CanGeneratedSubejctCount => MatchSubejctCount - GeneratedSubjectCount;
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +36,13 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
}
|
||||
|
||||
public class SubjectGeneratedTask
|
||||
{
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public bool IsHaveGeneratedTask { get; set; }
|
||||
}
|
||||
|
||||
public class ConsistentQuery : PageInput
|
||||
{
|
||||
[NotDefault]
|
||||
@@ -46,6 +55,15 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
}
|
||||
|
||||
public class GroupConsistentSimpleQuery
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
[NotDefault]
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
}
|
||||
public class GroupConsistentQuery : PageInput
|
||||
{
|
||||
[NotDefault]
|
||||
@@ -56,13 +74,21 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
}
|
||||
|
||||
public class ConsistentConfirmGenerateCommand
|
||||
public class SelfConsistentSimpleQuery
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TaskConsistentRuleId { get; set; }
|
||||
[NotDefault]
|
||||
public Guid DoctorUserId { get; set; }
|
||||
}
|
||||
|
||||
public class ConsistentConfirmGenerateCommand: SelfConsistentSimpleQuery
|
||||
{
|
||||
|
||||
|
||||
public List<Guid> SubejctIdList { get; set; }
|
||||
|
||||
public bool IsAutoAllocateGenerateTask { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +96,13 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
[NotDefault]
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
public List<Guid> SubejctIdList { get; set; }
|
||||
|
||||
public bool IsAutoAllocateGenerateTask { get; set; }
|
||||
}
|
||||
|
||||
public class DoctorSelfConsistentSubjectView: ConsistentCommonView
|
||||
@@ -86,7 +118,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class ConsistentCommonView
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public String TrialSiteCode { get; set; }
|
||||
public string SubjectCode { get; set; }
|
||||
@@ -105,6 +137,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public List<VisitTaskGroupSimpleDTO> SubjectTaskVisitList => VisitTaskList.GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Select(g => g.First()).OrderBy(t=>t.VisitTaskNum).ToList();
|
||||
|
||||
public List<VisitTaskGroupSimpleDTO> VisitTaskList { get; set; } = new List<VisitTaskGroupSimpleDTO>();
|
||||
|
||||
public List<UserSimpleInfo> DoctorUserList { get; set; }=new List<UserSimpleInfo>();
|
||||
}
|
||||
|
||||
public class VisitTaskGroupSimpleDTO
|
||||
@@ -166,31 +200,12 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
}
|
||||
|
||||
|
||||
//public class DoctorConsistentRuleSubjectView
|
||||
//{
|
||||
// public Guid TrialId => VisitTaskList.Select(t => t.TrialId).First();
|
||||
// public Guid SiteId => VisitTaskList.Select(t => t.SiteId).First();
|
||||
|
||||
// public String TrialSiteCode => VisitTaskList.Select(t => t.TrialSiteCode).First();
|
||||
// public string SubjectCode => VisitTaskList.Select(t => t.SubjectCode).First();
|
||||
|
||||
// public Guid SubjectId { get; set; }
|
||||
|
||||
// public bool IsHaveGeneratedTask { get; set; }
|
||||
// public int? ValidTaskCount { get; set; }
|
||||
|
||||
// public int? ValidVisitCount => VisitTaskList.Select(t => t.TaskName).Distinct().Count();
|
||||
|
||||
// public List<VisitTaskSimpleView> VisitTaskList { get; set; }
|
||||
|
||||
// //public List<UserSimpleInfo> HistoryDoctorUserList => VisitTaskList.SelectMany(t => t.RelationDoctorUserList).DistinctBy(t=>t.UserId).ToList();
|
||||
//}
|
||||
|
||||
public class InfluenceTaskInfo
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
@@ -233,7 +248,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
@@ -287,6 +302,17 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
|
||||
}
|
||||
public class UpdateTrialSiteCodeCommand
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public string VirtualSiteCode { get; set; }
|
||||
}
|
||||
|
||||
public class UpdateTrialSiteCodeCommandView: UpdateTrialSiteCodeCommand
|
||||
{
|
||||
public DateTime Creatime { get; set; }
|
||||
}
|
||||
|
||||
///<summary> TaskConsistentRuleAddOrEdit 列表查询参数模型</summary>
|
||||
public class TaskConsistentRuleAddOrEdit
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public string MedicalNo { get; set; } = string.Empty;
|
||||
|
||||
public int AuditState { get; set; }
|
||||
public DateTime? AuditSignTime { get; set; }
|
||||
@@ -54,7 +53,6 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
//开始读片时间
|
||||
public DateTime? FirstReadingTime { get; set; }
|
||||
|
||||
public string MedicalNo { get; set; } = string.Empty;
|
||||
|
||||
//读片时间差
|
||||
public TimeSpan? ReadingDurationTimeSpan { get; set; }
|
||||
@@ -71,7 +69,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
if (!ReadingDurationTimeSpan.HasValue)
|
||||
return "";
|
||||
else return string.Format("{0}d {1}h {2}min", (SignTime - FirstReadingTime)?.Days, (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes)
|
||||
else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds)
|
||||
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
|
||||
}
|
||||
}
|
||||
@@ -95,19 +93,27 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class TaskMedicalReviewQuery : PageInput
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid? SiteId { get; set; }
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传了Id 就不查询这条数据
|
||||
/// 传了Id
|
||||
/// </summary>
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
public Guid? MedicalManagerUserId { get; set; }
|
||||
|
||||
public bool IsGetBeRead { get; set; } = false;
|
||||
public DateTime? BeginSignTime { get; set; }
|
||||
public AuditAdvice? AuditAdviceEnum { get; set; }
|
||||
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
public DateTime? EndSignTime { get; set; }
|
||||
|
||||
public bool IsGetBeRead { get; set; } = false;
|
||||
|
||||
public bool IsGetNextMedicalReviewTask { get; set; } = false;
|
||||
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public string TrialSiteCode { get; set; } = String.Empty;
|
||||
public string TaskName { get; set; } = String.Empty;
|
||||
@@ -115,7 +121,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public bool? IsUrgent { get; set; }
|
||||
public Guid? DoctorUserId { get; set; }
|
||||
|
||||
|
||||
public bool? IsInvalid { get; set; }
|
||||
public TaskState? TaskState { get; set; }
|
||||
|
||||
public MedicalReviewAuditState? AuditState { get; set; }
|
||||
@@ -126,6 +132,20 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public ReadingTaskState? ReadingTaskState { get; set; }
|
||||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
|
||||
public MedicalReviewDoctorUserIdea? DoctorUserIdeaEnum { get; set; }
|
||||
|
||||
public Arm? ArmEnum { get; set; }
|
||||
|
||||
public DateTime? BeginAuditSignTime { get; set; }
|
||||
public DateTime? EndAuditSignTime { get; set; }
|
||||
|
||||
public bool? IsEffect { get; set; }
|
||||
public bool? IsHaveQuestion { get; set; }
|
||||
|
||||
|
||||
public DateTime? BeginAllocateDate { get; set; }
|
||||
public DateTime? EndAllocateDate { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -54,10 +54,16 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public Guid UpdateUserId { get; set; }
|
||||
|
||||
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public string BlindTrialSiteCode { get; set; }
|
||||
public String TrialSiteCode { get; set; } = String.Empty;
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public string MedicalNo { get; set; } = string.Empty;
|
||||
|
||||
public string BlindSubjectCode { get; set; } = string.Empty;
|
||||
|
||||
public bool IsPMSetBack { get; set; }
|
||||
|
||||
#region 标准配置
|
||||
@@ -86,7 +92,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
/// <summary>
|
||||
/// 任务展示访视 读片任务显示是否顺序
|
||||
/// </summary>
|
||||
public bool IsReadingTaskViewInOrder { get; set; } = true;
|
||||
public ReadingOrder IsReadingTaskViewInOrder { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -150,7 +156,18 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public bool IsCanEditUrgentState { get; set; }
|
||||
|
||||
public DateTime? FirstReadingTime { get;set; }
|
||||
|
||||
public string ReadingDuration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!SignTime.HasValue)
|
||||
return "";
|
||||
else return string.Format("{0}h:{1}m:{2}s", (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes, (SignTime - FirstReadingTime)?.Seconds)
|
||||
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UserSimpleInfo
|
||||
@@ -299,13 +316,14 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
public int UrgentCount { get; set; }
|
||||
|
||||
// public int UrgentCount => UnReadCanReadTaskList.Count(t => t.IsUrgent);
|
||||
|
||||
public int UrgentCount => UnReadCanReadTaskList.Count(t => t.IsUrgent);
|
||||
public List<IRUnreadTaskView> UnReadCanReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||
// public List<IRUnreadTaskView> UnReadCanReadTaskList => UnReadTaskList.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).ToList();
|
||||
|
||||
public List<IRUnreadTaskView> UnReadCanReadTaskList => UnReadTaskList.Where(y => y.IsFrontTaskNeedSignButNotSign == false && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)).ToList();
|
||||
|
||||
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||
public List<IRUnreadTaskView> UnReadTaskList { get; set; } = new List<IRUnreadTaskView>();
|
||||
}
|
||||
|
||||
public class IRUnreadTaskView
|
||||
@@ -355,8 +373,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class GetOrderReadingIQueryableInDto
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public string? SubjectCode { get; set; } = null;
|
||||
|
||||
@@ -369,7 +389,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid? SiteId { get; set; }
|
||||
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
@@ -391,6 +412,15 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public DateTime? EndAllocateDate { get; set; }
|
||||
|
||||
|
||||
|
||||
public DateTime? BeginSignTime { get; set; }
|
||||
|
||||
public DateTime? EndSignTime { get; set; }
|
||||
|
||||
public DateTime? BeginRequestReReadingTime { get; set; }
|
||||
public DateTime? EndRequestReReadingTime { get; set; }
|
||||
|
||||
public Guid? RootReReadingTaskId { get; set; }
|
||||
|
||||
public string? TaskCode { get; set; }
|
||||
@@ -412,6 +442,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public RequestReReadingResult? RequestReReadingResultEnum { get; set; }
|
||||
|
||||
|
||||
public bool? IsEffect { get; set; }
|
||||
|
||||
public string? RequestReReadingReason { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -467,7 +501,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid? SiteId { get; set; }
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
@@ -489,7 +523,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid? SiteId { get; set; }
|
||||
public Guid? TrialSiteId { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
@@ -498,6 +532,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public int? SubjectAllocateState { get; set; }
|
||||
|
||||
public List<Arm> ArmList { get; set; }=new List<Arm>() { };
|
||||
|
||||
[NotDefault]
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
@@ -529,7 +566,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class SubjectAssignStat
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
@@ -609,7 +646,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public class SubjectAssignView
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid SiteId { get; set; }
|
||||
public Guid TrialSiteId { get; set; }
|
||||
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
var list = await _taskAllocationRuleRepository.Where(t => t.TrialId == trialId).ProjectTo<TaskAllocationRuleDTO>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
//所有标准都是一样 后台只返回任意一个标准的就好了
|
||||
var trialTaskConfig = _repository.Where<ReadingQuestionCriterionTrial>(t => t.TrialId == trialId && t.IsConfirm).ProjectTo<TrialTaskConfigView>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
var trialTaskConfig = await _repository.Where<ReadingQuestionCriterionTrial>(t => t.TrialId == trialId && t.IsConfirm).ProjectTo<TrialTaskConfigView>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||||
|
||||
return (list, trialTaskConfig);
|
||||
}
|
||||
@@ -116,9 +116,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
// return ResponseOutput.Ok();
|
||||
//}
|
||||
|
||||
public async Task<List<SubjectCancelDoctorView>> GetSubjectCancelDoctorHistoryList(Guid subjectId)
|
||||
public async Task<List<SubjectCancelDoctorView>> GetSubjectCancelDoctorHistoryList(Guid subjectId,Guid trialReadingCriterionId)
|
||||
{
|
||||
var list = await _subjectCanceDoctorRepository.Where(t => t.SubjectId == subjectId).ProjectTo<SubjectCancelDoctorView>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
var list = await _subjectCanceDoctorRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId==trialReadingCriterionId).ProjectTo<SubjectCancelDoctorView>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,12 @@ using IRaCIS.Core.Domain.Share;
|
||||
using System.Linq.Expressions;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using System.Linq;
|
||||
using Nito.AsyncEx;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using Medallion.Threading;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
@@ -31,16 +34,32 @@ namespace IRaCIS.Core.Application.Service
|
||||
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<Enroll> _enrollRepository;
|
||||
private readonly IDistributedLockProvider _distributedLockProvider;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IRepository<TrialSite> _trialSiteRepository;
|
||||
|
||||
private readonly AsyncLock _mutex = new AsyncLock();
|
||||
private readonly IRepository<TrialVirtualSiteCodeUpdate> _trialVirtualSiteCodeUpdateRepository;
|
||||
|
||||
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository)
|
||||
private readonly IVisitTaskHelpeService _visitTaskCommonService;
|
||||
|
||||
|
||||
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository, IDistributedLockProvider distributedLockProvider,
|
||||
IRepository<Trial> trialRepository, IRepository<TrialSite> trialSiteRepository, IRepository<TrialVirtualSiteCodeUpdate> trialVirtualSiteCodeUpdateRepository, IVisitTaskHelpeService visitTaskCommonService)
|
||||
{
|
||||
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
||||
_visitTaskRepository = visitTaskRepository;
|
||||
_subjectUserRepository = subjectUserRepository;
|
||||
_subjectRepository = subjectRepository;
|
||||
_enrollRepository = enrollRepository;
|
||||
_distributedLockProvider = distributedLockProvider;
|
||||
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
_trialSiteRepository = trialSiteRepository;
|
||||
|
||||
_trialVirtualSiteCodeUpdateRepository = trialVirtualSiteCodeUpdateRepository;
|
||||
|
||||
_visitTaskCommonService = visitTaskCommonService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,7 +72,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
|
||||
|
||||
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => taskIdList.Contains(t.Id), u => new VisitTask() { TaskState = TaskState.NotEffect },true);
|
||||
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => taskIdList.Contains(t.Id), u => new VisitTask() { TaskState = TaskState.Adbandon }, true);
|
||||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
@@ -68,14 +87,14 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// <param name="queryVisitTask"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<AnalysisTaskView>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask)
|
||||
public async Task<IResponseOutput<PageOutput<AnalysisTaskView>>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask )
|
||||
{
|
||||
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId)
|
||||
.Where(t => t.IsAnalysisCreate)
|
||||
|
||||
.WhereIf(queryVisitTask.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == queryVisitTask.TrialReadingCriterionId)
|
||||
|
||||
.WhereIf(queryVisitTask.SiteId != null, t => t.Subject.SiteId == queryVisitTask.SiteId)
|
||||
.WhereIf(queryVisitTask.TrialSiteId != null, t => t.Subject.TrialSiteId == queryVisitTask.TrialSiteId)
|
||||
.WhereIf(queryVisitTask.SubjectId != null, t => t.SubjectId == queryVisitTask.SubjectId)
|
||||
.WhereIf(queryVisitTask.TaskState != null, t => t.TaskState == queryVisitTask.TaskState)
|
||||
.WhereIf(queryVisitTask.IsUrgent != null, t => t.IsUrgent == queryVisitTask.IsUrgent)
|
||||
@@ -85,19 +104,22 @@ namespace IRaCIS.Core.Application.Service
|
||||
.WhereIf(queryVisitTask.TaskAllocationState != null, t => t.TaskAllocationState == queryVisitTask.TaskAllocationState)
|
||||
.WhereIf(queryVisitTask.IsSelfAnalysis != null, t => t.IsSelfAnalysis == queryVisitTask.IsSelfAnalysis)
|
||||
.WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum)
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => /*(t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) ||*/ (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) /*&& t.IsAnalysisCreate == false*/))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => (t.Subject.Code.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
|
||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate!.Value.AddDays(1))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.Subject.Code.Contains(queryVisitTask.SubjectCode)||t.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate))
|
||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime >= queryVisitTask.BeginAllocateDate)
|
||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime <= queryVisitTask.EndAllocateDate)
|
||||
.WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime >= queryVisitTask.BeginSignTime)
|
||||
.WhereIf(queryVisitTask.EndSignTime != null, t => t.SignTime <= queryVisitTask.EndSignTime)
|
||||
.ProjectTo<AnalysisTaskView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
|
||||
|
||||
var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray);
|
||||
|
||||
//var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).ProjectTo<TrialTaskConfigView>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
return pageList;
|
||||
var trialTaskConfig = _repository.Where<Trial>(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion=t.ReadingQuestionCriterionTrialList.Any(t=>t.IsSigned && t.IsConfirm && t.ReadingType==ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault();
|
||||
|
||||
return ResponseOutput.Ok(pageList, trialTaskConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,13 +144,12 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// 确认生成自身一致性分析任务
|
||||
/// </summary>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <param name="_visitTaskCommonService"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
//[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
public async Task<IResponseOutput> ConfirmGenerateSelfConsistentTask(ConsistentConfirmGenerateCommand inCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
|
||||
public async Task<IResponseOutput> ConfirmGenerateSelfConsistentTask(ConsistentConfirmGenerateCommand inCommand)
|
||||
{
|
||||
|
||||
|
||||
@@ -136,13 +157,34 @@ namespace IRaCIS.Core.Application.Service
|
||||
var doctorUserId = inCommand.DoctorUserId;
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
//随机分配
|
||||
if (inCommand.IsAutoAllocateGenerateTask)
|
||||
{
|
||||
var subjectList = (await GetSelfConsistentRuleMatchSubjectIdListAsync(new SelfConsistentSimpleQuery() { TaskConsistentRuleId = inCommand.TaskConsistentRuleId, DoctorUserId = inCommand.DoctorUserId })).ToList();
|
||||
|
||||
if (subjectList.Any(t => t.IsHaveGeneratedTask))
|
||||
{
|
||||
//已手动分配,不允许自动分配
|
||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
||||
}
|
||||
|
||||
if (subjectList.Count<2 * filterObj.PlanSubjectCount)
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
||||
}
|
||||
|
||||
inCommand.SubejctIdList = GetRandomSubjectIdList(subjectList.Select(t => t.SubjectId).ToList(), filterObj.PlanSubjectCount);
|
||||
}
|
||||
|
||||
var list = await GetIQueryableDoctorSelfConsistentSubjectView(filterObj, doctorUserId, inCommand.SubejctIdList).ToListAsync();
|
||||
|
||||
//var (group, query) = GetIQueryableDoctorSelfConsistentRuleSubjectView(filterObj, inCommand.SubejctIdList);
|
||||
|
||||
//var list = query.OrderByDescending(t => t.IsHaveGeneratedTask).ToList();
|
||||
|
||||
using (await _mutex.LockAsync())
|
||||
var @lock = _distributedLockProvider.CreateLock($"VisitTaskCode");
|
||||
|
||||
using (await @lock.AcquireAsync())
|
||||
{
|
||||
int maxCodeInt = 0;
|
||||
|
||||
@@ -152,9 +194,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var blindSubjectCode = string.Empty;
|
||||
|
||||
var subjectTask = _visitTaskRepository.Where(t => t.SubjectId == subject.SubjectId && t.TrialReadingCriterionId==trialReadingCriterionId && t.IsSelfAnalysis == true).OrderByDescending(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
var subjectTask = _visitTaskRepository.Where(t => t.SubjectId == subject.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsSelfAnalysis == true).OrderByDescending(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
|
||||
if (subjectTask!=null && subjectTask.BlindSubjectCode != String.Empty)
|
||||
if (subjectTask != null && subjectTask.BlindSubjectCode != String.Empty)
|
||||
{
|
||||
blindSubjectCode = subjectTask.BlindSubjectCode;
|
||||
}
|
||||
@@ -162,11 +204,11 @@ namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
var maxCodeStr = _visitTaskRepository.Where(t => t.TrialId == subject.TrialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsSelfAnalysis == true).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
|
||||
if ( !string.IsNullOrEmpty(maxCodeStr))
|
||||
if (!string.IsNullOrEmpty(maxCodeStr))
|
||||
{
|
||||
int.TryParse(maxCodeStr.Substring(maxCodeStr.Length - filterObj.BlindSubjectNumberOfPlaces), out maxCodeInt);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
blindSubjectCode = filterObj.BlindTrialSiteCode + (maxCodeInt + 1).ToString($"D{filterObj.BlindSubjectNumberOfPlaces}");
|
||||
}
|
||||
@@ -187,7 +229,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
var lastTask = (subject.VisitTaskList.Take(filterObj.PlanVisitCount).Last()).Clone();
|
||||
|
||||
var existGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId &&t.TrialReadingCriterionId==trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum == lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
var existGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum == lastTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]).ProjectTo<VisitTaskSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
|
||||
|
||||
if (existGlobal == null)
|
||||
@@ -200,7 +242,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
ReadingCategory = ReadingCategory.Global,
|
||||
TaskName = lastTask.TaskName + "_Global",
|
||||
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
||||
TrialReadingCriterionId=trialReadingCriterionId,
|
||||
TrialReadingCriterionId = trialReadingCriterionId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -242,16 +284,17 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<DoctorGroupConsistentSubjectView>> GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery)
|
||||
public async Task<IResponseOutput<PageOutput<DoctorGroupConsistentSubjectView>> > GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery)
|
||||
{
|
||||
var trialId = inQuery.TrialId;
|
||||
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.TrialReadingCriterionId==inQuery.TrialReadingCriterionId && t.IsSelfAnalysis == false);
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.IsSelfAnalysis == false);
|
||||
|
||||
|
||||
if (filterObj == null)
|
||||
{
|
||||
return new PageOutput<DoctorGroupConsistentSubjectView>();
|
||||
object tt = null;
|
||||
return ResponseOutput.Ok(new PageOutput<DoctorGroupConsistentSubjectView>(), new { Rule = tt, IsAllowAutoAllocate = false }) ;
|
||||
}
|
||||
|
||||
var query = await GetGroupConsistentQueryAsync(filterObj);
|
||||
@@ -259,7 +302,13 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var pagedList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(DoctorSelfConsistentSubjectView.SubjectCode) : inQuery.SortField, inQuery.Asc);
|
||||
|
||||
return pagedList;
|
||||
var rule = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == false && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
|
||||
var list = await GetGroupConsistentRuleMatchSubjectIdListAsync(new GroupConsistentSimpleQuery() { TrialId = inQuery.TrialId, TrialReadingCriterionId = inQuery.TrialReadingCriterionId });
|
||||
|
||||
var isAllowAutoAllocate = !list.Any(t => t.IsHaveGeneratedTask) && list.Count() > 2*(rule?.PlanSubjectCount??0);
|
||||
|
||||
return ResponseOutput.Ok(pagedList, new {Rule=rule, IsAllowAutoAllocate = isAllowAutoAllocate });
|
||||
}
|
||||
|
||||
|
||||
@@ -268,32 +317,54 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// 确认生成组间一致性分析任务
|
||||
/// </summary>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <param name="_visitTaskCommonService"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
public async Task<IResponseOutput> ConfirmGenerateGroupConsistentTask(GroupConsistentConfirmGenrateCommand inCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
|
||||
public async Task<IResponseOutput> ConfirmGenerateGroupConsistentTask(GroupConsistentConfirmGenrateCommand inCommand)
|
||||
{
|
||||
var trialId = inCommand.TrialId;
|
||||
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.IsSelfAnalysis == false);
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.IsSelfAnalysis == false);
|
||||
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
//随机分配
|
||||
if (inCommand.IsAutoAllocateGenerateTask)
|
||||
{
|
||||
var subjectSelectList = (await GetGroupConsistentRuleMatchSubjectIdListAsync(new GroupConsistentSimpleQuery() { TrialId = inCommand.TrialId, TrialReadingCriterionId = inCommand.TrialReadingCriterionId })).ToList();
|
||||
|
||||
if (subjectSelectList.Any(t => t.IsHaveGeneratedTask))
|
||||
{
|
||||
//已手动分配过,不允许自动分配
|
||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]);
|
||||
}
|
||||
|
||||
if (subjectSelectList.Count< 2 * filterObj.PlanSubjectCount)
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]);
|
||||
}
|
||||
|
||||
inCommand.SubejctIdList = GetRandomSubjectIdList(subjectSelectList.Select(t => t.SubjectId).ToList(), filterObj.PlanSubjectCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var query = await GetGroupConsistentQueryAsync(filterObj, inCommand.SubejctIdList);
|
||||
|
||||
var subjectList = query.ToList();
|
||||
|
||||
var doctorUserIdQuery = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId).Where(t => t.EnrollReadingCategoryList.Where(t=>t.TrialReadingCriterionId==trialReadingCriterionId).Any(c => c.ReadingCategory == ReadingCategory.Global || c.ReadingCategory == ReadingCategory.Visit))
|
||||
var doctorUserIdQuery = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId).Where(t => t.EnrollReadingCategoryList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(c => c.ReadingCategory == ReadingCategory.Global || c.ReadingCategory == ReadingCategory.Visit))
|
||||
.Where(t => t.EnrollReadingCriteriaList.Any(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsJoinAnalysis == true))
|
||||
join user in _repository.Where<User>() on enroll.DoctorId equals user.DoctorId
|
||||
select user.Id;
|
||||
|
||||
var configDoctorUserIdList = await doctorUserIdQuery.ToListAsync();
|
||||
|
||||
using (await _mutex.LockAsync())
|
||||
var @lock = _distributedLockProvider.CreateLock($"VisitTaskCode");
|
||||
|
||||
using (await @lock.AcquireAsync())
|
||||
{
|
||||
int maxCodeInt = 0;
|
||||
|
||||
@@ -305,7 +376,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var blindSubjectCode = string.Empty;
|
||||
|
||||
var subjectTask = _visitTaskRepository.Where(t => t.SubjectId == subject.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsSelfAnalysis==false).OrderByDescending(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
var subjectTask = _visitTaskRepository.Where(t => t.SubjectId == subject.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsSelfAnalysis == false).OrderByDescending(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
if (subjectTask != null && subjectTask.BlindSubjectCode != String.Empty)
|
||||
{
|
||||
blindSubjectCode = subjectTask.BlindSubjectCode;
|
||||
@@ -333,7 +404,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
//需要处理的医生
|
||||
|
||||
var needAddDoctorUserIdList = configDoctorUserIdList.Except(subject.VisitTaskList.Select(t => (Guid)t.DoctorUserId)).ToList();
|
||||
var needAddDoctorUserIdList = configDoctorUserIdList.Except(subject.VisitTaskList.Select(t => t.DoctorUserId!.Value)).ToList();
|
||||
|
||||
if (needAddDoctorUserIdList.Count == 0)
|
||||
{
|
||||
@@ -366,10 +437,10 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
TrialReadingCriterionId = task.TrialReadingCriterionId,
|
||||
|
||||
BlindSubjectCode=blindSubjectCode,
|
||||
BlindTrialSiteCode=filterObj.BlindTrialSiteCode
|
||||
BlindSubjectCode = blindSubjectCode,
|
||||
BlindTrialSiteCode = filterObj.BlindTrialSiteCode
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -455,7 +526,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
#region Subejct 维度
|
||||
|
||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId== trialReadingCriterionId &&
|
||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId &&
|
||||
u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject) && u.DoctorUserId == doctorUserId;
|
||||
|
||||
|
||||
@@ -489,16 +560,16 @@ namespace IRaCIS.Core.Application.Service
|
||||
var query = subjectQuery.Select(t => new DoctorSelfConsistentSubjectView()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
TrialSiteId = t.TrialSiteId,
|
||||
SubjectCode = t.Code,
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
SubjectId = t.Id,
|
||||
|
||||
IsReReadingOrBackInfluenceAnalysis=t.IsReReadingOrBackInfluenceAnalysis,
|
||||
IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis,
|
||||
|
||||
BlindSubjectCode = t.SubjectVisitTaskList.Where(t => t.IsAnalysisCreate && t.TrialReadingCriterionId == trialReadingCriterionId).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault(),
|
||||
|
||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.DoctorUserId == doctorUserId && c.IsSelfAnalysis == true && c.TrialReadingCriterionId==trialReadingCriterionId),
|
||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.DoctorUserId == doctorUserId && c.IsSelfAnalysis == true && c.TrialReadingCriterionId == trialReadingCriterionId),
|
||||
|
||||
|
||||
ValidVisitCount = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count(),
|
||||
@@ -521,7 +592,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
|
||||
TrialReadingCriterionId=c.TrialReadingCriterionId,
|
||||
TrialReadingCriterionId = c.TrialReadingCriterionId,
|
||||
IsClinicalDataSign = c.IsClinicalDataSign,
|
||||
IsNeedClinicalDataSign = c.IsNeedClinicalDataSign,
|
||||
|
||||
@@ -559,7 +630,12 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 组间一致性分析 满足条件的subject 筛选
|
||||
/// </summary>
|
||||
/// <param name="filterObj"></param>
|
||||
/// <param name="subejctIdList"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<IQueryable<DoctorGroupConsistentSubjectView>> GetGroupConsistentQueryAsync(TaskConsistentRule filterObj, List<Guid>? subejctIdList = null)
|
||||
{
|
||||
|
||||
@@ -570,7 +646,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
|
||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId
|
||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && u.TrialReadingCriterionId == trialReadingCriterionId
|
||||
&& (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
||||
|
||||
|
||||
@@ -611,14 +687,21 @@ namespace IRaCIS.Core.Application.Service
|
||||
var query = subjectQuery.Select(t => new DoctorGroupConsistentSubjectView()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
TrialSiteId = t.TrialSiteId,
|
||||
SubjectCode = t.Code,
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
SubjectId = t.Id,
|
||||
IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis,
|
||||
|
||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId==trialReadingCriterionId),
|
||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId == trialReadingCriterionId),
|
||||
|
||||
DoctorUserList = t.SubjectDoctorList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsConfirmed).Select(t => new UserSimpleInfo()
|
||||
{
|
||||
UserId = t.Id,
|
||||
FullName = t.DoctorUser.FullName,
|
||||
UserCode = t.DoctorUser.UserCode,
|
||||
UserName = t.DoctorUser.UserName
|
||||
}).ToList(),
|
||||
|
||||
ValidVisitCount = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count(),
|
||||
|
||||
@@ -658,7 +741,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
[HttpPost]
|
||||
public async Task<TaskConsistentRuleBasic?> GetConsistentRule(TaskConsistentRuleQuery inQuery)
|
||||
{
|
||||
return await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == inQuery.IsSelfAnalysis && t.TrialReadingCriterionId==inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
return await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == inQuery.IsSelfAnalysis && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -667,13 +750,23 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<List<TaskConsistentRuleView>> GetSelfConsistentDoctorStatList(TaskConsistentRuleQuery inQuery)
|
||||
public async Task<IResponseOutput<List<TaskConsistentRuleView>>> GetSelfConsistentDoctorStatList(TaskConsistentRuleQuery inQuery)
|
||||
{
|
||||
|
||||
|
||||
var trialId = inQuery.TrialId;
|
||||
|
||||
var taskConsistentRuleQueryable = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId && t.EnrollStatus==EnrollStatus.ConfirmIntoGroup)
|
||||
join user in _repository.Where<User>() on enroll.DoctorId equals user.DoctorId
|
||||
join taskConsistentRule in _repository.Where<TaskConsistentRule>(t => t.TrialId == trialId &&t.TrialReadingCriterionId==inQuery.TrialReadingCriterionId && t.IsSelfAnalysis) on enroll.TrialId equals taskConsistentRule.TrialId
|
||||
Expression<Func<VisitTask, bool>> comonTaskFilter = u => u.TrialId == trialId && u.IsAnalysisCreate == false && u.TaskState == TaskState.Effect && u.ReadingTaskState == ReadingTaskState.HaveSigned && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject);
|
||||
|
||||
//&& u.TrialReadingCriterionId == trialReadingCriterionId &&u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && u.DoctorUserId == doctorUserId;
|
||||
|
||||
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
||||
|
||||
|
||||
var taskConsistentRuleQueryable = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId && t.EnrollStatus == EnrollStatus.ConfirmIntoGroup
|
||||
&& t.EnrollReadingCriteriaList.Any(c => c.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && c.IsJoinAnalysis))
|
||||
join user in _repository.Where<User>() on enroll.DoctorUserId equals user.Id
|
||||
join taskConsistentRule in _repository.Where<TaskConsistentRule>(t => t.TrialId == trialId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.IsSelfAnalysis) on enroll.TrialId equals taskConsistentRule.TrialId
|
||||
select new TaskConsistentRuleView()
|
||||
{
|
||||
Id = taskConsistentRule.Id,
|
||||
@@ -692,7 +785,20 @@ namespace IRaCIS.Core.Application.Service
|
||||
IsHaveReadingPeriod = taskConsistentRule.IsHaveReadingPeriod,
|
||||
PlanVisitCount = taskConsistentRule.PlanVisitCount,
|
||||
|
||||
GeneratedSubjectCount = taskConsistentRule.Trial.VisitTaskList.Where(t => t.IsAnalysisCreate && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.IsSelfAnalysis == true && t.DoctorUserId == user.Id).Select(t => t.SubjectId).Distinct().Count(),
|
||||
GeneratedSubjectCount = taskConsistentRule.TrialReadingCriterion.VisitTaskList.Where(t => t.IsAnalysisCreate && t.IsSelfAnalysis == true && t.DoctorUserId == user.Id).Select(t => t.SubjectId).Distinct().Count(),
|
||||
|
||||
|
||||
MatchSubejctCount = taskConsistentRule.Trial.SubjectList.AsQueryable()
|
||||
.Where(t => taskConsistentRule.IsHaveReadingPeriod == false ? t.SubjectVisitTaskList.AsQueryable()
|
||||
.Where(visitTaskFilter).Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < DateTime.Now && t.DoctorUserId == user.Id)
|
||||
.Count() >= taskConsistentRule.PlanVisitCount :
|
||||
|
||||
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter)
|
||||
.Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < DateTime.Now && t.DoctorUserId == user.Id)
|
||||
.Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(taskConsistentRule.PlanVisitCount + 1).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
||||
.Count(),
|
||||
|
||||
|
||||
|
||||
AnalysisDoctorUser = new UserSimpleInfo()
|
||||
{
|
||||
@@ -719,10 +825,48 @@ namespace IRaCIS.Core.Application.Service
|
||||
//var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
// .ProjectTo<TaskConsistentRuleView>(_mapper.ConfigurationProvider);
|
||||
|
||||
return await taskConsistentRuleQueryable.ToListAsync();
|
||||
var list= await taskConsistentRuleQueryable.ToListAsync();
|
||||
|
||||
var rule= await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == true && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo<TaskConsistentRuleBasic>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
|
||||
return ResponseOutput.Ok(list, rule);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput> UpdateTrialVirtualSiteCode(UpdateTrialSiteCodeCommand inCommand)
|
||||
{
|
||||
|
||||
if (_trialSiteRepository.Where(t => t.TrialId == inCommand.TrialId, false, true).Any(t => t.TrialSiteCode == inCommand.VirtualSiteCode))
|
||||
{
|
||||
return ResponseOutput.NotOk(_localizer["TaskConsistent_SiteCodeExists"]);
|
||||
}
|
||||
|
||||
var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == inCommand.TrialId);
|
||||
|
||||
var oldCode = trial.VitrualSiteCode;
|
||||
|
||||
trial.VitrualSiteCode = inCommand.VirtualSiteCode;
|
||||
|
||||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trial.Id, u => new VisitTask() { BlindTrialSiteCode = inCommand.VirtualSiteCode });
|
||||
|
||||
await _taskConsistentRuleRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trial.Id, u => new TaskConsistentRule() { BlindTrialSiteCode = inCommand.VirtualSiteCode });
|
||||
|
||||
|
||||
await _visitTaskRepository.ExecuteUpdateAsync(t => t.TrialId == trial.Id, s => s.SetProperty(e => e.BlindSubjectCode, u => u.BlindSubjectCode.Replace(oldCode, inCommand.VirtualSiteCode)));
|
||||
|
||||
await _trialVirtualSiteCodeUpdateRepository.AddAsync(new TrialVirtualSiteCodeUpdate() { VirturalSiteCode = inCommand.VirtualSiteCode, TrialId = inCommand.TrialId });
|
||||
|
||||
await _trialRepository.SaveChangesAsync();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
public async Task<List<UpdateTrialSiteCodeCommandView>> GetUpdateVirtualSiteCodeList(Guid trialId)
|
||||
{
|
||||
var list = await _trialVirtualSiteCodeUpdateRepository.Where(t => t.TrialId == trialId).Select(t => new UpdateTrialSiteCodeCommandView() { TrialId = trialId, VirtualSiteCode = t.VirturalSiteCode, Creatime = t.CreateTime }).OrderByDescending(t=>t.Creatime).ToListAsync();
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
@@ -732,7 +876,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var verifyExp1 = new EntityVerifyExp<TaskConsistentRule>()
|
||||
{
|
||||
VerifyExp = t => t.TrialId == addOrEditTaskConsistentRule.TrialId && t.IsSelfAnalysis == addOrEditTaskConsistentRule.IsSelfAnalysis && t.TrialReadingCriterionId==addOrEditTaskConsistentRule.TrialReadingCriterionId,
|
||||
VerifyExp = t => t.TrialId == addOrEditTaskConsistentRule.TrialId && t.IsSelfAnalysis == addOrEditTaskConsistentRule.IsSelfAnalysis && t.TrialReadingCriterionId == addOrEditTaskConsistentRule.TrialReadingCriterionId,
|
||||
//"已有该项目配置,不允许继续增加"
|
||||
VerifyMsg = _localizer["TaskConsistent_TaskGenerated"]
|
||||
};
|
||||
@@ -743,6 +887,22 @@ namespace IRaCIS.Core.Application.Service
|
||||
return ResponseOutput.NotOk(_localizer["TaskConsistent_MedicalAuditTaskExists"]);
|
||||
}
|
||||
|
||||
|
||||
if (_trialSiteRepository.Where(t => t.TrialId == addOrEditTaskConsistentRule.TrialId, false, true).Any(t => t.TrialSiteCode == addOrEditTaskConsistentRule.BlindTrialSiteCode))
|
||||
{
|
||||
return ResponseOutput.NotOk(_localizer["TaskConsistent_SiteCodeExists"]);
|
||||
}
|
||||
|
||||
var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == addOrEditTaskConsistentRule.TrialId);
|
||||
|
||||
if (string.IsNullOrEmpty(trial.VitrualSiteCode))
|
||||
{
|
||||
await _trialVirtualSiteCodeUpdateRepository.AddAsync(new TrialVirtualSiteCodeUpdate() { VirturalSiteCode = addOrEditTaskConsistentRule.BlindTrialSiteCode, TrialId = addOrEditTaskConsistentRule.TrialId });
|
||||
}
|
||||
|
||||
trial.VitrualSiteCode = addOrEditTaskConsistentRule.BlindTrialSiteCode;
|
||||
|
||||
|
||||
var entity = await _taskConsistentRuleRepository.InsertOrUpdateAsync(addOrEditTaskConsistentRule, true, verifyExp1);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
@@ -757,7 +917,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
var config = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == taskConsistentRuleId);
|
||||
|
||||
|
||||
if (await _visitTaskRepository.AnyAsync(t => t.IsAnalysisCreate && t.TrialId == config.TrialId && t.IsSelfAnalysis == config.IsSelfAnalysis && t.TrialReadingCriterionId==config.TrialReadingCriterionId))
|
||||
if (await _visitTaskRepository.AnyAsync(t => t.IsAnalysisCreate && t.TrialId == config.TrialId && t.IsSelfAnalysis == config.IsSelfAnalysis && t.TrialReadingCriterionId == config.TrialReadingCriterionId))
|
||||
{
|
||||
//"该标准已产生一致性分析任务,不允许删除"
|
||||
throw new BusinessValidationFailedException(_localizer["TaskConsistent_SignedTaskCannotBeInvalidated"]);
|
||||
@@ -770,8 +930,65 @@ namespace IRaCIS.Core.Application.Service
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取自身一致性分析 符合条件的subject 数组
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SubjectGeneratedTask>> GetSelfConsistentRuleMatchSubjectIdListAsync(SelfConsistentSimpleQuery inQuery)
|
||||
{
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inQuery.TaskConsistentRuleId);
|
||||
|
||||
var subjectList = await GetIQueryableDoctorSelfConsistentSubjectView(filterObj, inQuery.DoctorUserId).Select(t => new SubjectGeneratedTask() { SubjectId = t.SubjectId, IsHaveGeneratedTask = t.IsHaveGeneratedTask }).ToListAsync();
|
||||
|
||||
return subjectList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取组件一致性分析符合条件的subject 数组
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SubjectGeneratedTask>> GetGroupConsistentRuleMatchSubjectIdListAsync(GroupConsistentSimpleQuery inQuery)
|
||||
{
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == inQuery.TrialId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.IsSelfAnalysis == false);
|
||||
|
||||
var subjectList = await (await GetGroupConsistentQueryAsync(filterObj)).Select(t => new SubjectGeneratedTask() { SubjectId = t.SubjectId, IsHaveGeneratedTask = t.IsHaveGeneratedTask }).ToListAsync();
|
||||
|
||||
return subjectList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机算法,选择指定数量的 subject
|
||||
/// </summary>
|
||||
/// <param name="matchSubjectIdList"></param>
|
||||
/// <param name="countToSelect"></param>
|
||||
/// <returns></returns>
|
||||
public List<Guid> GetRandomSubjectIdList(List<Guid> matchSubjectIdList, int countToSelect)
|
||||
{
|
||||
|
||||
// 使用 Fisher-Yates 随机置换算法来选择指定数量的 GUID
|
||||
Random random = new Random();
|
||||
|
||||
for (int i = 0; i < countToSelect; i++)
|
||||
{
|
||||
// 生成一个随机索引
|
||||
int randomIndex = random.Next(i, matchSubjectIdList.Count);
|
||||
|
||||
// 将选中的元素与当前元素交换位置
|
||||
Guid temp = matchSubjectIdList[randomIndex];
|
||||
matchSubjectIdList[randomIndex] = matchSubjectIdList[i];
|
||||
matchSubjectIdList[i] = temp;
|
||||
}
|
||||
|
||||
return matchSubjectIdList.Take(countToSelect).ToList();
|
||||
|
||||
// 使用洗牌算法来随机选择指定数量的GUID
|
||||
//Random random = new Random();
|
||||
//return matchSubjectIdList.OrderBy(g => random.Next()).Take(countToSelect).ToList();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user