Compare commits
1789 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71e28f1a37 | |||
| 375e50bab7 | |||
| 39e2651edf | |||
| b461216d87 | |||
| dc6ae39130 | |||
| 4b65f1e922 | |||
| 99439a4809 | |||
| 419d5de7f1 | |||
| a56ffaee58 | |||
| e925d5bdb2 | |||
| 9ec97f7d37 | |||
| 3c532389d9 | |||
| 1094f318f9 | |||
| 56f261b8ce | |||
| 34b12b89e4 | |||
| bca8f2ddb9 | |||
| 4023a59097 | |||
| 8afcbf3d5e | |||
| 69c2cd339c | |||
| 4c7ce217da | |||
| d66209452c | |||
| 77352245fc | |||
| 17ebdce96e | |||
| 3962178c68 | |||
| 7c6dcbbe38 | |||
| 75ed6375c2 | |||
| 290578d824 | |||
| cd2f5aa1e1 | |||
| 79d150829a | |||
| 270de86658 | |||
| edefc8f3e7 | |||
| f1b3ec7d7c | |||
| 5171af975d | |||
| 33b9113993 | |||
| a53626b66c | |||
| a27dcd6399 | |||
| 14908c4eed | |||
| dfef88d663 | |||
| 1afe020e83 | |||
| 7544e0c2e9 | |||
| 68d72fce53 | |||
| 423f2fcb7c | |||
| 92b715de3a | |||
| 912bc2edb8 | |||
| a5f6c24aec | |||
| 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();
|
||||
@@ -169,6 +134,51 @@ namespace IRaCIS.Api.Controllers
|
||||
return returnModel;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[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")]
|
||||
@@ -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,31 +66,28 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
|
||||
<PackageReference Include="aliyun-net-sdk-sts" Version="3.1.2" />
|
||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||
<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="EasyCaching.Interceptor.Castle" Version="1.9.1" />
|
||||
<PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.9.1" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.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="Serilog.AspNetCore" Version="6.0.1" />
|
||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.23" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.2" />
|
||||
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.7.0" />
|
||||
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.7.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Email" Version="2.4.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.4.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-14
@@ -23,6 +23,13 @@ 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;
|
||||
using EasyCaching.Core;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -82,15 +89,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"));
|
||||
|
||||
|
||||
@@ -108,14 +113,15 @@ namespace IRaCIS.Core.API
|
||||
//JWT Token 验证
|
||||
services.AddJWTAuthSetup(_configuration);
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
|
||||
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||
// EasyCaching 缓存
|
||||
services.AddEasyCachingSetup();
|
||||
services.AddEasyCachingSetup(_configuration);
|
||||
|
||||
//services.AddDistributedMemoryCache();
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
services.AddhangfireSetup(_configuration);
|
||||
|
||||
// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
|
||||
services.AddQuartZSetup(_configuration);
|
||||
|
||||
@@ -137,7 +143,7 @@ namespace IRaCIS.Core.API
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
services.AddAuthorizationPolicySetup(_configuration);
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
|
||||
services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
@@ -162,8 +168,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 +187,7 @@ namespace IRaCIS.Core.API
|
||||
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
app.UseLogDashboard("/back/logs");
|
||||
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
@@ -218,8 +226,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 +237,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>();
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
using IRaCIS.Core.Application.Triggers;
|
||||
using Hangfire.SqlServer;
|
||||
using IRaCIS.Core.Application.Triggers;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using Medallion.Threading;
|
||||
using Medallion.Threading.SqlServer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
@@ -37,17 +41,28 @@ 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>();
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
//注意区分 easy caching 也有 IDistributedLockProvider
|
||||
services.AddSingleton<IDistributedLockProvider>(sp =>
|
||||
{
|
||||
//var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
|
||||
|
||||
return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value);
|
||||
});
|
||||
|
||||
//services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
using EasyCaching.Core;
|
||||
using EasyCaching.Core.Configurations;
|
||||
using EasyCaching.Interceptor.Castle;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class EasyCachingSetup
|
||||
{
|
||||
public static void AddEasyCachingSetup(this IServiceCollection services)
|
||||
public static void AddEasyCachingSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddEasyCaching(options =>
|
||||
{
|
||||
options.UseInMemory();
|
||||
|
||||
//options.UseRedis(configuration, EasyCachingConstValue.DefaultRedisName).WithMessagePack(EasyCachingConstValue.DefaultRedisName);
|
||||
|
||||
|
||||
});
|
||||
|
||||
//services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultRedisName);
|
||||
|
||||
services.ConfigureCastleInterceptor(options => options.CacheProviderName = EasyCachingConstValue.DefaultInMemoryName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace IRaCIS.Core.API
|
||||
.MinimumLevel.Override("Hangfire", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System.Net.Http.HttpClient.HttpReports", LogEventLevel.Warning)
|
||||
.Enrich.WithClientIp()
|
||||
.Enrich.WithClientAgent()
|
||||
|
||||
.Enrich.FromLogContext()
|
||||
|
||||
//控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型
|
||||
@@ -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,55 +0,0 @@
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class JsonPatchDocumentFilter : IDocumentFilter
|
||||
{
|
||||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
||||
{
|
||||
var schemas = swaggerDoc.Components.Schemas.ToList();
|
||||
foreach (var item in schemas)
|
||||
{
|
||||
if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
|
||||
swaggerDoc.Components.Schemas.Remove(item.Key);
|
||||
}
|
||||
|
||||
swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema
|
||||
{
|
||||
Type = "object",
|
||||
Properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{ "op", new OpenApiSchema { Type = "string" } },
|
||||
{"value", new OpenApiSchema{ Type = "object", Nullable = true } },
|
||||
{ "path", new OpenApiSchema { Type = "string" } }
|
||||
}
|
||||
});
|
||||
|
||||
swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema
|
||||
{
|
||||
Type = "array",
|
||||
Items = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" }
|
||||
},
|
||||
Description = "Array of operations to perform"
|
||||
});
|
||||
|
||||
foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
|
||||
.Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
|
||||
{
|
||||
foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
|
||||
path.Value.RequestBody.Content.Remove(item.Key);
|
||||
|
||||
var response = path.Value.RequestBody.Content.SingleOrDefault(c => c.Key == "application/json-patch+json");
|
||||
|
||||
response.Value.Schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ namespace IRaCIS.Core.API
|
||||
{
|
||||
public static void AddSwaggerSetup(this IServiceCollection services)
|
||||
{
|
||||
services.AddSwaggerExamplesFromAssemblyOf<JsonPatchUserRequestExample>();
|
||||
|
||||
services.AddSwaggerGen(options =>
|
||||
{
|
||||
@@ -63,7 +62,6 @@ namespace IRaCIS.Core.API
|
||||
// 在header中添加token,传递到后台
|
||||
options.OperationFilter<SecurityRequirementsOperationFilter>();
|
||||
|
||||
options.DocumentFilter<JsonPatchDocumentFilter>();
|
||||
|
||||
// 添加登录按钮
|
||||
options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Hangfire;
|
||||
using Hangfire.SqlServer;
|
||||
using Hangfire.Tags.SqlServer;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public static class hangfireSetup
|
||||
public static class hangfireSetup
|
||||
{
|
||||
public static void AddhangfireSetup(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
@@ -15,24 +14,29 @@ namespace IRaCIS.Core.API
|
||||
|
||||
services.AddHangfire(hangFireConfig =>
|
||||
{
|
||||
|
||||
//hangFireConfig.UseInMemoryStorage();
|
||||
|
||||
//指定存储介质
|
||||
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
|
||||
{
|
||||
SchemaName = "hangfire",
|
||||
SchemaName = "dbo",
|
||||
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
|
||||
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
|
||||
QueuePollInterval = TimeSpan.Zero,
|
||||
UseRecommendedIsolationLevel = true,
|
||||
UsePageLocksOnDequeue = true,
|
||||
DisableGlobalLocks = true
|
||||
});
|
||||
|
||||
hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
||||
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
|
||||
//.UseHangfireHttpJob();
|
||||
|
||||
});
|
||||
|
||||
services.AddHangfireServer();
|
||||
services.AddHangfireServer(option =>
|
||||
{
|
||||
option.Queues = new[] { "immediately_once","default","sys_init" , "not_immediately_once" };
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,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": true,
|
||||
|
||||
"OpenSignDocumentBeforeWork": true,
|
||||
|
||||
"OpenTrialRelationDelete": true,
|
||||
|
||||
"OpenLoginLimit": true,
|
||||
"LoginMaxFailCount": 5,
|
||||
|
||||
"LoginFailLockMinutes": 30
|
||||
|
||||
},
|
||||
|
||||
"SystemEmailSendConfig": {
|
||||
"Port": 465,
|
||||
"Host": "smtp.qiye.aliyun.com",
|
||||
"FromEmail": "study@extimaging.com",
|
||||
"FromName": "研究单位阅片系统",
|
||||
"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,
|
||||
@@ -61,34 +57,42 @@
|
||||
"EnableReadDeepClone": true,
|
||||
"EnableWriteDeepClone": false
|
||||
}
|
||||
},
|
||||
"redis": {
|
||||
"MaxRdSecond": 120,
|
||||
"EnableLogging": false,
|
||||
"LockMs": 5000,
|
||||
"SleepMs": 300,
|
||||
"dbconfig": {
|
||||
"Password": "xc@123456",
|
||||
"IsSsl": false,
|
||||
"SslHost": null,
|
||||
"ConnectionTimeout": 5000,
|
||||
"AllowAdmin": true,
|
||||
"Endpoints": [
|
||||
{
|
||||
"Host": "47.117.164.182",
|
||||
"Port": 6379
|
||||
}
|
||||
],
|
||||
"Database": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"IRaCISImageStore": {
|
||||
"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; }
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<NoWarn>1701;1702;1591;1587</NoWarn>
|
||||
<NoWarn>1701;1702;1591;1587</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<Using Include="IRaCIS.Core.Application;" />
|
||||
<Using Include="IRaCIS.Core.Application;" />
|
||||
<Using Include="AutoMapper.QueryableExtensions;" />
|
||||
<Using Include="Microsoft.EntityFrameworkCore;" />
|
||||
<Using Include="IRaCIS.Core.Domain.Models;" />
|
||||
@@ -50,60 +50,56 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Resources\zh-CN.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\en-US.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\zh-CN.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<Content Include="Resources\en-US.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Collection.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="BeetleX.BNR" Version="1.0.1" />
|
||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
|
||||
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
|
||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.3" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="1.9.1" />
|
||||
<PackageReference Include="EasyCaching.Redis" Version="1.9.1" />
|
||||
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.7.0" />
|
||||
<PackageReference Include="EasyCaching.Interceptor.AspectCore" Version="1.9.1" />
|
||||
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
|
||||
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.1.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
<PackageReference Include="fo-dicom" Version="5.1.1" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.1.0" />
|
||||
<PackageReference Include="fo-dicom.Codecs" Version="5.10.8" />
|
||||
<PackageReference Include="FreeSpire.Doc" Version="11.6.0" />
|
||||
<PackageReference Include="Hangfire.Core" Version="1.8.5" />
|
||||
<PackageReference Include="Magicodes.IE.Core" Version="2.7.4.5" />
|
||||
<PackageReference Include="Magicodes.IE.Csv" Version="2.7.4.5">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="fo-dicom.Drawing" Version="4.0.8" />
|
||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.0.3" />
|
||||
<PackageReference Include="Hangfire" Version="1.7.31">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
<PackageReference Include="Magicodes.IE.Excel" Version="2.7.4.5">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Magicodes.IE.Core" Version="2.6.9" />
|
||||
<PackageReference Include="Magicodes.IE.Csv" Version="2.6.9">
|
||||
<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="MailKit" Version="3.4.2" />
|
||||
<PackageReference Include="MediatR" Version="11.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MimeKit" Version="3.4.2" />
|
||||
<PackageReference Include="MiniExcel" Version="1.28.1" />
|
||||
<PackageReference Include="MiniWord" Version="0.6.1" />
|
||||
<PackageReference Include="Magicodes.IE.Excel.AspNetCore" Version="2.7.4.5" />
|
||||
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||
<PackageReference Include="MediatR" Version="12.1.1" />
|
||||
<PackageReference Include="MimeKit" Version="4.2.0" />
|
||||
<PackageReference Include="MiniExcel" Version="1.31.2" />
|
||||
<PackageReference Include="MiniWord" Version="0.7.0" />
|
||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.0.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
||||
<PackageReference Include="NPOI" Version="2.6.0" />
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.0" />
|
||||
<PackageReference Include="Quartz" Version="3.5.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
|
||||
<PackageReference Include="WinSCP" Version="5.21.5" />
|
||||
<PackageReference Include="NPOI" Version="2.6.2" />
|
||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.1" />
|
||||
<PackageReference Include="Quartz" Version="3.7.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.11" />
|
||||
<PackageReference Include="WinSCP" Version="6.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
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,106 @@ 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
|
||||
{
|
||||
|
||||
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 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 +536,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 +855,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 +917,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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user