Compare commits
1744 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8fc886a1db | |||
| 5832610d3d | |||
| e675542136 | |||
| 8f7a3ab713 | |||
| 02d98cfa75 | |||
| 8bb1e8cf43 | |||
| b3e37c7ea4 | |||
| 5bdb89df7d | |||
| 10d50f3b5a | |||
| bb6d36c8be | |||
| d91f4dc728 | |||
| f01e5335d6 | |||
| 3e8794b335 | |||
| 79375f7106 | |||
| 72b2047862 | |||
| 8b124e1c60 | |||
| 5b2449b607 | |||
| 3f4a5e3040 | |||
| 75a24b8aef | |||
| 493c46ed15 | |||
| 5c2467bdbb | |||
| 0777ea830c | |||
| b75223f8a0 | |||
| 6a4e42f9dc | |||
| f7eec6327a | |||
| 1a4301233c | |||
| b6b5a5d0de | |||
| 92c435cf23 | |||
| 8697ec952c | |||
| c6d3ae7c8b | |||
| 376c02f44c | |||
| da9a7affa9 | |||
| ac62f48a71 | |||
| 3d8cdd6ac6 | |||
| 9380b40c28 | |||
| cc823daee5 | |||
| b4594a4c47 | |||
| c8660c0426 | |||
| 375a724169 | |||
| 67375c3cbd | |||
| 1645aaf69a | |||
| 99b7d3a4f8 | |||
| eac77e45d2 | |||
| ebf05df568 | |||
| f464b25c2b | |||
| b0dbe1442c | |||
| 5ae3220e67 | |||
| f31a6408ac | |||
| 9234e7ebe9 | |||
| 609a7fb427 | |||
| a92bbbb275 | |||
| c2bf16e1ff | |||
| dce2509613 | |||
| 1ac336220e | |||
| a47f2fd496 | |||
| 45c0704b40 | |||
| 97cf5ce93c | |||
| 786367f9fe | |||
| f8c9cb1564 | |||
| ee11290037 | |||
| 42f3f6fb67 | |||
| 2a844b11bd | |||
| 5579fe4e95 | |||
| ee96435379 | |||
| 4fce96db0e | |||
| 14e7ecd171 | |||
| ffeece79fe | |||
| 5c86989dfa | |||
| c6a8c4d24f | |||
| 477691ec70 | |||
| 5518609d54 | |||
| 9f706d3123 | |||
| 5956d32c36 | |||
| a60e00159d | |||
| 47277086ac | |||
| c7571570e9 | |||
| 83d6859347 | |||
| a42986dcab | |||
| 13fbf36de0 | |||
| 4ba2aa4769 | |||
| 6b1a6a81eb | |||
| 62f8d5823f | |||
| 5cbefec0b0 | |||
| b154540885 | |||
| 9eda07b253 | |||
| 2995d2273a | |||
| 8fffdb244d | |||
| 657da0c554 | |||
| 1912e1cfcd | |||
| 3313c0223d | |||
| 3c9b87ba01 | |||
| 65b52a1836 | |||
| 684dbbd8e1 | |||
| 5a3127bb8e | |||
| 0b9cf600ba | |||
| b2f4fa3fb9 | |||
| ecae4f663a | |||
| 200da3375b | |||
| a3cedaa7b8 | |||
| 37fc48c64d | |||
| 1e4ee0a5e9 | |||
| bc383d9b23 | |||
| 27634b5aac | |||
| 2d479a15ec | |||
| a719ca752f | |||
| 089e329e4c | |||
| b84abaa0a9 | |||
| 6f4d85ea2b | |||
| 0f47a14e69 | |||
| 788c24a6f3 | |||
| a6c0bc7a21 | |||
| 661140ebf8 | |||
| 9692ae569e | |||
| f6d46bcf12 | |||
| 595635d93d | |||
| 89d92baf56 | |||
| 995605a2b6 | |||
| 749c123229 | |||
| f24f60cdef | |||
| 451ffec65b | |||
| 033ac555f2 | |||
| 14b57769d3 | |||
| 7c5b1b6fd1 | |||
| 14bc9f4429 | |||
| b72b13509b | |||
| daaf4540a4 | |||
| eee828ca46 | |||
| a084a6b49b | |||
| 1676056e43 | |||
| a601cf3ef8 | |||
| 3a7ddab1f3 | |||
| d1634d0813 | |||
| 31ccf4cefa | |||
| f528b7ff5e | |||
| d48333e71e | |||
| 7c0c096be4 | |||
| b23befe18c | |||
| ea48a57f95 | |||
| c7faf920db | |||
| 6f722a43f5 | |||
| cbe66ac397 | |||
| 0006f12151 | |||
| 8a3db78cd0 | |||
| 3dfe229024 | |||
| a8e4d6285d | |||
| bfe82bd322 | |||
| e0ebd083b9 | |||
| 6c6b18818a | |||
| 4338481f9f | |||
| e05f43b0b8 | |||
| a4e26f9895 | |||
| bc1e39450d | |||
| 87aa2cd8da | |||
| 9fa9896f0a | |||
| c4c034f2bb | |||
| aaed933eb9 | |||
| c7b541dec6 | |||
| e24933f0dd | |||
| e46b51d6a1 | |||
| f3f00e3d0f | |||
| 5a71e3eb25 | |||
| d9b108553a | |||
| b9a99cef90 | |||
| 2f366b55d9 | |||
| 13263cf39c | |||
| e03e93b0f5 | |||
| d62d1f2047 | |||
| ca3f3b6f9d | |||
| 96e1a2c393 | |||
| b6403580de | |||
| 8c5cca7ba5 | |||
| 4200daa1b9 | |||
| 1a5cfa8bbd | |||
| c371c4b127 | |||
| bd8123af59 | |||
| 00cb2fc67c | |||
| ea157cdb71 | |||
| aa343ade2e | |||
| 536e9ef262 | |||
| d200f12fa8 | |||
| c85bb7f22b | |||
| d575d8ac73 | |||
| 585b665b53 | |||
| 8ffe69d38e | |||
| 5e743b162d | |||
| b9ccf4bb12 | |||
| 4bc2c3107a | |||
| 008f5203c0 | |||
| 5d2acf44c1 | |||
| c04d3a3fe4 | |||
| 33ef76ad98 | |||
| c77cf1bf1e | |||
| f9274c8fda | |||
| 5ae02e0d1f | |||
| dcdf03ca8e | |||
| 775927c484 | |||
| bf230924d7 | |||
| d81fee17ba | |||
| 0a398bd712 | |||
| a7d41772f7 | |||
| 08754b9a24 | |||
| 133120e8c0 | |||
| ce3bfaeb5c | |||
| 7e518bf3ab | |||
| 106cbfacce | |||
| eb58745f19 | |||
| cf0fa32101 | |||
| d8894e92c0 | |||
| fc800672e1 | |||
| 462ef4671e | |||
| 212701fa8c | |||
| 75ccbe9bfb | |||
| 56e3bf64f2 | |||
| 228254db09 | |||
| 711c3f3639 | |||
| 5aa4c81c0d | |||
| db9ce69594 | |||
| 891044eaf7 | |||
| 2e84fb8063 | |||
| d0e6f06f38 | |||
| 32a7fc3239 | |||
| 29e4df9792 | |||
| 447bc6cb13 | |||
| dbb23132b3 | |||
| 179c283d75 | |||
| 427cb38f39 | |||
| ca9193438b | |||
| d3d991cb3a | |||
| d8ea93dcd6 | |||
| 3a649cfcfc | |||
| 446d47167b | |||
| 7b10424238 | |||
| 9bfca25044 | |||
| 2bde5d1309 | |||
| 93646d8f58 | |||
| 9162f6ec99 | |||
| e413191bf4 | |||
| 36cb770a86 | |||
| 7a383a3fa5 | |||
| c9342b6ad1 | |||
| aadbc191a8 | |||
| 4c9b46a20c | |||
| 0bde983ae9 | |||
| f55e295c01 | |||
| e06f564905 | |||
| 1a64de066e | |||
| 53251e53a0 | |||
| f0cde942fb | |||
| 7c9a07f384 | |||
| 96b9d264a9 | |||
| 0f3802474d | |||
| f4c8d6c999 | |||
| fd25c99609 | |||
| 79da2c0adc | |||
| 7ec682668c | |||
| 93df8b81b7 | |||
| a089807bf0 | |||
| f97956c181 | |||
| 8bc59c53b6 | |||
| a136ed3f87 | |||
| d903e76d7a | |||
| ac1c0e6baa | |||
| e57617c305 | |||
| 4d307bc6fa | |||
| f3f3eb463b | |||
| a8232341dd | |||
| 4e2b03000d | |||
| 4e777e05db | |||
| 1f7fe0d854 | |||
| a58d7c9314 | |||
| 22d66ce856 | |||
| 546d7e7280 | |||
| 9f2d241d87 | |||
| bcdd8b7e2b | |||
| 11ad8f8d5f | |||
| 24b2067f50 | |||
| f85c51f7de | |||
| 449098ad72 | |||
| d8c1f9ee6f | |||
| 05bc298cfc | |||
| d03c405d54 | |||
| be786c2cbe | |||
| 3a32825642 | |||
| 72e6bcc297 | |||
| 586000a98d | |||
| eae14095c0 | |||
| f7027d3fe6 | |||
| ca0a29b033 | |||
| 9e695dcfe8 | |||
| 4a8fd956ff | |||
| 284495700a | |||
| 1ba147009b | |||
| 2c541e68e1 | |||
| 95b39ea5e7 | |||
| 44e109cefa | |||
| 48763989d9 | |||
| f88bbee37b | |||
| fa3e1a6c35 | |||
| 6a5ce9aaa6 | |||
| bd7f840536 | |||
| 53fab12535 | |||
| 77745cfae6 | |||
| 73cb05956f | |||
| b3386c20ab | |||
| 83f419bff1 | |||
| c6a4a2dd0b | |||
| de3c59b7f5 | |||
| 28c89ce51d | |||
| a6fcf3421c | |||
| 2fcb2493d1 | |||
| 64b2b7850f | |||
| 429b53feba | |||
| a7042ba8a6 | |||
| f4c0413360 | |||
| 216b14663c | |||
| 895bda2e3f | |||
| 459866e924 | |||
| bdada76518 | |||
| 53129d2fcb | |||
| f174a555dd | |||
| 21da76f493 | |||
| 4d74de93ba | |||
| 92780b7152 | |||
| 0d73d19e44 | |||
| 689511a130 | |||
| d22d4d01c5 | |||
| fe691c2460 | |||
| f0d3c787d9 | |||
| 6b0945dc6f | |||
| d84358db3a | |||
| 5bb90e6f15 | |||
| 0840ac2c8b | |||
| 44a153ebb0 | |||
| 2214bdc1ad | |||
| c958e49118 | |||
| f7ae01ddc1 | |||
| 71b68f3354 | |||
| a7e2e56175 | |||
| 7f4e82c27c | |||
| 6e2013f0c7 | |||
| 438e0947ac | |||
| 2e2d912aeb | |||
| 44d0f67e18 | |||
| 22225dd841 | |||
| 650d1e9647 | |||
| 9265147e12 | |||
| 8358d67f3e | |||
| 2930c2b640 | |||
| 42e64d77cb | |||
| 440fc103b1 | |||
| 128e3c747e | |||
| a9439758c9 | |||
| 1247baaa36 | |||
| 59239060a6 | |||
| 42eae556e8 | |||
| a61b20ace6 | |||
| 9425fc521e | |||
| 47c629f9a1 | |||
| 11a669bf99 | |||
| 366aba68ce | |||
| 2f5a4d5515 | |||
| f7c41d1b9a | |||
| fbd24fd059 | |||
| cc6994e238 | |||
| 96c07f86b5 | |||
| e502721d13 | |||
| a3b52dc9ff | |||
| e07fe76e39 | |||
| a4ee90ca5c | |||
| c016187498 | |||
| b0d74d31de | |||
| a85255b5fd | |||
| 888dfbcafb | |||
| 5de4745303 | |||
| 6883e3b5fa | |||
| ef15b96f15 | |||
| 03810e0093 | |||
| bbbc9da76e | |||
| 11b4cf0351 | |||
| 6df64d68af | |||
| 3925fe74af | |||
| edb48d8364 | |||
| 1d6b67658e | |||
| bcd1476d2d | |||
| d2251e4cb2 | |||
| bd275539d1 | |||
| 6042909915 | |||
| 38fc05e0d9 | |||
| 3ddbd59995 | |||
| 0a2a5bdd7a | |||
| 088aa83fea | |||
| 0797b8b262 | |||
| 54a9db2acb | |||
| e9f88a9c92 | |||
| 311d651ba7 | |||
| 7789252f76 | |||
| c58e96bce7 | |||
| 2a0ee12780 | |||
| e7bc9168ae | |||
| 98e5cb4979 | |||
| 6fc6829bc8 | |||
| 516f0fa1b4 | |||
| 6f556c45df | |||
| e237d58906 | |||
| cc9807846e | |||
| df7f9dbaeb | |||
| dee350742f | |||
| 735f9a9534 | |||
| 859f10ee1f | |||
| a002eeed25 | |||
| c9c5e5658f | |||
| edfcb53491 | |||
| d158c13c7c | |||
| f2dc43b47f | |||
| e7cb246639 | |||
| 19d109b3bf | |||
| b2fc4b9886 | |||
| e6dd0f0abe | |||
| 6f4186ae07 | |||
| 44a3d03974 | |||
| 649f6897a4 | |||
| 9edc30cef0 | |||
| b0aaa2b791 | |||
| 108a4ee2bf | |||
| 1083b80849 | |||
| a2ff420f89 | |||
| 5d718f7621 | |||
| 63096d5919 | |||
| b80f1794e2 | |||
| 166c64798e | |||
| 150b51b327 | |||
| 878e9541da | |||
| 8b416b113c | |||
| b8dd85c88f | |||
| 7098b15d0d | |||
| 1bd796cd94 | |||
| cd41f8f060 | |||
| 2e117d6641 | |||
| 70513ff8b8 | |||
| 049c3918a4 | |||
| d71286b265 | |||
| 80eb9aa036 | |||
| 70813984be | |||
| f904ca8f11 | |||
| 068c347178 | |||
| c9f5b2a330 | |||
| 529dc52823 | |||
| b4b4c82e59 | |||
| 276e7ee729 | |||
| 808dfe7d31 | |||
| 88b800415c | |||
| 1679b6b406 | |||
| 748cc495be | |||
| c3ad6ae8cb | |||
| da44e67d65 | |||
| 70be5ae184 | |||
| fe260a6a06 | |||
| 631afde7b6 | |||
| 7a6e4d5f2c | |||
| 8683273022 | |||
| 2c9f691d8e | |||
| 398a804b41 | |||
| 79ffa3e29a | |||
| db0319bfba | |||
| 747ad313e6 | |||
| 4f5b7be7b8 | |||
| e3b9576a2d | |||
| 0dcd74388f | |||
| 302f99172f | |||
| 05adb5ee84 | |||
| 013f63b52f | |||
| 640c28a260 | |||
| 2c06dfb553 | |||
| 63ae52d99c | |||
| 03026a84c7 | |||
| fd33e4c3d4 | |||
| 4606b3980c | |||
| be6affb2c6 | |||
| b75fc89011 | |||
| 5849309dad | |||
| 02dd9aca32 | |||
| 4c4905e60b | |||
| c63251b832 | |||
| 808ade6e8d | |||
| 73fb523b3d | |||
| 0c56b55c2a | |||
| e66b56af58 | |||
| a718aa9c69 | |||
| 49749b3f59 | |||
| 045c6bfc9f | |||
| 91a6f20dba | |||
| 4eb5c97725 | |||
| 978b230f00 | |||
| 9d2632106c | |||
| dd73415c00 | |||
| f0635ba323 | |||
| 38205b3b97 | |||
| ae7306a3ef | |||
| 5448216e7a | |||
| 4f111a710d | |||
| f5df39a971 | |||
| 1866257ff5 | |||
| 8d9fbbf7e9 | |||
| bcd87dfa6d | |||
| 653aca500f | |||
| ca36fd35a6 | |||
| 260b2ad5c9 | |||
| 230413a5cc | |||
| d9618472cb | |||
| 9d96789302 | |||
| 0a69979417 | |||
| ce21c72f37 | |||
| b4ade5e956 | |||
| c79f387af2 | |||
| 9171a62979 | |||
| 793704c111 | |||
| 0cb5c8ca94 | |||
| ca5f50586b | |||
| 6f09c10bd7 | |||
| 8205f33ec6 | |||
| 5360c577af | |||
| ea48fcac64 | |||
| fbc639030a | |||
| eef042b469 | |||
| d34bf1ee7d | |||
| 6987f4be83 | |||
| 1b443af123 | |||
| aa100c2383 | |||
| e3541d78ce | |||
| c0b973370c | |||
| 129419df9d | |||
| ac635c4b38 | |||
| f05f7168ac | |||
| 21a5c25760 | |||
| 756b44db5e | |||
| 38538ca358 | |||
| e22b019147 | |||
| 39fab36541 | |||
| b96a1dcefc | |||
| 4ab56202f0 | |||
| 9baa6e3c85 | |||
| 300b4582ec | |||
| 3cdd9b6af2 | |||
| 355d71769a | |||
| 851f785f50 | |||
| c462dbb745 | |||
| 5706fea2eb | |||
| c403951050 | |||
| 214e425796 | |||
| 2ea2c037e8 | |||
| a20ed9c876 | |||
| d995cc01bc | |||
| 3643693bde | |||
| 928c3ea3c2 | |||
| 779b07b1b5 | |||
| 2aea40d26f | |||
| 7a2a05063b | |||
| fa58ac7419 | |||
| 44ad83790d | |||
| 48ede05926 | |||
| 50ef2e83ce | |||
| 1be72c87f2 | |||
| 961b76fd1e | |||
| bc6a82a7fe | |||
| 1ac81b8f17 | |||
| 79e556ac80 | |||
| 50fdea4095 | |||
| f77c1f0256 | |||
| 9775d3b93f | |||
| 4fb431f3bd | |||
| e66edbf2c7 | |||
| 8828de9456 | |||
| 484ad67152 | |||
| 97e8ec44cb | |||
| 3454e330f5 | |||
| e91af9cea4 | |||
| 8e1d2855c6 | |||
| 0e01bd167e | |||
| ec4952766e | |||
| e976de18e0 | |||
| 81f5b47918 | |||
| 5e7ddc07db | |||
| 11a8e6e565 | |||
| b9f78c5f0b | |||
| af4aec6a69 | |||
| f8c3064b07 | |||
| d3c0e5979a | |||
| 43a720e09e | |||
| 8a232be59f | |||
| 01018737fd | |||
| 0c228fab1f | |||
| 0d0e795faf | |||
| 76965111fe | |||
| 67d2067a28 | |||
| 4e63395a35 | |||
| 1d85f49a97 | |||
| bcad91dc18 | |||
| d516b8a4dc | |||
| 2d651ca51d | |||
| f9b52f9433 | |||
| f6f3fcf1d3 | |||
| 1d3e324b9a | |||
| 350101091a | |||
| 343360cdbe | |||
| 739c3ad4cb | |||
| ed38a863d4 | |||
| 5d797959e3 | |||
| 3626d2e1bf | |||
| 7b272a0b21 | |||
| cdd0c52182 | |||
| 8b490dd4f9 | |||
| f30494ad30 | |||
| 6e6b456115 | |||
| ebc56e5eb7 | |||
| 2b5fb427df | |||
| 8f62b8cd5f | |||
| de673afb9e | |||
| 8bd4ef169c | |||
| 59ff0f2ad0 | |||
| fd478715f3 | |||
| 8b21f29978 | |||
| 367f698348 | |||
| bda31f2ba7 | |||
| f9d48272ef | |||
| 865412a551 | |||
| c033ef2d28 | |||
| e1ddb5920f | |||
| 4f6225047e | |||
| 107e3ec360 | |||
| 2b766e216c | |||
| 419453a8c5 | |||
| 862128abf0 | |||
| 491b0522ab | |||
| 5d61780b7c | |||
| 6bd3956e2e | |||
| 3a7963d0f9 | |||
| 9cd2c684b5 | |||
| b9a5881333 | |||
| 9bbf81875f | |||
| 09a1d06c8d | |||
| 1e8daafba4 | |||
| a726021ea9 | |||
| 189ed2a22d | |||
| b03397ca87 | |||
| d9bf39acb0 | |||
| 21b68e6bb9 | |||
| aa15145765 | |||
| c6b7902eca | |||
| 72d60bea62 | |||
| 1239b1e542 | |||
| 420e730003 | |||
| 56e682314f | |||
| 8e8fb1cc8c | |||
| cf00e51559 | |||
| 8a9b61185e | |||
| ac406ac6f3 | |||
| 9f43bd5294 | |||
| 7b853c74f3 | |||
| 83bd026c4e | |||
| 3fce40b4c9 | |||
| 75056923dc | |||
| 597d4b7469 | |||
| e7ddec4329 | |||
| 5f1a25c2ec | |||
| 5b8f08f3a3 | |||
| 544ceefef7 | |||
| 33c55db206 | |||
| ce12fa0d22 | |||
| 2f50c17320 | |||
| 83b6fe7cb2 | |||
| 63eeb88066 | |||
| dfeb4204e7 | |||
| 2a8f66f360 | |||
| d34f047418 | |||
| 56331ea150 | |||
| 482d789870 | |||
| 0e6055881a | |||
| f10d1b0a9e | |||
| a2ef29e75d | |||
| 6468a6505b | |||
| 0e1655004a | |||
| 26421f78e2 | |||
| 22d3d542ae | |||
| 714f48deb7 | |||
| dda82466c9 | |||
| 1678f9a021 | |||
| fc9969570d | |||
| 5c760a83d6 | |||
| bed0b41789 | |||
| 4859fd301a | |||
| 957c85d641 | |||
| a1c4c00d1c | |||
| 2cd8e25466 | |||
| d7829c371f | |||
| 36f236f69f | |||
| 80b877879c | |||
| f698d77719 | |||
| bebb76e51a | |||
| af86dd92c5 | |||
| 3ed4d29af3 | |||
| 14f4f66f84 | |||
| d4ffe2eadf | |||
| b0c3ba2a11 | |||
| 0adf7a5c84 | |||
| 2e9a252910 | |||
| ecb4854c78 | |||
| b8ecc5e591 | |||
| 9dc272fd17 | |||
| 763430099b | |||
| 28d28cffd7 | |||
| 78e9d430bd | |||
| 499fa59b92 | |||
| 817164c4f3 | |||
| e0ad618d1a | |||
| 9329ef34e2 | |||
| 2c7444c15b | |||
| a586b267db | |||
| f665b1f623 | |||
| c34425b231 | |||
| 7e47e07747 | |||
| 90e1f87fb4 | |||
| 05a9ef9410 | |||
| c41b6b2eb3 | |||
| c8ce49a383 | |||
| 919a6c7028 | |||
| 8a1a07980d | |||
| 8556f7cdf6 | |||
| 0d82e3e72b | |||
| 8bbdbc6cf5 | |||
| ac10d4ca70 | |||
| 1355688a36 | |||
| 88c8d5e34c | |||
| b54ebcb0d1 | |||
| 3532a8c5c0 | |||
| fe28fd355b | |||
| 9a976022e5 | |||
| 240a577361 | |||
| 3851eb0c29 | |||
| 976f6d8224 | |||
| 1461240f27 | |||
| 0c29fcb9bd | |||
| a754a4fcc6 | |||
| 0e165a196c | |||
| 53d29fe79d | |||
| 2854acf146 | |||
| 73035a4369 | |||
| 1da0435b4e | |||
| 84ccbe3ac0 | |||
| 4a86ae0bfd | |||
| ceb1337cde | |||
| 6013555139 | |||
| 1e533706aa | |||
| 2fe9e88c52 | |||
| 2a0b21c8b1 | |||
| f8a5e753da | |||
| 559b18ff5a | |||
| b95592db96 | |||
| a3c471de38 | |||
| 36576d1936 | |||
| e000b7ea6d | |||
| 74c3b2c180 | |||
| 0b7878b1c6 | |||
| 8cffbd9901 | |||
| d32eae030e | |||
| b991e9950f | |||
| 683abe0035 | |||
| a77eabd379 | |||
| c58913062a | |||
| e736fe6557 | |||
| 43464ee4aa | |||
| 26e246e71a | |||
| 98a9a62b2d | |||
| 5210684c50 | |||
| 7ea2dc7176 | |||
| a8c5bf8e34 | |||
| ff3b0db3ea | |||
| e7917d5ee7 | |||
| 2cd3cdaf38 | |||
| d5639a26d6 | |||
| a13cdae4d2 | |||
| 2d53a9e82c | |||
| 57c860a643 | |||
| 744230d7ec | |||
| 8f4cd8a447 | |||
| 9e2d1289c9 | |||
| d05e5ed2c0 | |||
| 070b99d6ef | |||
| eae1040695 | |||
| 06dde739c3 | |||
| 8875595012 | |||
| 1bb95bd1b5 | |||
| 40599918ba | |||
| 1b4483dfa5 | |||
| e18987f235 | |||
| 817089d81b | |||
| 41883ca5da | |||
| 4d71478d50 | |||
| 43ef5bcdd9 | |||
| 55bd30c24d | |||
| 7447b30892 | |||
| 18d4ee0dfa | |||
| f0be7d2e9e | |||
| a0747230ac | |||
| 1df06fc0ee | |||
| cde58ace66 | |||
| ece6bb6e0a | |||
| 0d5810a8fb | |||
| 2bae90e339 | |||
| 0a994573cd | |||
| e941bd8266 | |||
| b167ec794a | |||
| fb3647fc99 | |||
| fbe94c0f57 | |||
| d87aa2620e | |||
| 83b006c615 | |||
| 9feba1c570 | |||
| 57c4b198f7 | |||
| 127b643e44 | |||
| 2fbd0b09f6 | |||
| 520aa26a11 | |||
| d09dae8378 | |||
| 8689ac9139 | |||
| 212a7ed2b8 | |||
| d9b3e56930 | |||
| 7fae8de733 | |||
| be8af75e61 | |||
| b4cf5cd2a3 | |||
| 7649e60d28 | |||
| 0aa981eea5 | |||
| 122b50e114 | |||
| 9b6e8feabf | |||
| 73862c10c5 | |||
| 63572942ea | |||
| ea6c6c8490 | |||
| 11455e6c78 | |||
| f7ed595f7c | |||
| 8b481aaae2 | |||
| a8cff18985 | |||
| 39f14c8d11 | |||
| f9a46561e8 | |||
| 5a55fea38a | |||
| 884e03fab5 | |||
| 584ad2a7c4 | |||
| 4abad486d2 | |||
| 1958dca2be | |||
| ba121827ac | |||
| b946672e9e | |||
| e21e1488e7 | |||
| 3a03eec1ab | |||
| f9277de9ef | |||
| 3b37cec42d | |||
| 514a8a2d0f | |||
| 80ad4be4cb | |||
| 6da34061da | |||
| 97d5010f0c | |||
| 18dfc3ca37 | |||
| 9f27d4ff11 | |||
| f828a7d1e2 | |||
| f19febaa6e | |||
| e344392450 | |||
| f9c61cabcc | |||
| 7ce98a8c81 | |||
| c4860cdb74 | |||
| 989511ad68 | |||
| 5b92110f43 | |||
| 431375946b | |||
| 1a6ffa5d84 | |||
| bb6744dc6f | |||
| 84973bb441 | |||
| 4e8c228b92 | |||
| 505ebd2d41 | |||
| 0fd1b52036 | |||
| df4493e5af | |||
| 38629114b6 | |||
| f43c384a27 | |||
| 5f119d6f0e | |||
| 2eecca60f0 | |||
| bca9993e68 | |||
| 466ac5e03e | |||
| 9901eb83ad | |||
| 9b73522a8e | |||
| d1b5d5fadc | |||
| 8c267ec6f4 | |||
| 46c4416434 | |||
| c0bd5c9d88 | |||
| df8d4e3afc | |||
| 32deb59df4 | |||
| fa92144439 | |||
| 04cfb2b977 | |||
| 7760d85721 | |||
| 23cbf79474 | |||
| a86c43d8d9 | |||
| 8c43bcf030 | |||
| 482a91a08c | |||
| d495d03619 | |||
| c223244f10 | |||
| 6a7971f314 | |||
| 19ebce1c98 | |||
| 1f04bdb57a | |||
| 6e1feebc11 | |||
| 43174b37cf | |||
| a0fe1db962 | |||
| 4309ee627a | |||
| 371cc24520 | |||
| ac2fbc07dd | |||
| 79133ccde8 | |||
| 1d4a2eb1b0 | |||
| 62a1200cf3 | |||
| eac6fe52a6 | |||
| bd6a11b77a | |||
| 93fc3a8306 | |||
| 90286d435e | |||
| 55dac5c0c1 | |||
| fa97d752c8 | |||
| 421bee68dc | |||
| d5fccaf23b | |||
| e4a567044e | |||
| f17849ad6f | |||
| 818055ca6c | |||
| f77f2ce224 | |||
| 74121384a7 | |||
| ad1e29e62b | |||
| 4b1db3a673 | |||
| 1dc0219fa1 | |||
| e4d9bdf998 | |||
| b00ac06cee | |||
| 04dd15df5f | |||
| a42867879d | |||
| 9dcd9c900a | |||
| 9d289bede7 | |||
| 99dd1b6f3d | |||
| 6886c24204 | |||
| b5fc28bc18 | |||
| 78e52831d1 | |||
| de7a913fc1 | |||
| 548d9cd820 | |||
| f03c384dab | |||
| e010732c2f | |||
| fcc93e7c4d | |||
| ac99397530 | |||
| 67f996c47f | |||
| f9f80a1d58 | |||
| f33e3fa623 | |||
| 095be8aa1a | |||
| 82d06c7426 | |||
| 6e7d288832 | |||
| e8e1142363 | |||
| 3ae1d6d726 | |||
| dc10030a67 | |||
| 0930b9116b | |||
| 39c1919884 | |||
| 91db0054d8 | |||
| 8f745481f0 | |||
| cbd90961aa | |||
| 76d913bbd3 | |||
| 473851c9fd | |||
| 8ec9a29f93 | |||
| 5c33aaa599 | |||
| a7e7f19c6c | |||
| cf03ff62e7 | |||
| 43893886b8 | |||
| 7c4002c252 | |||
| 525ce01abf | |||
| e659c49d6f | |||
| f24f168295 | |||
| cf4cace26e | |||
| 4eaa7abb1f | |||
| 6d7b09d73f | |||
| 82b0fc771d | |||
| b928edb036 | |||
| e5c9bf0688 | |||
| 032936982d | |||
| 57257a66ba | |||
| 2838a21a2f | |||
| f4c391f340 | |||
| 7d5f6a29a0 | |||
| 8294d6dc80 | |||
| 691b842591 | |||
| d8f7d1dcea | |||
| af06deb9a8 | |||
| de3c4b5338 | |||
| 69ec28cf36 | |||
| 1a7e9fcace | |||
| 2923d9e761 | |||
| 833f3d5075 | |||
| f6ca102297 | |||
| 432a2bca21 | |||
| 011189564a | |||
| 59b6be751f | |||
| 0d49e56efd | |||
| 3c3c94a035 | |||
| cb2d6e9bdf | |||
| c9eff0d0ac | |||
| f556583f06 | |||
| f5ab48f031 | |||
| f910085116 | |||
| f7830e6a3b | |||
| ba0bed7eef | |||
| 3160672ecc | |||
| 6ca4ff736a | |||
| c6b568c17c | |||
| f04d20f57d | |||
| cb2aa0cfa4 | |||
| e7f17f97d6 | |||
| 9528bb4bfb | |||
| 63a74b81ed | |||
| 6e45ac9df8 | |||
| 028053e908 | |||
| b0a3aa4b18 | |||
| ec59d60e43 | |||
| d07838071a | |||
| e8f2dfc5d6 | |||
| c8ee8a6081 | |||
| 6a8498527e | |||
| 49ce934300 | |||
| 1815311e72 | |||
| 4566d8ebcf | |||
| c86e393f4d | |||
| dfecd1cb3b | |||
| 1dae1834a4 | |||
| a123d6c255 | |||
| 11e7cc6806 | |||
| 9f1ff445fa | |||
| c7869abfaa | |||
| 6d87f7f1e3 | |||
| 33bcabaa73 | |||
| 4165afcc12 | |||
| 3e3fc13602 | |||
| 6ff47341c7 | |||
| 3bac8fc9e2 | |||
| 44af846e11 | |||
| 9f52d771e9 | |||
| 55ba1a4cb9 | |||
| f47a75f208 | |||
| c7e61ad247 | |||
| c9f7a2b3f7 | |||
| 3f3a9093b2 | |||
| 638de8c386 | |||
| 4f3b19953b | |||
| 6be7076bce | |||
| 880847659f | |||
| ab284bd7a0 | |||
| d9c8b9a453 | |||
| a04fb8394e | |||
| 561db9a9c9 | |||
| 1c2030a425 | |||
| d4a3f1c69a | |||
| 0a1d5bd5aa | |||
| 2869804272 | |||
| d654775cce | |||
| 0d8bb7de6a | |||
| 2663633798 | |||
| aee50bf668 | |||
| 402a08f03d | |||
| 040f721394 | |||
| 0017b9c98e | |||
| d311290547 | |||
| 95d0363bc3 | |||
| 6f3065f7a6 | |||
| a2bb52421b | |||
| 5fad6877a5 | |||
| 156e9df954 | |||
| 4227002816 | |||
| 86e6db400e | |||
| 02883db402 | |||
| d339f5f476 | |||
| 2134aa4bef | |||
| 2bbf70639d | |||
| c28fbf0093 | |||
| eddc091c0f | |||
| 354dba5de7 | |||
| b0f189c338 | |||
| bd028771b6 | |||
| 74b8869293 | |||
| 424174636e | |||
| a59f71a01e | |||
| fba9a7ce19 | |||
| 74fe7c6e15 | |||
| cd8b7db66a | |||
| e5f92c198c | |||
| 63d0e45343 | |||
| 3bcf88ffe3 | |||
| 3ab00c54bf | |||
| 24e03d5d3d | |||
| ef923e7be0 | |||
| bad2f59f85 | |||
| bf8938ea31 | |||
| be3567b904 | |||
| 8d80545229 | |||
| 87a4b3f58d | |||
| 54812bf4bb | |||
| aae8ea1d5c | |||
| fcaa0f1cfd | |||
| 1709a9746c | |||
| 656e9cc9d7 | |||
| f4171d5973 | |||
| 2c8b90aa1b | |||
| bfea26342e | |||
| 873e66d7a6 | |||
| 0b1d2b0da9 | |||
| de04d51cd7 | |||
| 8c49955057 | |||
| 95b932554d | |||
| 3b20301edc | |||
| fe666d3c08 | |||
| afe5f1e58f | |||
| 31a902605d | |||
| 128b2a00bf | |||
| b29ea57acd | |||
| 2842791af4 | |||
| cbf193587c | |||
| ca04fd1b3b | |||
| 7d17d993af | |||
| 0b42547455 | |||
| 77659dedca | |||
| e0d6424de7 | |||
| 8519913ece | |||
| 12646eb205 | |||
| a5c2fce817 | |||
| 5d50ef975c | |||
| 41d08f71a3 | |||
| 8ee34d7656 | |||
| 107c95aa9f | |||
| e7c389ea0f | |||
| e947ec3feb | |||
| 3e4def27ee | |||
| d1a8b836cc | |||
| 5b87b9719d | |||
| 6ed1ae85c2 | |||
| 616cc5e286 | |||
| 18e53c6974 | |||
| 7b07f88749 | |||
| c737c494a7 | |||
| 51aebaab21 | |||
| 08281d161f | |||
| b818c05525 | |||
| 1a85dbf81a | |||
| 32ce326133 | |||
| 82070e9bbf | |||
| 12c67cac8f | |||
| 7bbbb51eb0 | |||
| 00dddb2383 | |||
| 54db21b08d | |||
| a42472fb39 | |||
| 36a19a1c0a | |||
| 65118a567d | |||
| 0e57d5d505 | |||
| abfadf48e5 | |||
| 5d3d9bc153 | |||
| d0e89e74bd | |||
| 836b763ab5 | |||
| c0dcfe9a7e | |||
| dd4e28d0ad | |||
| 73badc1b14 | |||
| 3439a6b691 | |||
| e7a34e51a9 | |||
| 19959965a2 | |||
| 1b04ed9506 | |||
| 3f33509c18 | |||
| ae546cd016 | |||
| 9d72564a3f | |||
| c243e01908 | |||
| 9403347d96 | |||
| 48e2e098c3 | |||
| 397afad22b | |||
| fa85421e5d | |||
| 631c0c4327 | |||
| 75badd8b69 | |||
| 6578b610c9 | |||
| 4f262f8224 | |||
| 7a61b4fb9c | |||
| 58294c2e62 | |||
| 5cbad9d31c | |||
| 5ff59c6321 | |||
| 20624b9358 | |||
| 113adaa7e7 | |||
| e46640f603 | |||
| a07334ec37 | |||
| 5f26cbd80f | |||
| e7112ded44 | |||
| b6892509a4 | |||
| 10b23cb394 | |||
| 163f803af9 | |||
| 8187f20111 | |||
| 34cd92cd6f | |||
| 45c6936726 | |||
| 719e975a71 | |||
| a6b65378d9 | |||
| c7517b56da | |||
| 77be8b7e4a | |||
| 11a6ecb5bb | |||
| edabc6b376 | |||
| 11b18c1499 | |||
| 1d17d5af82 | |||
| d65c1d5bb8 | |||
| 9878bde8da | |||
| 831832413a | |||
| 39bb28f1bd | |||
| ae3219be57 | |||
| 652e4d7ef1 | |||
| 1c16dcf961 | |||
| fe81bb224a | |||
| cbae1e8d5e | |||
| 5752a3bb68 | |||
| b9b02b4ed0 | |||
| 66af10f522 | |||
| 80370e000a | |||
| c88b83bb6b | |||
| 4b012e825a | |||
| ed3d18b168 | |||
| 30829a2d62 | |||
| b62560a4c7 | |||
| aad722603a | |||
| a489350d21 | |||
| 54198b8c96 | |||
| 5bd9cd680b | |||
| cb7a85d583 | |||
| bde25001e5 | |||
| 6c8720c471 | |||
| a9703942f6 | |||
| bd6819bf77 | |||
| eed270be72 | |||
| 2ad02f3798 | |||
| daed7ea078 | |||
| e0842e1b4d | |||
| a82c371015 | |||
| 6e3145685d | |||
| 5ef01658d6 | |||
| 66a65a770d | |||
| 54976b389b | |||
| 9ccde75731 | |||
| 4a05a09da5 | |||
| 81406bfccc | |||
| cad6ee8dfa | |||
| c706cc97cc | |||
| a713666a8d | |||
| f4b082b3c5 | |||
| 32ebad2978 | |||
| 622d8bcb3a | |||
| 4f4a4525b4 | |||
| b4171a6086 | |||
| 234c6e11c8 | |||
| 81c59c3f12 | |||
| 6cd0f20424 | |||
| 840eca51b8 | |||
| fc877c9b40 | |||
| 0709f886b0 | |||
| 0e55c50d4c | |||
| d6a7e8dc62 | |||
| c4c237f131 | |||
| dffdaa369c | |||
| d154123b71 | |||
| 6baae40a38 | |||
| ffbd575fd7 | |||
| 20ef960389 | |||
| fe54d51e3f | |||
| e1ba59c0b6 | |||
| 58e4cd82ef | |||
| 64a433ea10 | |||
| 816e12c6f1 | |||
| 081cd7fc98 | |||
| d21632dbef | |||
| 2a7280b501 | |||
| 94f3d12a6b | |||
| 372fa13239 | |||
| cfb6ba593b | |||
| 733a6677be | |||
| 6f1a0f14a5 | |||
| fb2b3ace59 | |||
| c2c553e032 | |||
| 4b07a9f6b9 | |||
| 8c743f5b7b | |||
| 4d017bb55b | |||
| 298efa20b3 | |||
| af2f2f468e | |||
| 492963f298 | |||
| 7cbede4507 | |||
| 271fa2bccc | |||
| a862ec5561 | |||
| 38b9775ad2 | |||
| 37aed2fb1c | |||
| 22616a0b4d | |||
| cc3513846f | |||
| 42e0a52b99 | |||
| 4c4470af16 | |||
| 2251029356 | |||
| 57558af3eb | |||
| 2cc72cc16b | |||
| d7f82d7473 | |||
| 4471ecf150 | |||
| dcb231f788 | |||
| ea0d3e08d8 | |||
| fd914997ba | |||
| 4809b012e8 | |||
| f49fafe866 | |||
| 6c298d54c6 | |||
| 12a7d5b8fd | |||
| 9975eced9b | |||
| 456eaf5dee | |||
| 2b3d5b4960 | |||
| f0414fcdc3 | |||
| 7aa4b719e5 | |||
| 45a52e1f58 | |||
| 15a2294688 | |||
| 2c4ca49059 | |||
| 4e587b5b18 | |||
| ec93a4f4dc | |||
| f750f2d4c9 | |||
| 3807db1b86 | |||
| f51380d274 | |||
| 4543a69698 | |||
| 1a39de861b | |||
| 752d47c023 | |||
| e5ffd496dd | |||
| 70039bcedf | |||
| 7fa5d24c6c | |||
| 2b5108cb76 | |||
| 62a3e7608f | |||
| 97f06689ec | |||
| bb1d784797 | |||
| a808680819 | |||
| c8f606b302 | |||
| bc6ce155c6 | |||
| efbe1d3511 | |||
| 1f82b6cecf | |||
| 0e72420b8e | |||
| 9ed80154af | |||
| 6bbf0a0984 | |||
| cfe076f6c5 | |||
| 771937cf78 | |||
| 37773dac6b | |||
| 797eff73fa | |||
| cdd714e2a4 | |||
| 3859db7c8b | |||
| a2de5c7632 | |||
| 694cf0f59a | |||
| c370c6e4af | |||
| 1c3ef26eac | |||
| 3323481b60 | |||
| d17aff4cc0 | |||
| f5dfc768b6 | |||
| 7e9888d4f9 | |||
| 451beb023e | |||
| 3b1d8239ca | |||
| c7580473b0 | |||
| 8677ac1192 | |||
| 700f6488aa | |||
| 078fff447c | |||
| 18272935ea | |||
| 5fa60d16b6 | |||
| 7e831fcedb | |||
| 26c8718a39 | |||
| 073ab6b16b | |||
| 4e004cbe8c | |||
| c70ee0412d | |||
| d8d1eb3915 | |||
| 0f55406cef | |||
| cda209d3d3 | |||
| f5b4a36f25 | |||
| c9b6287b46 | |||
| 18c81854d0 | |||
| e836cd2daa | |||
| 4e4336c461 | |||
| e3519d47a6 | |||
| 75f806ce80 | |||
| 7d708e03c7 | |||
| 9e0f4eb0d6 | |||
| 6996ab51b4 | |||
| 518b2fddd3 | |||
| 3fd3160a95 | |||
| 6791470880 | |||
| 62c39ee163 | |||
| 273303f1b6 | |||
| 5786c493c7 | |||
| 35bd4d7e21 | |||
| feb476f83e | |||
| 67f11fc7c7 | |||
| 68a86e9e8c | |||
| 3ca58dc9a0 | |||
| bf46830b85 | |||
| 042d2a1d71 | |||
| 32595ca92f | |||
| 0241f5f635 | |||
| 6196c76dd1 | |||
| 951776ea6b | |||
| 8f38cef49f | |||
| 2662d89c53 | |||
| 20d7ca22b5 | |||
| a81bb9e3b9 | |||
| 34d36b024d | |||
| 316aa7d94c | |||
| 6192c2e144 | |||
| 3be5f50f3a | |||
| a52adf9723 | |||
| 3780a182ca | |||
| 63c6b8da69 | |||
| 6bc3b2f16d | |||
| 368d97bc8f | |||
| 92656b691d | |||
| 9c632648dc | |||
| 1052be18d4 | |||
| d9262b1623 | |||
| 7b77f123b9 | |||
| 8db12bc919 | |||
| 8cd5d3ba9b | |||
| 1f7459259b | |||
| 03d5e93c55 | |||
| 91c2425ff8 | |||
| a4396c07d9 | |||
| cf0bf46f7e | |||
| 9ccbf2a22f | |||
| 8ae0ae96e3 | |||
| 1abfc0dc63 | |||
| 2024812f61 | |||
| 5518770cf6 | |||
| 9e9d3ed2d0 | |||
| 2175755cd6 | |||
| 2f88a1ea6f | |||
| 91ca4e5adf | |||
| 813cc033c6 | |||
| a696b0f1a8 | |||
| 829dec352a | |||
| ad42d77694 | |||
| 7aa443ab59 | |||
| 20a86b1918 | |||
| 704b1c9390 | |||
| cb916d5ef1 | |||
| 21b457d281 | |||
| e59d5c15e2 | |||
| ea79b01d4c | |||
| 8f4b47aad6 | |||
| b6d73ffd92 | |||
| a59f2f2f60 | |||
| af603b7bc6 | |||
| aa32fe4671 | |||
| 2aa16d0d12 | |||
| 4f4f335e89 | |||
| 2c53d5fa09 | |||
| ec4b1c58ef | |||
| d51a605f54 | |||
| 4133953b93 | |||
| 855f4980d5 | |||
| 087a834661 | |||
| dcd9121e4c | |||
| d5f72ca7de | |||
| 01c9aeef48 | |||
| 68d236ee5e | |||
| 5a50b95987 | |||
| f947ffa800 | |||
| cadbae617d | |||
| 17a29c6729 | |||
| 6b0eed3fb7 | |||
| 866e08c05e | |||
| e17a19e281 | |||
| f03028dde8 | |||
| cb78bd6a66 | |||
| f45cb3db86 | |||
| 421bc39b6d | |||
| 2a532a8ee6 | |||
| 3a520cb38d | |||
| c930df4153 | |||
| eb72ae82e7 | |||
| 6e1b4f5403 | |||
| d8eb8f6982 | |||
| 194e00941c | |||
| a4eebf60cc | |||
| b7e7251d52 | |||
| 3e7920e22f | |||
| 127a9b8221 | |||
| 8c6145ddf1 | |||
| 9b1b42f42d | |||
| 707e55fe31 | |||
| ebd9596a5f | |||
| 9d405b3f1b | |||
| 4b6fdd5d27 | |||
| 9235f1f5ea | |||
| c41fa2d735 | |||
| 3d666377c3 | |||
| 9909eaab74 | |||
| 08bb3e748a | |||
| 8964b65d87 | |||
| e288d1411a | |||
| 4cc104236e | |||
| f92380b1e0 | |||
| 5d0d1fcacb | |||
| ef7e0ebf81 | |||
| 5e559bf13b | |||
| 8441427fcd | |||
| 5d0660145f | |||
| 28a18b336d | |||
| c984a9116b | |||
| bed17af3b2 | |||
| dc0de31164 | |||
| 0a941cee30 | |||
| 39ee653979 | |||
| a0d763ed86 | |||
| 4666e030ac | |||
| 1e26ca3189 | |||
| 9e968c3063 | |||
| 1c546fcb2b | |||
| 3520c1213c | |||
| 7ca524c3d3 | |||
| 84bdeffebe | |||
| 5133a38f6c | |||
| 8fb35857ff | |||
| caacfb86a6 | |||
| e687f50b2a | |||
| e31f4b7dd4 | |||
| bf9d833d38 | |||
| ad753ed2a8 | |||
| f1017af518 | |||
| f7b2e069da | |||
| eaf4cc3b61 | |||
| 7432642bdb | |||
| 114ad74522 | |||
| 38a6cbf1b9 | |||
| d295d29756 | |||
| d20f566ee3 | |||
| 18c8600684 | |||
| bfbf51dd9a | |||
| de210bcf9c | |||
| e6ad1bfe9a | |||
| ac8af5f4b0 | |||
| 4b741ca108 | |||
| 86e330c586 | |||
| ab5b0ba083 | |||
| da77c35b7c | |||
| 9296871b28 | |||
| e22a4a097d | |||
| 70ac13c8d4 | |||
| 79d4c6a116 | |||
| e18b890f96 | |||
| ab89154e67 | |||
| 228f970cf9 | |||
| a95bcbd180 | |||
| 9b46d68729 | |||
| 275baf16db | |||
| bf630825e0 | |||
| c9f93f4d70 | |||
| 44e05180c5 | |||
| fd3aeaff4c | |||
| d201cc4c86 | |||
| cc9f1d8e82 | |||
| 183d6cf5f4 | |||
| d30b12b425 | |||
| 0faa78ed29 | |||
| 39f3bc738d | |||
| c7ef738dd9 | |||
| 47ed7caf1f | |||
| 0fe37fb5c1 | |||
| 3f9ffb029b | |||
| 72c4fedfd5 | |||
| ff47324c35 | |||
| 332f020662 | |||
| e1d60b3482 | |||
| c1f87bb410 | |||
| ea7f7b5155 | |||
| 8c4655e44d | |||
| 4ad3ee56bf | |||
| c5a138d7cf | |||
| 60a75aaaa1 | |||
| 225569ce7c | |||
| 88975db473 | |||
| 8825a841fa | |||
| 695d8af721 | |||
| 0f27f1cb9f | |||
| 108be7ce51 | |||
| 2ff9518a3a | |||
| b3fc87bd18 | |||
| 6b9464017d | |||
| a8a2ce677d | |||
| 26cd63936f | |||
| 261a038cf3 | |||
| 35aed3a31c | |||
| 0f3834414c | |||
| 8a8b78498e | |||
| e9988526b0 | |||
| ef642356da | |||
| 2e00b68bba | |||
| 0236657832 | |||
| 99f9d48ae4 | |||
| c1db506baf | |||
| 40bb3897f1 | |||
| 8e22284833 | |||
| b28ef3b82e | |||
| 0655d5bdb0 | |||
| b0c9a2fee2 | |||
| cae80eeeba | |||
| 8ef9e98833 | |||
| ec5c472e3c | |||
| 4480c0189d | |||
| 0ccdc000cd | |||
| a321e25c04 | |||
| 9936a15079 | |||
| 25263ec709 | |||
| 4800b1d4ad | |||
| 0d1e599712 | |||
| 9bde1171d6 | |||
| 21f5be6e21 | |||
| 7843dc63ed | |||
| 120dd22561 | |||
| 7d58c687c5 | |||
| 007c14ba9e | |||
| 0882fb3aad | |||
| 9cb7896b5e | |||
| ab0d75903a | |||
| 5dc560eff1 | |||
| 68788c5294 | |||
| 46abd0ab77 | |||
| cfc7e0ec16 | |||
| d04db9521d | |||
| 717134932e | |||
| 53043eae50 | |||
| 41a7c43fe9 | |||
| cb8b603296 | |||
| 61cb10d1fe | |||
| fafbf9fcea | |||
| d7b1937495 | |||
| e2716c2a7b | |||
| 99b7abb930 | |||
| 68b233559e | |||
| 869c66d20c | |||
| 3c43498fdb | |||
| 99d681bde5 | |||
| 7e64174acb | |||
| cacd825835 | |||
| 07f7a420f3 | |||
| dab955b151 | |||
| a79338ab32 | |||
| 4c4fb90637 | |||
| e56df5384e | |||
| fda332f424 | |||
| 25daabda9c | |||
| af3b22551d | |||
| 2a334a714f | |||
| 0f60809c32 | |||
| e936416f25 | |||
| 4b7d96be33 | |||
| ce06163a4c | |||
| f1a70bb6ad | |||
| 6a7a5cc2dd | |||
| 70679cbf17 | |||
| 91f6c67cc6 | |||
| 288fe4c690 | |||
| bc3d2c0f71 | |||
| 50527d9c33 | |||
| 1a5c2806e0 | |||
| 0134c96f28 | |||
| f59f8e214c | |||
| 7bd30717bb | |||
| 01375d0adc | |||
| 31ee156d86 | |||
| 3eaa8a1078 | |||
| 64605dfa25 | |||
| 88b7b4d2f6 | |||
| d78e5469b2 | |||
| 744229da06 | |||
| ecf9ac911c | |||
| 2832f0f3b0 | |||
| db04a40f48 | |||
| eec4f8de5a | |||
| 57b28e7356 | |||
| 7589a25ed3 | |||
| 7dec6bbc1a | |||
| df0f50187e | |||
| 15666271fd | |||
| fc18f02423 | |||
| 5deaf6ce7f | |||
| c416cc1e9a | |||
| 27f40962f7 | |||
| 8838871c0d | |||
| ce4ca4b382 | |||
| 0aba716ae0 | |||
| e516e009de | |||
| 5602f45ebd | |||
| 1225d18e75 | |||
| aac6a9a279 | |||
| 6738f6a90a | |||
| 9b27865675 | |||
| 8bc4b0d244 | |||
| 6e6974bfdd | |||
| 0cd9d1867c | |||
| f8720f9c1d | |||
| 674cd139ea | |||
| 8b3b69fbb8 | |||
| b69430e3cb | |||
| f42d9a4587 | |||
| 225cd8c949 | |||
| 6fcd163988 | |||
| 2441a6ae3b | |||
| e7ff7547a1 | |||
| bfda98d254 | |||
| d3ea103c85 | |||
| c6b36bf805 | |||
| f0bcf2d070 | |||
| 11644212c9 | |||
| 0c6b968fd5 | |||
| e31e6177fb | |||
| 4998f6034d | |||
| 6fafa66975 | |||
| caa573551e | |||
| 75c598c912 | |||
| dcbb9fa391 | |||
| 932cb89a44 | |||
| b4ffae867b | |||
| b055365f18 | |||
| b8e21e5265 | |||
| 55d2ec2dd7 | |||
| f96ce12758 | |||
| 2e743448f7 | |||
| 7c8efc6139 | |||
| 28cab4bd11 | |||
| d1418b94d3 | |||
| b97036b98c | |||
| 3ddf04fb09 | |||
| 3cf38fa3cf | |||
| 52515f3dfe | |||
| d03aa27f9e | |||
| b827d678aa | |||
| 153eefcc71 | |||
| c00b63a1b0 | |||
| c5194c1c3a | |||
| e911305aaa | |||
| 9a430dfa0e | |||
| b81619d854 | |||
| 5ea5323112 | |||
| 8cf077d9f1 | |||
| ab4630ab24 | |||
| 2d1d3979b1 | |||
| 38cdc008e5 | |||
| c15ef3137c | |||
| 523f09d8aa | |||
| 9a5b5636e9 | |||
| 1ad7308108 | |||
| b194451752 | |||
| c96934e503 | |||
| 3212dfdf7a | |||
| 567d204a62 | |||
| d86988cb8f | |||
| 9b2cdee052 | |||
| ccd53bfdf8 | |||
| 867a0728ea | |||
| 3515469ca5 | |||
| b66f747562 |
@@ -0,0 +1,25 @@
|
||||
**/.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
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["IRaCIS.Core.API/IRaCIS.Core.API.csproj", "IRaCIS.Core.API/"]
|
||||
COPY ["IRaCIS.Core.Application/IRaCIS.Core.Application.csproj", "IRaCIS.Core.Application/"]
|
||||
COPY ["IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj", "IRaCIS.Core.Infra.EFCore/"]
|
||||
COPY ["IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj", "IRaCIS.Core.Domain/"]
|
||||
COPY ["IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj", "IRaCIS.Core.Domain.Share/"]
|
||||
COPY ["IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj", "IRaCIS.Core.Infrastructure/"]
|
||||
RUN dotnet restore "IRaCIS.Core.API/IRaCIS.Core.API.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/IRaCIS.Core.API"
|
||||
RUN dotnet build "IRaCIS.Core.API.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "IRaCIS.Core.API.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]
|
||||
@@ -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
|
||||
|
||||
@@ -227,3 +227,5 @@
|
||||
|
||||
|
||||
//app.Run();
|
||||
|
||||
//测试同步
|
||||
|
||||
@@ -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,11 @@ using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Aliyun.Acs.Core;
|
||||
using Aliyun.Acs.Core.Profile;
|
||||
using Aliyun.Acs.Sts.Model.V20150401;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using MassTransit;
|
||||
|
||||
namespace IRaCIS.Api.Controllers
|
||||
{
|
||||
@@ -35,64 +37,16 @@ namespace IRaCIS.Api.Controllers
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取医生详情
|
||||
/// </summary>
|
||||
/// <param name="attachmentService"></param>
|
||||
/// <param name="_doctorService"></param>
|
||||
/// <param name="_educationService"></param>
|
||||
/// <param name="_trialExperienceService"></param>
|
||||
/// <param name="_researchPublicationService"></param>
|
||||
/// <param name="_vacationService"></param>
|
||||
/// <param name="doctorId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet, Route("doctor/getDetail/{doctorId:guid}")]
|
||||
|
||||
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);
|
||||
|
||||
var sowList = _doctorService.GetDoctorSowList(doctorId);
|
||||
var ackSowList = _doctorService.GetDoctorAckSowList(doctorId);
|
||||
|
||||
var doctorDetail = new DoctorDetailDTO
|
||||
{
|
||||
AuditView =await _doctorService.GetAuditState(doctorId),
|
||||
BasicInfoView = await _doctorService.GetBasicInfo(doctorId),
|
||||
EmploymentView = await _doctorService.GetEmploymentInfo(doctorId),
|
||||
AttachmentList = await attachmentService.GetAttachments(doctorId),
|
||||
|
||||
EducationList = education.EducationList,
|
||||
PostgraduateList = education.PostgraduateList,
|
||||
|
||||
TrialExperienceView = await _trialExperienceService.GetTrialExperience(doctorId),
|
||||
ResearchPublicationView = await _researchPublicationService.GetResearchPublication(doctorId),
|
||||
|
||||
SpecialtyView =await _doctorService.GetSpecialtyInfo(doctorId),
|
||||
InHoliday = (await _vacationService.OnVacation(doctorId)).IsSuccess,
|
||||
IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(doctorId),
|
||||
SowList = sowList,
|
||||
AckSowList = ackSowList
|
||||
};
|
||||
|
||||
return ResponseOutput.Ok(doctorDetail);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> 系统用户登录接口[New] </summary>
|
||||
[HttpPost, Route("user/login")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> Login(UserLoginDTO loginUser, [FromServices] IEasyCachingProvider provider, [FromServices] IUserService _userService,
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> Login(UserLoginDTO loginUser, [FromServices] IEasyCachingProvider provider, [FromServices] IUserService _userService,
|
||||
[FromServices] ITokenService _tokenService, [FromServices] IConfiguration configuration)
|
||||
{
|
||||
|
||||
|
||||
var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
|
||||
|
||||
if (returnModel.IsSuccess)
|
||||
@@ -160,6 +114,17 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
|
||||
var option = new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddMonths(1),
|
||||
HttpOnly = true, // 确保 cookie 只能通过 HTTP 访问
|
||||
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified, // 设置 SameSite 属性
|
||||
Secure = false // 确保 cookie 只能通过 HTTPS 访问
|
||||
};
|
||||
|
||||
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
|
||||
|
||||
}
|
||||
|
||||
var userId = returnModel.Data.BasicInfo.Id.ToString();
|
||||
@@ -170,6 +135,51 @@ namespace IRaCIS.Api.Controllers
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("user/GenerateSTS")]
|
||||
public IResponseOutput GenerateSTS( [FromServices] IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile($"appsettings.{webHostEnvironment.EnvironmentName}.json")
|
||||
.Build();
|
||||
|
||||
|
||||
IClientProfile profile = DefaultProfile.GetProfile("cn-shanghai", configuration["AliyunOSS:accessKeyId"], configuration["AliyunOSS:accessKeySecret"]);
|
||||
DefaultAcsClient client = new DefaultAcsClient(profile);
|
||||
|
||||
|
||||
// 创建一个STS请求
|
||||
AssumeRoleRequest request = new AssumeRoleRequest
|
||||
{
|
||||
RoleArn = "acs:ram::1899121822495495:role/oss-upload", // 角色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= configuration["AliyunOSS:region"],
|
||||
BucketName = configuration["AliyunOSS:bucketName"],
|
||||
ViewEndpoint = configuration["AliyunOSS:viewEndpoint"],
|
||||
|
||||
};
|
||||
|
||||
return ResponseOutput.Ok(stsToken);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpGet, Route("imageShare/ShareImage")]
|
||||
[AllowAnonymous]
|
||||
@@ -196,23 +206,25 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
[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);
|
||||
|
||||
var lang = decodeUrl.Substring(decodeUrl.IndexOf("lang=") + "lang=".Length, 2);
|
||||
|
||||
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+ $"?ErrorMessage={System.Web.HttpUtility.UrlEncode("您的初始化链接已过期")} ";
|
||||
decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang == "zh" ? "您的初始化链接已过期" : "Error!The initialization link has expired. Return")} ";
|
||||
}
|
||||
|
||||
return Redirect(decodeUrl);
|
||||
|
||||
@@ -12,6 +12,7 @@ using IRaCIS.Core.Application.Service.Inspection.DTO;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Application.Auth;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace IRaCIS.Core.API.Controllers.Special
|
||||
{
|
||||
@@ -21,13 +22,14 @@ namespace IRaCIS.Core.API.Controllers.Special
|
||||
public class FinancialChangeController : ControllerBase
|
||||
{
|
||||
private readonly ITrialService _trialService;
|
||||
private readonly ICalculateService _calculateService;
|
||||
|
||||
public FinancialChangeController(ITrialService trialService, ICalculateService calculateService
|
||||
)
|
||||
|
||||
private IStringLocalizer _localizer { get; set; }
|
||||
public FinancialChangeController(ITrialService trialService, IStringLocalizer localizer
|
||||
)
|
||||
{
|
||||
_trialService = trialService;
|
||||
_calculateService = calculateService;
|
||||
_localizer = localizer;
|
||||
_trialService = trialService;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,272 +52,36 @@ namespace IRaCIS.Core.API.Controllers.Special
|
||||
/// <param name="param"></param>
|
||||
/// <returns>新记录Id</returns>
|
||||
[HttpPost, Route("trial/addOrUpdateTrial")]
|
||||
[Authorize(Policy = IRaCISPolicy.PM_APM)]
|
||||
//[Authorize(Policy = IRaCISPolicy.PM_APM)]
|
||||
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AddOrUpdateTrial", "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput<Trial>> AddOrUpdateTrial(TrialCommand param)
|
||||
{
|
||||
var userId = Guid.Parse(User.FindFirst("id").Value);
|
||||
var result = await _trialService.AddOrUpdateTrial(param);
|
||||
|
||||
if (_trialService.TrialExpeditedChange)
|
||||
{
|
||||
var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(param.Id.Value);
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
|
||||
|
||||
calcList.ForEach(t =>
|
||||
{
|
||||
if (needCalReviewerIds.Contains(t.DoctorId))
|
||||
{
|
||||
_calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
t.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(t.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新工作量[AUTH]
|
||||
/// </summary>
|
||||
/// <param name="_trialWorkloadService"></param>
|
||||
/// <param name="workLoadAddOrUpdateModel"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[HttpPost, Route("doctorWorkload/workLoadAddOrUpdate")]
|
||||
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput> WorkLoadAddOrUpdate([FromServices] IDoctorWorkloadService _trialWorkloadService, WorkloadCommand workLoadAddOrUpdateModel)
|
||||
{
|
||||
var userId = Guid.Parse(User.FindFirst("id").Value);
|
||||
var result = await _trialWorkloadService.AddOrUpdateWorkload(workLoadAddOrUpdateModel, userId);
|
||||
if (result.IsSuccess && workLoadAddOrUpdateModel.DataFrom == 2)
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
workLoadAddOrUpdateModel.DoctorId
|
||||
},
|
||||
CalculateMonth = workLoadAddOrUpdateModel.WorkTime
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpDelete, Route("doctorWorkload/deleteWorkLoad/{id:guid}/{trialId:guid}")]
|
||||
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput> DeleteWorkLoad([FromServices] IDoctorWorkloadService _trialWorkloadService, Guid id)
|
||||
{
|
||||
//先判断该工作量的费用是否被锁定,如果被锁定,则不能删除
|
||||
var workload = await _trialWorkloadService.GetWorkloadDetailById(id);
|
||||
var yearMonth = workload.WorkTime.ToString("yyyy-MM");
|
||||
var isLock = await _calculateService.IsLock(workload.DoctorId, yearMonth);
|
||||
|
||||
if (isLock)
|
||||
{
|
||||
return ResponseOutput.NotOk("Expenses have been settled and workload can not be reset.");
|
||||
}
|
||||
|
||||
var deleteResult = await _trialWorkloadService.DeleteWorkload(id);
|
||||
if (workload.DataFrom == (int)Domain.Share.WorkLoadFromStatus.FinalConfirm)
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
workload.DoctorId
|
||||
},
|
||||
CalculateMonth = workload.WorkTime
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
return deleteResult;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新汇率(会触发没有对锁定的费用计算)
|
||||
/// </summary>
|
||||
|
||||
[HttpPost, Route("exchangeRate/addOrUpdateExchangeRate")]
|
||||
public async Task<IResponseOutput> AddOrUpdateExchangeRate([FromServices] IExchangeRateService _exchangeRateService, [FromServices] IPaymentAdjustmentService _costAdjustmentService, ExchangeRateCommand addOrUpdateModel)
|
||||
{
|
||||
var result = await _exchangeRateService.AddOrUpdateExchangeRate(addOrUpdateModel);
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, addOrUpdateModel.YearMonth);
|
||||
foreach (var item in calcList)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
item.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(item.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
}
|
||||
await _costAdjustmentService.CalculateCNY(addOrUpdateModel.YearMonth, addOrUpdateModel.Rate);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新 职称单价[AUTH]
|
||||
/// </summary>
|
||||
|
||||
[HttpPost, Route("rankPrice/addOrUpdateRankPrice")]
|
||||
public async Task<IResponseOutput> AddOrUpdateRankPrice([FromServices] IReviewerPayInfoService _reviewerPayInfoService, [FromServices] IRankPriceService _rankPriceService, RankPriceCommand addOrUpdateModel)
|
||||
{
|
||||
if (addOrUpdateModel.Id != Guid.Empty && addOrUpdateModel.Id != null)
|
||||
{
|
||||
var needCalReviewerIds =await _reviewerPayInfoService.GetReviewerIdByRankId(Guid.Parse(addOrUpdateModel.Id.ToString()));
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
|
||||
|
||||
foreach (var item in calcList)
|
||||
{
|
||||
if (item != null && needCalReviewerIds.Contains(item.DoctorId))
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
item.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(item.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
var userId = Guid.Parse(User.FindFirst("id").Value);
|
||||
return await _rankPriceService.AddOrUpdateRankPrice(addOrUpdateModel, userId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新(替换)医生支付展信息[AUTH]
|
||||
/// </summary>
|
||||
|
||||
[HttpPost, Route("reviewerPayInfo/addOrUpdateReviewerPayInfo")]
|
||||
public async Task<IResponseOutput> AddOrUpdateReviewerPayInfo([FromServices] IReviewerPayInfoService _doctorPayInfoService, ReviewerPayInfoCommand addOrUpdateModel)
|
||||
{
|
||||
var userId = Guid.Parse(User.FindFirst("id").Value);
|
||||
var result =await _doctorPayInfoService.AddOrUpdateReviewerPayInfo(addOrUpdateModel, userId);
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(addOrUpdateModel.DoctorId, string.Empty);
|
||||
foreach (var item in calcList)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
item.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(item.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 保存(替换)项目支付价格信息(会触发没有被锁定的费用计算)[AUTH]
|
||||
/// </summary>
|
||||
|
||||
[HttpPost, Route("trialPaymentPrice/addOrUpdateTrialPaymentPrice")]
|
||||
public async Task<IResponseOutput> AddOrUpdateTrialPaymentPrice([FromServices] ITrialPaymentPriceService _trialPaymentPriceService, TrialPaymentPriceCommand addOrUpdateModel)
|
||||
{
|
||||
var userId = Guid.Parse(User.FindFirst("id").Value);
|
||||
var result =await _trialPaymentPriceService.AddOrUpdateTrialPaymentPrice(addOrUpdateModel);
|
||||
var needCalReviewerIds = await _trialService.GetTrialEnrollmentReviewerIds(addOrUpdateModel.TrialId);
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
|
||||
|
||||
|
||||
foreach (var item in calcList)
|
||||
{
|
||||
if (item != null && needCalReviewerIds.Contains(item.DoctorId))
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
item.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(item.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量更新奖励费用[AUTH]
|
||||
/// </summary>
|
||||
|
||||
[HttpPost, Route("volumeReward/addOrUpdatevolumeRewardPriceList")]
|
||||
public async Task<IResponseOutput> AddOrUpdateAwardPriceList([FromServices] IVolumeRewardService _volumeRewardService, IEnumerable<AwardPriceCommand> addOrUpdateModel)
|
||||
{
|
||||
|
||||
var result =await _volumeRewardService.AddOrUpdateVolumeRewardPriceList(addOrUpdateModel);
|
||||
|
||||
var calcList = await _calculateService.GetNeedCalculateReviewerList(Guid.Empty, string.Empty);
|
||||
foreach (var item in calcList)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
await _calculateService.CalculateMonthlyPayment(new CalculateDoctorAndMonthDTO()
|
||||
{
|
||||
NeedCalculateReviewers = new List<Guid>()
|
||||
{
|
||||
item.DoctorId
|
||||
},
|
||||
CalculateMonth = DateTime.Parse(item.YearMonth)
|
||||
}, User.FindFirst("id").Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 计算医生月度费用,并将计算的结果存入费用表
|
||||
/// </summary>
|
||||
[HttpPost, Route("financial/calculateMonthlyPayment")]
|
||||
public async Task<IResponseOutput> CalculateMonthlyPayment(CalculateDoctorAndMonthDTO param)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return ResponseOutput.NotOk("Invalid parameter.");
|
||||
}
|
||||
return await _calculateService.CalculateMonthlyPayment(param, User.FindFirst("id").Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Financials /Monthly Payment 列表查询接口
|
||||
/// </summary>
|
||||
[HttpPost, Route("financial/getMonthlyPaymentList")]
|
||||
public async Task<IResponseOutput<PaymentDTO>> GetMonthlyPaymentList([FromServices] IPaymentService _paymentService, [FromServices] IExchangeRateService _exchangeRateService, MonthlyPaymentQueryDTO queryParam)
|
||||
{
|
||||
return ResponseOutput.Ok(new PaymentDTO
|
||||
{
|
||||
CostList = await _paymentService.GetMonthlyPaymentList(queryParam),
|
||||
ExchangeRate = await _exchangeRateService.GetExchangeRateByMonth(queryParam.StatisticsDate.ToString("yyyy-MM"))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
||||
using IRaCIS.Core.Application.Service.Inspection.Interface;
|
||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||
using IRaCIS.Core.Application.Service.Reading.Interface;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
@@ -36,6 +37,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
private readonly IHttpContextAccessor _httpContext;
|
||||
private readonly ITrialConfigService _trialConfigService;
|
||||
private readonly INoneDicomStudyService _noneDicomStudyService;
|
||||
private readonly IClinicalAnswerService _clinicalAnswerService;
|
||||
private readonly ISubjectService _subjectService;
|
||||
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||||
private readonly ISubjectVisitService _subjectVisitService;
|
||||
@@ -62,6 +64,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
IReadingMedicineQuestionService readingMedicineQuestionService,
|
||||
ITrialConfigService _trialConfigService,
|
||||
INoneDicomStudyService noneDicomStudyService,
|
||||
IClinicalAnswerService clinicalAnswerService,
|
||||
ISubjectService _subjectService,
|
||||
IReadingClinicalDataService _readingClinicalDataService,
|
||||
ISubjectVisitService subjectVisitService,
|
||||
@@ -82,6 +85,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
this._httpContext = httpContext;
|
||||
this._trialConfigService = _trialConfigService;
|
||||
this._noneDicomStudyService = noneDicomStudyService;
|
||||
this._clinicalAnswerService = clinicalAnswerService;
|
||||
this._subjectService = _subjectService;
|
||||
this._readingClinicalDataService = _readingClinicalDataService;
|
||||
this._subjectVisitService = subjectVisitService;
|
||||
@@ -112,6 +116,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingImageTask/SubmitOncologyReadingInfo")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SetOncologyReadingInfo(DataInspectionDto<SubmitOncologyReadingInfoInDto> opt)
|
||||
{
|
||||
@@ -127,6 +133,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingImageTask/SubmitDicomVisitTask")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SubmitDicomVisitTask(DataInspectionDto<SubmitDicomVisitTaskInDto> opt)
|
||||
{
|
||||
@@ -144,6 +152,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingImageTask/SubmitGlobalReadingInfo")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SubmitGlobalReadingInfo(DataInspectionDto<SubmitGlobalReadingInfoInDto> opt)
|
||||
{
|
||||
@@ -161,6 +171,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialReadingInfoSign")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> TrialReadingInfoSign(DataInspectionDto<TrialReadingInfoSignInDto> opt)
|
||||
{
|
||||
@@ -178,6 +190,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingMedicalReview/FinishMedicalReview")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt)
|
||||
{
|
||||
@@ -193,6 +207,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingMedicineQuestion/ConfirmReadingMedicineQuestion")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(DataInspectionDto<ConfirmReadingMedicineQuestionInDto> opt)
|
||||
{
|
||||
@@ -209,6 +225,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingImageTask/SubmitVisitTaskQuestions")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SubmitVisitTaskQuestions(DataInspectionDto<SubmitVisitTaskQuestionsInDto> opt)
|
||||
{
|
||||
@@ -219,12 +237,102 @@ namespace IRaCIS.Core.API.Controllers
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// CRC签名临床数据
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ClinicalAnswer/CRCSignClinicalData")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> CRCSignClinicalData(DataInspectionDto<CRCSignClinicalDataInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _clinicalAnswerService.CRCSignClinicalData(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// CRC确认临床数据
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ClinicalAnswer/CRCConfirmClinical")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> CRCConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _clinicalAnswerService.CRCConfirmClinical(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CRC撤销临床数据
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ClinicalAnswer/CRCCancelConfirmClinical")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> CRCCancelConfirmClinical(DataInspectionDto<CRCCancelConfirmClinicalInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _clinicalAnswerService.CRCCancelConfirmClinical(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// PM确认临床数据
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ClinicalAnswer/PMConfirmClinical")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> PMConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _clinicalAnswerService.PMConfirmClinical(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 提交结构化录入并签名
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SubmitClinicalFormAndSign(DataInspectionDto<SubmitClinicalFormInDto> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _clinicalAnswerService.SubmitClinicalForm(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提交阅片裁判问题
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeVisitTaskResult")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(DataInspectionDto<SaveJudgeVisitTaskResult> opt)
|
||||
{
|
||||
@@ -262,7 +370,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialProcessInfoConfirm")]
|
||||
[UnitOfWork]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt" })]
|
||||
//[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt" })]
|
||||
public async Task<IResponseOutput> ConfigTrialProcessInfoConfirm(DataInspectionDto<TrialProcessConfig> opt)
|
||||
{
|
||||
opt.Data.IsTrialProcessConfirmed = true;
|
||||
@@ -318,6 +426,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <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)
|
||||
{
|
||||
@@ -332,6 +441,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// 设置QC 通过或者不通过 7:QC failed 8:QC passed
|
||||
/// </summary>
|
||||
[HttpPost, Route("Inspection/QCOperation/QCPassedOrFailed")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> QCPassedOrFailed(DataInspectionDto<QCPassedOrFailedDto> opt)
|
||||
{
|
||||
@@ -345,6 +455,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// 一致性核查 回退 对话记录不清除 只允许PM回退
|
||||
/// </summary>
|
||||
[HttpPost, Route("Inspection/QCOperation/CheckBack")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> CheckBack(DataInspectionDto<IDDto> opt)
|
||||
{
|
||||
@@ -361,7 +472,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/ReadClinicalData/ReadClinicalDataSign")]
|
||||
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ReadClinicalDataSign(DataInspectionDto<ReadingClinicalDataSignIndto> opt)
|
||||
{
|
||||
@@ -376,8 +487,9 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// CRC 设置已经重传完成
|
||||
/// </summary>
|
||||
[HttpPost, Route("Inspection/QCOperation/SetReuploadFinished")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt)
|
||||
public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
var result = await _qCOperationService.SetReuploadFinished(opt.Data);
|
||||
@@ -391,6 +503,8 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/TrialConfig/updateTrialState")]
|
||||
//[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> UpdateTrialState(DataInspectionDto<UpdateTrialStateDto> opt)
|
||||
{
|
||||
@@ -406,11 +520,11 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/TrialDocument/userConfirm")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> UserConfirm(DataInspectionDto<UserConfirmCommand> opt)
|
||||
{
|
||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||
|
||||
opt.Data.SignText = opt.SignInfo.SignText;
|
||||
var result = await _trialDocumentService.UserConfirm(opt.Data);
|
||||
await _inspectionService.CompletedSign(singid, result);
|
||||
@@ -423,6 +537,7 @@ namespace IRaCIS.Core.API.Controllers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost, Route("Inspection/VisitTask/ConfirmReReading")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
[UnitOfWork]
|
||||
|
||||
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt , [FromServices] IVisitTaskHelpeService _visitTaskCommonService,[FromServices] IVisitTaskService _visitTaskService)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["IRaCIS.Core.API/IRaCIS.Core.API.csproj", "IRaCIS.Core.API/"]
|
||||
COPY ["IRaCIS.Core.Application/IRaCIS.Core.Application.csproj", "IRaCIS.Core.Application/"]
|
||||
COPY ["IRaCIS.Core.Infra.EFCore/IRaCIS.Core.Infra.EFCore.csproj", "IRaCIS.Core.Infra.EFCore/"]
|
||||
COPY ["IRaCIS.Core.Domain/IRaCIS.Core.Domain.csproj", "IRaCIS.Core.Domain/"]
|
||||
COPY ["IRaCIS.Core.Domain.Share/IRaCIS.Core.Domain.Share.csproj", "IRaCIS.Core.Domain.Share/"]
|
||||
COPY ["IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj", "IRaCIS.Core.Infrastructure/"]
|
||||
RUN dotnet restore "IRaCIS.Core.API/IRaCIS.Core.API.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/IRaCIS.Core.API"
|
||||
RUN dotnet build "IRaCIS.Core.API.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "IRaCIS.Core.API.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "IRaCIS.Core.API.dll"]
|
||||
@@ -6,6 +6,10 @@
|
||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||
<LangVersion>default</LangVersion>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<Version>1.0.1.001</Version>
|
||||
<Company>上海展影医疗科技有限公司</Company>
|
||||
<Product>IRC影像系统 (EICS)</Product>
|
||||
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
@@ -21,10 +25,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="UploadFile\**" />
|
||||
<Compile Remove="wwwroot\**" />
|
||||
<Content Remove="UploadFile\**" />
|
||||
|
||||
<EmbeddedResource Remove="UploadFile\**" />
|
||||
<EmbeddedResource Remove="wwwroot\**" />
|
||||
|
||||
@@ -65,26 +66,23 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.1" />
|
||||
<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="Hangfire.AspNetCore" Version="1.8.5" />
|
||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||
<PackageReference Include="Hangfire.SqlServer" Version="1.8.5" />
|
||||
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
|
||||
<PackageReference Include="LogDashboard" Version="1.4.8" />
|
||||
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
|
||||
<PackageReference Include="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" />
|
||||
@@ -102,33 +100,59 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="NLog.config">
|
||||
<Content Update="appsettings.Uat_Study.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminResetUser_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminResetUser.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\EmailConfigTest.html">
|
||||
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialSiteSurveyReject_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserExistJoin.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\AdminAddUser.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin.html">
|
||||
<Content Update="wwwroot\EmailTemplate\TrialDoctorFirstJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\SubjectEnrollConfirmOrPDProgress.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\TrialUserFirstJoin_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\UserOptCommon_US.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\EmailTemplate\UserOptCommon.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
@@ -143,5 +167,13 @@
|
||||
|
||||
<ProjectExtensions><VisualStudio><UserProperties anonymizetagsetting_1json__JsonSchema="http://json.schemastore.org/jovo-language-model" properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="..\.dockerignore" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="..\.dockerignore" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -16,19 +16,6 @@
|
||||
医生基本信息 、工作信息 专业信息、审核状态
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Api.Controllers.ExtraController.GetDoctorDetail(IRaCIS.Application.Interfaces.IAttachmentService,IRaCIS.Application.Interfaces.IDoctorService,IRaCIS.Application.Interfaces.IEducationService,IRaCIS.Application.Interfaces.ITrialExperienceService,IRaCIS.Application.Interfaces.IResearchPublicationService,IRaCIS.Application.Interfaces.IVacationService,System.Guid)">
|
||||
<summary>
|
||||
获取医生详情
|
||||
</summary>
|
||||
<param name="attachmentService"></param>
|
||||
<param name="_doctorService"></param>
|
||||
<param name="_educationService"></param>
|
||||
<param name="_trialExperienceService"></param>
|
||||
<param name="_researchPublicationService"></param>
|
||||
<param name="_vacationService"></param>
|
||||
<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)">
|
||||
<summary> 系统用户登录接口[New] </summary>
|
||||
</member>
|
||||
@@ -41,49 +28,6 @@
|
||||
<param name="param"></param>
|
||||
<returns>新记录Id</returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.WorkLoadAddOrUpdate(IRaCIS.Application.Services.IDoctorWorkloadService,IRaCIS.Application.Contracts.WorkloadCommand)">
|
||||
<summary>
|
||||
添加或更新工作量[AUTH]
|
||||
</summary>
|
||||
<param name="_trialWorkloadService"></param>
|
||||
<param name="workLoadAddOrUpdateModel"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateExchangeRate(IRaCIS.Application.Interfaces.IExchangeRateService,IRaCIS.Application.Interfaces.IPaymentAdjustmentService,IRaCIS.Application.Contracts.ExchangeRateCommand)">
|
||||
<summary>
|
||||
添加或更新汇率(会触发没有对锁定的费用计算)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateRankPrice(IRaCIS.Application.Interfaces.IReviewerPayInfoService,IRaCIS.Application.Interfaces.IRankPriceService,IRaCIS.Application.Contracts.RankPriceCommand)">
|
||||
<summary>
|
||||
添加或更新 职称单价[AUTH]
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateReviewerPayInfo(IRaCIS.Application.Interfaces.IReviewerPayInfoService,IRaCIS.Application.Contracts.ReviewerPayInfoCommand)">
|
||||
<summary>
|
||||
添加或更新(替换)医生支付展信息[AUTH]
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateTrialPaymentPrice(IRaCIS.Application.Interfaces.ITrialPaymentPriceService,IRaCIS.Application.Contracts.TrialPaymentPriceCommand)">
|
||||
<summary>
|
||||
保存(替换)项目支付价格信息(会触发没有被锁定的费用计算)[AUTH]
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.AddOrUpdateAwardPriceList(IRaCIS.Application.Interfaces.IVolumeRewardService,System.Collections.Generic.IEnumerable{IRaCIS.Application.Interfaces.AwardPriceCommand})">
|
||||
<summary>
|
||||
批量更新奖励费用[AUTH]
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.CalculateMonthlyPayment(IRaCIS.Application.Contracts.CalculateDoctorAndMonthDTO)">
|
||||
<summary>
|
||||
计算医生月度费用,并将计算的结果存入费用表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.Special.FinancialChangeController.GetMonthlyPaymentList(IRaCIS.Application.Interfaces.IPaymentService,IRaCIS.Application.Interfaces.IExchangeRateService,IRaCIS.Application.Contracts.MonthlyPaymentQueryDTO)">
|
||||
<summary>
|
||||
Financials /Monthly Payment 列表查询接口
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.GetInspectionList(IRaCIS.Core.Application.Service.Inspection.DTO.GetDataInspectionDto)">
|
||||
<summary>
|
||||
获取稽查数据
|
||||
@@ -139,6 +83,41 @@
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.CRCSignClinicalData(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.CRCSignClinicalDataInDto})">
|
||||
<summary>
|
||||
CRC签名临床数据
|
||||
</summary>
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.CRCConfirmClinical(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.CRCConfirmClinicalInDto})">
|
||||
<summary>
|
||||
CRC确认临床数据
|
||||
</summary>
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.CRCCancelConfirmClinical(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.CRCCancelConfirmClinicalInDto})">
|
||||
<summary>
|
||||
CRC撤销临床数据
|
||||
</summary>
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.PMConfirmClinical(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.CRCConfirmClinicalInDto})">
|
||||
<summary>
|
||||
PM确认临床数据
|
||||
</summary>
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitClinicalFormAndSign(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SubmitClinicalFormInDto})">
|
||||
<summary>
|
||||
提交结构化录入并签名
|
||||
</summary>
|
||||
<param name="opt"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitJudgeVisitTaskResult(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SaveJudgeVisitTaskResult})">
|
||||
<summary>
|
||||
提交阅片裁判问题
|
||||
@@ -230,63 +209,14 @@
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadBaseController.DicomFileUploadAsync(System.Func{System.String,System.IO.Stream,System.Int32,System.Threading.Tasks.Task},System.String)">
|
||||
<summary> 流式上传 Dicom上传 </summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.ArchiveStudyNew(System.Guid,System.Guid,System.String,System.Nullable{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)">
|
||||
<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.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,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy})">
|
||||
<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="_noneDicomStudyRepository"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.StudyController.UploadVisitCheckExcel(System.Guid)">
|
||||
@@ -296,92 +226,15 @@
|
||||
<param name="trialId"></param>
|
||||
<returns></returns>
|
||||
</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)">
|
||||
<summary>
|
||||
上传文件[FileUpload]
|
||||
</summary>
|
||||
<param name="attachmentType">附件类型</param>
|
||||
<param name="doctorId">医生Id</param>
|
||||
<returns>返回文件信息</returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.UploadNonDoctorFile(System.String)">
|
||||
<summary>
|
||||
上传文件( 不是医生个人的文件)[FileUpload]
|
||||
例如:阅片章程等
|
||||
</summary>
|
||||
<param name="type">文件类型</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.FileController.DownloadAttachment(System.Guid[])">
|
||||
<summary>
|
||||
下载多个医生的所有附件
|
||||
</summary>
|
||||
<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>
|
||||
下载指定医生的指定附件
|
||||
</summary>
|
||||
<param name="doctorId">医生Id</param>
|
||||
<param name="attachmentIds">要下载的附件Id</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.API.Controllers.UploadDownLoadController.LocalFilePreview(System.String)">
|
||||
<summary> 缩略图 </summary>
|
||||
</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>
|
||||
@@ -440,113 +293,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>
|
||||
|
||||
@@ -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>
|
||||
+20
-64
@@ -9,6 +9,12 @@ 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 IRaCIS.Application.Services.BackGroundJob;
|
||||
using Hangfire;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -50,23 +56,18 @@ namespace IRaCIS.Core.API
|
||||
.Build();
|
||||
|
||||
|
||||
//// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, host.Services);
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
|
||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
|
||||
|
||||
|
||||
//// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, host.Services);
|
||||
|
||||
//缓存项目的状态 匿名化数据
|
||||
await InitCache(host);
|
||||
|
||||
|
||||
////缓存项目的状态 匿名化数据
|
||||
//await InitCache(host);
|
||||
|
||||
host.Run();
|
||||
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -75,46 +76,6 @@ namespace IRaCIS.Core.API
|
||||
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Nlog 废弃
|
||||
//var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.config").GetCurrentClassLogger();
|
||||
//try
|
||||
//{
|
||||
// var ihostBuilder = CreateHostBuilder(args);
|
||||
|
||||
// ihostBuilder.UseEnvironment(environment);
|
||||
|
||||
// ihostBuilder.ConfigureAppConfiguration((hostContext, config) =>
|
||||
// {
|
||||
|
||||
// //Console.WriteLine(hostContext.HostingEnvironment.EnvironmentName);
|
||||
// config.AddJsonFile("appsettings.json", false, true)
|
||||
// .AddJsonFile($"appsettings.{environment}.json", false, true);
|
||||
// });
|
||||
|
||||
// var host = ihostBuilder.Build();
|
||||
|
||||
// CacheTrialStatus(host);
|
||||
|
||||
// host.Run();
|
||||
|
||||
//}
|
||||
//catch (Exception exception)
|
||||
//{
|
||||
// //NLog: catch setup errors
|
||||
// logger.Error(exception, "Stopped program because of exception");
|
||||
//}
|
||||
//finally
|
||||
//{
|
||||
// // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
|
||||
// NLog.LogManager.Shutdown();
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
@@ -133,26 +94,21 @@ namespace IRaCIS.Core.API
|
||||
//webBuilder.UseSerilog();//在宿主机启动的时候配置serilog,与微软ILogger进行整合
|
||||
webBuilder.UseStartup<Startup>();
|
||||
}).UseSerilog()
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory());//使用Autofac替代本身容器
|
||||
//ConfigureLogging(logging =>
|
||||
//{
|
||||
// logging.ClearProviders();
|
||||
// logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||
//})
|
||||
//.UseNLog()
|
||||
// NLog: Setup NLog for Dependency injection;
|
||||
|
||||
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
|
||||
|
||||
|
||||
private static async Task InitCache(IHost host)
|
||||
{
|
||||
var _mediator = host.Services.GetService(typeof(IMediator)) as IMediator;
|
||||
var _repository = host.Services.GetService(typeof(IRepository)) as IRepository;
|
||||
|
||||
await _mediator.Send(new AnonymizeCacheRequest());
|
||||
//初始化 国际化数据,并且监测国际化文件变更
|
||||
//await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_repository);
|
||||
|
||||
await _mediator.Send(new TrialStateCacheRequest());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,27 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:3305",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IRaCIS.Development": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"profiles": {
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||
"publishAllPorts": true
|
||||
},
|
||||
"IRaCIS.Staging": {
|
||||
"Uat_Study": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Staging"
|
||||
"ASPNETCORE_ENVIRONMENT": "Uat_Study"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6200"
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
},
|
||||
"IRaCIS.Production": {
|
||||
"Test_Study": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Production"
|
||||
"ASPNETCORE_ENVIRONMENT": "Test_Study"
|
||||
},
|
||||
"applicationUrl": "http://localhost:6300"
|
||||
"applicationUrl": "http://localhost:6100"
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-12
@@ -23,6 +23,12 @@ using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using Invio.Extensions.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Autofac.Core;
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -82,15 +88,13 @@ namespace IRaCIS.Core.API
|
||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
{
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
.AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
|
||||
|
||||
services.AddOptions().Configure<SystemEmailSendConfig>( _configuration.GetSection("SystemEmailSendConfig"));
|
||||
services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.GetSection("SystemEmailSendConfig"));
|
||||
services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
|
||||
|
||||
@@ -116,6 +120,7 @@ namespace IRaCIS.Core.API
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
services.AddhangfireSetup(_configuration);
|
||||
|
||||
// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
|
||||
services.AddQuartZSetup(_configuration);
|
||||
|
||||
@@ -137,7 +142,7 @@ namespace IRaCIS.Core.API
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
services.AddAuthorizationPolicySetup(_configuration);
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
|
||||
services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
@@ -162,8 +167,10 @@ namespace IRaCIS.Core.API
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
//app.UsePathBase(PathString.FromUriComponent("/api"));
|
||||
|
||||
//本地化
|
||||
app.UseLocalization();
|
||||
|
||||
@@ -179,7 +186,7 @@ namespace IRaCIS.Core.API
|
||||
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
app.UseLogDashboard("/back/logs");
|
||||
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
@@ -218,8 +225,8 @@ namespace IRaCIS.Core.API
|
||||
|
||||
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(env);
|
||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
@@ -229,17 +236,21 @@ namespace IRaCIS.Core.API
|
||||
////文件伺服 必须带Token 访问
|
||||
////app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
|
||||
|
||||
endpoints.MapControllers();
|
||||
|
||||
endpoints.MapHub<UploadHub>("/UploadHub");
|
||||
});
|
||||
|
||||
|
||||
var hangfireJobService = app.ApplicationServices.GetRequiredService<IIRaCISHangfireJob>();
|
||||
|
||||
await hangfireJobService.InitHangfireJobTaskAsync();
|
||||
//有的时候每调用
|
||||
//HangfireJobHelper.NotImmediatelyOnceOnlyJob<IIRaCISHangfireJob>(t => t.InitHangfireJobTaskAsync(),TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EFSaving.Concurrency
|
||||
{
|
||||
public class Sample
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
// Ensure database is created and has a person in it
|
||||
using (var setupContext = new PersonContext())
|
||||
{
|
||||
setupContext.Database.EnsureDeleted();
|
||||
setupContext.Database.EnsureCreated();
|
||||
|
||||
setupContext.People.Add(new Person { FirstName = "John", LastName = "Doe" });
|
||||
setupContext.SaveChanges();
|
||||
}
|
||||
|
||||
#region ConcurrencyHandlingCode
|
||||
using var context = new PersonContext();
|
||||
// Fetch a person from database and change phone number
|
||||
var person = context.People.Single(p => p.PersonId == 1);
|
||||
person.PhoneNumber = "555-555-5555";
|
||||
|
||||
// Change the person's name in the database to simulate a concurrency conflict
|
||||
context.Database.ExecuteSqlRaw(
|
||||
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1");
|
||||
|
||||
var saved = false;
|
||||
while (!saved)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Attempt to save changes to the database
|
||||
context.SaveChanges();
|
||||
saved = true;
|
||||
}
|
||||
catch (DbUpdateConcurrencyException ex)
|
||||
{
|
||||
foreach (var entry in ex.Entries)
|
||||
{
|
||||
if (entry.Entity is Person)
|
||||
{
|
||||
var proposedValues = entry.CurrentValues;
|
||||
var databaseValues = entry.GetDatabaseValues();
|
||||
|
||||
foreach (var property in proposedValues.Properties)
|
||||
{
|
||||
var proposedValue = proposedValues[property];
|
||||
var databaseValue = databaseValues[property];
|
||||
|
||||
// TODO: decide which value should be written to database
|
||||
// proposedValues[property] = <value to be saved>;
|
||||
}
|
||||
|
||||
// Refresh original values to bypass next concurrency check
|
||||
entry.OriginalValues.SetValues(databaseValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
"Don't know how to handle concurrency conflicts for "
|
||||
+ entry.Metadata.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class PersonContext : DbContext
|
||||
{
|
||||
public DbSet<Person> People { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
// Requires NuGet package Microsoft.EntityFrameworkCore.SqlServer
|
||||
optionsBuilder.UseSqlServer(
|
||||
@"Server=(localdb)\mssqllocaldb;Database=EFSaving.Concurrency;Trusted_Connection=True");
|
||||
}
|
||||
}
|
||||
|
||||
public class Person
|
||||
{
|
||||
public int PersonId { get; set; }
|
||||
|
||||
[ConcurrencyCheck]
|
||||
public string FirstName { get; set; }
|
||||
|
||||
[ConcurrencyCheck]
|
||||
public string LastName { get; set; }
|
||||
|
||||
public string PhoneNumber { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ namespace IRaCIS.Core.API.Utility
|
||||
|
||||
if (string.IsNullOrWhiteSpace(boundary))
|
||||
{
|
||||
throw new InvalidDataException("Missing content-type boundary.");
|
||||
throw new InvalidDataException(
|
||||
"Missing content-type boundary.");
|
||||
}
|
||||
|
||||
if (boundary.Length > lengthLimit)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using Hangfire.Dashboard;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Core.API.Filter
|
||||
{
|
||||
|
||||
//从cookie 中取值
|
||||
public class hangfireAuthorizationFilter : IDashboardAuthorizationFilter
|
||||
{
|
||||
public bool Authorize(DashboardContext context)
|
||||
{
|
||||
var httpContext = context.GetHttpContext();
|
||||
|
||||
// Allow all authenticated users to see the Dashboard (potentially dangerous).
|
||||
//return httpContext.User.Identity.IsAuthenticated;
|
||||
|
||||
var jwtToken = httpContext.Request.Cookies["access_token"]?.ToString();
|
||||
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
|
||||
if (handler.CanReadToken(jwtToken))
|
||||
{
|
||||
|
||||
var jwtSecurityToken = handler.ReadJwtToken(jwtToken);
|
||||
|
||||
return jwtSecurityToken.Claims.Any(t => t.Type == JwtIRaCISClaimType.UserTypeEnum && (t.Value == UserTypeEnum.Admin.ToString()|| t.Value== UserTypeEnum.SuperAdmin.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.MemoryCacheTrialStatus(), Cron.Daily);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Hangfire.Dashboard;
|
||||
|
||||
namespace IRaCIS.Core.API.Filter
|
||||
{
|
||||
public class hangfireAuthorizationFilter : IDashboardAuthorizationFilter
|
||||
{
|
||||
public bool Authorize(DashboardContext context)
|
||||
{
|
||||
var httpContext = context.GetHttpContext();
|
||||
|
||||
// Allow all authenticated users to see the Dashboard (potentially dangerous).
|
||||
return httpContext.User.Identity.IsAuthenticated;
|
||||
|
||||
//return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// })
|
||||
//}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -12,8 +12,8 @@ namespace IRaCIS.Core.API
|
||||
|
||||
public static void UseIRacisHostStaticFileStore(this IApplicationBuilder app, IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
|
||||
var iRaCISDataFolder = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
var iRaCISDataFolder = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
if (!Directory.Exists(iRaCISDataFolder))
|
||||
{
|
||||
@@ -26,13 +26,7 @@ namespace IRaCIS.Core.API
|
||||
RequestPath = $"/{StaticData.Folder.IRaCISDataFolder}",
|
||||
ServeUnknownFileTypes = true,
|
||||
DefaultContentType = "application/octet-stream"
|
||||
|
||||
// // Set up custom content types - associating file extension to MIME type
|
||||
//var provider = new FileExtensionContentTypeProvider();
|
||||
// // Add new mappings
|
||||
// provider.Mappings[".myapp"] = "application/x-msdownload";
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders.Physical;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Hosting.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.VisualBasic;
|
||||
using SharpCompress.Common;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
|
||||
|
||||
public class MultiDiskStaticFilesMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IWebHostEnvironment _hostingEnv;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
private string iRaCISDefaultDataFolder = string.Empty;
|
||||
|
||||
public MultiDiskStaticFilesMiddleware(RequestDelegate next, IWebHostEnvironment hostingEnv, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_next = next;
|
||||
_hostingEnv = hostingEnv;
|
||||
_loggerFactory = loggerFactory;
|
||||
|
||||
iRaCISDefaultDataFolder = FileStoreHelper.GetIRaCISRootDataFolder(_hostingEnv);
|
||||
|
||||
if (!Directory.Exists(iRaCISDefaultDataFolder))
|
||||
{
|
||||
Directory.CreateDirectory(iRaCISDefaultDataFolder);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
var path = context.Request.Path.Value;
|
||||
var isIRacisFile = path.StartsWith($"/{StaticData.Folder.IRaCISDataFolder}");
|
||||
|
||||
var isDicomFile = path.Contains($"{StaticData.Folder.DicomFolder}");
|
||||
|
||||
|
||||
|
||||
//先从默认里面去找
|
||||
if (isIRacisFile)
|
||||
{
|
||||
|
||||
|
||||
|
||||
#region 方式二
|
||||
|
||||
//var defaultFileProvider = new PhysicalFileProvider(iRaCISDefaultDataFolder);
|
||||
|
||||
//var staticFileOptions = new StaticFileOptions
|
||||
//{
|
||||
// FileProvider = defaultFileProvider,
|
||||
// RequestPath = $"/{StaticData.Folder.IRaCISDataFolder}",
|
||||
// ServeUnknownFileTypes = true,
|
||||
// DefaultContentType = "application/octet-stream"
|
||||
//};
|
||||
|
||||
//var a = defaultFileProvider.GetFileInfo(context.Request.Path).Exists;
|
||||
|
||||
//var staticFileMiddleware = new StaticFileMiddleware(_next, _hostingEnv, Options.Create(staticFileOptions), _loggerFactory);
|
||||
//await staticFileMiddleware.Invoke(context);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region 文档上传默认会加wwwroot 奇怪...
|
||||
|
||||
var defaultFileProvider = new PhysicalFileProvider(FileStoreHelper.GetIRaCISRootPath(_hostingEnv));
|
||||
|
||||
if (defaultFileProvider.GetFileInfo(path).Exists)
|
||||
{
|
||||
|
||||
var actrualPath = defaultFileProvider.GetFileInfo(path).PhysicalPath;
|
||||
|
||||
await context.Response.SendFileAsync(new PhysicalFileInfo(new FileInfo(actrualPath)));
|
||||
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
//没找到
|
||||
//dicom影像,从多个文件夹尝试,因为会存在切换磁盘
|
||||
if (isDicomFile)
|
||||
{
|
||||
var defaultRoot = Path.GetPathRoot(iRaCISDefaultDataFolder);
|
||||
|
||||
//除默认部署路径的其他路径
|
||||
var disks = DriveInfo.GetDrives()
|
||||
.Where(d => d.IsReady && d.DriveType == DriveType.Fixed)/*.Where(t => !t.Name.Contains("C") && !t.Name.Contains("c"))*/
|
||||
.OrderBy(d => d.AvailableFreeSpace)
|
||||
.Select(d => d.RootDirectory.FullName)
|
||||
.ToArray().Where(t=>!t.Contains(defaultRoot));
|
||||
|
||||
|
||||
foreach (var item in disks)
|
||||
{
|
||||
var otherFileStoreFolder = Path.Combine(item, _hostingEnv.EnvironmentName);
|
||||
|
||||
if (!Directory.Exists(otherFileStoreFolder))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var otherFileProvider= new PhysicalFileProvider(otherFileStoreFolder);
|
||||
|
||||
|
||||
|
||||
if (otherFileProvider.GetFileInfo(path).Exists)
|
||||
{
|
||||
|
||||
var actrualPath = otherFileProvider.GetFileInfo(path).PhysicalPath;
|
||||
|
||||
//方式一
|
||||
await context.Response.SendFileAsync( new PhysicalFileInfo(new FileInfo(actrualPath)));
|
||||
|
||||
#region 方式二 报错 otherFileProvider 应该还包含/{StaticData.Folder.IRaCISDataFolder} 这一层级
|
||||
//var otherStaticFileOptions = new StaticFileOptions
|
||||
//{
|
||||
// FileProvider = otherFileProvider,
|
||||
// RequestPath = $"/{StaticData.Folder.IRaCISDataFolder}",
|
||||
// ServeUnknownFileTypes = true,
|
||||
// DefaultContentType = "application/octet-stream"
|
||||
//};
|
||||
//var staticFileMiddleware = new StaticFileMiddleware(_next, _hostingEnv, Options.Create(otherStaticFileOptions), _loggerFactory);
|
||||
//await staticFileMiddleware.Invoke(context);
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 如果所有磁盘都不存在所请求的文件,则将请求传递给下一个中间件组件。
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//private static string GetContentType(string path)
|
||||
//{
|
||||
// var provider = new FileExtensionContentTypeProvider();
|
||||
// if (!provider.TryGetContentType(path, out var contentType))
|
||||
// {
|
||||
// contentType = "application/octet-stream";
|
||||
// }
|
||||
|
||||
// return contentType;
|
||||
//}
|
||||
|
||||
//private async Task ServeFileAsync(HttpContext context, IFileInfo fileInfo)
|
||||
//{
|
||||
// var response = context.Response;
|
||||
// response.ContentType = GetContentType(fileInfo.PhysicalPath);
|
||||
|
||||
// using (var fileStream = fileInfo.CreateReadStream())
|
||||
// {
|
||||
// await fileStream.CopyToAsync(response.Body);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using Hangfire;
|
||||
using Hangfire.Dashboard;
|
||||
using IRaCIS.Core.API._PipelineExtensions.Serilog;
|
||||
using IRaCIS.Core.API._PipelineExtensions.Serilog;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Serilog;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
@@ -12,9 +13,14 @@ namespace IRaCIS.Core.API
|
||||
{
|
||||
public class ApiResponseHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
||||
{
|
||||
public ApiResponseHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
public IStringLocalizer _localizer;
|
||||
public ApiResponseHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
IStringLocalizer localizer,
|
||||
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
{
|
||||
}
|
||||
_localizer = localizer;
|
||||
|
||||
}
|
||||
|
||||
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||
{
|
||||
@@ -24,14 +30,16 @@ namespace IRaCIS.Core.API
|
||||
{
|
||||
Response.ContentType = "application/json";
|
||||
Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||
await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您无权访问该接口", ApiResponseCodeEnum.NoToken)));
|
||||
//---您无权访问该接口
|
||||
await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["ApiResponse_NoAccess"], ApiResponseCodeEnum.NoToken)));
|
||||
}
|
||||
|
||||
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
|
||||
{
|
||||
Response.ContentType = "application/json";
|
||||
Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||
await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您的权限不允许进行该操作",ApiResponseCodeEnum.HaveTokenNotAccess)));
|
||||
//---您的权限不允许进行该操作
|
||||
await Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["ApiResponse_Permission"],ApiResponseCodeEnum.HaveTokenNotAccess)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
using IRaCIS.Core.Application.Auth;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class AuthorizationPolicySetup
|
||||
{
|
||||
|
||||
public static void AddAuthorizationPolicySetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
//影像质控策略 只允许 CRC IQC进行操作
|
||||
options.AddPolicy(IRaCISPolicy.CRC_IQC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ClinicalResearchCoordinator).ToString(), ((int)UserTypeEnum.IQC).ToString());
|
||||
});
|
||||
|
||||
//一致性核查策略 只允许 CRC PM APM 进行操作
|
||||
options.AddPolicy(IRaCISPolicy.PM_APM_CRC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(), ((int)UserTypeEnum.ClinicalResearchCoordinator).ToString(), ((int)UserTypeEnum.APM).ToString());
|
||||
});
|
||||
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM_APM, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(), ((int)UserTypeEnum.APM).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM_IQC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(), ((int)UserTypeEnum.IQC).ToString());
|
||||
});
|
||||
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString());
|
||||
});
|
||||
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.IQC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.IQC).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.CRC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ClinicalResearchCoordinator).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM_APM_CRC_QC, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(),((int)UserTypeEnum.ClinicalResearchCoordinator).ToString(), ((int)UserTypeEnum.APM).ToString(), ((int)UserTypeEnum.IQC).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.SPM_CPM, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.SPM).ToString(), ((int)UserTypeEnum.CPM).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM_APM_SPM_CPM, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(), ((int)UserTypeEnum.APM).ToString(),((int)UserTypeEnum.SPM).ToString(), ((int)UserTypeEnum.CPM).ToString());
|
||||
});
|
||||
|
||||
options.AddPolicy(IRaCISPolicy.PM_APM_SPM_CPM_SMM_CMM, policyBuilder =>
|
||||
{
|
||||
policyBuilder.RequireClaim("userTypeEnumInt", ((int)UserTypeEnum.ProjectManager).ToString(), ((int)UserTypeEnum.APM).ToString(), ((int)UserTypeEnum.SPM).ToString(),
|
||||
((int)UserTypeEnum.CPM).ToString(), ((int)UserTypeEnum.SMM).ToString(), ((int)UserTypeEnum.CMM).ToString());
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ using MediatR;
|
||||
using IRaCIS.Application.Services;
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using AutoMapper;
|
||||
using Quartz;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -65,7 +66,6 @@ namespace IRaCIS.Core.API
|
||||
containerBuilder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
|
||||
containerBuilder.RegisterType<UserInfo>().As<IUserInfo>().InstancePerLifetimeScope();
|
||||
|
||||
|
||||
//containerBuilder.RegisterType<Dictionary>().InstancePerLifetimeScope();
|
||||
//Autofac 注册拦截器 需要注意的是生成api上服务上的动态代理AOP失效 间接掉用不影响
|
||||
//containerBuilder.RegisterType<TrialStatusAutofacAOP>();
|
||||
|
||||
@@ -37,12 +37,16 @@ namespace IRaCIS.Core.API
|
||||
triggerOptions.AddTrigger<AddSubjectTrigger>();
|
||||
triggerOptions.AddTrigger<ChallengeStateTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectStateTrigger>();
|
||||
triggerOptions.AddTrigger<AddCRCCliniaclDataTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitCheckPassedTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitFinalVisitTrigger>();
|
||||
triggerOptions.AddTrigger<SubjectVisitTrigger>();
|
||||
triggerOptions.AddTrigger<TrialCriterionSignTrigger>();
|
||||
triggerOptions.AddTrigger<TableQuestionRowTrigger>();
|
||||
|
||||
//triggerOptions.AddTrigger<AddlTrialUserTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIsFrontTaskNeedSignButNotSignTrigger>();
|
||||
triggerOptions.AddTrigger<VisitTaskIAfterSignTrigger>();
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ namespace IRaCIS.Core.API
|
||||
services.AddLogDashboard(opt =>
|
||||
{
|
||||
//opt.PathMatch = "/api/LogDashboard";
|
||||
opt.PathMatch = "/LogDashboard";
|
||||
opt.PathMatch = "/back/logs";
|
||||
|
||||
//opt.AddAuthorizationFilter(new LogDashboardBasicAuthFilter("admin", "zhizhun2018"));
|
||||
|
||||
//opt.AddAuthorizationFilter(new LogDashBoardAuthFilter());
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
@@ -22,6 +23,9 @@ namespace IRaCIS.Core.API
|
||||
// 设置时间格式
|
||||
options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
//options.SerializerSettings.Converters.Add(new JSONCustomDateConverter()) ;
|
||||
|
||||
//IsoDateTimeConverter
|
||||
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||
|
||||
})
|
||||
|
||||
@@ -1,44 +1,48 @@
|
||||
|
||||
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 class QuartZSetup
|
||||
{
|
||||
public static void AddQuartZSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
//services.AddTransient<CacheTrialStatusQuartZJob>();
|
||||
services.AddTransient<CancelTaskQuartZJob>();
|
||||
|
||||
//services.AddQuartz(q =>
|
||||
//{
|
||||
// // base quartz scheduler, job and trigger configuration
|
||||
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();
|
||||
// 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)
|
||||
// //.StartNow()
|
||||
// //.WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(15))//开始秒数 15s
|
||||
// // .RepeatForever())//持续工作
|
||||
// .WithCronSchedule("0 0 0/2 * * ?")//每小时执行一次
|
||||
// .WithDescription("My regular trial work trigger")
|
||||
// );
|
||||
//});
|
||||
// 基本Quartz调度器、作业和触发器配置
|
||||
//var jobKey = new JobKey("RegularTrialWork", "regularWorkGroup");
|
||||
//q.AddJob<CacheTrialStatusQuartZJob>(jobKey, j => j
|
||||
// .WithDescription("Trial regular work")
|
||||
//);
|
||||
|
||||
//// ASP.NET Core hosting
|
||||
//services.AddQuartzServer(options =>
|
||||
//{
|
||||
// // when shutting down we want jobs to complete gracefully
|
||||
// options.WaitForJobsToComplete = true;
|
||||
//});
|
||||
//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;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,10 @@ namespace IRaCIS.Core.API
|
||||
config.WriteTo.Email(new EmailConnectionInfo()
|
||||
{
|
||||
EmailSubject = "系统警告,请速速查看!",//邮件标题
|
||||
FromEmail = "iracis_grr@163.com",//发件人邮箱
|
||||
MailServer = "smtp.163.com",//smtp服务器地址
|
||||
NetworkCredentials = new NetworkCredential("iracis_grr@163.com", "XLWVQKZAEKLDWOAH"),//两个参数分别是发件人邮箱与客户端授权码
|
||||
Port = 25,//端口号
|
||||
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})");
|
||||
|
||||
@@ -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,33 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=IRaCIS_New_Tet;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"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"region": "oss-cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-sir-store",
|
||||
"viewEndpoint": "https://zy-sir-cache.oss-cn-shanghai.aliyuncs.com"
|
||||
},
|
||||
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.165.18,1434;Database=Prod_Study;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.165.18,1434;Database=Prod_Study.hangfire;User ID=sa;Password=WHxckj@2019;TrustServerCertificate=true"
|
||||
},
|
||||
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "study@extimaging.com",
|
||||
"FromName": "study.extimaging",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "https://study.extimaging.com/login"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +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
|
||||
},
|
||||
//"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,31 +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
|
||||
|
||||
},
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat@extimaging.com",
|
||||
"FromName": "UAT_IRC",
|
||||
"AuthorizationCode": "SHzyyl2021"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"region": "oss-cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-sir-test-store",
|
||||
"viewEndpoint": "https://zy-sir-test-store.oss-cn-shanghai.aliyuncs.com"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.Study;User ID=sa;Password=dev123456DEV;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=123.56.94.154,1433\\MSSQLSERVER;Database=Test.Study.hangfire;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-study@extimaging.com",
|
||||
"FromName": "Test_Study",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
|
||||
"SiteUrl": "http://test.study.extimaging.com/login"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AliyunOSS": {
|
||||
"regionId": "cn-shanghai",
|
||||
"region": "oss-cn-shanghai",
|
||||
"endpoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||
"accessKeyId": "LTAI5tKvzs7ed3UfSpNk3xwQ",
|
||||
"accessKeySecret": "zTIceGEShlZDGnLrCFfIGFE7TXVRio",
|
||||
"bucketName": "zy-sir-uat-store",
|
||||
"viewEndpoint": "https://zy-sir-uat-store.oss-cn-shanghai.aliyuncs.com"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"RemoteNew": "Server=47.117.164.182,1434;Database=Uat.Study;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||
"Hangfire": "Server=47.117.164.182,1434;Database=Uat.Study.hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||
},
|
||||
"BasicSystemConfig": {
|
||||
|
||||
"OpenUserComplexPassword": false,
|
||||
|
||||
"OpenSignDocumentBeforeWork": false,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": false,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "uat-study@extimaging.com",
|
||||
"FromName": "Uat_Study",
|
||||
"AuthorizationCode": "zhanying123",
|
||||
"SiteUrl": "http://uat.study.extimaging.com/login"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"hang": "Server=ZHOU;Database=IRaCIS;User ID=sa;Password=sa123456;"
|
||||
},
|
||||
"JwtSetting": {
|
||||
"SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f", // 密钥
|
||||
"Issuer": "IRaCIS", // 颁发者
|
||||
"Audience": "ZhiZhun", // 接收者
|
||||
"TokenExpireDays": "7" // 过期时间(7day)
|
||||
"SecurityKey": "3e6dbfa227234a03977a2f421bdb7f4f",
|
||||
"Issuer": "IRaCIS",
|
||||
"Audience": "ZhiZhun",
|
||||
"TokenExpireDays": "7"
|
||||
},
|
||||
//ip
|
||||
"IpRateLimiting": {
|
||||
"EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
|
||||
"StackBlockedRequests": false, // set to false, rejected calls are not added to the throttle counter
|
||||
"EnableEndpointRateLimiting": true,
|
||||
"StackBlockedRequests": false,
|
||||
"RealIpHeader": "X-Real-IP",
|
||||
"ClientIdHeader": "X-ClientId",
|
||||
"QuotaExceededResponse": {
|
||||
@@ -19,12 +17,11 @@
|
||||
"StatusCode": 429
|
||||
},
|
||||
"HttpStatusCode": 429,
|
||||
//"IpWhitelist": [ "127.0.0.1", "::1/10", "192.168.0.0/24" ],
|
||||
"EndpointWhitelist": [ "post:/study/archivestudy/*" ],
|
||||
//"EndpointWhitelist": [ ],
|
||||
//"EndpointWhitelist": ["post:/trial/getTrialList"], //demo
|
||||
"EndpointWhitelist": [
|
||||
"post:/study/archivestudy/*"
|
||||
],
|
||||
|
||||
"IpWhitelist": [],
|
||||
//"ClientWhitelist": [ "dev-id-1", "dev-id-2" ],
|
||||
"GeneralRules": [
|
||||
{
|
||||
"Endpoint": "*",
|
||||
@@ -48,7 +45,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"easycaching": {
|
||||
"inmemory": {
|
||||
"MaxRdSecond": 120,
|
||||
@@ -63,32 +59,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"IRaCISImageStore": {
|
||||
"SwitchingMode": "RemainingDiskCapacity",
|
||||
"SwitchingRatio": 80,
|
||||
"NotificationEmail": "872297557@qq.com"
|
||||
},
|
||||
"IRaCISBasicConfig": {
|
||||
|
||||
"DoctorCodePrefix": "RE",
|
||||
|
||||
"UserCodePrefix": "U",
|
||||
|
||||
"QCChallengeCodePrefix": "Q",
|
||||
|
||||
"NoneDicomStudyCodePrefix": "NST",
|
||||
|
||||
"DicomStudyCodePrefix": "ST",
|
||||
|
||||
"SystemSiteCodePrefix": "S",
|
||||
|
||||
"DefaultPassword": "123456",
|
||||
|
||||
"DefaultInternalOrganizationName": "ExtImaging",
|
||||
|
||||
"ImageShareExpireDays": 10,
|
||||
|
||||
"BlindTaskPrefix": "Follow Up "
|
||||
"ImageShareExpireDays": 10
|
||||
}
|
||||
|
||||
//网站根地址,为了访问文件 dicom 和上传的文档... 实测发现不用将域名拼接返回,浏览器会自动加上当前ip,避免了多环境读取环境配置文件
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
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>
|
||||
<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>
|
||||
User ID: {1}
|
||||
</div>
|
||||
<div>
|
||||
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
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
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>
|
||||
<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>
|
||||
User ID: {1}
|
||||
</div>
|
||||
<div>
|
||||
Role: {2}
|
||||
</div>
|
||||
<div>
|
||||
Password: {3}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<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'>
|
||||
您好:
|
||||
</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}。
|
||||
</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>
|
||||
</body>
|
||||
</html>
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear Sir or Madam:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Thank you for using our IRC imaging system.
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
{0}。
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目阅片相关工作。
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -38,10 +38,9 @@
|
||||
</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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the service provider of {1} trial(Protocol ID is {2}), Extensive Imaging invites you to participate in the independent assessment work of this trial.
|
||||
</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>
|
||||
<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>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
<div>
|
||||
Protocol ID: {2}
|
||||
</div>
|
||||
<div>
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {4}
|
||||
</div>
|
||||
<div>
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Login URL: {6}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目阅片相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the service provider of {1}trial (Protocol ID is {2}), Extensive Imaging invites you to participate in the independent assessment work of this trial.
|
||||
</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>
|
||||
<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>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
<div>
|
||||
Protocol ID: {2}
|
||||
</div>
|
||||
<div>
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
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
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;font-size: 16px'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
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>
|
||||
<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>
|
||||
Trial ID: {1}
|
||||
</div>
|
||||
<div>
|
||||
Protocol ID: {2}
|
||||
</div>
|
||||
<div>
|
||||
Study Name: {3}
|
||||
</div>
|
||||
<div>
|
||||
Site ID: {4}
|
||||
</div>
|
||||
<div>
|
||||
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>
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the service provider of {1} trial (Protocol ID is {2}), Extensive Imaging invites you to participate in related work of this trial.
|
||||
</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>
|
||||
<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>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
<div>
|
||||
Protocol ID: {2}
|
||||
</div>
|
||||
<div>
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {4}
|
||||
</div>
|
||||
<div>
|
||||
Role: {5}
|
||||
</div>
|
||||
<div>
|
||||
Login URL: {6}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@
|
||||
尊敬的 {0} ,您好:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
展影医疗作为 [{1} (实验方案号:{2 })] 项目的IRC供应商,诚邀您参加该项目IRC相关工作,欢迎您提供指导和建议,非常感谢!
|
||||
展影医疗作为 [{1} (试验方案号:{2 })] 项目的供应商,诚邀您参加该项目相关工作。
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;'>
|
||||
该项目采用电子化工作流,系统及您的账号信息如下:
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear {0},
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
As the service provider of {1} trial (Protocol ID is {2}), Extensive Imaging invites you to participate in related work of this trial.
|
||||
</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:
|
||||
</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>
|
||||
Trial ID: {3}
|
||||
</div>
|
||||
<div>
|
||||
Protocol ID: {2}
|
||||
</div>
|
||||
<div>
|
||||
Study Name: {1}
|
||||
</div>
|
||||
<div>
|
||||
User Name: {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
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style='line-height: 24px;font-size: 16px;color:#333;margin-top: 20px;padding-bottom: 40px;'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,18 +8,18 @@
|
||||
<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;'>
|
||||
{1},验证码是: {2},请在3分钟内输入该验证码,进行后续操作。如非本人操作,请忽略该邮件。
|
||||
{0},验证码是: {1},请在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 style="font-size: 14px;">展影医疗</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<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'>
|
||||
<div style='padding-top: 20px;'>
|
||||
<div style='line-height: 40px;font-size: 16px'>
|
||||
Dear Sir or Madam:
|
||||
</div>
|
||||
<div style='line-height: 40px;padding-left: 40px;margin-bottom: 10px;font-size: 16px'>
|
||||
Thank you for using our imaging system.
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<div style='line-height: 24px;font-size: 14px;color:#333;margin-top: 20px;padding-bottom: 40px;font-size: 16px'>
|
||||
<div>Best regards,</div>
|
||||
<div style="font-size: 16px;">Extensive Imaging</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -414,8 +414,8 @@ var abp = abp || {};
|
||||
|
||||
//Inputs
|
||||
createInput(modalUxContent, 'tenancyName', 'Tenancy Name (Leave empty for Host)');
|
||||
createInput(modalUxContent, 'userName', 'Username or email address','text','admin');
|
||||
createInput(modalUxContent, 'password', 'Password','password');
|
||||
createInput(modalUxContent, 'userName', 'Username or email address','text','cyldev');
|
||||
createInput(modalUxContent, 'password', 'Password','password','123456');
|
||||
|
||||
//Buttons
|
||||
var authBtnWrapper = document.createElement('div');
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace IRaCIS.Core.Application.Auth
|
||||
|
||||
public int IsAdmin { get; }
|
||||
|
||||
public bool IsTestUser { get; set; }
|
||||
|
||||
public string Phone { get; set; } = String.Empty;
|
||||
|
||||
public static IRaCISClaims Create(UserBasicInfo user)
|
||||
@@ -31,6 +33,7 @@ namespace IRaCIS.Core.Application.Auth
|
||||
RealName = user.RealName,
|
||||
UserTypeEnum=user.UserTypeEnum,
|
||||
UserTypeId=user.UserTypeId,
|
||||
IsTestUser=user.IsTestUser,
|
||||
Code = user.Code,
|
||||
PermissionStr = user.PermissionStr,
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ namespace IRaCIS.Core.Application.Auth
|
||||
new Claim(JwtIRaCISClaimType.UserTypeEnum,user.UserTypeEnum.ToString()),
|
||||
new Claim(JwtIRaCISClaimType.UserTypeEnumInt,((int)user.UserTypeEnum).ToString()),
|
||||
new Claim(JwtIRaCISClaimType.UserTypeShortName,user.UserTypeShortName),
|
||||
new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr)
|
||||
new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr),
|
||||
|
||||
new Claim(JwtIRaCISClaimType.IsTestUser,user.IsTestUser.ToString())
|
||||
};
|
||||
|
||||
////创建令牌
|
||||
|
||||
@@ -1,52 +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;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public class CacheTrialStatusQuartZJob: IJob
|
||||
{
|
||||
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<CacheTrialStatusQuartZJob> _logger;
|
||||
|
||||
public CacheTrialStatusQuartZJob(IRepository<Trial> trialRepository, IEasyCachingProvider provider,ILogger<CacheTrialStatusQuartZJob> logger)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
|
||||
{
|
||||
_logger.LogInformation($"开始执行QuartZ定时任务作业");
|
||||
try
|
||||
{
|
||||
var list = _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
|
||||
.ToList();
|
||||
|
||||
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(1)));
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($" 查询和缓存过程出现异常"+e.Message);
|
||||
}
|
||||
_logger.LogInformation("QuartZ定时任务作业结束");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
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;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public class CancelTaskQuartZJob : IJob
|
||||
{
|
||||
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly ILogger<CancelTaskQuartZJob> _logger;
|
||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||
|
||||
public CancelTaskQuartZJob(IRepository<Subject> subjectRepository, IEasyCachingProvider provider, ILogger<CancelTaskQuartZJob> logger, IRepository<VisitTask> visitTaskRepository)
|
||||
{
|
||||
_subjectRepository = subjectRepository;
|
||||
_logger = logger;
|
||||
_visitTaskRepository = visitTaskRepository;
|
||||
}
|
||||
|
||||
public async Task Execute(IJobExecutionContext context)
|
||||
|
||||
{
|
||||
_logger.LogInformation($"开始执行QuartZ定时取消任务作业");
|
||||
|
||||
try
|
||||
{
|
||||
JobDataMap dataMap = context.JobDetail.JobDataMap;
|
||||
|
||||
bool isInOrder = (bool)dataMap.Get("IsInOrder");
|
||||
|
||||
if (isInOrder)
|
||||
{
|
||||
Guid subjectId = (Guid)dataMap.Get("SubjectId");
|
||||
|
||||
Guid trialReadingCriterionId = (Guid)dataMap.Get("TrialReadingCriterionId");
|
||||
|
||||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == subjectId && t.TrialReadingCriterionId==trialReadingCriterionId, u => new VisitTask() { SubjectCriterionClaimUserId = null });
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Guid id = (Guid)dataMap.Get("VisitTaskId");
|
||||
|
||||
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == id && t.ReadingTaskState!=ReadingTaskState.HaveSigned, u => new VisitTask() { DoctorUserId = null }, true);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"QuartZ定时取消任务异常" + e.Message);
|
||||
}
|
||||
_logger.LogInformation("QuartZ定时取消任务作业结束");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
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.EntityFrameworkCore.SqlServer.Query.Internal;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
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);
|
||||
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<IRaCISCHangfireJob> _logger;
|
||||
|
||||
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)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
|
||||
_internationalizationRepository = internationalizationRepository;
|
||||
}
|
||||
|
||||
public async Task InitHangfireJobTaskAsync()
|
||||
{
|
||||
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
|
||||
|
||||
|
||||
//项目状态 立即加载到缓存中
|
||||
await MemoryCacheTrialStatusAsync();
|
||||
|
||||
|
||||
//创建项目缓存 定时任务
|
||||
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)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
#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文件变更 实时刷新数据
|
||||
WatchJsonFile(usJsonPath);
|
||||
WatchJsonFile(cnJsonPath);
|
||||
|
||||
}
|
||||
|
||||
public void WatchJsonFile(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("IRaCISCHangfireJob_FileNotFound"));
|
||||
}
|
||||
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(Path.GetDirectoryName(filePath), Path.GetFileName(filePath));
|
||||
watcher.Changed += (sender, e) => LoadJsonFile(filePath);
|
||||
watcher.EnableRaisingEvents = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void LoadJsonFile(string filePath)
|
||||
{
|
||||
|
||||
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile(filePath);
|
||||
|
||||
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,65 +0,0 @@
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Application.Services.BackGroundJob
|
||||
{
|
||||
|
||||
public interface IIRaCISCacheHangfireJob
|
||||
{
|
||||
Task MemoryCacheTrialStatus();
|
||||
}
|
||||
public class IRaCISCacheHangfireJob: IIRaCISCacheHangfireJob
|
||||
{
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILogger<IRaCISCacheHangfireJob> _logger;
|
||||
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
|
||||
|
||||
public IRaCISCacheHangfireJob(IRepository<Trial> trialRepository, IRepository<SystemAnonymization> systemAnonymizationRepository, IEasyCachingProvider provider,ILogger<IRaCISCacheHangfireJob> logger)
|
||||
{
|
||||
_trialRepository = trialRepository;
|
||||
_provider = provider;
|
||||
_logger = logger;
|
||||
_systemAnonymizationRepository = systemAnonymizationRepository;
|
||||
}
|
||||
public async Task MemoryCacheTrialStatus()
|
||||
{
|
||||
_logger.LogInformation("hangfire 定时任务开始~");
|
||||
try
|
||||
{
|
||||
await CacheTrialStatusAsync();
|
||||
|
||||
await CacheAnonymizeAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("hangfire 定时任务执行失败"+e.Message);
|
||||
|
||||
}
|
||||
|
||||
_logger.LogInformation("hangfire 定时任务执行结束");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task CacheTrialStatusAsync()
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
private async Task CacheAnonymizeAsync()
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
using EasyCaching.Core;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -13,7 +16,7 @@ namespace IRaCIS.Core.Application.Filter;
|
||||
|
||||
public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
{
|
||||
|
||||
public IStringLocalizer _localizer { get; set; }
|
||||
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
|
||||
@@ -21,11 +24,12 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
|
||||
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
||||
|
||||
public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo, IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
||||
public LimitUserRequestAuthorization(IEasyCachingProvider provider, IUserInfo userInfo, IStringLocalizer localizer ,IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig)
|
||||
{
|
||||
_provider = provider;
|
||||
_userInfo = userInfo;
|
||||
_verifyConfig = verifyConfig;
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,14 +47,15 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
{
|
||||
//1、用户登陆的时候,设置缓存
|
||||
|
||||
|
||||
|
||||
//没有从请求中取到token
|
||||
if (string.IsNullOrWhiteSpace(_userInfo.UserToken))
|
||||
{
|
||||
context.HttpContext.Response.ContentType = "application/json";
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
|
||||
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("当前请求未从Header/Url取到用户Token,请联系开发者")));
|
||||
//---当前请求未从Header/Url取到用户Token,请联系开发者
|
||||
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"])));
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AuthTokenMissing"]));
|
||||
}
|
||||
|
||||
//2、在这里取缓存 进行比较 看是否有其他人进行了登陆,如果其他人登陆了,就把之前用户挤掉
|
||||
@@ -76,7 +81,13 @@ public class LimitUserRequestAuthorization : IAsyncAuthorizationFilter
|
||||
|
||||
context.HttpContext.Response.ContentType = "application/json";
|
||||
context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
|
||||
await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk("您的账户在其他地方已登陆,您被迫下线。", ApiResponseCodeEnum.LoginInOtherPlace)));
|
||||
//---您的账户在其他地方已登陆,您被迫下线。
|
||||
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace));
|
||||
|
||||
|
||||
//await context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(ResponseOutput.NotOk(_localizer["LimitUser_AccountLoggedInElsewhere"], ApiResponseCodeEnum.LoginInOtherPlace)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
{
|
||||
|
||||
|
||||
public class ModelActionFilter : ActionFilterAttribute, IActionFilter
|
||||
{
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
public IStringLocalizer _localizer;
|
||||
public ModelActionFilter(IStringLocalizer localizer)
|
||||
{
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
|
||||
@@ -19,7 +28,8 @@ namespace IRaCIS.Core.Application.Filter
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToArray();
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk("提供给接口的参数无效。" +JsonConvert.SerializeObject( validationErrors)));
|
||||
//---提供给接口的参数无效。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ModelAction_InvalidAPIParameter"] + JsonConvert.SerializeObject( validationErrors)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
@@ -10,10 +11,13 @@ namespace IRaCIS.Core.Application.Filter
|
||||
{
|
||||
private readonly ILogger<ProjectExceptionFilter> _logger;
|
||||
|
||||
public ProjectExceptionFilter(ILogger<ProjectExceptionFilter> logger)
|
||||
public IStringLocalizer _localizer;
|
||||
|
||||
public ProjectExceptionFilter(IStringLocalizer localizer, ILogger<ProjectExceptionFilter> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
_localizer = localizer;
|
||||
}
|
||||
public void OnException(ExceptionContext context)
|
||||
{
|
||||
//context.ExceptionHandled;//记录当前这个异常是否已经被处理过了
|
||||
@@ -22,7 +26,8 @@ namespace IRaCIS.Core.Application.Filter
|
||||
{
|
||||
if (context.Exception.GetType().Name == "DbUpdateConcurrencyException")
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk("并发更新,当前不允许该操作" + context.Exception.Message));
|
||||
//---并发更新,当前不允许该操作
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["ProjectException_ConcurrentUpdateNotAllowed"] + context.Exception.Message));
|
||||
}
|
||||
|
||||
if (context.Exception.GetType() == typeof(BusinessValidationFailedException))
|
||||
@@ -35,7 +40,7 @@ namespace IRaCIS.Core.Application.Filter
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(" 程序异常,请联系开发人员。 " + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["Project_ExceptionContactDeveloper"] + (context.Exception.InnerException is null ? (context.Exception.Message /*+ context.Exception.StackTrace*/)
|
||||
: (context.Exception.InnerException?.Message /*+ context.Exception.InnerException?.StackTrace*/)), ApiResponseCodeEnum.ProgramException));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Text.RegularExpressions;
|
||||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
|
||||
namespace IRaCIS.Core.Application.Filter
|
||||
@@ -10,36 +12,60 @@ namespace IRaCIS.Core.Application.Filter
|
||||
/// <summary>
|
||||
/// 主要为了 处理项目结束 锁库,不允许操作
|
||||
/// </summary>
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
public class TrialResourceFilter : Attribute, IAsyncResourceFilter
|
||||
{
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly IUserInfo _userInfo;
|
||||
|
||||
private readonly string _trialOpt;
|
||||
public IStringLocalizer _localizer;
|
||||
private readonly List<string> _trialOptList=new List<string>();
|
||||
|
||||
|
||||
|
||||
|
||||
public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo, string trialOpt)
|
||||
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
|
||||
{
|
||||
_provider = provider;
|
||||
_userInfo = userInfo;
|
||||
_trialOpt = trialOpt;
|
||||
_localizer = localizer;
|
||||
//_trialOpt = trialOpt;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
|
||||
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
|
||||
//{
|
||||
// _provider = provider;
|
||||
// _userInfo = userInfo;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//优先选择异步的方法
|
||||
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
|
||||
{
|
||||
// var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault();
|
||||
//var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
|
||||
|
||||
#region 处理新的用户类型,不能操作项目相关接口
|
||||
|
||||
// 后期列举出具体的类型,其他任何用户类型,都不允许操作
|
||||
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA)
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk("对不起,您的账户没有操作权限。"));
|
||||
if (!_userInfo.RequestUrl.Contains("TrialDocument/userConfirm"))
|
||||
{
|
||||
//---对不起,您的账户没有操作权限。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
|
||||
|
||||
return;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -60,6 +86,26 @@ namespace IRaCIS.Core.Application.Filter
|
||||
var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
|
||||
trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
|
||||
}
|
||||
else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId"))
|
||||
{
|
||||
var headerStr = context.HttpContext.Request.Headers["Referer"].ToString();
|
||||
|
||||
var trialIdIndex = headerStr.IndexOf("trialId");
|
||||
|
||||
|
||||
var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
trialIdStr = matchResult.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#region body 中取数据
|
||||
@@ -77,14 +123,41 @@ namespace IRaCIS.Core.Application.Filter
|
||||
|
||||
if (trialIdIndex > -1)
|
||||
{
|
||||
trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 36);
|
||||
// (?<="trialId" *: *").*?(?=",)
|
||||
|
||||
//使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}
|
||||
|
||||
var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
if (matchResult.Success)
|
||||
{
|
||||
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
|
||||
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
|
||||
|
||||
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
trialIdStr = matchResult.Value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//---正则取请求Refer 中trialId 失败,请联系开发人员核查
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
|
||||
}
|
||||
|
||||
//使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因
|
||||
//trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
//通过path 或者body 找到trialId 了
|
||||
if (trialIdStr != string.Empty)
|
||||
if ( !string.IsNullOrWhiteSpace(trialIdStr))
|
||||
{
|
||||
|
||||
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
|
||||
@@ -101,10 +174,17 @@ namespace IRaCIS.Core.Application.Filter
|
||||
|
||||
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
|
||||
|
||||
var trialStatusStr = cacheResultDic[trialIdStr];
|
||||
var trialStatusStr = cacheResultDic[trialIdStr].Value;
|
||||
|
||||
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
|
||||
if (string.IsNullOrWhiteSpace(trialStatusStr))
|
||||
{
|
||||
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
|
||||
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
|
||||
}
|
||||
|
||||
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
|
||||
if (trialStatusStr.Value == StaticData.TrialState.TrialOngoing || _trialOpt==TrialOpt.BeforeOngoingCantOpt)
|
||||
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) )
|
||||
{
|
||||
|
||||
await next.Invoke();
|
||||
@@ -113,20 +193,27 @@ namespace IRaCIS.Core.Application.Filter
|
||||
// 项目停止、或者完成 不允许操作
|
||||
else
|
||||
{
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk("本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改"));
|
||||
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
|
||||
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId))
|
||||
{
|
||||
await next.Invoke();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
//如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改
|
||||
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk("该接口参数中,没有传递项目编号,请核对。"));
|
||||
//---该接口参数中,没有传递项目编号,请核对。
|
||||
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"]));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Application.Services.BusinessFilter
|
||||
{
|
||||
@@ -74,7 +75,8 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
||||
|
||||
else if(statusCode != 200&&!(objectResult.Value is IResponseOutput))
|
||||
{
|
||||
var apiResponse = ResponseOutput.NotOk("程序错误,请联系开发人员。");
|
||||
//---程序错误,请联系开发人员。
|
||||
var apiResponse = ResponseOutput.NotOk(StaticData.International("UnifiedAPI_ProgramError"));
|
||||
|
||||
objectResult.Value = apiResponse;
|
||||
objectResult.DeclaredType = apiResponse.GetType();
|
||||
@@ -114,4 +116,4 @@ namespace IRaCIS.Application.Services.BusinessFilter
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,52 @@ namespace IRaCIS.Core.Application.Helper
|
||||
|
||||
public CriterionType? CriterionType { get; set; }
|
||||
|
||||
|
||||
//是否翻译依赖其他属性
|
||||
public bool IsTranslateDenpendOtherProperty =>!string.IsNullOrWhiteSpace(DependPropertyName);
|
||||
|
||||
public string DependPropertyName { get; set; }=string.Empty;
|
||||
|
||||
public string DependPropertyValueStr { get; set; } = string.Empty;
|
||||
|
||||
// 普通翻译的字典
|
||||
public DictionaryTranslateAttribute(string dicParentCode)
|
||||
{
|
||||
DicParentCode = dicParentCode;
|
||||
|
||||
}
|
||||
|
||||
//针对不同的标准 翻译的字典不一样
|
||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType )
|
||||
{
|
||||
DicParentCode = dicParentCode;
|
||||
|
||||
CriterionType = criterionType;
|
||||
}
|
||||
|
||||
//针对业务某个属性的值 不一样 用的翻译字典不一样
|
||||
|
||||
public DictionaryTranslateAttribute(string dicParentCode,string dependPropertyName, string dependPropertyValueStr)
|
||||
{
|
||||
DicParentCode = dicParentCode;
|
||||
|
||||
DependPropertyName = dependPropertyName;
|
||||
|
||||
DependPropertyValueStr = dependPropertyValueStr;
|
||||
|
||||
}
|
||||
|
||||
public DictionaryTranslateAttribute(string dicParentCode, CriterionType criterionType, string dependPropertyName, string dependPropertyValueStr)
|
||||
{
|
||||
DicParentCode = dicParentCode;
|
||||
|
||||
DependPropertyName = dependPropertyName;
|
||||
|
||||
CriterionType = criterionType;
|
||||
|
||||
DependPropertyValueStr = dependPropertyValueStr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
using IRaCIS.Application.Interfaces;
|
||||
using DocumentFormat.OpenXml.Drawing.Diagrams;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
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;
|
||||
@@ -8,17 +13,22 @@ using MiniExcelLibs.OpenXml;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NPOI.HSSF.UserModel;
|
||||
using NPOI.XSSF.UserModel;
|
||||
using SkiaSharp;
|
||||
using System.IO;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service;
|
||||
|
||||
public static class ExcelExportHelper
|
||||
{
|
||||
//MiniExcel_Export
|
||||
public static async Task<IActionResult> DataExportAsync(string code, object data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||
public static async Task<IActionResult> DataExportAsync(string code, ExcelExportInfo data, string exportFileNamePrefix, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||
{
|
||||
|
||||
//判断是否有字典翻译
|
||||
|
||||
object translateData = data;
|
||||
|
||||
if (_dictionaryService != null && translateType != null)
|
||||
{
|
||||
|
||||
@@ -30,7 +40,8 @@ public static class ExcelExportHelper
|
||||
//一个值 对应不同的字典翻译
|
||||
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||
.SelectMany(c =>
|
||||
c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t.CriterionType == criterionType || t.CriterionType == null).Select(k => new { c.Name, k.DicParentCode })
|
||||
c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t?.CriterionType == criterionType || t?.CriterionType == null)
|
||||
.Select(k => new { c.Name, k.DicParentCode, k.IsTranslateDenpendOtherProperty, k.DependPropertyName, k.DependPropertyValueStr })
|
||||
).ToList();
|
||||
|
||||
|
||||
@@ -58,15 +69,32 @@ public static class ExcelExportHelper
|
||||
|
||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
//翻译的属性依赖其他属性
|
||||
if (needTranslateProperty.IsTranslateDenpendOtherProperty)
|
||||
{
|
||||
if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t=>data.IsEn_US?t.Value:t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
}
|
||||
}
|
||||
//普通翻译 或者某一标准翻译
|
||||
else
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).FirstOrDefault()?.ValueCN ?? String.Empty;
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
itemDic.Add("No", no++);
|
||||
|
||||
|
||||
newObjList.Add(itemDic);
|
||||
}
|
||||
|
||||
@@ -76,8 +104,9 @@ public static class ExcelExportHelper
|
||||
}
|
||||
|
||||
|
||||
data = dic;
|
||||
//data = dic;
|
||||
|
||||
translateData = dic;
|
||||
|
||||
}
|
||||
|
||||
@@ -91,22 +120,65 @@ public static class ExcelExportHelper
|
||||
//模板路径
|
||||
var tplPath = physicalPath;
|
||||
|
||||
#region 根据中英文 删除模板sheet
|
||||
|
||||
// 打开模板文件
|
||||
var templateFile = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
// 获取文件流
|
||||
var templateStream = new MemoryStream();
|
||||
templateFile.CopyTo(templateStream);
|
||||
templateStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var workbook = new XSSFWorkbook(templateStream);
|
||||
|
||||
int sheetCount = workbook.NumberOfSheets;
|
||||
|
||||
if (sheetCount == 2)
|
||||
{
|
||||
if (data.IsEn_US)
|
||||
{
|
||||
workbook.RemoveSheetAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
workbook.RemoveSheetAt(1);
|
||||
}
|
||||
|
||||
var memoryStream2 = new MemoryStream();
|
||||
workbook.Write(memoryStream2);
|
||||
|
||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
templateStream = memoryStream2;
|
||||
}
|
||||
|
||||
// 文件名称 从sheet里面取
|
||||
fileNmae = workbook.GetSheetName(0);
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#region MiniExcel
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
var memoryStream = new MemoryStream();
|
||||
|
||||
var config = new OpenXmlConfiguration()
|
||||
{
|
||||
IgnoreTemplateParameterMissing = true,
|
||||
};
|
||||
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, data, config);
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, templateStream.ToArray(), translateData, config);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
|
||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
{
|
||||
FileDownloadName = $"{exportFileNamePrefix}_{fileNmae.Substring(0, fileNmae.LastIndexOf('.'))}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||
FileDownloadName = $"{exportFileNamePrefix}_{fileNmae/*.Substring(0, fileNmae.LastIndexOf('.'))*/}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
|
||||
};
|
||||
|
||||
#endregion
|
||||
@@ -127,22 +199,34 @@ public static class ExcelExportHelper
|
||||
|
||||
|
||||
|
||||
public static async Task<MemoryStream> DataExport_NpoiTestAsync(string code, object data, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||
public static async Task<(MemoryStream, string)> DataExport_NpoiTestAsync(string code, ExcelExportInfo data, IRepository<CommonDocument> _commonDocumentRepository, IWebHostEnvironment _hostEnvironment, IDictionaryService? _dictionaryService = null, Type? translateType = null, CriterionType? criterionType = null)
|
||||
{
|
||||
//判断是否有字典翻译
|
||||
|
||||
object translateData = data;
|
||||
|
||||
if (_dictionaryService != null && translateType != null)
|
||||
{
|
||||
|
||||
////只标注单个的时候
|
||||
//var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||
// .Select(c => new { c.Name, DicParentCode = ((DictionaryTranslateAttribute?)c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false)[0])?.DicParentCode }).ToList();
|
||||
|
||||
|
||||
//一个值 对应不同的字典翻译
|
||||
var needTranslatePropertyList = translateType.GetProperties().Where(t => t.IsDefined(typeof(DictionaryTranslateAttribute), true))
|
||||
.SelectMany(c =>
|
||||
c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t.CriterionType == criterionType || t.CriterionType == null).Select(k => new { c.Name, k.DicParentCode })
|
||||
c.GetCustomAttributes(typeof(DictionaryTranslateAttribute), false).Select(f => (DictionaryTranslateAttribute?)f).Where(t => t.CriterionType == criterionType || t.CriterionType == null)
|
||||
.Select(k => new { c.Name, k.DicParentCode, k.IsTranslateDenpendOtherProperty, k.DependPropertyName, k.DependPropertyValueStr })
|
||||
).ToList();
|
||||
|
||||
|
||||
|
||||
//字典表查询出所有需要翻译的数据
|
||||
|
||||
var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslatePropertyList.Select(t => t.DicParentCode).Distinct().ToArray());
|
||||
|
||||
|
||||
var dic = JsonConvert.DeserializeObject<IDictionary<string, object>>(data.ToJsonNotIgnoreNull());
|
||||
|
||||
foreach (var key in dic.Keys)
|
||||
@@ -158,11 +242,30 @@ public static class ExcelExportHelper
|
||||
{
|
||||
var itemDic = JsonConvert.DeserializeObject<IDictionary<string, object>>(item.ToJsonNotIgnoreNull());
|
||||
|
||||
|
||||
foreach (var needTranslateProperty in needTranslatePropertyList)
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
//翻译的属性依赖其他属性
|
||||
if (needTranslateProperty.IsTranslateDenpendOtherProperty)
|
||||
{
|
||||
if (item[needTranslateProperty.DependPropertyName]?.ToString().ToLower() == needTranslateProperty.DependPropertyValueStr.ToLower())
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
}
|
||||
}
|
||||
//普通翻译 或者某一标准翻译
|
||||
else
|
||||
{
|
||||
var beforeValue = itemDic[needTranslateProperty.Name]?.ToString();
|
||||
|
||||
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).Select(t => data.IsEn_US ? t.Value : t.ValueCN).FirstOrDefault() ?? String.Empty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
itemDic[needTranslateProperty.Name] = translateDataList[needTranslateProperty.DicParentCode].Where(t => t.Code.ToLower() == beforeValue?.ToLower()).FirstOrDefault()?.ValueCN ?? String.Empty;
|
||||
}
|
||||
|
||||
itemDic.Add("No", no++);
|
||||
@@ -175,21 +278,55 @@ public static class ExcelExportHelper
|
||||
}
|
||||
|
||||
|
||||
data = dic;
|
||||
|
||||
//data = dic;
|
||||
translateData = dic;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
||||
var (physicalPath, fileName) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);
|
||||
|
||||
|
||||
//模板路径
|
||||
var tplPath = physicalPath;
|
||||
|
||||
#region 根据中英文 删除模板sheet
|
||||
|
||||
// 打开模板文件
|
||||
var templateFile = new FileStream(tplPath, FileMode.Open, FileAccess.Read);
|
||||
|
||||
// 获取文件流
|
||||
var templateStream = new MemoryStream();
|
||||
templateFile.CopyTo(templateStream);
|
||||
templateStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var workbook = new XSSFWorkbook(templateStream);
|
||||
|
||||
int sheetCount = workbook.NumberOfSheets;
|
||||
|
||||
if (sheetCount == 2)
|
||||
{
|
||||
if (data.IsEn_US)
|
||||
{
|
||||
workbook.RemoveSheetAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
workbook.RemoveSheetAt(1);
|
||||
}
|
||||
|
||||
var memoryStream2 = new MemoryStream();
|
||||
workbook.Write(memoryStream2);
|
||||
|
||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
templateStream = memoryStream2;
|
||||
}
|
||||
|
||||
// 文件名称 从sheet里面取
|
||||
fileName = workbook.GetSheetName(0);
|
||||
#endregion
|
||||
|
||||
#region MiniExcel
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
@@ -199,14 +336,14 @@ public static class ExcelExportHelper
|
||||
IgnoreTemplateParameterMissing = true,
|
||||
};
|
||||
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, data, config);
|
||||
await MiniExcel.SaveAsByTemplateAsync(memoryStream, tplPath, translateData, config);
|
||||
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
|
||||
return memoryStream;
|
||||
return (memoryStream, fileName);
|
||||
|
||||
//var wb = new HSSFWorkbook(memoryStream);
|
||||
//var wb = new HSSFWorkbook(memoryStream);
|
||||
|
||||
//var sheet = wb.GetSheetAt(0);
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
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
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,107 @@
|
||||
|
||||
|
||||
using Aliyun.OSS;
|
||||
using Aliyun.OSS.Util;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
|
||||
public static class FileStoreHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 上传文件到OOS
|
||||
/// </summary>
|
||||
/// <param name="filePath">本地文件路径</param>
|
||||
/// <param name="oosPath">OOS路径例如(test/test)</param>
|
||||
/// <param name="isDeleteOriginalFile">是否删除本地文件</param>
|
||||
/// <returns>返回文件路径</returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
public static string UploadOOS(string filePath,string oosPath, bool isDeleteOriginalFile)
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile($"appsettings.{enviromentName}.json")
|
||||
.Build();
|
||||
|
||||
var endpoint = configuration.GetSection("AliyunOSS:endpoint").Value;
|
||||
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
|
||||
|
||||
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
|
||||
var accessKeyId = configuration.GetSection("AliyunOSS:accessKeyId").Value;
|
||||
var accessKeySecret = configuration.GetSection("AliyunOSS:accessKeySecret").Value;
|
||||
// 填写Bucket名称,例如examplebucket。
|
||||
var bucketName = configuration.GetSection("AliyunOSS:bucketName").Value;
|
||||
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
|
||||
|
||||
var fileNameList = filePath.Split('\\').ToList();
|
||||
var fileName = fileNameList[fileNameList.Count() - 1];
|
||||
if (oosPath != string.Empty)
|
||||
{
|
||||
fileName = oosPath + "/" + fileName;
|
||||
}
|
||||
var objectName = fileName;
|
||||
// 填写本地文件完整路径,例如D:\\localpath\\examplefile.txt。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
|
||||
var localFilename = filePath;
|
||||
// 创建OSSClient实例。
|
||||
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
|
||||
try
|
||||
{
|
||||
// 上传文件。
|
||||
var result = client.PutObject(bucketName, objectName, localFilename);
|
||||
var expiration = DateTime.Now.AddYears(1);
|
||||
var url = client.GeneratePresignedUri(bucketName, objectName, expiration).ToString();
|
||||
if (File.Exists(filePath)&& isDeleteOriginalFile)
|
||||
{
|
||||
// 删除文件
|
||||
File.Delete(filePath);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new BusinessValidationFailedException("上传异常!");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static ObjectMetadata BuildCallbackMetadata(string callbackUrl, string callbackBody)
|
||||
{
|
||||
string callbackHeaderBuilder = new CallbackHeaderBuilder(callbackUrl, callbackBody).Build();
|
||||
string CallbackVariableHeaderBuilder = new CallbackVariableHeaderBuilder().
|
||||
AddCallbackVariable("x:var1", "x:value1").AddCallbackVariable("x:var2", "x:value2").Build();
|
||||
var metadata = new ObjectMetadata();
|
||||
metadata.AddHeader(HttpHeaders.Callback, callbackHeaderBuilder);
|
||||
metadata.AddHeader(HttpHeaders.CallbackVar, CallbackVariableHeaderBuilder);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private static string GetCallbackResponse(PutObjectResult putObjectResult)
|
||||
{
|
||||
string callbackResponse = null;
|
||||
using (var stream = putObjectResult.ResponseStream)
|
||||
{
|
||||
var buffer = new byte[4 * 1024];
|
||||
var bytesRead = stream.Read(buffer, 0, buffer.Length);
|
||||
callbackResponse = Encoding.Default.GetString(buffer, 0, bytesRead);
|
||||
}
|
||||
return callbackResponse;
|
||||
}
|
||||
|
||||
//处理文件名 压缩包,或者目录类的 会带上相对路径
|
||||
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName)
|
||||
public static (string TrustedFileNameForFileStorage, string RealName) GetStoreFileName(string fileName,bool isChangeToPdfFormat=false)
|
||||
{
|
||||
|
||||
//带目录层级,需要后端处理前端的路径
|
||||
@@ -25,7 +115,26 @@ public static class FileStoreHelper
|
||||
fileName = fileName.Split("/").Last();
|
||||
}
|
||||
|
||||
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileName;
|
||||
var matchResult = Regex.Match(fileName, @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}");
|
||||
|
||||
//如果有guid
|
||||
if (matchResult.Success)
|
||||
{
|
||||
fileName = fileName.Replace($"{matchResult.Value}", "");
|
||||
}
|
||||
|
||||
|
||||
var trustedFileNameForFileStorage = string.Empty;
|
||||
|
||||
if (isChangeToPdfFormat==false)
|
||||
{
|
||||
trustedFileNameForFileStorage= Path.GetFileNameWithoutExtension(fileName) + Guid.NewGuid().ToString()+Path.GetExtension(fileName) ;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
trustedFileNameForFileStorage= Path.GetFileNameWithoutExtension(fileName) + Guid.NewGuid().ToString() + ".pdf";
|
||||
}
|
||||
|
||||
return (trustedFileNameForFileStorage, fileName);
|
||||
}
|
||||
@@ -73,14 +182,16 @@ public static class FileStoreHelper
|
||||
|
||||
if (systemClinicalData == null || systemClinicalData.Path == string.Empty)
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据库没有找到对应的数据模板文件,请联系系统运维人员。");
|
||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||
}
|
||||
|
||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, systemClinicalData.Path);
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据模板文件存储路径上未找对应文件,请联系系统运维人员。");
|
||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
||||
}
|
||||
|
||||
return (filePath, systemClinicalData.FileName);
|
||||
@@ -101,14 +212,16 @@ public static class FileStoreHelper
|
||||
|
||||
if (trialClinicalData == null|| trialClinicalData.Path==string.Empty)
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据库没有找到对应的数据模板文件,请联系系统运维人员。");
|
||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||
}
|
||||
|
||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, trialClinicalData.Path);
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据模板文件存储路径上未找对应文件,请联系系统运维人员。");
|
||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
||||
}
|
||||
|
||||
return (filePath, trialClinicalData.FileName);
|
||||
@@ -123,14 +236,16 @@ public static class FileStoreHelper
|
||||
|
||||
if (doc == null)
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据库没有找到对应的数据模板文件,请联系系统运维人员。");
|
||||
//---数据库没有找到对应的数据模板文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileNotFound"));
|
||||
}
|
||||
|
||||
var filePath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, doc.Path);
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
throw new BusinessValidationFailedException("数据模板文件存储路径上未找对应文件,请联系系统运维人员。");
|
||||
//---数据模板文件存储路径上未找对应文件,请联系系统运维人员。
|
||||
throw new BusinessValidationFailedException(StaticData.International("FileStore_TemplateFileStoragePathInvalid"));
|
||||
}
|
||||
|
||||
return (filePath, doc.Name.Trim('/'));
|
||||
@@ -199,6 +314,54 @@ public static class FileStoreHelper
|
||||
return (serverFilePath, relativePath);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 获取通用文档存放路径(excel模板 )
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetCommonDocPath(IWebHostEnvironment _hostEnvironment, string fileName)
|
||||
@@ -264,6 +427,28 @@ public static class FileStoreHelper
|
||||
return (serverFilePath, relativePath);
|
||||
}
|
||||
|
||||
//获取 中心调研用户路径
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetTrialSiteSurveyFilePath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
//上传根路径
|
||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), StaticData.Folder.UploadSiteSurveyData);
|
||||
|
||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||||
|
||||
|
||||
var (trustedFileNameForFileStorage, realFileName) = FileStoreHelper.GetStoreFileName(fileName);
|
||||
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{StaticData.Folder.UploadSiteSurveyData}/{trustedFileNameForFileStorage}";
|
||||
|
||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
return (serverFilePath, relativePath);
|
||||
}
|
||||
|
||||
|
||||
public static (string PhysicalPath, string RelativePath, string FileRealName) GetClinicalTemplatePath(IWebHostEnvironment _hostEnvironment, string fileName,Guid trialId)
|
||||
{
|
||||
@@ -345,6 +530,36 @@ public static class FileStoreHelper
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 上传截图
|
||||
/// </summary>
|
||||
/// <param name="_hostEnvironment"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <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)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteid.ToString(), subjectId.ToString());
|
||||
|
||||
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
|
||||
|
||||
var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName);
|
||||
|
||||
|
||||
var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteid}/{subjectId}/{trustedFileNameForFileStorage}";
|
||||
|
||||
var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
return (serverFilePath, relativePath, fileRealName);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通用获取文件路径
|
||||
/// </summary>
|
||||
@@ -409,6 +624,26 @@ public static class FileStoreHelper
|
||||
return (serverFilePath, relativePath, fileRealName);
|
||||
}
|
||||
|
||||
// 获取 入组确认 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)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.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 serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
|
||||
|
||||
return (serverFilePath, relativePath, fileRealName);
|
||||
}
|
||||
|
||||
|
||||
public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment,Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
||||
{
|
||||
@@ -419,7 +654,12 @@ public static class FileStoreHelper
|
||||
|
||||
public static (string PhysicalPath, string RelativePath) GetDicomInstanceFilePath(IWebHostEnvironment _hostEnvironment, Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId, Guid studyId, Guid instanceId)
|
||||
{
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
#region 切换存储前
|
||||
//var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
#endregion
|
||||
var rootPath = Path.Combine(FileStoreHelper.GetBestStoreDisk(_hostEnvironment), StaticData.Folder.IRaCISDataFolder) ;
|
||||
|
||||
|
||||
|
||||
//加入访视层级 和Data
|
||||
var path = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(),
|
||||
@@ -441,8 +681,64 @@ public static class FileStoreHelper
|
||||
return (physicalPath, relativePath);
|
||||
}
|
||||
|
||||
public static string GetBestStoreDisk(IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
|
||||
var json = File.ReadAllText( Path.Combine(_hostEnvironment.ContentRootPath, "appsettings.json"));
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
int switchingRatio = 80;
|
||||
|
||||
try
|
||||
{
|
||||
switchingRatio = (int)jsonObject["IRaCISImageStore"]["SwitchingRatio"];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
//---解析Json文件配置出现问题
|
||||
throw new BusinessValidationFailedException(StaticData.International("SysMon_JsonConfig") + e.Message);
|
||||
}
|
||||
|
||||
//默认存储的路径
|
||||
var defaultStoreRootFolder = FileStoreHelper.GetIRaCISRootPath(_hostEnvironment);
|
||||
|
||||
|
||||
DriveInfo defaultDrive = new DriveInfo(Path.GetPathRoot(defaultStoreRootFolder));
|
||||
|
||||
var drives = DriveInfo.GetDrives().Where(t => !t.Name.Contains("C") && !t.Name.Contains("c"))
|
||||
.Where(d => d.DriveType == DriveType.Fixed && d.IsReady)
|
||||
//剩余空间最多的
|
||||
.OrderByDescending(d => d.AvailableFreeSpace)
|
||||
|
||||
//存储空间相同,则按照按照总空间从大到小排序
|
||||
.ThenByDescending(d => d.TotalSize - d.TotalFreeSpace);
|
||||
|
||||
var bestDrive = drives.FirstOrDefault();
|
||||
var bestStoreRootFolder = string.Empty;
|
||||
|
||||
//仅仅只有C 盘
|
||||
if (bestDrive == null || ((double)(defaultDrive.TotalSize - defaultDrive.TotalFreeSpace) / defaultDrive.TotalSize) * 100 < switchingRatio)
|
||||
{
|
||||
bestStoreRootFolder = defaultStoreRootFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
bestStoreRootFolder = Path.Combine(bestDrive?.RootDirectory.FullName, _hostEnvironment.EnvironmentName);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(bestStoreRootFolder))
|
||||
{
|
||||
Directory.CreateDirectory(bestStoreRootFolder);
|
||||
}
|
||||
|
||||
return bestStoreRootFolder;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 获取医生通用文件存放路径
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static IRaCIS.Core.Application.Service.Common.SystemMonitor;
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper
|
||||
{
|
||||
public static class InternationalizationHelper
|
||||
{
|
||||
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
|
||||
|
||||
private static void VerifyFolder()
|
||||
{
|
||||
if (!Directory.Exists(JsonFileFolder) ||
|
||||
!Directory.GetFiles(JsonFileFolder).Any(filePath => Path.GetExtension(filePath).Equals(".json", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new BusinessValidationFailedException(StaticData.International("InternationalizationHelper_PathError"));
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task BatchAddJsonKeyValueAsync(List<BatchAddInternationalizationDto> batchAddDtos)
|
||||
{
|
||||
VerifyFolder();
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.En_US_Dic[item.Code] = item.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in batchAddDtos)
|
||||
{
|
||||
jsonObject[item.Code] = item.Value;
|
||||
|
||||
StaticData.Zh_CN_Dic[item.Code] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task AddOrUpdateJsonKeyValueAsync(string key, string value, string valueCN)
|
||||
{
|
||||
|
||||
VerifyFolder();
|
||||
|
||||
var usJsonPath = Path.Combine(JsonFileFolder, StaticData.En_US_Json);
|
||||
var cnJsonPath = Path.Combine(JsonFileFolder, StaticData.Zh_CN_Json);
|
||||
|
||||
|
||||
//更新json 文件 同时更新内存缓存的数据
|
||||
foreach (var filePath in new string[] { usJsonPath, cnJsonPath })
|
||||
{
|
||||
var json = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
JObject jsonObject = JObject.Parse(json, new JsonLoadSettings() { CommentHandling = CommentHandling.Load });
|
||||
|
||||
// 添加或更新指定的键值对
|
||||
|
||||
if (filePath.Contains(StaticData.En_US_Json))
|
||||
{
|
||||
jsonObject[key] = value;
|
||||
|
||||
StaticData.En_US_Dic[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonObject[key] = valueCN;
|
||||
|
||||
StaticData.Zh_CN_Dic[key] = valueCN;
|
||||
}
|
||||
|
||||
|
||||
await File.WriteAllTextAsync(filePath, jsonObject.ToString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using MailKit;
|
||||
using MailKit.Security;
|
||||
using MimeKit;
|
||||
using NPOI.HPSF;
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Application.Helper;
|
||||
@@ -31,6 +33,7 @@ public static class SendEmailHelper
|
||||
|
||||
await smtp.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
||||
|
||||
|
||||
await smtp.SendAsync(messageToSend);
|
||||
|
||||
await smtp.DisconnectAsync(true);
|
||||
@@ -40,10 +43,26 @@ public static class SendEmailHelper
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw new Exception("邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员") ;
|
||||
//---邮件发送失败,您进行的操作未能成功,请检查邮箱或联系维护人员
|
||||
throw new Exception(StaticData.International("SendEmail_SendFail"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
||||
{
|
||||
using (var client = new MailKit.Net.Smtp.SmtpClient())
|
||||
{
|
||||
|
||||
await client.ConnectAsync(_systemEmailConfig.Host, _systemEmailConfig.Port, SecureSocketOptions.SslOnConnect);
|
||||
|
||||
await client.AuthenticateAsync(_systemEmailConfig.FromEmail, _systemEmailConfig.AuthorizationCode);
|
||||
|
||||
await client.DisconnectAsync(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||
@@ -60,7 +79,8 @@ public static class SendEmailHelper
|
||||
|
||||
if (sMTPEmailConfig.ToMailAddressList.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("没有收件人");
|
||||
//---没有收件人
|
||||
throw new ArgumentException(StaticData.International("SendEmail_NoRecipient"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -88,10 +108,19 @@ public static class SendEmailHelper
|
||||
{
|
||||
//builder.Attachments.Add(item.FileName, item.FileData);
|
||||
|
||||
builder.Attachments.Add(item.FileName, item.FileStream);
|
||||
var attachment = builder.Attachments.Add(item.FileName, item.FileStream);
|
||||
|
||||
//解决附件名过长 奇怪的名字
|
||||
foreach (var param in attachment.ContentDisposition.Parameters)
|
||||
param.EncodingMethod = ParameterEncodingMethod.Rfc2047;
|
||||
foreach (var param in attachment.ContentType.Parameters)
|
||||
param.EncodingMethod = ParameterEncodingMethod.Rfc2047;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
messageToSend.Body = builder.ToMessageBody();
|
||||
|
||||
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
|
||||
@@ -113,8 +142,11 @@ public static class SendEmailHelper
|
||||
await smtp.DisconnectAsync(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -123,12 +155,12 @@ public static class SendEmailHelper
|
||||
|
||||
public class SMTPEmailConfig
|
||||
{
|
||||
public int Port { get; set; }
|
||||
public int Port { get; set; }
|
||||
|
||||
public string Host { get; set; }
|
||||
|
||||
|
||||
public string UserName { get; set; }
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string AuthorizationCode { get; set; }
|
||||
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="BeetleX.BNR" Version="1.0.1" />
|
||||
<PackageReference Include="EntityFrameworkCore.Triggered" Version="3.2.1" />
|
||||
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.7.0" />
|
||||
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
|
||||
@@ -74,17 +75,16 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="fo-dicom.Drawing" Version="4.0.8" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.0.3" />
|
||||
<PackageReference Include="Hangfire" Version="1.7.31">
|
||||
<PackageReference Include="FreeSpire.Doc" Version="10.8.0" />
|
||||
<PackageReference Include="Hangfire.Core" Version="1.8.5" />
|
||||
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.2" />
|
||||
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.2">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Core" Version="2.6.9" />
|
||||
<PackageReference Include="Magicodes.IE.Csv" Version="2.6.9">
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.2">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.6.9">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.6.9" />
|
||||
<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" />
|
||||
@@ -92,7 +92,7 @@
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MimeKit" Version="3.4.2" />
|
||||
<PackageReference Include="MiniExcel" Version="1.28.1" />
|
||||
<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>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,236 +1,2 @@
|
||||
{
|
||||
"test{0}{1}": "英文本地化{0}{1}",
|
||||
"RequiredAttribute": "{0} is required",
|
||||
|
||||
// SiteSurvey 服务--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// TrialSiteEquipmentSurveyService
|
||||
"CPMNotOperation": "CPM/APM Disallow operation", //CPM/APM 不允许操作
|
||||
"IsLockNotOperation": "The operation cannot be performed if it is locked", //已锁定 不允许操作
|
||||
|
||||
// TrialSiteSurveyService
|
||||
"ValidationEmail": "Please input a legal email", // 验证邮箱
|
||||
"ValidationPhone": "Please input a legal phone", // 验证手机号
|
||||
"SiteNotExistUpdateDisable": "The project Site does not have the survey record of the handover person, so it is not allowed to choose to update", // site不存在禁止更新
|
||||
"RecordLockUpdateDisable": "Your record is not locked, you are not allowed to choose to update, if submitted, can be rejected after operation", //记录锁定禁止更新
|
||||
"SiteLockUpdateDisableOther": "At the current Site, your survey record has been locked, and it is not allowed to update other people's email survey record", //Site锁定禁止更新其他人
|
||||
"SiteLockUpdateDisableSelf": "At the current Site, your survey record has been locked, and there are other unlocked records, so you are not allowed to update your own survey record", //Site锁定禁止更新自己
|
||||
"SiteLockUpdateDisableEmail": "Currently, there are unlocked survey records in the Site, and the survey records of the locked mailbox are not allowed to be updated", //Site锁定禁止更新邮箱调研记录
|
||||
"EmailNotLatestDisableEmail{0}": "The questionnaire corresponding to this mailbox {0} is not the latest locked record and is not allowed to be updated!", //邮箱调研表不是最新 不允许更新
|
||||
"SiteExistOtherUpdateDisable": "Other users have already filled in the survey form under this Site, you are not allowed to continue to fill in", //存在其他用户调研表不允许填写
|
||||
"IsLockUpdateDisable": "The operation is not allowed because it has been locked", //已锁定,不允许操作
|
||||
"OnlyAbolishNotFiled": "Only uncommitted records are allowed to be annulled", //只允许废除未提交的记录
|
||||
"AdminOperateDisable": "The Admin operation is not allowed", // 不允许Admin操作
|
||||
"UserWrongNotSubmit": "Personnel information is not allowed to be submitted because there are incorrect items", // 人员信息有不正确项,不允许提交
|
||||
"FillInTheType{0}": "Please enter the type of account to be generated. Name of person {0}", // 请填写生成账号的类型。人员姓名
|
||||
|
||||
// TrialSiteUserSurveyService
|
||||
"InfoInconformity": "The user name in the system is {0}, which is inconsistent with the entered information. You can modify the information to be consistent with the system and save the information", // 信息不一致 修改一致进行保存
|
||||
|
||||
|
||||
// TrialSiteUser 服务------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// TrialConfigService
|
||||
"NoDataDound": "No data for the signature scenario was found in the system", //未在系统中找到该签名场景的数据
|
||||
"PasswordError": "password error", //密码错误
|
||||
"UserBeDisabled": "The user has been disabled!",
|
||||
"ProjSetDisable": "The project is not Initializing/Ongoing and configuration confirmation is not allowed", //不允许确认配置
|
||||
"QCRepate": "The serial number of QC problem display is not allowed to repeat", // QC问题显示序号不允许重复
|
||||
"ParentNumToLow": "Please confirm that the parent problem number is smaller than the child problem number", // 父问题的序号要比子问题序号小,请确认
|
||||
"ExistUnconfirmedItems": "Project, basic configuration, process configuration, urgent configuration, visit plan, unconfirmed items", // 存在未确认项
|
||||
"NotAllCanOperate": "only in Initializing or Ongoing State can operate", //只有“初始化中”和“正在进行中”才能进行操作
|
||||
|
||||
// TrialExternalUserService
|
||||
"InfoDoNotAgree{0}{1}": "The user account name in the system is {0} Phone number: {1}. The information is inconsistent with the entered information. Now, modify the page information to be consistent with the system information and save the information", // 用户信息不一致
|
||||
"UserExist": "The email address and user type already exist", //该邮箱和用户类型,已存在该账户
|
||||
|
||||
// TrialMaintenanceService
|
||||
"OneTrial": "Only one pm is allowed in a trial",
|
||||
"Participant": "Participant has participated in site maintenance",
|
||||
|
||||
// TrialService
|
||||
"OnlyPMAPM": "Only PM/APM can perform this operation!",
|
||||
"TrialIDExist": "Same Trial ID already exists.",
|
||||
"ProjNot": "Operations are allowed only when the project is initialized or in progress",
|
||||
"TrialConfirm": "The Trial visit schedule has been confirmed and cannot be deleted",
|
||||
"TrialIntoTheGroup": "The Trial cannot be deleted because a doctor has been enrolled in the Trial or is in the enrollment process",
|
||||
"TrialHaveSite": "There is a Site under this Trial and it cannot be deleted",
|
||||
"TrialHaveParticipants": "There are participants under this Trial and they cannot be deleted",
|
||||
"NotRevertEditable": "VisitPlan has been generated for some subjects,can not revert editable state",
|
||||
|
||||
// TrialSiteService
|
||||
"CodeRepeated": "Code is not allowed to be repeated",
|
||||
"CRCCanNotDeleted": "The site has been associated with CRC, and couldn't be deleted",
|
||||
"SiteCanNotDeleted": "The subjects has been added to this site, and couldn't be deleted",
|
||||
"StudyCanNotDeleted": "The site has been uploaded study, and couldn't be deleted.",
|
||||
|
||||
// Visit -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// SubjectService
|
||||
"VisitNotConfirmed": "The trial visit plan has not been confirmed yet.Please contact the project manager to confirm the visit plan before adding subject",
|
||||
"ExistedTrial": "A subjects with the same subject ID already existed in this trial.",
|
||||
"TheLastVisit": "The subject is not allowed to set this visit as the last visit since there is already an visit set as the last visit",
|
||||
"ImagesUploaded": "The subject uploaded the image after this visit, and this visit is not allowed to be set as the last visit",
|
||||
"StudyImagesCanBotDeleted": "This subject has executed a visit with uploading study images,and couldn't be deleted",
|
||||
|
||||
// SubjectVisitService
|
||||
"ContainsVisitnum": "This subject's visit plan already contains a visit with the same visitnum",
|
||||
"LastEvaluationNotAllowed": "After setting the last evaluation, you are not allowed to add scheduled outbound visits",
|
||||
"CRCSubmit": "PD confirmation status cannot be modified after CRC submission",
|
||||
"BacktrackingVisits": "After the CRC is submitted, the PD confirmation status cannot be changed",
|
||||
"ImageUpload": "The subject uploaded the image after this visit, and this visit is not allowed to be set as the last visit",
|
||||
"AssociatedUploaded": "This visit is associated with the uploaded study images and couldn't be deleted",
|
||||
"InPlanCanNotDeleted": "This visit is InPlan and couldn't be deleted",
|
||||
|
||||
// VisitPlanService
|
||||
"OnlyInitializing": "only in Initializing or Ongoing State can operate",
|
||||
"AccordWithVisitNum": "For the visit plan, the VisitDay with a larger VisitNum should be larger than the VisitDay with a smaller VisitNum",
|
||||
"same/VisitName": "A visit with the same VisitName/VisitNum already existed in the current visit plan",
|
||||
"AlreadyBaseline": "A visit already is baseline in the current visit plan",
|
||||
"IsUploadVideo": "A CRC has uploaded image data for the baseline and is not allowed to modify the baseline",
|
||||
"VisitHasBeenExecuted": "The visit plan has been assigned to the subjects and executed",
|
||||
"OnlyProgressCanEdit": "Modification validation is allowed only during project initialization or in progress",
|
||||
"NoBaselineNoConfirmation": "No baseline, no confirmation allowed",
|
||||
"NotConfirmedCanNotVisit": "If the project configuration is not confirmed, the visit plan is not allowed to be confirmed",
|
||||
"VisitDayNotMinimum": "Baseline VisitDay is not minimum and confirmation is not allowed",
|
||||
|
||||
//Document-----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//SystemDocumentService
|
||||
"ExistsFileName": "The filename of the same type already exists",
|
||||
"SignedUser": "A user has signed the document",
|
||||
|
||||
//TrialDocumentService
|
||||
|
||||
//同类型已存在该文件名 上面存在 ExistsFileName
|
||||
"ExistsSignedUser": "This document, which has been signed by the user, cannot be deleted",
|
||||
//password error 上面存在 PasswordError
|
||||
//The user has been disabled 上面存在 UserBeDisabled
|
||||
"DocumentsSigned": "The document has been signed",
|
||||
"FileBeDelete": "File deleted or cancelled, signing failed",
|
||||
|
||||
//QC--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ClinicalDataService
|
||||
|
||||
// NoneDicomStudyService
|
||||
|
||||
// QCListService
|
||||
"NotFirstTrial": "The current user is not a preliminary user and cannot perform this operation",
|
||||
"NotReviewUser": "The current user is not a review user and cannot perform this operation",
|
||||
|
||||
// QCOperationService
|
||||
"AuditQuestionMust": "The audit question must be filled out and saved, otherwise no challenge is allowed to be added",
|
||||
"VisitNoClose": "The current viewer has unclosed query for CRC upload permission. No further query is allowed",
|
||||
"NotFinish": "CRC retransmission request /QC agrees to retransmission challenge and is not allowed to close the challenge until CRC setup retransmission is complete",
|
||||
"QCHasBeenReplied": "This QC inquiry has been answered",
|
||||
"OperationUserMustBeCRC/PM": "Only CRC and PM are allowed",
|
||||
"CanNotCloseQuery": "Visits that perform conformance checks are not allowed to close queries",
|
||||
"OnlyPMCanSet": "Only PM manual Settings are allowed to pass the consistency check",
|
||||
"CanNotSettingConsistency": "Currently, the PM approves the rollback and does not allow the consistency check to pass",
|
||||
"ConsistencyNotClose": "Compliance check challenge unclosed/audit status is not passed, setting conformance check is not allowed to pass",
|
||||
"PassDataNotFallback": "The data that passes the verification is not allowed to apply for rollback",
|
||||
"OnlyPMFallback": "Only PM rollback is allowed",
|
||||
"UnderDetectionNotFallback": "Data to be verified/verified is not allowed to be rolled back",
|
||||
"OnlyPMCanOperation": "Only PM operations are allowed",
|
||||
"OnlyExcelCSV": "Only Excel and CSV are allowed!",
|
||||
"ExcelVerificationFailed": "Please upload an Excel file in the specified format to ensure valid data",
|
||||
"QCUnconfirmed": "The QC problem is not confirmed, it is not allowed to receive the task",
|
||||
"MustBeFinish": "You are not allowed to pick up new subjects until you have already picked up other subjects",
|
||||
"BeReceive": "It is currently claimed and not allowed to be claimed",
|
||||
"CancelQCTask": "The project is configured to not review, not receive or cancel the QC Task",
|
||||
"FirstTriaPassed": "The first examination has been passed, can not continue to receive",
|
||||
"CanNotReceive": "The item is configured as single audit and cannot be collected if SubmmitState: submitted or AuditState: to be audited/audited is not met. Please refresh the interface",
|
||||
"MustBeDifferent": "The retrial cannot be the same person as the first trial",
|
||||
"IsNotSatisfied": "The project is configured for review and does not meet the submission status: Submitted or reviewed status: pending review /QC, it is not allowed to receive, please refresh the interface",
|
||||
"VisitNotUploaded": "Visitors who have not uploaded any Dicom/ non-DICOM data are not allowed to submit",
|
||||
"MandatoryFailed": "The project is configured to require filling in the date of first administration, but subjects do not fill in the date of first administration, which is not allowed to submit",
|
||||
"YouBeenRemoved": "You have been removed from the project and are not allowed to do this",
|
||||
"QuestionsNotClosed": "The operation is not allowed if it is not closed",
|
||||
"CanNotSetQCPassed": "QC Passed cannot be set if the value is not Passed",
|
||||
"MustSetQuestion": "The audit question must be filled out and saved, otherwise submission will not be allowed",
|
||||
"CanNotChangeQCPassed": "The audit status of the item is not InPrimaryQC and cannot be changed to QCPassed",
|
||||
// "必须填写审核问题,并保存,否则不允许提交" 上面 MustSetQuestion
|
||||
"TrialIsDoubleCheck{0}": "The audit status of the item is {0} and cannot be changed to QCPassed",
|
||||
"CanNotSetQCFailed": "QC Failed cannot be set in the unchecked state",
|
||||
"NotInPrimaryQCQCFailed": "The project is configured as a single audit. The current audit status is not InPrimaryQC and cannot be changed to QCFailed",
|
||||
"TrialIsDoubleCheckCanNotQCFailed{0}": "The project is configured with double audit. The current audit status is {0} and cannot be changed to QCFailed",
|
||||
"CRCHasBeenSubmitted": "CRC has submitted an unmodified group confirmation status",
|
||||
"CannotBeChangedPD": "PD confirmation status cannot be modified for rollback visits",
|
||||
"OtherQCProcessAudit": "Other QC is conducting audit, current operation is not allowed",
|
||||
"ForwardFailed": "Forward failure",
|
||||
|
||||
// QCQuestionService
|
||||
|
||||
// TrialQCQuestionService
|
||||
"QCHasConfirmed": "QC has confirmed that operation is not allowed",
|
||||
"BeforeClearSubproblem": "The parent problem can only be deleted if the child problem is cleared",
|
||||
"HasQCAuditRecord": "There is QC audit record, it is not allowed to delete the problem item",
|
||||
|
||||
//ImageAndDoc -----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//DicomArchiveService
|
||||
|
||||
//ImageShareService
|
||||
"NoImage": "There is no image in the current study and cannot be shared!",
|
||||
"ResourceNotExist": "The resource does not exist! ",
|
||||
"PasswordIsError": "Shared password error!",
|
||||
"ResourceExpired": "Resource sharing has expired!",
|
||||
|
||||
//InstanceService
|
||||
|
||||
//SeriesService
|
||||
|
||||
//StudyListService
|
||||
|
||||
"TimeTooLow": "当前访视检查时间不能小于该访视之前检查的时间,请核对检查数据是否有误",
|
||||
"SomeoneLoading": "当前有人正在上传归档该检查!",
|
||||
"VisitEnd": "受试者访视结束,不允许上传!",
|
||||
"DICOMUploaded{0}{1}{2}{3}": "{0}: This DICOM images have been uploaded and allocate to the {1} of the subject {2} (Study ID: {3}), which cannot continue to upload and assign it to others.",
|
||||
|
||||
//StudyService
|
||||
|
||||
//SystemAnonymizationService
|
||||
|
||||
//ReadingGlobalTaskService
|
||||
"ReadingGlobal_NotGlobal": "The current task is not a global reading task",
|
||||
//ReadingImageTaskService
|
||||
"ReadingImage_NotVisit": "The current task is not a visit task",
|
||||
"ReadingImage_CantSplit": "This is currently a baseline task and cannot be split and combined",
|
||||
"ReadingImage_BeSigned": "The current task has been signed!",
|
||||
"ReadingImage_Beinvalid": "The current task is invalid!",
|
||||
"ReadingImage_NotaTask": "The combined lesions were not the same visiting task",
|
||||
"ReadingImage_DeleteError": "The current lesion splits into other lesions or other lesions merge into the current lesion, and deletion fails",
|
||||
"ReadingImage_Idnotcorrespond": "InstanceId and SeriesId do not correspond !",
|
||||
"ReadingImage_Twice": "The same question is passed in twice",
|
||||
"ReadingImage_MaxQuestion": "The maximum number of problems currently submitted is {0}!",
|
||||
"ReadingImage_Maxlesion": "According to the relevant rules of RECIST1.1, the number of target lesions in the same organ does not exceed {0}!",
|
||||
"ReadingImage_Maximum": "Problems {0} The maximum number of the same problems is {1}, and {2} already exist",
|
||||
"ReadingImage_RequiredQuestion": "The answer to the required question {0} is empty or not saved",
|
||||
"ReadingImage_ClinicalRead": "Clinical data not read!",
|
||||
"ReadingImage_IDMust": "When there is no task Id, the standard Id must be passed",
|
||||
"ReadingImage_TaskFinish": "The current subject has completed all the task of reading the film!",
|
||||
"ReadingImage_NeedRest": "You have read the video continuously for {0} hours, please rest for {1} minutes before continuing to read the video.",
|
||||
//ReadingJudgeTaskService
|
||||
"ReadingJudge_SouceIdNull": "The SouceId of the current referee global task is null",
|
||||
//ReadingOncologyTaskService
|
||||
"ReadingOncology_TaskError": "The current task is not an oncology task",
|
||||
"ReadingOncology_Abnormal": "Abnormal, the referee result is null",
|
||||
//ReadingCalculate
|
||||
"ReadingCalculate_Abnormal": "The PCWG3 standard configuration is abnormal!",
|
||||
"ReadingCalculate_Questionable": "The lesions have the following problems:",
|
||||
"ReadingCalculate_NoMarker": "Lesion {0} no marker exists,",
|
||||
"ReadingCalculate_StatusIsEmpty": "Lesion {0} status is empty,",
|
||||
"ReadingCalculate_NoMarkerEmpty": "Lesion {0} is unmarked and the status is empty,",
|
||||
"ReadingCalculate_NoDeveloped": "The current standard calculation is not well developed!",
|
||||
//ReadingMedicalReviewService
|
||||
"MedicalReview_invalid": "The medical audit was invalid and the operation failed",
|
||||
"MedicalReview_SaveQuestion": "Please save the medical review question first",
|
||||
"MedicalReview_NeedSave": "Save the question and conclusion first",
|
||||
"MedicalReview_NotClosed": "Dialogue not closed"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,238 +1,2 @@
|
||||
{
|
||||
"test{0}{1}": "中文本地化{0}{1}",
|
||||
"RequiredAttribute": "{0} 字段是必须的",
|
||||
// SiteSurvey 服务--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// TrialSiteEquipmentSurveyService
|
||||
"CPMNotOperation": "CPM/APM 不允许操作", //CPM/APM 不允许操作
|
||||
"IsLockNotOperation": "已锁定 不允许操作", //已锁定 不允许操作
|
||||
|
||||
// TrialSiteSurveyService
|
||||
"ValidationEmail": "请输入正确的邮箱", // 验证邮箱
|
||||
"ValidationPhone": "请输入正确的手机号", // 验证手机号
|
||||
"SiteNotExistUpdateDisable": "该项目Site不存在该交接人的调研记录,不允许选择更新", // site不存在禁止更新
|
||||
"RecordLockUpdateDisable": "您的记录未锁定,不允许选择更新,若已经提交,可被驳回后进行操作", //记录锁定禁止更新
|
||||
"SiteLockUpdateDisableOther": "当前Site 您的调研记录已锁定,不允许更新其他人邮箱调研记录", //Site锁定禁止更新其他人
|
||||
"SiteLockUpdateDisableSelf": "当前Site 您的调研记录已锁定,也存在其他未锁定的记录,不允许更新自己的调研记录", //Site锁定禁止更新自己
|
||||
"SiteLockUpdateDisableEmail": "当前Site 存在未锁定的调研记录,不允许更新已锁定邮箱的调研记录", //Site锁定禁止更新邮箱调研记录
|
||||
"EmailNotLatestDisableEmail{0}": "该邮箱{0}对应的调查表不是最新锁定的记录,不允许更新!", //邮箱调研表不是最新 不允许更新
|
||||
"SiteExistOtherUpdateDisable": "该Site下已经有其他用户已填写的调研表,您不被允许继续填写", //存在其他用户调研表不允许填写
|
||||
"IsLockUpdateDisable": "已锁定,不允许操作", //已锁定,不允许操作
|
||||
"OnlyAbolishNotFiled": "只允许废除未提交的记录", //只允许废除未提交的记录
|
||||
"AdminOperateDisable": "不允许Admin操作", // 不允许Admin操作
|
||||
"UserWrongNotSubmit": "人员信息有不正确项,不允许提交", // 人员信息有不正确项,不允许提交
|
||||
"FillInTheType{0}": "请填写生成账号的类型。人员姓名{0}", // 请填写生成账号的类型。人员姓名
|
||||
|
||||
// TrialSiteUserSurveyService
|
||||
"InfoInconformity{0}": "该用户在系统中账户名为:{0} ,与填写信息存在不一致项, 现将界面信息修改为与系统一致,可进行保存", // 信息不一致 修改一致进行保存
|
||||
|
||||
|
||||
// TrialSiteUser 服务------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// TrialConfigService
|
||||
"NoDataDound": "未在系统中找到该签名场景的数据", //未在系统中找到该签名场景的数据
|
||||
"PasswordError": "密码错误", //密码错误
|
||||
"UserBeDisabled": "用户被禁用", // 用户被禁用
|
||||
"ProjSetDisable": "项目不在Initializing/Ongoing,不允许确认配置", //不允许确认配置
|
||||
"QCRepate": "QC问题显示序号不允许重复", // QC问题显示序号不允许重复
|
||||
"ParentNumToLow": "父问题的序号要比子问题序号小,请确认", // 父问题的序号要比子问题序号小,请确认
|
||||
"ExistUnconfirmedItems": "项目、基础配置、流程配置、加急配置、访视计划,有未确认项", // 存在未确认项
|
||||
"NotAllCanOperate": "只有“初始化中”和“正在进行中”才能进行操作", //只有“初始化中”和“正在进行中”才能进行操作
|
||||
|
||||
// TrialExternalUserService
|
||||
"InfoDoNotAgree{0}{1}": "该用户在系统中账户名为:{0} 电话:{1},与填写信息存在不一致项, 现将界面信息修改为与系统一致,可进行保存", // 用户信息不一致
|
||||
"UserExist": "该邮箱和用户类型,已存在该账户", //该邮箱和用户类型,已存在该账户
|
||||
|
||||
// TrialMaintenanceService
|
||||
"OneTrial": "一次验证中只能一个PM",
|
||||
"Participant": "参与过现场维护工作",
|
||||
|
||||
// TrialService
|
||||
"OnlyPMAPM": "仅PM/APM可以操作!",
|
||||
"TrialIDExist": "相同的试用ID已经存在。",
|
||||
"ProjNot": "项目初始化或者进行中时,才允许操作",
|
||||
"TrialConfirm": "Trial访视计划已经确认,无法删除",
|
||||
"TrialIntoTheGroup": "该Trial有医生入组或在入组流程中,无法删除",
|
||||
"TrialHaveSite": "该Trial下面有Site,无法删除",
|
||||
"TrialHaveParticipants": "该Trial下面有参与者,无法删除",
|
||||
"NotRevertEditable": "部分主题已生成VisitPlan,无法恢复编辑状态",
|
||||
|
||||
// TrialSiteService
|
||||
"CodeRepeated": "编码不允许重复",
|
||||
"CRCCanNotDeleted": "该站点已与CRC关联,无法删除",
|
||||
"SiteCanNotDeleted": "主题已添加到本网站,无法删除",
|
||||
"StudyCanNotDeleted": "该网站已上传研究,无法删除",
|
||||
|
||||
// Visit -------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// SubjectService
|
||||
"VisitNotConfirmed": "试访计划尚未确定。添加主题前请联系项目经理确认访问计划",
|
||||
"ExistedTrial": "在本试验中已经存在一个具有相同受试者ID的受试者.",
|
||||
"TheLastVisit": "该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视",
|
||||
"ImagesUploaded": "该受试者此访视后有影像上传,该访视不允许设置为末次访视",
|
||||
"StudyImagesCanBotDeleted": "本课题已上传研究图像进行访问,无法删除",
|
||||
|
||||
// SubjectVisitService
|
||||
"ContainsVisitnum": "这个主题的访问计划已经包含了一个访问次数相同的访问",
|
||||
//该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视 这个在上面有 TheLastVisit
|
||||
"LastEvaluationNotAllowed": "设置末次评估后,不允许添加计划外访视",
|
||||
"CRCSubmit": "CRC提交后,不允许修改PD确认状态",
|
||||
"BacktrackingVisits": "回退的访视,不允许修改PD确认状态",
|
||||
"ImageUpload": "该受试者此访视后有影像上传,该访视不允许设置为末次访视",
|
||||
"AssociatedUploaded": "本次访问与上传的研究图片有关,无法删除",
|
||||
"InPlanCanNotDeleted": "此访问为InPlan,不能删除",
|
||||
|
||||
// VisitPlanService
|
||||
"OnlyInitializing": "只有“初始化中”和“正在进行中”才能进行操作",
|
||||
"AccordWithVisitNum": "对于访问计划,具有较大VisitNum的VisitDay应该大于具有较小VisitNum的VisitDay",
|
||||
"same/VisitName": "当前访问计划中已经存在具有相同VisitName/VisitNum的访问",
|
||||
"AlreadyBaseline": "已访视是当前访视计划的基线",
|
||||
"IsUploadVideo": "有CRC已经为基线上传了影像数据,不允许修改基线",
|
||||
"VisitHasBeenExecuted": "访问计划已分配给受试者并执行",
|
||||
"OnlyProgressCanEdit": "仅仅在项目初始化或者进行中时,才允许修改确认",
|
||||
"NoBaselineNoConfirmation": "没有基线,不允许确认",
|
||||
"NotConfirmedCanNotVisit": "项目配置未确认,不允许确认访视计划",
|
||||
"VisitDayNotMinimum": "基线VisitDay 不是最小的, 不允许确认",
|
||||
|
||||
|
||||
//Document-----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//SystemDocumentService
|
||||
"ExistsFileName": "同类型已存在该文件名",
|
||||
"SignedUser": "该文档下已有签名的用户",
|
||||
|
||||
//TrialDocumentService
|
||||
|
||||
//同类型已存在该文件名 上面存在 ExistsFileName
|
||||
"ExistsSignedUser": "该文档,已有用户签名,不允许删除",
|
||||
//password error 上面存在 PasswordError
|
||||
//The user has been disabled 上面存在 UserBeDisabled
|
||||
"DocumentsSigned": "该文档已经签名",
|
||||
"FileBeDelete": "文件已删除或者废除,签署失败",
|
||||
|
||||
//QC--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ClinicalDataService
|
||||
|
||||
// NoneDicomStudyService
|
||||
|
||||
// QCListService
|
||||
"NotFirstTrial": "当前用户不是初审用户,不允许操作",
|
||||
"NotReviewUser": "当前用户不是复审用户,不允许操作",
|
||||
|
||||
// QCOperationService
|
||||
"AuditQuestionMust": "必须填写审核问题,并保存,否则不允许添加质疑",
|
||||
"VisitNoClose": "当前访视有未关闭的 同意CRC上传的质疑,不允许再次添加质疑",
|
||||
"NotFinish": "CRC申请重传的/QC同意重传的质疑,在CRC设置重传完成前不允许关闭质疑",
|
||||
"QCHasBeenReplied": "此QC质询已回复",
|
||||
"OperationUserMustBeCRC/PM": "一致性核查对话操作用户 只允许 CRC/PM",
|
||||
"CanNotCloseQuery": "执行一致性核查的访视 不允许关闭质疑",
|
||||
"OnlyPMCanSet": "只允许PM 手动设置一致性核查通过",
|
||||
"CanNotSettingConsistency": "当前是PM同意回退,不允许设置一致性核查通过",
|
||||
"ConsistencyNotClose": "致性核查质疑未关闭/审核状态不是通过,不允许设置一致性核查通过",
|
||||
"PassDataNotFallback": "核查通过的数据不允许申请回退",
|
||||
"OnlyPMFallback": "只允许PM 回退",
|
||||
"UnderDetectionNotFallback": "待核查/核查通过的数据不允许回退",
|
||||
"OnlyPMCanOperation": "只允许PM 操作",
|
||||
"OnlyExcelCSV": "只允许Excel、 CSV!",
|
||||
"ExcelVerificationFailed": "请上传规定格式的Excel文件,保证有有效数据",
|
||||
"QCUnconfirmed": "QC问题未确认,不允许领取任务",
|
||||
"MustBeFinish": "您已经领取了其他受试者,完成后才允许领取新的受试者",
|
||||
"BeReceive": "当前已被领取,不允许领取",
|
||||
"CancelQCTask": "项目配置为不审,没有领取或者取消QC Task",
|
||||
"FirstTriaPassed": "初审已通过,不能继续领取",
|
||||
"CanNotReceive": "项目配置为单审,不满足SubmmitState:已提交 或者 AuditState:待审核/审核中, 不允许领取,请刷新界面",
|
||||
"MustBeDifferent": "复审不能和初审是同一个人",
|
||||
"IsNotSatisfied": "项目配置为复审,不满足提交状态:已提交 或者 审核状态:待审核/QC中, 不允许领取,请刷新界面",
|
||||
"VisitNotUploaded": "有访视未上传任何Dicom/非Dicom数据 不允许提交",
|
||||
"MandatoryFailed": "项目配置了需要填写首次给药日期 但是受试者没有填写首次给药日期,不允许提交",
|
||||
"YouBeenRemoved": "您已经被移出项目,不允许该操作",
|
||||
"QuestionsNotClosed": "有质疑未关闭,不允许该操作",
|
||||
"CanNotSetQCPassed": "不审状态下,不允许设置为QC Passed",
|
||||
"MustSetQuestion": "必须填写审核问题,并保存,否则不允许提交",
|
||||
"CanNotChangeQCPassed": "项目配置为单审 当前审核状态不为 InPrimaryQC,不能变更到 QCPassed",
|
||||
// "必须填写审核问题,并保存,否则不允许提交" 上面 MustSetQuestion
|
||||
"TrialIsDoubleCheck{0}": "项目配置为双审 当前审核状态为 {0},不能变更到 QCPassed",
|
||||
"CanNotSetQCFailed": "不审状态下,不允许设置为QC Failed",
|
||||
"NotInPrimaryQCQCFailed": "项目配置为单审 当前审核状态不为 InPrimaryQC,不能变更到 QCFailed",
|
||||
"TrialIsDoubleCheckCanNotQCFailed{0}": "项目配置为双审 当前审核状态为 {0},不能变更到 QCFailed",
|
||||
"CRCHasBeenSubmitted": "CRC已提交了 不能修改入组确认状态",
|
||||
"CannotBeChangedPD": "回退的访视,不允许修改PD确认状态",
|
||||
"OtherQCProcessAudit": "其他QC正在进行审核,当前操作不允许",
|
||||
"ForwardFailed": "转发失败",
|
||||
|
||||
// QCQuestionService
|
||||
|
||||
// TrialQCQuestionService
|
||||
"QCHasConfirmed": "QC已确认,不允许操作",
|
||||
"BeforeClearSubproblem": "清除子问题 才允许删除父问题",
|
||||
"HasQCAuditRecord": "已有QC审核记录,不允许删除问题项",
|
||||
|
||||
|
||||
//ImageAndDoc -----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//DicomArchiveService
|
||||
|
||||
//ImageShareService
|
||||
"NoImage": "目前研究中没有图片,不能分享!",
|
||||
"ResourceNotExist": "资源不存在!",
|
||||
"PasswordIsError": "共享密码错误!",
|
||||
"ResourceExpired": "资源共享过期!",
|
||||
|
||||
//InstanceService
|
||||
|
||||
//SeriesService
|
||||
|
||||
//StudyListService
|
||||
|
||||
"TimeTooLow": "当前访视检查时间不能小于该访视之前检查的时间,请核对检查数据是否有误",
|
||||
"SomeoneLoading": "当前有人正在上传归档该检查!",
|
||||
"VisitEnd": "受试者访视结束,不允许上传!",
|
||||
"DICOMUploaded{0}{1}{2}{3}": "{0}:此DICOM图片已上传并分配给课题{2}(研究ID:{3})的{1},课题{2}无法继续上传并分配给他人。",
|
||||
|
||||
//StudyService
|
||||
|
||||
//SystemAnonymizationService
|
||||
|
||||
//ReadingGlobalTaskService
|
||||
"ReadingGlobal_NotGlobal": "系统调用错误,当前任务不是全局阅片任务。",
|
||||
//ReadingImageTaskService
|
||||
"ReadingImage_NotVisit": "系统调用错误,当前任务不是访视任务。",
|
||||
"ReadingImage_CantSplit": "当前任务是基线任务,不能执行分裂病灶的操作。",
|
||||
"ReadingImage_BeSigned": "当前任务已经签名,请勿重复提交。",
|
||||
"ReadingImage_Beinvalid": "当前任务已失效,不能执行阅片。",
|
||||
"ReadingImage_NotaTask": "合并的病灶并非同一个访视任务",
|
||||
"ReadingImage_DeleteError": "当前病灶分裂出其他病灶或者其他病灶合并到了当前病灶,删除失败。",
|
||||
"ReadingImage_Idnotcorrespond": "病灶标记添加失败,影像的InstanceId和SeriesId不对应。",
|
||||
"ReadingImage_Twice": "系统调用错误,提交的问题及答案重复。",
|
||||
"ReadingImage_MaxQuestion": "按照《独立影像评估章程》的相关规则,当前病灶类型的病灶数量不超过{0}个。",
|
||||
"ReadingImage_Maxlesion": "按照《独立影像评估章程》的相关规则,同一器官的靶病灶数量不超过{0}个,请确认",
|
||||
"ReadingImage_Maximum": "\"{0}\"的重复次数限制为{1},目前已重复{2}次。",
|
||||
"ReadingImage_RequiredQuestion": "\"{0}\"已设置为必填,当前答案为空或未保存。",
|
||||
"ReadingImage_ClinicalRead": "临床数据未阅读,请确认!",
|
||||
"ReadingImage_IDMust": "系统调用失败,当没有任务ID的时候,标准ID必传。",
|
||||
"ReadingImage_TaskFinish": "当前受试者所有阅片任务已完成,请知悉。",
|
||||
"ReadingImage_NeedRest": "您已连续阅片{0}个小时,请休息{1}分钟后,再继续阅片。",
|
||||
//ReadingJudgeTaskService
|
||||
"ReadingJudge_SouceIdNull": "系统调用失败,当前裁判的全局任务的SouceId为null。",
|
||||
//ReadingOncologyTaskService
|
||||
"ReadingOncology_TaskError": "系统调用错误,当前任务不是肿瘤学任务。",
|
||||
"ReadingOncology_Abnormal": "系统调用异常,裁判结果为null。",
|
||||
//ReadingCalculate
|
||||
"ReadingCalculate_Abnormal": "PCWG3标准配置错误,数据验证失败。",
|
||||
"ReadingCalculate_Questionable": "病灶存在以下问题:",
|
||||
"ReadingCalculate_NoMarker": "病灶{0}缺少标记",
|
||||
"ReadingCalculate_StatusIsEmpty": "病灶{0}状态为空",
|
||||
"ReadingCalculate_NoMarkerEmpty": "病灶{0}未做标记,且状态为空",
|
||||
"ReadingCalculate_NoDeveloped": "当前标准自动计算未完成开发,请知悉。",
|
||||
//ReadingMedicalReviewService
|
||||
"MedicalReview_invalid": "该医学审核任务已失效,操作失败。",
|
||||
"MedicalReview_SaveQuestion": "无法执行当前操作,请先保存医学审核问题。",
|
||||
"MedicalReview_NeedSave": "无法执行当前操作,请先保存医学审核问题和结论。",
|
||||
"MedicalReview_NotClosed": "无法执行当前操作,当前医学质询对话未关闭。"
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -205,6 +205,10 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public List<ReadingCategory> ReadingCategoryList { get; set; }
|
||||
}
|
||||
|
||||
public class ConvertedRowInfo : ReadingTableAnswerRowInfo
|
||||
{
|
||||
public Guid OriginalId { get; set; }
|
||||
}
|
||||
public class GenerateTaskCommand
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
@@ -288,7 +292,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public String VisitName { get; set; }
|
||||
|
||||
public String BlindName { get; set; }
|
||||
public bool IsBaseLine { get; set; }
|
||||
|
||||
public DateTime? CheckPassedTime { get; set; }
|
||||
|
||||
|
||||
@@ -137,6 +137,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public string BlindSubjectCode { get; set; } = string.Empty;
|
||||
public string BlindTrialSiteCode { get; set; } = string.Empty;
|
||||
|
||||
public bool IsNeedClinicalDataSign { get; set; }
|
||||
public bool IsClinicalDataSign { get; set; }
|
||||
}
|
||||
|
||||
public class VisitTaskSimpleDTO :VisitTaskGroupSimpleDTO
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
//读片时间差
|
||||
public TimeSpan? ReadingDurationTimeSpan { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 全局是否有更新
|
||||
/// </summary>
|
||||
public bool? IsGlobalHaveUpdate { get; set; } = false;
|
||||
|
||||
//时间差 换成字符串
|
||||
public string ReadingDuration
|
||||
{
|
||||
@@ -66,7 +71,7 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
if (!ReadingDurationTimeSpan.HasValue)
|
||||
return "";
|
||||
else return string.Format("{0}天{1}小时{2}分钟", (SignTime - FirstReadingTime)?.Days, (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes)
|
||||
else return string.Format("{0}d {1}h {2}min", (SignTime - FirstReadingTime)?.Days, (SignTime - FirstReadingTime)?.Hours, (SignTime - FirstReadingTime)?.Minutes)
|
||||
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
|
||||
}
|
||||
}
|
||||
@@ -79,6 +84,11 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public UserSimpleInfo DoctorUser { get; set; }
|
||||
}
|
||||
|
||||
public class GetNextMedicalReviewTaskInDto
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid MedicalReviewId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
///<summary>TaskMedicalReviewQuery 列表查询参数模型</summary>
|
||||
@@ -87,8 +97,16 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public Guid TrialId { get; set; }
|
||||
public Guid? SiteId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传了Id 就不查询这条数据
|
||||
/// </summary>
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public Guid? SubjectId { get; set; }
|
||||
|
||||
|
||||
public bool IsGetBeRead { get; set; } = false;
|
||||
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public string TrialSiteCode { get; set; } = String.Empty;
|
||||
|
||||
@@ -8,6 +8,7 @@ using IRaCIS.Core.Domain.Share;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace IRaCIS.Core.Application.ViewModel
|
||||
{
|
||||
@@ -24,6 +25,16 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public decimal VisitTaskNum { get; set; }
|
||||
|
||||
public bool IsUrgent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加急类型
|
||||
/// </summary>
|
||||
public TaskUrgentType? TaskUrgentType { get; set; }
|
||||
|
||||
|
||||
public string TaskUrgentRemake { get; set; } = string.Empty;
|
||||
|
||||
public ReadingCategory ReadingCategory { get; set; }
|
||||
|
||||
public TaskAllocationState TaskAllocationState { get; set; }
|
||||
@@ -34,7 +45,6 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public DateTime? AllocateTime { get; set; }
|
||||
public Guid SubjectId { get; set; }
|
||||
|
||||
public bool IsUrgent { get; set; }
|
||||
public Arm ArmEnum { get; set; }
|
||||
public Guid? DoctorUserId { get; set; }
|
||||
|
||||
@@ -51,11 +61,26 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public bool IsPMSetBack { get; set; }
|
||||
|
||||
|
||||
|
||||
#region 标准配置
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public string TrialReadingCriterionName { get; set; }
|
||||
|
||||
public bool IsAutoCreate { get; set; }
|
||||
|
||||
|
||||
public bool IsNeedClinicalDataSign { get; set; }
|
||||
|
||||
public bool IsClinicalDataSign { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
public CompleteClinicalDataEnum CompleteClinicalDataEnum =>
|
||||
(IsNeedClinicalDataSign && IsClinicalDataSign) ? CompleteClinicalDataEnum.Complete : (IsNeedClinicalDataSign && IsClinicalDataSign == false) ? CompleteClinicalDataEnum.NotComplete : CompleteClinicalDataEnum.NA;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -86,35 +111,18 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public CriterionType CriterionType { get; set; }
|
||||
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 仲裁对象
|
||||
///// </summary>
|
||||
//public ArbitrationRule ArbitrationRule { get; set; } = ArbitrationRule.Reading;
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 阅片模式
|
||||
///// </summary>
|
||||
//public ReadingMethod ReadingType { get; set; } = ReadingMethod.Double;
|
||||
|
||||
///// <summary>
|
||||
///// 全局阅片
|
||||
///// </summary>
|
||||
//public bool IsGlobalReading { get; set; } = true;
|
||||
|
||||
///// <summary>
|
||||
///// 仲裁阅片
|
||||
///// </summary>
|
||||
//public bool IsArbitrationReading { get; set; } = true;
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 肿瘤学阅片 原字段 IsClinicalReading
|
||||
///// </summary>
|
||||
//public bool IsOncologyReading { get; set; }
|
||||
#endregion
|
||||
|
||||
public PIAuditState PIAuditState { get; set; }
|
||||
public string NotAgreeReason { get; set; }
|
||||
public string PIAuditNote { get; set; } = string.Empty;
|
||||
|
||||
public bool? IsEnrollment { get; set; }
|
||||
|
||||
public bool? IsPDConfirm { get; set; }
|
||||
|
||||
public List<string> PIAuditImagePathList { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -128,8 +136,19 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public string UserTypeShortName { get; set; }
|
||||
|
||||
public bool IsCanEditUrgentState { get; set; }
|
||||
|
||||
|
||||
public bool? IsBaseline { get; set; }
|
||||
|
||||
public bool? IsEnrollmentConfirm { get; set; }
|
||||
|
||||
public PDStateEnum? PDState { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public bool IsClinicalDataSigned { get; set; } = false;
|
||||
}
|
||||
|
||||
public class UserSimpleInfo
|
||||
@@ -139,6 +158,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public string UserName { get; set; }
|
||||
public string FullName { get; set; }
|
||||
|
||||
public UserTypeEnum UserTypeEnum { get; set; }
|
||||
|
||||
//public string UserTypeShortName { get; set; }
|
||||
}
|
||||
|
||||
@@ -151,6 +172,23 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
}
|
||||
|
||||
|
||||
public class PIReaingTaskView : ReadingTaskView
|
||||
{
|
||||
public Guid? FirstAuditUserId { get; set; }
|
||||
|
||||
public string FirstAuditUserName { get; set; }
|
||||
public DateTime? FirstAuditTime { get; set; }
|
||||
|
||||
|
||||
public Guid? LatestReplyUserId { get; set; }
|
||||
|
||||
public string LatestReplyUserName { get; set; }
|
||||
public DateTime? LatestReplyTime { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ReadingTaskView : VisitTaskView
|
||||
{
|
||||
|
||||
@@ -159,7 +197,19 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public ReReadingApplyState ReReadingApplyState { get; set; }
|
||||
public DateTime? SuggesteFinishedTime { get; set; }
|
||||
|
||||
//任务来源访视Id 方便回更访视读片状态
|
||||
public Guid? SourceSubjectVisitId { get; set; }
|
||||
public Guid? SouceReadModuleId { get; set; }
|
||||
|
||||
|
||||
public List<PIReadingResult> PIReadingResultList { get; set; }
|
||||
}
|
||||
|
||||
public class PIReadingResult
|
||||
{
|
||||
public Guid QuestionId { get; set; }
|
||||
|
||||
public string Answer { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +273,12 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public ReReadingApplyState ReReadingApplyState { get; set; }
|
||||
public DateTime? SuggesteFinishedTime { get; set; }
|
||||
|
||||
|
||||
|
||||
public string UserName { get; set; }
|
||||
public string FullName { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class IRUnReadSubjectView
|
||||
@@ -232,13 +288,24 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
public Guid SubjectId { get; set; }
|
||||
public string SubjectCode { get; set; } = String.Empty;
|
||||
|
||||
public Guid? ClaimUserId { get; set; }
|
||||
|
||||
public string? ClaimUserName { get; set; }
|
||||
public bool IsUrgent => UnReadTaskList.Any(t => t.IsUrgent);
|
||||
|
||||
public int UnReadTaskCount { get; set; }
|
||||
|
||||
public int UnReadCanReadTaskCount { get; set; }
|
||||
|
||||
public int HaveReadTaskCount { get; set; }
|
||||
|
||||
public int TotalTaskCount { get; set; }
|
||||
|
||||
public bool ExistReadingApply { get; set; }
|
||||
|
||||
public DateTime? SuggesteFinishedTime => UnReadTaskList.Max(t => t.SuggesteFinishedTime);
|
||||
public DateTime? SuggesteFinishedTime { get; set; }
|
||||
|
||||
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>();
|
||||
}
|
||||
@@ -260,13 +327,18 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public string TaskBlindName { get; set; }
|
||||
|
||||
public Arm ArmEnum { get; set; }
|
||||
|
||||
public Guid? VisistId { get; set; }
|
||||
public DateTime? SuggesteFinishedTime { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public bool IsClinicalDataSigned { get; set; } = false;
|
||||
public bool IsNeedClinicalDataSign { get; set; }
|
||||
|
||||
public bool IsClinicalDataSign { get; set; }
|
||||
|
||||
public bool IsFrontTaskNeedSignButNotSign { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -284,9 +356,9 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public class GetOrderReadingIQueryableInDto
|
||||
{
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public string? SubjectCode { get; set; } = null;
|
||||
|
||||
@@ -329,6 +401,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public ReReadingApplyState? ReReadingApplyState { get; set; }
|
||||
|
||||
public RequestReReadingType? RequestReReadingType { get; set; }
|
||||
|
||||
|
||||
public bool? IsSelfAnalysis { get; set; }
|
||||
|
||||
@@ -336,13 +410,98 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
|
||||
public Guid? TrialReadingCriterionId { get; set; }
|
||||
|
||||
public CompleteClinicalDataEnum? CompleteClinicalDataEnum { get; set; }
|
||||
|
||||
public RequestReReadingResult? RequestReReadingResultEnum { get; set; }
|
||||
|
||||
public PIAuditState? PIAuditState { get; set; }
|
||||
|
||||
|
||||
|
||||
public string? FirstAuditUserName { get; set; }
|
||||
|
||||
|
||||
public bool? IsWaitPIAudit { get; set; }
|
||||
|
||||
|
||||
public string? LatestReplyUserName { get; set; }
|
||||
|
||||
public DateTime? FirstAuditTimeBegin { get; set; }
|
||||
public DateTime? FirstAuditTimeEnd { get; set; }
|
||||
public DateTime? LatestReplyTimeBegin { get; set; }
|
||||
public DateTime? LatestReplyTimeEnd { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class PIAuditTaskEnrollOrPdCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public bool? IsEnrollment { get; set; }
|
||||
|
||||
public bool? IsPDConfirm { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class PIAuditTaskCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
public string NotAgreeReason { get; set; }
|
||||
public string PIAuditNote { get; set; } = string.Empty;
|
||||
|
||||
public List<string> PIAuditImagePathList { get; set; }
|
||||
|
||||
public PIAuditState PIAuditState { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class PIAuditTaskReplyCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
|
||||
public string ReplyContent { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class PIAuditDialogQuery
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid VisitTaskId { get; set; }
|
||||
}
|
||||
|
||||
public class ClinicalDataDialog
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class PIAuditDialogListView : PIAuditTaskCommand
|
||||
{
|
||||
|
||||
public string ReplyContent { get; set; } = string.Empty;
|
||||
|
||||
public bool? IsEnrollment { get; set; }
|
||||
|
||||
public bool? IsPDConfirm { get; set; }
|
||||
|
||||
public bool IsCurrentUser { get; set; }
|
||||
|
||||
public Guid CreateUserId { get; set; }
|
||||
|
||||
public string CreateUserName { get; set; }
|
||||
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
|
||||
public UserTypeEnum UserTypeEnum { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -369,15 +528,15 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
/// </summary>
|
||||
public int FinishTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 未完成裁判任务数量
|
||||
/// </summary>
|
||||
public int UnReadJudgeTaskCount { get; set; }
|
||||
///// <summary>
|
||||
///// 未完成裁判任务数量
|
||||
///// </summary>
|
||||
//public int UnReadJudgeTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 完成裁判任务数量
|
||||
/// </summary>
|
||||
public int FinishJudgeTaskCount { get; set; }
|
||||
///// <summary>
|
||||
///// 完成裁判任务数量
|
||||
///// </summary>
|
||||
//public int FinishJudgeTaskCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 建议完成时间
|
||||
@@ -688,6 +847,17 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class AIRReReadingCommand
|
||||
{
|
||||
[NotDefault]
|
||||
public Guid TrialId { get; set; }
|
||||
|
||||
[NotDefault]
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class ApplyReReadingCommand
|
||||
{
|
||||
|
||||
@@ -739,6 +909,19 @@ namespace IRaCIS.Core.Application.ViewModel
|
||||
CancelAssign = 4,
|
||||
}
|
||||
|
||||
public class ClaimSubjectDto
|
||||
{
|
||||
public bool IsInOrder { get; set; }
|
||||
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public Guid TrialReadingCriterionId { get; set; }
|
||||
|
||||
public Guid SubejctId { get; set; }
|
||||
|
||||
public bool IsClaim { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace IRaCIS.Core.Application.Interfaces
|
||||
|
||||
//Task<PageOutput<TaskMedicalReviewView>> GetTaskMedicalReviewList(TaskMedicalReviewQuery queryTaskMedicalReview);
|
||||
|
||||
|
||||
|
||||
Task<TaskMedicalReviewView> GetNextMedicalReviewTask(GetNextMedicalReviewTaskInDto inDto);
|
||||
Task<IResponseOutput<PageOutput<TaskMedicalReviewView>>> GetMIMMedicalReviewTaskList(TaskMedicalReviewQuery inQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
Task AddTaskAsync(GenerateTaskCommand generateTaskCommand);
|
||||
|
||||
Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId);
|
||||
|
||||
Task AddConvertedTask(Guid taskId);
|
||||
|
||||
Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId,bool? isManualSelectVisit=null,List<Guid>? subjectVisitIdList=null);
|
||||
}
|
||||
}
|
||||
@@ -17,5 +17,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
Task<IResponseOutput> ConfirmReReading(ConfirmReReadingCommand agreeReReadingCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService);
|
||||
|
||||
Task<(int, List<IRUnReadSubjectView>)> GetOrderReadingIQueryable(GetOrderReadingIQueryableInDto inDto);
|
||||
|
||||
Task<IQueryable<VisitTask>> GetNotOrderReadingQueryableAsync(Guid trialId, Guid trialReadingCriterionId);
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||
// 生成时间 2022-06-07 13:14:38
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 分配规则
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class TaskAllocationRuleService : BaseService, ITaskAllocationRuleService
|
||||
{
|
||||
|
||||
private readonly IRepository<TaskAllocationRule> _taskAllocationRuleRepository;
|
||||
private readonly IRepository<User> _userRepository;
|
||||
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
|
||||
private readonly IRepository<SubjectCanceDoctor> _subjectCanceDoctorRepository;
|
||||
|
||||
|
||||
|
||||
public TaskAllocationRuleService(IRepository<TaskAllocationRule> taskAllocationRuleRepository, IRepository<User> userRepository, IRepository<Trial> trialRepository, IRepository<SubjectCanceDoctor> subjectCanceDoctorRepository)
|
||||
{
|
||||
_taskAllocationRuleRepository = taskAllocationRuleRepository;
|
||||
_userRepository = userRepository;
|
||||
_trialRepository = trialRepository;
|
||||
_subjectCanceDoctorRepository = subjectCanceDoctorRepository;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取计划列表 医生带阅片类型
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<(List<TaskAllocationRuleDTO>,object)> GetDoctorPlanAllocationRuleList(Guid trialId)
|
||||
{
|
||||
|
||||
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();
|
||||
|
||||
return (list, trialTaskConfig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<IResponseOutput> AddOrUpdateTaskAllocationRule(TaskAllocationRuleAddOrEdit addOrEditTaskAllocationRule)
|
||||
{
|
||||
|
||||
|
||||
//冗余 存
|
||||
|
||||
var enrollId = _repository.Where<Enroll>(t => t.TrialId == addOrEditTaskAllocationRule.TrialId && t.DoctorUserId == addOrEditTaskAllocationRule.DoctorUserId).Select(t => t.Id).FirstOrDefault();
|
||||
|
||||
if (enrollId == Guid.Empty)
|
||||
{
|
||||
return ResponseOutput.NotOk("错误,未在入组表中找到该医生得账号Id");
|
||||
}
|
||||
|
||||
addOrEditTaskAllocationRule.EnrollId = enrollId;
|
||||
|
||||
var verifyExp1 = new EntityVerifyExp<TaskAllocationRule>()
|
||||
{
|
||||
VerifyExp = t => t.DoctorUserId == addOrEditTaskAllocationRule.DoctorUserId && t.TrialId == addOrEditTaskAllocationRule.TrialId,
|
||||
VerifyMsg = "已有该医生配置,不允许继续增加"
|
||||
};
|
||||
|
||||
var entity = await _taskAllocationRuleRepository.InsertOrUpdateAsync(addOrEditTaskAllocationRule, true, verifyExp1);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("{taskAllocationRuleId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteTaskAllocationRule(Guid taskAllocationRuleId)
|
||||
{
|
||||
if (await _taskAllocationRuleRepository.Where(t => t.Id == taskAllocationRuleId).AnyAsync(t => t.DoctorUser.VisitTaskList.Where(u => u.TrialId == t.TrialId).Any()))
|
||||
{
|
||||
return ResponseOutput.NotOk("已分配任务给该医生,不允许删除");
|
||||
}
|
||||
|
||||
var success = await _taskAllocationRuleRepository.DeleteFromQueryAsync(t => t.Id == taskAllocationRuleId, true);
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
||||
//public async Task<IResponseOutput> AddSubjectCancelDoctorNote(CancelDoctorCommand command)
|
||||
//{
|
||||
// await _subjectCanceDoctorRepository.InsertOrUpdateAsync(command, true);
|
||||
|
||||
// return ResponseOutput.Ok();
|
||||
//}
|
||||
|
||||
public async Task<List<SubjectCancelDoctorView>> GetSubjectCancelDoctorHistoryList(Guid subjectId)
|
||||
{
|
||||
var list = await _subjectCanceDoctorRepository.Where(t => t.SubjectId == subjectId).ProjectTo<SubjectCancelDoctorView>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取项目下 医生账户信息下拉
|
||||
/// </summary>
|
||||
/// <param name="trialId"></param>
|
||||
/// <param name="_enrollRepository"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{trialId:guid}")]
|
||||
public async Task<List<TrialDoctorUserSelectView>> GetDoctorUserSelectList(Guid trialId, [FromServices] IRepository<Enroll> _enrollRepository)
|
||||
{
|
||||
var query = from enroll in _enrollRepository.Where(t => t.TrialId == trialId && t.EnrollStatus >= EnrollStatus.ConfirmIntoGroup)
|
||||
join user in _userRepository.AsQueryable() on enroll.DoctorId equals user.DoctorId
|
||||
select new TrialDoctorUserSelectView()
|
||||
{
|
||||
TrialId = enroll.TrialId,
|
||||
//ReadingType = enroll.Trial.ReadingType,
|
||||
DoctorUserId = user.Id,
|
||||
FullName = user.FullName,
|
||||
UserCode = user.UserCode,
|
||||
UserName = user.UserName,
|
||||
UserTypeEnum = user.UserTypeRole.UserTypeEnum,
|
||||
ReadingCategoryList = enroll.EnrollReadingCategoryList.Select(t => t.ReadingCategory).ToList()
|
||||
|
||||
};
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<List<TrialDoctorUserSelectView>> GetDoctorSelectList(DoctorSelectQuery selectQuery, [FromServices] IRepository<Enroll> _enrollRepository)
|
||||
{
|
||||
|
||||
var query = from allocationRule in _taskAllocationRuleRepository.Where(t => t.TrialId == selectQuery.TrialId && t.IsEnable)
|
||||
.WhereIf(selectQuery.ReadingCategory != null && selectQuery.TrialReadingCriterionId == null, t => t.Enroll.EnrollReadingCategoryList.Any(t => t.ReadingCategory == selectQuery.ReadingCategory))
|
||||
.WhereIf(selectQuery.TrialReadingCriterionId != null && selectQuery.ReadingCategory == null, t => t.Enroll.EnrollReadingCategoryList.Any(t => t.TrialReadingCriterionId == selectQuery.TrialReadingCriterionId))
|
||||
.WhereIf(selectQuery.TrialReadingCriterionId != null && selectQuery.ReadingCategory !=null,
|
||||
t => t.Enroll.EnrollReadingCategoryList.Any(t => t.TrialReadingCriterionId == selectQuery.TrialReadingCriterionId && t.ReadingCategory==selectQuery.ReadingCategory))
|
||||
join user in _userRepository.AsQueryable() on allocationRule.DoctorUserId equals user.Id
|
||||
select new TrialDoctorUserSelectView()
|
||||
{
|
||||
TrialId = allocationRule.TrialId,
|
||||
DoctorUserId = user.Id,
|
||||
FullName = user.FullName,
|
||||
UserCode = user.UserCode,
|
||||
UserName = user.UserName,
|
||||
UserTypeEnum = user.UserTypeRole.UserTypeEnum,
|
||||
|
||||
ReadingCategoryList = selectQuery.TrialReadingCriterionId == null ?
|
||||
|
||||
allocationRule.Enroll.EnrollReadingCategoryList.Where(t=> (selectQuery.ReadingCategory == null ?true: t.ReadingCategory == selectQuery.ReadingCategory) ).Select(t => t.ReadingCategory).OrderBy(t => t).ToList() :
|
||||
|
||||
allocationRule.Enroll.EnrollReadingCategoryList
|
||||
.Where(t => t.TrialReadingCriterionId == selectQuery.TrialReadingCriterionId && (selectQuery.ReadingCategory == null?true : t.ReadingCategory == selectQuery.ReadingCategory) )
|
||||
.Select(t => t.ReadingCategory).OrderBy(t => t).ToList()
|
||||
};
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
#region 废弃
|
||||
/// <summary>
|
||||
/// 获取访视任务 应用Subject后 医生比率情况
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Obsolete]
|
||||
public async Task<List<DoctorVisitTaskStatView>> GetSubjectApplyDoctorTaskStatList(ApplySubjectCommand assignConfirmCommand)
|
||||
{
|
||||
var taskAllocationRuleQueryable = _taskAllocationRuleRepository.Where(t => t.TrialId == assignConfirmCommand.TrialId && t.IsJudgeDoctor == assignConfirmCommand.IsJudgeDoctor)
|
||||
.ProjectTo<DoctorVisitTaskStatView>(_mapper.ConfigurationProvider, new { subjectIdList = assignConfirmCommand.SubjectIdList, isJudgeDoctor = assignConfirmCommand.IsJudgeDoctor });
|
||||
|
||||
return await taskAllocationRuleQueryable.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Obsolete]
|
||||
public async Task<List<DoctorVisitTaskStatView>> GetTaskAllocationRuleList(TaskAllocationRuleQuery queryTaskAllocationRule)
|
||||
{
|
||||
var taskAllocationRuleQueryable = _taskAllocationRuleRepository.Where(t => t.TrialId == queryTaskAllocationRule.TrialId /*&& t.IsJudgeDoctor == queryTaskAllocationRule.IsJudgeDoctor*/)
|
||||
.ProjectTo<DoctorVisitTaskStatView>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
||||
//var trialTaskConfig = _trialRepository.Where(t => t.Id == queryTaskAllocationRule.TrialId).ProjectTo<TrialProcessConfigDTO>(_mapper.ConfigurationProvider, new { isJudgeDoctor = queryTaskAllocationRule.IsJudgeDoctor }).FirstOrDefault();
|
||||
|
||||
return await taskAllocationRuleQueryable.ToListAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,756 +0,0 @@
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||
// 生成时间 2022-07-01 15:33:04
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
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;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// 一致性分析配置表
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(GroupName = "Trial")]
|
||||
public class TaskConsistentRuleService : BaseService, ITaskConsistentRuleService
|
||||
{
|
||||
|
||||
private readonly IRepository<TaskConsistentRule> _taskConsistentRuleRepository;
|
||||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||||
private readonly IRepository<SubjectUser> _subjectUserRepository;
|
||||
private readonly IRepository<Subject> _subjectRepository;
|
||||
private readonly IRepository<Enroll> _enrollRepository;
|
||||
|
||||
private readonly AsyncLock _mutex = new AsyncLock();
|
||||
|
||||
public TaskConsistentRuleService(IRepository<VisitTask> visitTaskRepository, IRepository<Enroll> enrollRepository, IRepository<TaskConsistentRule> taskConsistentRuleRepository, IRepository<SubjectUser> subjectUserRepository, IRepository<Subject> subjectRepository)
|
||||
{
|
||||
_taskConsistentRuleRepository = taskConsistentRuleRepository;
|
||||
_visitTaskRepository = visitTaskRepository;
|
||||
_subjectUserRepository = subjectUserRepository;
|
||||
_subjectRepository = subjectRepository;
|
||||
_enrollRepository = enrollRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置一致性分析任务失效
|
||||
/// </summary>
|
||||
/// <param name="taskIdList"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IResponseOutput> SetAnalysisTaskInvalid(List<Guid> taskIdList)
|
||||
{
|
||||
|
||||
|
||||
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => taskIdList.Contains(t.Id), u => new VisitTask() { TaskState = TaskState.NotEffect },true);
|
||||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一致性分析列表 (自身 组内 最后勾选 产生的任务)
|
||||
/// </summary>
|
||||
/// <param name="queryVisitTask"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<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.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)
|
||||
.WhereIf(queryVisitTask.DoctorUserId != null, t => t.DoctorUserId == queryVisitTask.DoctorUserId)
|
||||
.WhereIf(queryVisitTask.ReadingCategory != null, t => t.ReadingCategory == queryVisitTask.ReadingCategory)
|
||||
.WhereIf(queryVisitTask.ReadingTaskState != null, t => t.ReadingTaskState == queryVisitTask.ReadingTaskState)
|
||||
.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.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName))
|
||||
.WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => t.Subject.Code.Contains(queryVisitTask.SubjectCode))
|
||||
.WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime > queryVisitTask.BeginAllocateDate)
|
||||
.WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime < queryVisitTask.EndAllocateDate!.Value.AddDays(1))
|
||||
.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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 为自身一致性分析医生,选择Subejct 列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<PageOutput<DoctorSelfConsistentSubjectView>> GetDoctorSelfConsistentRuleSubjectList(ConsistentQuery inQuery)
|
||||
{
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inQuery.TaskConsistentRuleId);
|
||||
|
||||
var pagedList = await GetIQueryableDoctorSelfConsistentSubjectView(filterObj, inQuery.DoctorUserId).ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(DoctorSelfConsistentSubjectView.SubjectCode) : inQuery.SortField, inQuery.Asc);
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 确认生成自身一致性分析任务
|
||||
/// </summary>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <param name="_visitTaskCommonService"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ConfirmGenerateSelfConsistentTask(ConsistentConfirmGenerateCommand inCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
|
||||
{
|
||||
|
||||
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.Id == inCommand.TaskConsistentRuleId);
|
||||
var doctorUserId = inCommand.DoctorUserId;
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
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())
|
||||
{
|
||||
int maxCodeInt = 0;
|
||||
|
||||
foreach (var subject in list)
|
||||
{
|
||||
//处理 Subject 编号
|
||||
|
||||
var blindSubjectCode = string.Empty;
|
||||
|
||||
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)
|
||||
{
|
||||
blindSubjectCode = subjectTask.BlindSubjectCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
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))
|
||||
{
|
||||
int.TryParse(maxCodeStr.Substring(maxCodeStr.Length - filterObj.BlindSubjectNumberOfPlaces), out maxCodeInt);
|
||||
|
||||
}
|
||||
|
||||
blindSubjectCode = filterObj.BlindTrialSiteCode + (maxCodeInt + 1).ToString($"D{filterObj.BlindSubjectNumberOfPlaces}");
|
||||
}
|
||||
|
||||
subject.VisitTaskList = subject.VisitTaskList.Take(filterObj.PlanVisitCount).ToList();
|
||||
|
||||
subject.VisitTaskList.ForEach(t =>
|
||||
{
|
||||
t.DoctorUserId = doctorUserId;
|
||||
//t.TaskConsistentRuleId = filterObj.Id;
|
||||
t.BlindTrialSiteCode = filterObj.BlindTrialSiteCode;
|
||||
t.BlindSubjectCode = blindSubjectCode;
|
||||
});
|
||||
|
||||
|
||||
//最后一个访视添加全局
|
||||
if (filterObj.IsGenerateGlobalTask)
|
||||
{
|
||||
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();
|
||||
|
||||
|
||||
if (existGlobal == null)
|
||||
{
|
||||
existGlobal = new VisitTaskSimpleDTO()
|
||||
{
|
||||
SubjectId = lastTask.SubjectId,
|
||||
TrialId = lastTask.TrialId,
|
||||
ArmEnum = lastTask.ArmEnum,
|
||||
ReadingCategory = ReadingCategory.Global,
|
||||
TaskName = lastTask.TaskName + "_Global",
|
||||
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
||||
TrialReadingCriterionId=trialReadingCriterionId,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
existGlobal.DoctorUserId = doctorUserId;
|
||||
existGlobal.BlindSubjectCode = lastTask.BlindSubjectCode;
|
||||
existGlobal.BlindTrialSiteCode = lastTask.BlindTrialSiteCode;
|
||||
|
||||
subject.VisitTaskList.Add(existGlobal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
await _visitTaskCommonService.AddTaskAsync(new GenerateTaskCommand()
|
||||
{
|
||||
TrialId = filterObj.TrialId,
|
||||
|
||||
ReadingCategory = GenerateTaskCategory.SelfConsistent,
|
||||
|
||||
|
||||
//产生的过滤掉已经生成的
|
||||
GenerataConsistentTaskList = subject.VisitTaskList.Where(t => t.IsHaveGeneratedTask == false).ToList()
|
||||
});
|
||||
|
||||
await _visitTaskRepository.SaveChangesAsync();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 组间一致性分析 选择Subejct 列表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<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);
|
||||
|
||||
|
||||
if (filterObj == null)
|
||||
{
|
||||
return new PageOutput<DoctorGroupConsistentSubjectView>();
|
||||
}
|
||||
|
||||
var query = await GetGroupConsistentQueryAsync(filterObj);
|
||||
|
||||
|
||||
var pagedList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(DoctorSelfConsistentSubjectView.SubjectCode) : inQuery.SortField, inQuery.Asc);
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 确认生成组间一致性分析任务
|
||||
/// </summary>
|
||||
/// <param name="inCommand"></param>
|
||||
/// <param name="_visitTaskCommonService"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> ConfirmGenerateGroupConsistentTask(GroupConsistentConfirmGenrateCommand inCommand, [FromServices] IVisitTaskHelpeService _visitTaskCommonService)
|
||||
{
|
||||
var trialId = inCommand.TrialId;
|
||||
|
||||
var filterObj = await _taskConsistentRuleRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.IsSelfAnalysis == false);
|
||||
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
|
||||
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))
|
||||
join user in _repository.Where<User>() on enroll.DoctorId equals user.DoctorId
|
||||
select user.Id;
|
||||
|
||||
var configDoctorUserIdList = await doctorUserIdQuery.ToListAsync();
|
||||
|
||||
using (await _mutex.LockAsync())
|
||||
{
|
||||
int maxCodeInt = 0;
|
||||
|
||||
foreach (var subject in subjectList.Where(t => t.IsHaveGeneratedTask == false))
|
||||
{
|
||||
|
||||
//组间一致性分析 也用盲态SubjectCode
|
||||
//处理 Subject 编号
|
||||
|
||||
var blindSubjectCode = string.Empty;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
var maxCodeStr = _visitTaskRepository.Where(t => t.TrialId == subject.TrialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsSelfAnalysis == false).OrderByDescending(t => t.BlindSubjectCode).Select(t => t.BlindSubjectCode).FirstOrDefault();
|
||||
|
||||
if (!string.IsNullOrEmpty(maxCodeStr))
|
||||
{
|
||||
int.TryParse(maxCodeStr.Substring(maxCodeStr.Length - filterObj.BlindSubjectNumberOfPlaces), out maxCodeInt);
|
||||
|
||||
}
|
||||
|
||||
blindSubjectCode = filterObj.BlindTrialSiteCode + (maxCodeInt + 1).ToString($"D{filterObj.BlindSubjectNumberOfPlaces}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var subjectAddTaskList = new List<VisitTaskGroupSimpleDTO>();
|
||||
|
||||
|
||||
//需要处理的医生
|
||||
|
||||
var needAddDoctorUserIdList = configDoctorUserIdList.Except(subject.VisitTaskList.Select(t => (Guid)t.DoctorUserId)).ToList();
|
||||
|
||||
if (needAddDoctorUserIdList.Count == 0)
|
||||
{
|
||||
throw new BusinessValidationFailedException("请配置一致性分析的医生");
|
||||
}
|
||||
|
||||
|
||||
foreach (var needAddDoctorUserId in needAddDoctorUserIdList)
|
||||
{
|
||||
|
||||
//每个医生 都生成处理的任务
|
||||
foreach (var task in subject.SubjectTaskVisitList.Take(filterObj.PlanVisitCount))
|
||||
{
|
||||
|
||||
subjectAddTaskList.Add(new VisitTaskGroupSimpleDTO()
|
||||
{
|
||||
ReadingCategory = task.ReadingCategory,
|
||||
ReadingTaskState = task.ReadingTaskState,
|
||||
TaskBlindName = task.TaskBlindName,
|
||||
TaskName = task.TaskName,
|
||||
TaskState = task.TaskState,
|
||||
SubjectId = task.SubjectId,
|
||||
VisitTaskNum = task.VisitTaskNum,
|
||||
TrialId = task.TrialId,
|
||||
DoctorUserId = needAddDoctorUserId,
|
||||
ArmEnum = Arm.GroupConsistentArm,
|
||||
SouceReadModuleId = task.SouceReadModuleId,
|
||||
SourceSubjectVisitId = task.SourceSubjectVisitId,
|
||||
|
||||
TrialReadingCriterionId = task.TrialReadingCriterionId,
|
||||
|
||||
BlindSubjectCode=blindSubjectCode,
|
||||
BlindTrialSiteCode=filterObj.BlindTrialSiteCode
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//最后一个访视添加全局
|
||||
|
||||
if (filterObj.IsGenerateGlobalTask)
|
||||
{
|
||||
var lastTask = (subjectAddTaskList.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<VisitTaskGroupSimpleDTO>(_mapper.ConfigurationProvider).FirstOrDefault();
|
||||
|
||||
|
||||
if (existGlobal == null)
|
||||
{
|
||||
existGlobal = new VisitTaskSimpleDTO()
|
||||
{
|
||||
SubjectId = lastTask.SubjectId,
|
||||
TrialId = lastTask.TrialId,
|
||||
ReadingCategory = ReadingCategory.Global,
|
||||
TaskName = lastTask.TaskName + "_Global",
|
||||
TaskBlindName = lastTask.TaskBlindName + "_Global",
|
||||
|
||||
TrialReadingCriterionId = trialReadingCriterionId,
|
||||
|
||||
BlindSubjectCode = blindSubjectCode,
|
||||
BlindTrialSiteCode = filterObj.BlindTrialSiteCode
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
existGlobal.BlindSubjectCode = blindSubjectCode;
|
||||
existGlobal.BlindTrialSiteCode = filterObj.BlindTrialSiteCode;
|
||||
existGlobal.ArmEnum = Arm.GroupConsistentArm;
|
||||
existGlobal.DoctorUserId = needAddDoctorUserId;
|
||||
|
||||
subjectAddTaskList.Add(existGlobal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
await _visitTaskCommonService.AddTaskAsync(new GenerateTaskCommand()
|
||||
{
|
||||
TrialId = filterObj.TrialId,
|
||||
|
||||
ReadingCategory = GenerateTaskCategory.GroupConsistent,
|
||||
|
||||
|
||||
GenerataGroupConsistentTaskList = subjectAddTaskList
|
||||
});
|
||||
|
||||
|
||||
await _taskConsistentRuleRepository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 仅仅自身一致性时使用(
|
||||
/// </summary>
|
||||
/// <param name="filterObj"></param>
|
||||
/// <param name="doctorUserId"></param>
|
||||
/// <param name="subejctIdList"></param>
|
||||
/// <returns></returns>
|
||||
private IQueryable<DoctorSelfConsistentSubjectView> GetIQueryableDoctorSelfConsistentSubjectView(TaskConsistentRule filterObj, Guid doctorUserId, List<Guid>? subejctIdList = null)
|
||||
{
|
||||
var trialId = filterObj.TrialId;
|
||||
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
#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 &&
|
||||
u.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (u.ReReadingApplyState == ReReadingApplyState.Default || u.ReReadingApplyState == ReReadingApplyState.Reject) && u.DoctorUserId == doctorUserId;
|
||||
|
||||
|
||||
|
||||
|
||||
if (subejctIdList != null && subejctIdList?.Count > 0)
|
||||
{
|
||||
comonTaskFilter = comonTaskFilter.And(t => subejctIdList.Contains(t.SubjectId));
|
||||
}
|
||||
|
||||
|
||||
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
||||
|
||||
////所选访视数量 的访视 其中必有一个访视后有全局任务
|
||||
//if (filterObj.IsHaveReadingPeriod == true)
|
||||
//{
|
||||
// //这里的过滤条件 不能用 where(comonTaskFilter) 会报错,奇怪的问题 只能重新写一遍
|
||||
// visitTaskFilter = visitTaskFilter.And(c => c.Subject.SubjectVisitTaskList.Any(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.ReadingCategory == ReadingCategory.Global && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
// t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)));
|
||||
|
||||
//}
|
||||
|
||||
|
||||
var subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
||||
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count() >= filterObj.PlanVisitCount)
|
||||
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount + 1).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
||||
;
|
||||
|
||||
|
||||
|
||||
var query = subjectQuery.Select(t => new DoctorSelfConsistentSubjectView()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
SubjectCode = t.Code,
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
SubjectId = t.Id,
|
||||
|
||||
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),
|
||||
|
||||
|
||||
ValidVisitCount = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count(),
|
||||
|
||||
VisitTaskList = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).OrderBy(t => t.VisitTaskNum).Select(c => new VisitTaskSimpleDTO()
|
||||
{
|
||||
Id = c.Id,
|
||||
ReadingCategory = c.ReadingCategory,
|
||||
ReadingTaskState = c.ReadingTaskState,
|
||||
TaskBlindName = c.TaskBlindName,
|
||||
TaskCode = c.TaskCode,
|
||||
TaskName = c.TaskName,
|
||||
TaskState = c.TaskState,
|
||||
ArmEnum = c.ArmEnum,
|
||||
SubjectId = c.SubjectId,
|
||||
VisitTaskNum = c.VisitTaskNum,
|
||||
TrialId = c.TrialId,
|
||||
SourceSubjectVisitId = c.SourceSubjectVisitId,
|
||||
SouceReadModuleId = c.SouceReadModuleId,
|
||||
|
||||
|
||||
TrialReadingCriterionId=c.TrialReadingCriterionId,
|
||||
|
||||
//自身一致性才有意义
|
||||
//IsHaveGeneratedTask = c.Subject.SubjectVisitTaskList.Any(t => t.ConsistentAnalysisOriginalTaskId == c.Id),
|
||||
|
||||
GlobalVisitTaskList = c.Subject.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global]).Select(c => new VisitTaskSimpleDTO()
|
||||
{
|
||||
Id = c.Id,
|
||||
ReadingCategory = c.ReadingCategory,
|
||||
ReadingTaskState = c.ReadingTaskState,
|
||||
TaskBlindName = c.TaskBlindName,
|
||||
TaskCode = c.TaskCode,
|
||||
TaskName = c.TaskName,
|
||||
TaskState = c.TaskState,
|
||||
ArmEnum = c.ArmEnum,
|
||||
SubjectId = c.SubjectId,
|
||||
VisitTaskNum = c.VisitTaskNum,
|
||||
TrialId = c.TrialId,
|
||||
SourceSubjectVisitId = c.SourceSubjectVisitId,
|
||||
SouceReadModuleId = c.SouceReadModuleId,
|
||||
}).ToList(),
|
||||
|
||||
}).ToList()
|
||||
});
|
||||
|
||||
return query.OrderByDescending(t => t.IsHaveGeneratedTask);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private async Task<IQueryable<DoctorGroupConsistentSubjectView>> GetGroupConsistentQueryAsync(TaskConsistentRule filterObj, List<Guid>? subejctIdList = null)
|
||||
{
|
||||
|
||||
var trialId = filterObj.TrialId;
|
||||
var trialReadingCriterionId = filterObj.TrialReadingCriterionId;
|
||||
|
||||
//var trialConfig = (await _repository.Where<Trial>(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.IsReadingTaskViewInOrder }).FirstOrDefaultAsync()).IfNullThrowException();
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
if (subejctIdList != null && subejctIdList?.Count > 0)
|
||||
{
|
||||
comonTaskFilter = comonTaskFilter.And(t => subejctIdList.Contains(t.SubjectId));
|
||||
}
|
||||
|
||||
Expression<Func<VisitTask, bool>> visitTaskFilter = comonTaskFilter.And(t => t.ReadingCategory == ReadingCategory.Visit);
|
||||
|
||||
|
||||
////所选访视数量 的访视 其中必有一个访视后有全局任务
|
||||
//if (filterObj.IsHaveReadingPeriod == true)
|
||||
//{
|
||||
// //visitTaskFilter = visitTaskFilter.And(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Any(u => u.VisitTaskNum == t.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && u.ReadingCategory == ReadingCategory.Global));
|
||||
|
||||
// //这里的过滤条件 不能用 where(comonTaskFilter) 会报错,奇怪的问题 只能重新写一遍
|
||||
// visitTaskFilter = visitTaskFilter.And(c => c.Subject.SubjectVisitTaskList.Any(t => t.VisitTaskNum == c.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Global] && t.ReadingCategory == ReadingCategory.Global && t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||||
// t.SignTime!.Value.AddDays(filterObj.IntervalWeeks * 7) < DateTime.Now && (t.ReReadingApplyState == ReReadingApplyState.Default || t.ReReadingApplyState == ReReadingApplyState.Reject)));
|
||||
|
||||
//}
|
||||
|
||||
|
||||
IQueryable<Subject> subjectQuery = default;
|
||||
|
||||
//单重阅片没有组件一致性
|
||||
|
||||
subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId &&
|
||||
t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Select(t => t.DoctorUserId).Distinct().Count() == 2 &&
|
||||
t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count() >= filterObj.PlanVisitCount
|
||||
)
|
||||
.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount * 2 + 2).Any(t => t.ReadingCategory == ReadingCategory.Global))
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
||||
var query = subjectQuery.Select(t => new DoctorGroupConsistentSubjectView()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
SiteId = t.SiteId,
|
||||
SubjectCode = t.Code,
|
||||
TrialSiteCode = t.TrialSite.TrialSiteCode,
|
||||
SubjectId = t.Id,
|
||||
IsReReadingOrBackInfluenceAnalysis = t.IsReReadingOrBackInfluenceAnalysis,
|
||||
|
||||
IsHaveGeneratedTask = t.SubjectVisitTaskList.Any(c => c.IsSelfAnalysis == false && c.TrialReadingCriterionId==trialReadingCriterionId),
|
||||
|
||||
|
||||
ValidVisitCount = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count(),
|
||||
|
||||
VisitTaskList = t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter)
|
||||
.Select(c => new VisitTaskGroupSimpleDTO()
|
||||
{
|
||||
ReadingCategory = c.ReadingCategory,
|
||||
ReadingTaskState = c.ReadingTaskState,
|
||||
TaskBlindName = c.TaskBlindName,
|
||||
TaskName = c.TaskName,
|
||||
TaskState = c.TaskState,
|
||||
SubjectId = c.SubjectId,
|
||||
VisitTaskNum = c.VisitTaskNum,
|
||||
TrialId = c.TrialId,
|
||||
DoctorUserId = c.DoctorUserId,
|
||||
|
||||
SourceSubjectVisitId = c.SourceSubjectVisitId,
|
||||
SouceReadModuleId = c.SouceReadModuleId,
|
||||
TrialReadingCriterionId = c.TrialReadingCriterionId,
|
||||
|
||||
}).ToList()
|
||||
|
||||
//
|
||||
});
|
||||
|
||||
query = query.OrderByDescending(t => t.IsHaveGeneratedTask);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自身一致性分配 配置+ 统计已经生成数量统计表
|
||||
/// </summary>
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<List<TaskConsistentRuleView>> GetSelfConsistentDoctorStatList(TaskConsistentRuleQuery inQuery)
|
||||
{
|
||||
var trialId = inQuery.TrialId;
|
||||
|
||||
var taskConsistentRuleQueryable = from enroll in _repository.Where<Enroll>(t => t.TrialId == trialId)
|
||||
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
|
||||
select new TaskConsistentRuleView()
|
||||
{
|
||||
Id = taskConsistentRule.Id,
|
||||
CreateTime = taskConsistentRule.CreateTime,
|
||||
BlindTrialSiteCode = taskConsistentRule.BlindTrialSiteCode,
|
||||
BlindSubjectNumberOfPlaces = taskConsistentRule.BlindSubjectNumberOfPlaces,
|
||||
CreateUserId = taskConsistentRule.CreateUserId,
|
||||
IntervalWeeks = taskConsistentRule.IntervalWeeks,
|
||||
IsEnable = taskConsistentRule.IsEnable,
|
||||
PlanSubjectCount = taskConsistentRule.PlanSubjectCount,
|
||||
Note = taskConsistentRule.Note,
|
||||
TrialId = taskConsistentRule.TrialId,
|
||||
UpdateTime = taskConsistentRule.UpdateTime,
|
||||
UpdateUserId = taskConsistentRule.UpdateUserId,
|
||||
IsGenerateGlobalTask = taskConsistentRule.IsGenerateGlobalTask,
|
||||
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(),
|
||||
|
||||
AnalysisDoctorUser = new UserSimpleInfo()
|
||||
{
|
||||
UserId = user.Id,
|
||||
UserCode = user.UserCode,
|
||||
FullName = user.FullName,
|
||||
UserName = user.UserName
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//if (await _taskConsistentRuleRepository.AnyAsync(t => t.TrialId == inQuery.TrialId))
|
||||
//{
|
||||
// var rule = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId).ProjectTo<TaskConsistentRuleBatchAddOrEdit>(_mapper.ConfigurationProvider).FirstAsync();
|
||||
|
||||
// rule.IsBatchAdd = true;
|
||||
|
||||
// await BatchAddOrUpdateTaskConsistentRule(rule);
|
||||
//}
|
||||
|
||||
//#endregion
|
||||
|
||||
//var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
// .ProjectTo<TaskConsistentRuleView>(_mapper.ConfigurationProvider);
|
||||
|
||||
return await taskConsistentRuleQueryable.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<IResponseOutput> AddOrUpdateTaskConsistentRule(TaskConsistentRuleAddOrEdit addOrEditTaskConsistentRule)
|
||||
{
|
||||
|
||||
var verifyExp1 = new EntityVerifyExp<TaskConsistentRule>()
|
||||
{
|
||||
VerifyExp = t => t.TrialId == addOrEditTaskConsistentRule.TrialId && t.IsSelfAnalysis == addOrEditTaskConsistentRule.IsSelfAnalysis && t.TrialReadingCriterionId==addOrEditTaskConsistentRule.TrialReadingCriterionId,
|
||||
VerifyMsg = "已有该项目配置,不允许继续增加"
|
||||
};
|
||||
|
||||
if (await _visitTaskRepository.AnyAsync(t => t.IsSelfAnalysis == addOrEditTaskConsistentRule.IsSelfAnalysis && t.TrialId == addOrEditTaskConsistentRule.TrialId && t.TrialReadingCriterionId == addOrEditTaskConsistentRule.TrialReadingCriterionId))
|
||||
{
|
||||
return ResponseOutput.NotOk("该标准已有Subject 生成了任务,不允许修改配置");
|
||||
}
|
||||
|
||||
var entity = await _taskConsistentRuleRepository.InsertOrUpdateAsync(addOrEditTaskConsistentRule, true, verifyExp1);
|
||||
|
||||
return ResponseOutput.Ok(entity.Id.ToString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("{taskConsistentRuleId:guid}")]
|
||||
public async Task<IResponseOutput> DeleteTaskConsistentRule(Guid taskConsistentRuleId)
|
||||
{
|
||||
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))
|
||||
{
|
||||
throw new BusinessValidationFailedException("该标准已产生一致性分析任务,不允许删除");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var success = await _taskConsistentRuleRepository.DeleteFromQueryAsync(t => t.Id == taskConsistentRuleId, true);
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ using IRaCIS.Core.Domain.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
/// <summary>
|
||||
@@ -40,12 +42,16 @@ namespace IRaCIS.Core.Application.Service
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
public async Task<IResponseOutput> AddOrUpdateTaskMedicalReviewRule(TaskMedicalReviewRuleAddOrEdit addOrEditTaskTaskMedicalReviewRule)
|
||||
{
|
||||
var verifyExp1 = new EntityVerifyExp<TaskMedicalReviewRule>()
|
||||
{
|
||||
|
||||
VerifyExp = t => t.DoctorUserId == addOrEditTaskTaskMedicalReviewRule.DoctorUserId && t.TrialId == addOrEditTaskTaskMedicalReviewRule.TrialId,
|
||||
VerifyMsg = "已有该医生配置,不允许继续增加"
|
||||
//"已有该医生配置,不允许继续增加"
|
||||
VerifyMsg = _localizer["TaskMedicalRule_TaskAlreadyAssigned"]
|
||||
};
|
||||
|
||||
var entity = await _taskMedicalReviewRuleRepository.InsertOrUpdateAsync(addOrEditTaskTaskMedicalReviewRule, true, verifyExp1);
|
||||
@@ -56,12 +62,15 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
[HttpDelete("{taskMedicalReviewRuleId:guid}")]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
public async Task<IResponseOutput> DeleteTaskMedicalReviewRule(Guid taskMedicalReviewRuleId)
|
||||
{
|
||||
|
||||
if(await _taskMedicalReviewRuleRepository.Where(t=>t.Id== taskMedicalReviewRuleId).AnyAsync(t => t.TaskMedicalReviewList.Any()))
|
||||
{
|
||||
return ResponseOutput.NotOk("已产生医学审核任务");
|
||||
//"已产生医学审核任务"
|
||||
return ResponseOutput.NotOk(_localizer["TaskMedicalRule_TaskStarted"]);
|
||||
}
|
||||
|
||||
var success = await _taskMedicalReviewRuleRepository.DeleteFromQueryAsync(t => t.Id == taskMedicalReviewRuleId,true);
|
||||
|
||||
@@ -10,6 +10,7 @@ using IRaCIS.Core.Application.Interfaces;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Infrastructure;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
|
||||
namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
@@ -82,7 +83,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
public async Task<PageOutput<GenerateMedicalReviewTaskView>> GetGenerateMedicalReviewTaskList(GenerateMedicalReviewTaskQuery inQuery)
|
||||
{
|
||||
var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||
.Where(t => t.IsAnalysisCreate == false && t.TaskState == TaskState.Effect && t.ReadingTaskState == ReadingTaskState.HaveSigned)
|
||||
.Where(t => t.IsAnalysisCreate == false && (t.TaskState == TaskState.Effect||t.TaskState==TaskState.Freeze) && t.ReadingTaskState == ReadingTaskState.HaveSigned)
|
||||
|
||||
.WhereIf(inQuery.SiteId != null, t => t.Subject.SiteId == inQuery.SiteId)
|
||||
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||
@@ -111,6 +112,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
public async Task<IResponseOutput> ManuallyGeneratedAndAssignedMedicalReview(ManuallyGeneratedAndAssignedMedicalReviewCommand command)
|
||||
{
|
||||
|
||||
@@ -125,6 +127,56 @@ namespace IRaCIS.Core.Application.Service
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一个医学审核任务
|
||||
/// </summary>
|
||||
/// <param name="inDto"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||
[HttpPost]
|
||||
public async Task<TaskMedicalReviewView> GetNextMedicalReviewTask(GetNextMedicalReviewTaskInDto inDto)
|
||||
{
|
||||
var medicalReview = await _taskMedicalReviewRepository.Where(x => x.Id == inDto.MedicalReviewId).Include(x=>x.VisitTask).FirstNotNullAsync();
|
||||
|
||||
var subjectReview = (await GetMIMMedicalReviewTaskList(new TaskMedicalReviewQuery()
|
||||
{
|
||||
|
||||
TrialId = medicalReview.TrialId,
|
||||
IsGetBeRead = true,
|
||||
Id=inDto.MedicalReviewId,
|
||||
SubjectId= medicalReview.VisitTask.SubjectId,
|
||||
TrialReadingCriterionId = medicalReview.VisitTask.TrialReadingCriterionId,
|
||||
PageIndex=1,
|
||||
PageSize=1,
|
||||
})).Data;
|
||||
|
||||
if (subjectReview.CurrentPageData.Count == 1)
|
||||
{
|
||||
return subjectReview.CurrentPageData[0];
|
||||
}
|
||||
|
||||
var data = (await GetMIMMedicalReviewTaskList(new TaskMedicalReviewQuery()
|
||||
{
|
||||
|
||||
TrialId = medicalReview.TrialId,
|
||||
IsGetBeRead = true,
|
||||
Id = inDto.MedicalReviewId,
|
||||
TrialReadingCriterionId = medicalReview.VisitTask.TrialReadingCriterionId,
|
||||
PageIndex = 1,
|
||||
PageSize = 1,
|
||||
})).Data;
|
||||
|
||||
if (data.CurrentPageData.Count == 1)
|
||||
{
|
||||
return data.CurrentPageData[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessValidationFailedException(_localizer["MedicalReview_Finish"]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -134,24 +186,27 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// <param name="inQuery"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<(PageOutput<TaskMedicalReviewView>, object)> GetMIMMedicalReviewTaskList(TaskMedicalReviewQuery inQuery)
|
||||
public async Task<IResponseOutput< PageOutput<TaskMedicalReviewView>>> GetMIMMedicalReviewTaskList(TaskMedicalReviewQuery inQuery)
|
||||
{
|
||||
|
||||
var taskMedicalReviewQueryable = _taskMedicalReviewRepository.Where(t => t.VisitTask.TrialId == inQuery.TrialId && t.MedicalManagerUserId == _userInfo.Id&&t.VisitTask.TrialReadingCriterionId==inQuery.TrialReadingCriterionId)
|
||||
|
||||
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
|
||||
.WhereIf(inQuery.SiteId != null, t => t.VisitTask.Subject.SiteId == inQuery.SiteId)
|
||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode))
|
||||
.WhereIf(inQuery.Id != null, t => t.Id != inQuery.Id)
|
||||
.WhereIf(inQuery.IsUrgent != null, t => t.VisitTask.IsUrgent == inQuery.IsUrgent)
|
||||
.WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState)
|
||||
.WhereIf(inQuery.TaskState != null, t => t.VisitTask.TaskState == inQuery.TaskState)
|
||||
.WhereIf(inQuery.DoctorUserId != null, t => t.VisitTask.DoctorUserId == inQuery.DoctorUserId)
|
||||
.WhereIf(inQuery.ReadingCategory != null, t => t.VisitTask.ReadingCategory == inQuery.ReadingCategory)
|
||||
.WhereIf(inQuery.ReadingTaskState != null, t => t.VisitTask.ReadingTaskState == inQuery.ReadingTaskState)
|
||||
|
||||
.WhereIf(inQuery.IsGetBeRead,x=>!x.IsInvalid&&x.AuditState!= MedicalReviewAuditState.HaveSigned)
|
||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||
.ProjectTo<TaskMedicalReviewView>(_mapper.ConfigurationProvider);
|
||||
|
||||
var pageList = await taskMedicalReviewQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(TaskMedicalReviewView.Id) : inQuery.SortField, inQuery.Asc);
|
||||
|
||||
return (pageList, new
|
||||
return ResponseOutput.Ok(pageList, new
|
||||
{
|
||||
|
||||
IsConfirmMedicineQuestion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inQuery.TrialReadingCriterionId).Select(x => x.IsConfirmMedicineQuestion).FirstOrDefaultAsync()
|
||||
@@ -170,7 +225,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
if (await _taskMedicalReviewRepository.Where(t => command.MedicalReviewIdList.Contains(t.Id)).AnyAsync(t => t.AuditState == MedicalReviewAuditState.HaveSigned))
|
||||
{
|
||||
return ResponseOutput.NotOk("已签名的不允许设置为失效");
|
||||
//"已签名的不允许设置为失效"
|
||||
return ResponseOutput.NotOk(_localizer["TaskMedical_DirtyData"]);
|
||||
}
|
||||
|
||||
await _taskMedicalReviewRepository.UpdatePartialFromQueryAsync(t => command.MedicalReviewIdList.Contains(t.Id), c => new TaskMedicalReview() { IsInvalid = true },true);
|
||||
@@ -190,6 +246,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
/// <returns></returns>
|
||||
[UnitOfWork]
|
||||
[HttpPost]
|
||||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||||
|
||||
public async Task<IResponseOutput> AssignMedicalReviewTask(AssignMedicalReviewTaskCommand command)
|
||||
{
|
||||
|
||||
@@ -201,7 +259,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
{
|
||||
if (task.MedicalManagerUserId != null && task.MedicalManagerUserId != command.MedicalManagerUserId)
|
||||
{
|
||||
throw new BusinessValidationFailedException("当前有任务已分配给其他人,不允许分配,请刷新列表");
|
||||
//"当前有任务已分配给其他人,不允许分配,请刷新列表"
|
||||
throw new BusinessValidationFailedException(_localizer["TaskMedical_SubjectInOtherArm"]);
|
||||
}
|
||||
|
||||
task.MedicalManagerUserId = command.MedicalManagerUserId;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -12,100 +12,44 @@ namespace IRaCIS.Core.Application.Service
|
||||
public AllocationConfig()
|
||||
{
|
||||
|
||||
CreateMap<ReadingTableAnswerRowInfo, ConvertedRowInfo>()
|
||||
.ForMember(d => d.OriginalId, u => u.MapFrom(s => s.Id));
|
||||
|
||||
CreateMap<ConvertedRowInfo, ReadingTableAnswerRowInfo>();
|
||||
|
||||
|
||||
CreateMap<TaskAllocationRule, TaskAllocationRuleView>()
|
||||
.ForMember(o => o.UserCode, t => t.MapFrom(u => u.DoctorUser.UserCode))
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName))
|
||||
.ForMember(o => o.UserTypeShortName, t => t.MapFrom(u => u.DoctorUser.UserTypeRole.UserTypeShortName));
|
||||
|
||||
List<Guid> subjectIdList = new List<Guid>();
|
||||
bool isJudgeDoctor = false;
|
||||
|
||||
|
||||
CreateMap<TaskAllocationRule, DoctorVisitTaskStatView>()
|
||||
.ForMember(o => o.UserCode, t => t.MapFrom(u => u.DoctorUser.UserCode))
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName))
|
||||
.ForMember(o => o.UserTypeShortName, t => t.MapFrom(u => u.DoctorUser.UserTypeRole.UserTypeShortName))
|
||||
//.ForMember(o => o.ArmList, t => t.MapFrom(u => u.DoctorVisitTaskList.Where(c => c.TrialId == u.TrialId).Select(t => t.ArmEnum).Distinct()))
|
||||
.ForMember(o => o.TotalTaskCount, t => t.MapFrom(u => u.Trial.VisitTaskList.Count()))
|
||||
.ForMember(o => o.SelfUndoTaskCount, t => t.MapFrom(u => u.Trial.VisitTaskList.Count(t => t.DoctorUserId == u.DoctorUserId && t.ReadingTaskState != ReadingTaskState.HaveSigned)))
|
||||
.ForMember(o => o.TotalSubjectCount, t => t.MapFrom(u => u.Trial.SubjectList.Count()))
|
||||
.ForMember(o => o.SelfApplyedTaskCount, t => t.MapFrom(u => u.Trial.VisitTaskList.Count(t => t.DoctorUserId == u.DoctorUserId)))
|
||||
.ForMember(o => o.ApplyedTotalTaskCount, t => t.MapFrom(u => u.Trial.VisitTaskList.Count(t => t.DoctorUserId != null)))
|
||||
|
||||
//.ForMember(o => o.SelfApplyedSubjectCount, t => t.MapFrom(u => u.Trial.SubjectDoctorUserList.Where(t => t.DoctorUserId == u.DoctorUserId && t.SubjectArmVisitTaskList.Any(c => c.DoctorUserId != null)).Count()))
|
||||
.ForMember(o => o.SelfSubjectCount, t => t.MapFrom(u => u.Trial.SubjectDoctorUserList.Where(t => t.DoctorUserId == u.DoctorUserId).Count()))
|
||||
|
||||
.ForMember(o => o.ApplyedTotalSubjectCount, t => t.MapFrom(u => u.Trial.SubjectList.Count(c => c.SubjectVisitTaskList.Any(d => d.DoctorUserId != null))))
|
||||
|
||||
|
||||
|
||||
//该医生未应用Subject 数量
|
||||
//.ForMember(o => o.WaitApplySelfSubjectCount, t => t.MapFrom(u =>
|
||||
// subjectIdList.Count == 0 ? u.Trial.SubjectDoctorUserList.Where(t => t.DoctorUserId == u.DoctorUserId && t.SubjectArmVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Any(c => c.DoctorUserId == null)).Count()
|
||||
// : u.Trial.SubjectDoctorUserList.Where(t => t.DoctorUserId == u.DoctorUserId && subjectIdList.Contains(t.SubjectId) && t.SubjectArmVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Any(c => c.DoctorUserId == null)).Count()
|
||||
// ))
|
||||
|
||||
|
||||
.ForMember(o => o.WaitApplyTotalSubjectCount, t => t.MapFrom(u =>
|
||||
subjectIdList.Count == 0 ? u.Trial.SubjectList.Where(t => t.SubjectVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Any(c => c.DoctorUserId == null)).Count()
|
||||
: u.Trial.SubjectList.Where(t => subjectIdList.Contains(t.Id) && t.SubjectVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Any(c => c.DoctorUserId == null)).Count()
|
||||
))
|
||||
|
||||
//.ForMember(o => o.WaitApplySelfTaskCount, t => t.MapFrom(u =>
|
||||
//subjectIdList.Count == 0 ? u.Trial.SubjectDoctorUserList.Where(d => d.DoctorUserId == u.DoctorUserId).SelectMany(t => t.SubjectArmVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Where(t => t.DoctorUserId == null)).Count()
|
||||
//: u.Trial.SubjectDoctorUserList.Where(d => d.DoctorUserId == u.DoctorUserId && subjectIdList.Contains(d.SubjectId)).SelectMany(t => t.SubjectArmVisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Where(t => t.DoctorUserId == null)).Count()
|
||||
// ))
|
||||
|
||||
.ForMember(o => o.WaitApplyTotalTaskCount, t => t.MapFrom(u =>
|
||||
subjectIdList.Count == 0 ? u.Trial.VisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Where(t => t.DoctorUserId == null).Count()
|
||||
: u.Trial.VisitTaskList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Where(t => t.DoctorUserId == null && subjectIdList.Contains(t.SubjectId)).Count()))
|
||||
|
||||
;
|
||||
|
||||
var trialReadingCriterionId = Guid.Empty;
|
||||
CreateMap<TaskAllocationRule, TaskAllocationRuleDTO>()
|
||||
.ForMember(o => o.DoctorUser, t => t.MapFrom(u => u.Enroll.DoctorUser))
|
||||
.ForMember(o => o.CriterionReadingCategoryList, t => t.MapFrom(u => u.Enroll.EnrollReadingCategoryList.Select(t => new TrialCriterionReadingCategory() { EnrollId = t.EnrollId, ReadingCategory = t.ReadingCategory, TrialReadingCriterionId = t.TrialReadingCriterionId })))
|
||||
.ForMember(o => o.TrialReadingCriterionList, t => t.MapFrom(u => u.Trial.ReadingQuestionCriterionTrialList.Where(t => t.IsConfirm)))
|
||||
.ForMember(o => o.ReadingCategoryList, t => t.MapFrom(u => u.Enroll.EnrollReadingCategoryList.Where(t=>t.TrialReadingCriterionId== trialReadingCriterionId).OrderBy(t => t.ReadingCategory).Select(t => t.ReadingCategory).ToList()))
|
||||
;
|
||||
|
||||
CreateMap<ReadingQuestionCriterionTrial, TrialReadingCriterionDto>()
|
||||
.ForMember(t => t.TrialReadingCriterionId, u => u.MapFrom(c => c.Id))
|
||||
.ForMember(t => t.TrialReadingCriterionName, u => u.MapFrom(c => c.CriterionName));
|
||||
|
||||
CreateMap<TaskAllocationRule, AssignDoctorStatView>().IncludeBase<TaskAllocationRule, TaskAllocationRuleDTO>()
|
||||
.ForMember(o => o.AssignedSubjectCount, t => t.MapFrom(u => u.DoctorUser.VisitTaskList.Where(t => t.TrialId == u.TrialId).Select(t => t.SubjectId).Distinct().Count()))
|
||||
.ForMember(o => o.WaitDealTrialTaskCount, t => t.MapFrom(u => u.DoctorUser.VisitTaskList.Where(t => t.TrialId == u.TrialId).Where(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect).Count()))
|
||||
.ForMember(o => o.WaitDealAllTaskCount, t => t.MapFrom(u => u.DoctorUser.VisitTaskList.Where(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.TaskState == TaskState.Effect).Count()));
|
||||
|
||||
|
||||
CreateMap<Subject, SubjectAssignStat>()
|
||||
|
||||
.ForMember(o => o.SubjectId, t => t.MapFrom(u => u.Id))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Code))
|
||||
.ForMember(o => o.VisitTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Visit && t.TrialReadingCriterionId==trialReadingCriterionId && t.TaskState==TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()))
|
||||
.ForMember(o => o.VisitTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Visit && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()))
|
||||
.ForMember(o => o.GlobalTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Global && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()))
|
||||
.ForMember(o => o.OncologyTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Oncology && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()))
|
||||
.ForMember(o => o.JudgeTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Judge && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()))
|
||||
.ForMember(o => o.DoctorUserList, t => t.MapFrom(u => u.SubjectDoctorList.Where(t=>t.TrialReadingCriterionId== trialReadingCriterionId)));
|
||||
|
||||
CreateMap<SubjectUser, SubjectUserView>()
|
||||
.ForMember(o => o.DoctorUser, t => t.MapFrom(u => u.DoctorUser));
|
||||
.ForMember(o => o.JudgeTaskTypeCount, t => t.MapFrom(u => u.SubjectVisitTaskList.Where(t => t.ReadingCategory == ReadingCategory.Judge && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect).Select(t => t.VisitTaskNum).Distinct().Count()));
|
||||
|
||||
|
||||
CreateMap<SubjectUser, SubjectUserDTO>().IncludeBase<SubjectUser, SubjectUserView>()
|
||||
.ForMember(o => o.IsHaveReading, t => t.MapFrom(u => u.Subject.SubjectVisitTaskList.Any(t => t.ReadingTaskState != ReadingTaskState.WaitReading && t.TrialReadingCriterionId==u.TrialReadingCriterionId)));
|
||||
|
||||
|
||||
|
||||
CreateMap<SubjectVisitClinicalDialog, ClinicalDataDialog>();
|
||||
|
||||
|
||||
CreateMap<SubjectVisit, VisitGenerataTaskDTO>();
|
||||
|
||||
|
||||
CreateMap<VisitTask, VisitTaskViewBasic>()
|
||||
.ForMember(o => o.IsAutoCreate, t => t.MapFrom(u => u.TrialReadingCriterion.IsAutoCreate))
|
||||
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName))
|
||||
.ForMember(o => o.ReadingTool, t => t.MapFrom(u => u.TrialReadingCriterion.ReadingTool))
|
||||
.ForMember(o => o.IsReadingTaskViewInOrder, t => t.MapFrom(u => u.TrialReadingCriterion.IsReadingTaskViewInOrder))
|
||||
@@ -125,11 +69,12 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName))
|
||||
.ForMember(o => o.UserTypeShortName, t => t.MapFrom(u => u.DoctorUser.UserTypeRole.UserTypeShortName))
|
||||
.ForMember(o => o.IsClinicalDataSigned, t => t.MapFrom(u => u.Subject.ClinicalDataList.Any(c => c.IsSign && (c.ReadingId == u.SouceReadModuleId || c.ReadingId == u.SourceSubjectVisitId))))
|
||||
;
|
||||
|
||||
.ForMember(o => o.IsBaseline, t => t.MapFrom(u => u.SourceSubjectVisit.IsBaseLine))
|
||||
.ForMember(o => o.IsEnrollmentConfirm, t => t.MapFrom(u => u.SourceSubjectVisit.IsEnrollmentConfirm))
|
||||
.ForMember(o => o.PDState, t => t.MapFrom(u => u.SourceSubjectVisit.PDState)) ;
|
||||
|
||||
|
||||
var isEn_Us = true;
|
||||
|
||||
CreateMap<VisitTask, JudgeVisitTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
||||
|
||||
@@ -137,17 +82,19 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList));
|
||||
|
||||
CreateMap<VisitTask, ReadingTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
||||
.ForMember(t=>t.PIReadingResultList,u=>u.MapFrom(c=>c.ReadingTaskQuestionAnswerList
|
||||
.Where(t=>t.ReadingQuestionTrial.IsJudgeQuestion==true ).Select(d=>new PIReadingResult() { QuestionId= d.ReadingQuestionTrialId,Answer=d.Answer})));
|
||||
|
||||
;
|
||||
CreateMap<VisitTask, PIReaingTaskView>().IncludeBase<VisitTask, ReadingTaskView>()
|
||||
.ForMember(o => o.FirstAuditUserName, t => t.MapFrom(u => u.FirstAuditUser.UserName))
|
||||
.ForMember(o => o.LatestReplyUserName, t => t.MapFrom(u => u.LatestReplyUser.UserName));
|
||||
|
||||
CreateMap<VisitTask, AnalysisTaskView>().IncludeBase<VisitTask, VisitTaskView>()
|
||||
.ForMember(o => o.IsReReadingOrBackInfluenceAnalysis, t => t.MapFrom(u => u.Subject.IsReReadingOrBackInfluenceAnalysis));
|
||||
|
||||
|
||||
|
||||
CreateMap<CancelDoctorCommand, SubjectCanceDoctor>();
|
||||
|
||||
CreateMap<SubjectCanceDoctor, SubjectCancelDoctorView>();
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -163,7 +110,9 @@ namespace IRaCIS.Core.Application.Service
|
||||
CreateMap<VisitTask, IRHaveReadView>().IncludeBase<VisitTask, VisitTaskViewBasic>()
|
||||
.ForMember(o => o.SiteId, t => t.MapFrom(u => u.Subject.SiteId))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindTrialSiteCode : u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code));
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName));
|
||||
|
||||
|
||||
|
||||
@@ -180,22 +129,17 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.SubjectId, t => t.MapFrom(u => u.Id))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Code))
|
||||
.ForMember(o => o.IsJudge, t => t.MapFrom(u => isJudgeDoctor))
|
||||
.ForMember(o => o.IsAssignedDoctorUser, t => t.MapFrom(u => u.SubjectDoctorList.Where(t => isJudgeDoctor ? t.ArmEnum == Arm.JudgeArm : t.ArmEnum != Arm.JudgeArm).Any()))
|
||||
.ForMember(o => o.IsJudge, t => t.MapFrom(u => isJudgeDoctor));
|
||||
|
||||
|
||||
|
||||
.ForMember(o => o.TotalDoctorUserList, t => t.MapFrom(u => u.SubjectDoctorList.Where(t => isJudgeDoctor ? true : t.ArmEnum != Arm.JudgeArm).OrderBy(t => t.ArmEnum)));
|
||||
|
||||
CreateMap<SubjectUser, AssignDoctorView>()
|
||||
//.ForMember(o => o.AssignTime, t => t.MapFrom(u => u.AssignTime))
|
||||
.ForMember(o => o.UserCode, t => t.MapFrom(u => u.DoctorUser.UserCode))
|
||||
.ForMember(o => o.UserName, t => t.MapFrom(u => u.DoctorUser.UserName))
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.DoctorUser.FullName))
|
||||
.ForMember(o => o.UserTypeShortName, t => t.MapFrom(u => u.DoctorUser.UserTypeRole.UserTypeShortName));
|
||||
|
||||
|
||||
|
||||
|
||||
CreateMap<TaskAllocationRuleAddOrEdit, TaskAllocationRule>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CreateMap<User, TrialDoctorUserSelectView>()
|
||||
@@ -203,6 +147,7 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.FullName, t => t.MapFrom(u => u.FullName));
|
||||
|
||||
CreateMap<TaskMedicalReview, TaskMedicalReviewView>().IncludeMembers(t => t.VisitTask)
|
||||
.ForMember(o => o.IsAutoCreate, t => t.MapFrom(u => u.VisitTask.TrialReadingCriterion.IsAutoCreate))
|
||||
.ForMember(o => o.TrialReadingCriterionId, t => t.MapFrom(u => u.VisitTask.TrialReadingCriterion.Id))
|
||||
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.VisitTask.TrialReadingCriterion.CriterionName))
|
||||
.ForMember(o => o.ReadingTool, t => t.MapFrom(u => u.VisitTask.TrialReadingCriterion.ReadingTool))
|
||||
@@ -282,11 +227,6 @@ namespace IRaCIS.Core.Application.Service
|
||||
//CreateMap<TaskConsistentRule, TaskConsistentRuleView>()
|
||||
// .ForMember(o => o.GeneratedSubjectCount, t => t.MapFrom(u => u.DoctorVisitTaskList.Where(t => t.IsAnalysisCreate && t.TaskConsistentRuleId == u.Id).Select(t => t.SubjectId).Distinct().Count())) ;
|
||||
|
||||
CreateMap<TaskConsistentRule, TaskConsistentRuleBasic>();
|
||||
|
||||
CreateMap<TaskConsistentRuleAddOrEdit, TaskConsistentRule>();
|
||||
|
||||
CreateMap<TaskConsistentRuleBatchAddOrEdit, TaskConsistentRule>().ForMember(t => t.Id, u => u.Ignore()).ReverseMap();
|
||||
|
||||
|
||||
CreateMap<VisitTask, VisitTaskSimpleView>()
|
||||
@@ -296,8 +236,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
CreateMap<VisitTask, InfluenceTaskInfo>()
|
||||
.ForMember(o => o.TrialReadingCriterionName, t => t.MapFrom(u => u.TrialReadingCriterion.CriterionName))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.Subject.Code))
|
||||
.ForMember(o => o.TrialSiteCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindTrialSiteCode : u.Subject.TrialSite.TrialSiteCode))
|
||||
.ForMember(o => o.SubjectCode, t => t.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
|
||||
.ForMember(o => o.OptType, t => t.Ignore());
|
||||
|
||||
|
||||
@@ -306,8 +246,15 @@ namespace IRaCIS.Core.Application.Service
|
||||
.ForMember(o => o.Id, t => t.MapFrom(u => u.InfluenceTask.Id));
|
||||
|
||||
|
||||
CreateMap<PIAuditTaskCommand, PIAudit>();
|
||||
|
||||
CreateMap<PIAudit, PIAuditDialogListView>()
|
||||
.ForMember(o => o.CreateUserName, t => t.MapFrom(u => u.CreateUser.UserName))
|
||||
.ForMember(o => o.UserTypeEnum, t => t.MapFrom(u => u.CreateUser.UserTypeEnum))
|
||||
.ForMember(o => o.PIAuditState, t => t.MapFrom(u => u.VisitTask.PIAuditState))
|
||||
;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//--------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------
|
||||
// 此代码由T4模板自动生成 byzhouhang 20210918
|
||||
// 生成时间 2022-03-31 13:18:56
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||
@@ -49,7 +49,8 @@ namespace IRaCIS.Core.Application.Service
|
||||
var verifyExp1 = new EntityVerifyExp<CommonDocument>()
|
||||
{
|
||||
VerifyExp = t => t.Code == addOrEditCommonDocument.Code,
|
||||
VerifyMsg = "文档的Code不能够重复。"
|
||||
//---文档的Code不能够重复。
|
||||
VerifyMsg = _localizer["Document_CodeDuplication"]
|
||||
};
|
||||
|
||||
//var verifyExp3 = new EntityVerifyExp<CommonDocument>()
|
||||
@@ -61,10 +62,11 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
var verifyExp2 = new EntityVerifyExp<CommonDocument>()
|
||||
{
|
||||
VerifyExp = t => t.CriterionTypeEnum == addOrEditCommonDocument.CriterionTypeEnum && t.BusinessScenarioEnum==addOrEditCommonDocument.BusinessScenarioEnum &&
|
||||
t.IsDeleted==addOrEditCommonDocument.IsDeleted,
|
||||
VerifyMsg = "一个场景一个标准只允许有一个模板文档",
|
||||
IsVerify=addOrEditCommonDocument.CriterionTypeEnum !=null && addOrEditCommonDocument.IsDeleted==false
|
||||
VerifyExp = t => t.CriterionTypeEnum == addOrEditCommonDocument.CriterionTypeEnum && t.BusinessScenarioEnum == addOrEditCommonDocument.BusinessScenarioEnum &&
|
||||
t.IsDeleted == addOrEditCommonDocument.IsDeleted,
|
||||
//---一个场景一个标准只允许有一个模板文档
|
||||
VerifyMsg = _localizer["Document_SingleTemplate"],
|
||||
IsVerify = addOrEditCommonDocument.CriterionTypeEnum != null && addOrEditCommonDocument.IsDeleted == false
|
||||
};
|
||||
|
||||
|
||||
@@ -91,10 +93,11 @@ namespace IRaCIS.Core.Application.Service
|
||||
|
||||
|
||||
}
|
||||
catch (Exception )
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return ResponseOutput.NotOk("读取模板内容失败, 请将文件另存为docx格式尝试!");
|
||||
//---读取模板内容失败, 请将文件另存为docx格式尝试!
|
||||
return ResponseOutput.NotOk(_localizer["Document_ TemplateRead"]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user