Compare commits
675 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b21ef4f14 | |||
| 1e2869abb5 | |||
| 8bd46c6c18 | |||
| f7b4382a62 | |||
| 63d3ca4971 | |||
| 29518ddea6 | |||
| 20dd2ffd5d | |||
| e406511755 | |||
| e4abc61456 | |||
| c0c4df1254 | |||
| cc826afff1 | |||
| 53c18c4c4c | |||
| 0c9f29d3b4 | |||
| 14f03facd2 | |||
| b469be1b14 | |||
| c3e5b0c4b8 | |||
| 5ee992efb4 | |||
| 44b28f2d0a | |||
| b1db5bebd3 | |||
| 3f3caaaffe | |||
| b3d5b5f75e | |||
| ee5708f905 | |||
| 140a7bb3fd | |||
| 65ac1498b1 | |||
| 0f15eaabff | |||
| 54c8f71af7 | |||
| b31178c0c0 | |||
| 0af6919b5a | |||
| 393c915884 | |||
| ed274d2812 | |||
| 072e076bea | |||
| d6b5badccd | |||
| d237da548f | |||
| dee6bebcb7 | |||
| 40a98048bb | |||
| 1ea978eccd | |||
| bc8aeb8d7c | |||
| c35ec016dd | |||
| 283524cb4f | |||
| 10c9f6b8cc | |||
| e291953d09 | |||
| 1094c8ce2a | |||
| 747bb29729 | |||
| 4cab822a52 | |||
| adaa085e56 | |||
| 1f97243482 | |||
| b272a748ec | |||
| b121db89f0 | |||
| 35e6a47f2d | |||
| afeebf662b | |||
| 23ae346cee | |||
| d52c23b5c4 | |||
| 70e851e10d | |||
| a371db7522 | |||
| b755d12d7c | |||
| 30e3a363a8 | |||
| 6f692c34c2 | |||
| 6dac36ba1a | |||
| 2623a42ea7 | |||
| 8613c0a064 | |||
| e159f8a82b | |||
| 416793018f | |||
| c714a81edf | |||
| d9b5298572 | |||
| 38ec3d55ae | |||
| 046715fd07 | |||
| 07bd02d3c8 | |||
| b6ad1722f6 | |||
| 240b8218f0 | |||
| 8345b5b47d | |||
| 54f6fc1b12 | |||
| 2b59cb5d02 | |||
| d9d0ceac76 | |||
| 35400b4952 | |||
| 1d33619a85 | |||
| a4f3c4bb81 | |||
| 166c5f3f9c | |||
| 54c7e6cc7c | |||
| 859c9e4161 | |||
| b33fb79718 | |||
| 24faa2d887 | |||
| e9d3dda160 | |||
| 53ad439257 | |||
| d577410bb4 | |||
| df0e4ddcfa | |||
| 9948ea8df3 | |||
| 763220dcef | |||
| 208dab27dc | |||
| 3c816e989e | |||
| c44c333997 | |||
| 5fc700123f | |||
| 49437034a3 | |||
| 74486c8e30 | |||
| d6fc7f7911 | |||
| 2b5066f967 | |||
| a577589a92 | |||
| 62f02528c2 | |||
| 5b950914e3 | |||
| 99942982f6 | |||
| 18e9005c3d | |||
| d9f6dd22e1 | |||
| f5579c3deb | |||
| 60c0c66d22 | |||
| a2c17da35e | |||
| 20f46f2dab | |||
| cbf63c0f9c | |||
| f3db7525f9 | |||
| 694325e6b9 | |||
| 138702f077 | |||
| a739f856b4 | |||
| 68af0578d0 | |||
| 9042017a90 | |||
| 59b053faa9 | |||
| 63b9f4e775 | |||
| efe2e7f063 | |||
| 19b1d022e0 | |||
| 9e1372dc01 | |||
| a6a409c750 | |||
| fdcb81306d | |||
| ff395f1d56 | |||
| e346593ebb | |||
| fab6c8c55a | |||
| 282e56e5fc | |||
| a600f11422 | |||
| 2db4a293ed | |||
| 8641a11b53 | |||
| 980248d899 | |||
| 372ee55241 | |||
| 799c579121 | |||
| 4841a9ac1e | |||
| 287dd5d0bf | |||
| 32e23ca0a2 | |||
| b7d7b8c815 | |||
| 96fd034c5a | |||
| 6118e0a4f8 | |||
| c00d1fb89c | |||
| 900f4dfb64 | |||
| 11f8c9ca56 | |||
| 026f63c730 | |||
| e322952ff4 | |||
| e762da2bf5 | |||
| 822a4331aa | |||
| 2b2ba2a551 | |||
| 317fbc2ea7 | |||
| 0cd9d666c1 | |||
| 187ea3b92f | |||
| d2beb399dd | |||
| 15623ab515 | |||
| f771a23c2a | |||
| f20b8708a3 | |||
| 536ed731ed | |||
| 5b10619460 | |||
| 311ac85419 | |||
| ed8d2e285f | |||
| dba3351195 | |||
| 506d6504c7 | |||
| 1eede7832b | |||
| 5ec79bb61b | |||
| 548863845b | |||
| 2f73376ff6 | |||
| 9a8ee3a6aa | |||
| 28e367eb88 | |||
| 7d642b46c9 | |||
| 2be6757e23 | |||
| 4ca67212aa | |||
| 503f99ccbe | |||
| 93410b4075 | |||
| a96945201f | |||
| 35c495f8a8 | |||
| 9abd8e2c54 | |||
| b9a79f0658 | |||
| 83111d3338 | |||
| 92072d3640 | |||
| fd0ea313c2 | |||
| 79a15a08cc | |||
| 1af798fb04 | |||
| c19eb5bab7 | |||
| db693de576 | |||
| 651fa35018 | |||
| 36f1e9e8dd | |||
| 7e454467d1 | |||
| 978caf8e9c | |||
| 2bf4e5d8fd | |||
| dfb0c5a61c | |||
| 9d54fac8c5 | |||
| 5842590f6d | |||
| 06a60cac38 | |||
| dac5eb0d7d | |||
| 923edf166b | |||
| a0776e5462 | |||
| 9ac6d3df70 | |||
| a8a3104019 | |||
| 7cd476028a | |||
| fe96ff5924 | |||
| 890d349ee9 | |||
| 895eaa42c8 | |||
| 2e4457b56d | |||
| b30638fa82 | |||
| a3fac7bcb1 | |||
| 7228bdd9e9 | |||
| fa84171da4 | |||
| f4c3f685eb | |||
| db17d23360 | |||
| 76fe1e12d3 | |||
| d7f455c740 | |||
| d62d7172d0 | |||
| 9bfdb2f06a | |||
| d6436b01d4 | |||
| e848ee1972 | |||
| 2716b462b1 | |||
| 10f3db1ec2 | |||
| 0848a441b1 | |||
| 00c59958e6 | |||
| 9cc438a647 | |||
| 1053fdc8a8 | |||
| e1ee129f41 | |||
| dae0cab261 | |||
| 5871d054d3 | |||
| a69e8969a4 | |||
| dd05e26feb | |||
| 8cd8b7cf43 | |||
| 1d90aba7cd | |||
| 826aff3d36 | |||
| 718294f776 | |||
| 7a003eb490 | |||
| bcceb5d42d | |||
| b1802d7d79 | |||
| e14eeb4da3 | |||
| f726088cc9 | |||
| 4082850b7a | |||
| 641d61d242 | |||
| e2b67bb3f5 | |||
| 1f3e1ceb37 | |||
| 254e9508b6 | |||
| 631be6d7c7 | |||
| ca31e9a062 | |||
| 9fd7d9928a | |||
| 9362b2fb23 | |||
| 1735a4621e | |||
| 6ff332367d | |||
| e045302d38 | |||
| 88793cf011 | |||
| a4181f819b | |||
| 79aeb663c6 | |||
| 169301836a | |||
| 71bd67ba01 | |||
| 3e94dc6518 | |||
| 503322d57e | |||
| 0c9ffbf5e4 | |||
| fae7889995 | |||
| 532e514060 | |||
| b3a5047ba8 | |||
| 810e6ccb19 | |||
| 352e719fae | |||
| d8e0c73f56 | |||
| 46374be4c0 | |||
| 020c5280b3 | |||
| 4beba23f99 | |||
| 59f36cceb4 | |||
| d08b409f0e | |||
| 1612201101 | |||
| 924347361a | |||
| 061d212623 | |||
| af937b3f53 | |||
| 1faa72c5ea | |||
| db53e5a60b | |||
| 802e768bad | |||
| 67f17cffe0 | |||
| 70160cb937 | |||
| 6e22246555 | |||
| 7ed0258cfd | |||
| ddd06c8313 | |||
| d33b84c245 | |||
| 14cd5dd91c | |||
| 2b29ebc29b | |||
| 84b65ee122 | |||
| c3e9024a57 | |||
| d49b5663ba | |||
| e1386da5ae | |||
| b9f9af06f4 | |||
| 01a79e0612 | |||
| 3e69d72597 | |||
| f69c7af9d6 | |||
| ae03503d76 | |||
| 39eade67f0 | |||
| e6d7a0c0e0 | |||
| 98103451e9 | |||
| b64eed88cf | |||
| bafe61ae64 | |||
| 0579c4aeda | |||
| 7599e06b9d | |||
| 8e77d2e3ed | |||
| c2a129c56a | |||
| 111d5509bc | |||
| 7c9987f3de | |||
| f1471b6424 | |||
| 935369c05c | |||
| 2b03f382bd | |||
| 152a142d82 | |||
| f55ce703b0 | |||
| a08c8a0d64 | |||
| 76dd0c46ae | |||
| 1e8056f689 | |||
| d719015fa2 | |||
| 73fa62e6a2 | |||
| bb3f612772 | |||
| 99b6c63de7 | |||
| 8b046e61ab | |||
| ff2c619df7 | |||
| c9ffa64560 | |||
| 2969306d1e | |||
| 2fb558d388 | |||
| 9a0859f915 | |||
| 19bf8210f6 | |||
| 7a30fd0f28 | |||
| 432bf1ae12 | |||
| 967c0114d8 | |||
| 0f55c6da9d | |||
| 5e345418fb | |||
| de19c5bc32 | |||
| 1998842200 | |||
| 25a18e8366 | |||
| a2966e761c | |||
| 0508b8ffb3 | |||
| 9d4c69b39a | |||
| e11790ea92 | |||
| e559c2503b | |||
| c0a383ef58 | |||
| 9b6ddb0f16 | |||
| 45db942f66 | |||
| 41efcbfdf1 | |||
| 76c69a8464 | |||
| abe42ef3cf | |||
| 40f744ea4a | |||
| 7bc0d7f3dc | |||
| 9bbac291b6 | |||
| d7da7b69d4 | |||
| f6530cfb32 | |||
| 376dcc5bd5 | |||
| 89546b9874 | |||
| 385c40c895 | |||
| 8b9580abc8 | |||
| 3b9c8efeba | |||
| 5ba831c044 | |||
| 1141cc20e9 | |||
| 11a439a48f | |||
| 9ef3e53d77 | |||
| 104f46c9db | |||
| 0f0c670ec8 | |||
| c901f0e3d1 | |||
| 63e9428d6d | |||
| cbe7270f4b | |||
| fd67dad4b2 | |||
| 38b8f0085b | |||
| ab0e7afdb8 | |||
| 8045f96106 | |||
| 6481aa37e7 | |||
| 0b9ee87039 | |||
| 9b0d68d26d | |||
| 8ee7d7018f | |||
| 7c1c45417f | |||
| 1fbda0327c | |||
| 12f91c3b99 | |||
| 7d7c350df6 | |||
| caffff259e | |||
| 80b3defd37 | |||
| bbe1642786 | |||
| 4a2b9fdb41 | |||
| f7bc32ed90 | |||
| 592de4deb4 | |||
| ad5c36930e | |||
| c4570ebe62 | |||
| fdaf7180c0 | |||
| ee9152bbc4 | |||
| 413503e0f4 | |||
| 27c41af918 | |||
| fd21cf2539 | |||
| da485e1dde | |||
| 24dfa32ad4 | |||
| 1f9d9b2831 | |||
| 6211506aee | |||
| e1bd659dc5 | |||
| b56d45f411 | |||
| 35a2a0cc61 | |||
| ff43a5e71b | |||
| 8bdbc67535 | |||
| 85261bc3cf | |||
| 311359f6b8 | |||
| 0cb3646554 | |||
| cd02042d63 | |||
| db73a841b2 | |||
| a3e773cb4f | |||
| 09ed4adc93 | |||
| 530e4d412c | |||
| bff593394f | |||
| 32c38e9f95 | |||
| 005b0b9e0d | |||
| fdb124b12e | |||
| 652a446737 | |||
| 098196b599 | |||
| 01c5b96bc7 | |||
| 334743f3f0 | |||
| bd60f48cd1 | |||
| 4fe915cfd8 | |||
| 14cc78cffc | |||
| a04ae45402 | |||
| 0f68f170ad | |||
| 4033c8d004 | |||
| 68d320d9cf | |||
| 603a522c4b | |||
| 030aa36f94 | |||
| 577f35a3fe | |||
| 790ac40f4e | |||
| 44d9c23c0c | |||
| 547bd54085 | |||
| f38bcd2a09 | |||
| c2228d6d23 | |||
| 9ee85bfa3c | |||
| 434cdf8529 | |||
| f42ebcac61 | |||
| d594c6e52a | |||
| 9bb32c8779 | |||
| 13f983bc21 | |||
| 1fa81d1e4f | |||
| 9bd090da66 | |||
| e40a9fe9cb | |||
| 3200c71996 | |||
| 88dca637c2 | |||
| c65860796b | |||
| 8ea8572947 | |||
| 82ec00e9e9 | |||
| 0af8e2f017 | |||
| f56dcb0cce | |||
| 7957a33fc4 | |||
| e150fbb807 | |||
| 32a06be96d | |||
| f6c9490124 | |||
| e84c96f4ee | |||
| c330fdc145 | |||
| d38ce06f90 | |||
| fe34788cff | |||
| 8983cb59b4 | |||
| 3179fca112 | |||
| 9ad1bbdd7d | |||
| 74844bf9ce | |||
| 6296c54e2a | |||
| 4b8d9bf7bf | |||
| 7bfb6d2c5f | |||
| 9e2cede844 | |||
| d60229fa99 | |||
| 5c29eb5860 | |||
| 9a6220bda1 | |||
| 55b75d7c32 | |||
| 0b9115f6a6 | |||
| ce49d9ed45 | |||
| 13397b0bc8 | |||
| 388dac5f8d | |||
| ec0a4aeef9 | |||
| 8bf0be9699 | |||
| 7707b339dc | |||
| 303bf195d2 | |||
| 8eaa6606c4 | |||
| af1d4b3cd1 | |||
| 0fa16e2962 | |||
| 855f66566f | |||
| 913663068c | |||
| 6f05a9e456 | |||
| 5c86778902 | |||
| cfe9023ddd | |||
| 04815b9217 | |||
| 3a918f1aa5 | |||
| e3ee2cbe2f | |||
| 962f88f94d | |||
| 34f5978aea | |||
| 50576c4ba9 | |||
| b56bfcbfcf | |||
| 80cc578be9 | |||
| bb9c7066c7 | |||
| f3d70c0d12 | |||
| 372c6d5e0d | |||
| eca91b139b | |||
| 0d8626509c | |||
| e7548c08a6 | |||
| cfadc07b52 | |||
| 2f2f49c6c7 | |||
| 9a23c31313 | |||
| 27bdc95f6e | |||
| d74e3a9f60 | |||
| 10f8039b1b | |||
| f2adb16189 | |||
| d807fe0126 | |||
| fa464e6ed8 | |||
| 3c62d16ff8 | |||
| 2008a1f104 | |||
| 3716ad2f62 | |||
| 6c929043c1 | |||
| 3888b6f5d2 | |||
| b59415e461 | |||
| af160e3c96 | |||
| b5e6a81a52 | |||
| 58eb59bd61 | |||
| 104d44d757 | |||
| b29ed4d6a2 | |||
| 34008ef6db | |||
| a1dc17c582 | |||
| 01f339cb41 | |||
| 6315f1dc55 | |||
| 5df7c5c37d | |||
| dee2cae126 | |||
| 4d7ad9255a | |||
| ae5e9a75d6 | |||
| 53134ee4d2 | |||
| ea781dcd38 | |||
| 633a0bb777 | |||
| 3d83f18c71 | |||
| 89f6cd4244 | |||
| 1c154de18b | |||
| 6bb3be17ee | |||
| 8259e2fea3 | |||
| 152c5200cb | |||
| 99a1690481 | |||
| fa4564d491 | |||
| be5c25ba5f | |||
| 65e57aab7f | |||
| 5e04634837 | |||
| c9a8d7ad4c | |||
| 7c2ca13951 | |||
| ebf6c225f3 | |||
| 7083cc4493 | |||
| 711e2a53a5 | |||
| 5fd2f782c2 | |||
| 6147415cea | |||
| 6c34489aee | |||
| 1618f0454c | |||
| 1771e9731c | |||
| 1e509c0ec7 | |||
| 0d412c245f | |||
| 736266d8e8 | |||
| 05b2ab75a3 | |||
| e197a889d4 | |||
| 334e8f6267 | |||
| e430c40b99 | |||
| 1d6cb765cc | |||
| d7926a309a | |||
| cca587fb17 | |||
| 742b36ed4a | |||
| 50da5376b5 | |||
| d262057a73 | |||
| 797b076705 | |||
| 6633e26175 | |||
| 6c1c46601c | |||
| 411168be9c | |||
| efda03a0c9 | |||
| d4d632adce | |||
| 040ca6eb77 | |||
| 9bdfb355f1 | |||
| e392c436de | |||
| 294f59c4f3 | |||
| e6bdb51b5b | |||
| 5a7796939f | |||
| cad9eaf966 | |||
| 651af672f6 | |||
| 49375ec5a9 | |||
| 50f2a6a8b0 | |||
| 81280a3fed | |||
| 626de2e44a | |||
| 195d0d406c | |||
| 30ec92c805 | |||
| 9a276e3d3c | |||
| 75cceee734 | |||
| 00dcf84abe | |||
| 529033c5e4 | |||
| fecbc276c8 | |||
| f778451356 | |||
| 6b9f108fe1 | |||
| b848fbdd20 | |||
| beca7bbfc6 | |||
| a8af33a30a | |||
| 9a40cf66cc | |||
| 25f62a35ee | |||
| 24261a3dcb | |||
| 42e34b5e5c | |||
| 52f49994ab | |||
| 3f9e506d09 | |||
| 4c27e66870 | |||
| 0e909906be | |||
| 94bf9895af | |||
| b7f53f4036 | |||
| 49ffbad759 | |||
| a8f405ddc0 | |||
| 3396d73077 | |||
| 5ed24c209f | |||
| 14499009b6 | |||
| 77b2d7bed4 | |||
| 2d52102014 | |||
| 4e20a86155 | |||
| de0cb6788e | |||
| 3d8fc0776c | |||
| 38d1c2f92a | |||
| ada55aefd4 | |||
| 3bb1a9b46d | |||
| 751121e878 | |||
| 61c4d79fa1 | |||
| 22730f063c | |||
| 396244f044 | |||
| dccbe6be77 | |||
| f4fc51b66d | |||
| 7a8ec6221f | |||
| c84fed8af1 | |||
| 67216d1c92 | |||
| 24b30b1c4b | |||
| 62d065fccb | |||
| a5d1ad92c5 | |||
| bfe2478628 | |||
| dedab4e6ba | |||
| 52d1575890 | |||
| 3beac6177f | |||
| 3813b93dc5 | |||
| e0bf859cb2 | |||
| 8ac515acbd | |||
| aafc679e45 | |||
| f172a15e6e | |||
| c279733413 | |||
| 1b808595b8 | |||
| c833c88fe3 | |||
| 89fb8eac00 | |||
| 5c15967985 | |||
| 5ad84eebbf | |||
| e149a45981 | |||
| 4969e0f812 | |||
| bb7f6f3a1c | |||
| 991f1554ec | |||
| 02a1ffe8b7 | |||
| 56cbe08f39 | |||
| b048437b37 | |||
| 1353fed0ee | |||
| 8ec535be53 | |||
| 121ca01be3 | |||
| 229a83720f | |||
| 3bca306702 | |||
| 3c2701fe9d | |||
| 01058d42d3 | |||
| 59be897fd8 | |||
| 1a39d03c7e | |||
| 49eeee35bb | |||
| c1743c2934 | |||
| c906284f07 | |||
| 6427d1f5fb | |||
| 4b569e8fdb | |||
| 6b453648ee | |||
| 9cd09470d4 | |||
| 216d194d77 | |||
| 29600e9ac2 | |||
| 67fd739b0e | |||
| 083c68b528 | |||
| 121d3a3e64 | |||
| cfa38f2318 | |||
| 20f87c953c | |||
| 4f62f2f2d0 | |||
| ace5afca66 | |||
| 3dfffa557a | |||
| 2c878a90f8 | |||
| 03b5a01400 | |||
| d7e4a810f6 | |||
| 338ef9d988 | |||
| 65c67835f2 | |||
| d8d9e25191 | |||
| 3dd7859752 | |||
| 358699dbd3 | |||
| 2754973c8d | |||
| 8865db72d1 | |||
| 31158fed0e | |||
| ae624730aa | |||
| 3fd299bb49 | |||
| 9acfc4c544 |
@@ -0,0 +1,9 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- 在这里定义所有项目共享的属性 -->
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<!-- 如果需要Nullable等全局设置,也可以加在这里 -->
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,36 +1,35 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.416.8" />
|
<PackageReference Include="AWSSDK.S3" Version="4.0.24" />
|
||||||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
|
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
|
||||||
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
|
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
<PackageReference Include="DistributedLock.Core" Version="1.0.9" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.2.1" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.1" />
|
<PackageReference Include="fo-dicom" Version="5.2.6" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.1" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
|
||||||
<PackageReference Include="Minio" Version="6.0.4" />
|
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="Minio" Version="7.0.0" />
|
||||||
|
<PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.2" />
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.9.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ var _configuration = builder.Configuration;
|
|||||||
builder.Services.AddHealthChecks();
|
builder.Services.AddHealthChecks();
|
||||||
|
|
||||||
//本地化
|
//本地化
|
||||||
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
|
||||||
|
|
||||||
|
|
||||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public class AWSTempToken
|
|||||||
public string SecretAccessKey { get; set; }
|
public string SecretAccessKey { get; set; }
|
||||||
public string BucketName { get; set; }
|
public string BucketName { get; set; }
|
||||||
public string ViewEndpoint { get; set; }
|
public string ViewEndpoint { get; set; }
|
||||||
public DateTime Expiration { get; set; }
|
public DateTime? Expiration { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ObjectStoreUse
|
public enum ObjectStoreUse
|
||||||
@@ -231,8 +231,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -320,8 +320,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -397,8 +397,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -493,8 +493,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -625,8 +625,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.Service;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP;
|
||||||
|
|
||||||
|
|
||||||
|
public class SyncFileRecoveryService(IServiceScopeFactory _scopeFactory, FileSyncQueue _fileSyncQueue) : BackgroundService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly int _pageSize = 500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多个程序,如果恢复同一份数据,造成重复同步,SCP服务不恢复任务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stoppingToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
//在本地调试的时候,不干涉部署同步任务
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await Task.CompletedTask;
|
||||||
|
|
||||||
|
//using var scope = _scopeFactory.CreateScope();
|
||||||
|
//var fileUploadRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<FileUploadRecord>>();
|
||||||
|
|
||||||
|
//// 延迟启动,保证主机快速启动
|
||||||
|
//await Task.Delay(5000, stoppingToken);
|
||||||
|
|
||||||
|
//int page = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//while (!stoppingToken.IsCancellationRequested)
|
||||||
|
//{
|
||||||
|
// // 分页获取未入队任务
|
||||||
|
// var pending = await fileUploadRecordRepository
|
||||||
|
// .Where(x => x.IsNeedSync == true && (x.IsSync == false || x.IsSync == null))
|
||||||
|
// .OrderByDescending(x => x.Priority)
|
||||||
|
// .Select(t => new { t.Id, t.Priority })
|
||||||
|
// .Skip(page * _pageSize)
|
||||||
|
// .Take(_pageSize)
|
||||||
|
// .ToListAsync(stoppingToken);
|
||||||
|
|
||||||
|
// if (!pending.Any())
|
||||||
|
// break; // 扫描完毕,退出循环
|
||||||
|
|
||||||
|
// foreach (var file in pending)
|
||||||
|
// {
|
||||||
|
// //file.IsQueued = true; // 避免重复入队
|
||||||
|
// _fileSyncQueue.Enqueue(file.Id, file.Priority ?? 0); // 放入队列
|
||||||
|
// }
|
||||||
|
|
||||||
|
// page++; // 下一页
|
||||||
|
// await Task.Delay(200, stoppingToken); // 缓解数据库压力
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileSyncWorker(IServiceScopeFactory _scopeFactory, ILogger<FileSyncWorker> _logger, FileSyncQueue _fileSyncQueue) : BackgroundService
|
||||||
|
{
|
||||||
|
|
||||||
|
// ⭐ 自动根据服务器CPU
|
||||||
|
private readonly int _workerCount = Math.Max(1, Environment.ProcessorCount - 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _workerCount; i++)
|
||||||
|
Task.Run(() => WorkerLoop(stoppingToken));
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task WorkerLoop(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var id = await _fileSyncQueue.DequeueAsync(stoppingToken);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
var _fileUploadRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<FileUploadRecord>>();
|
||||||
|
var _uploadFileSyncRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<UploadFileSyncRecord>>();
|
||||||
|
|
||||||
|
var syncConfig = (scope.ServiceProvider.GetRequiredService<IOptionsMonitor<ObjectStoreServiceOptions>>()).CurrentValue;
|
||||||
|
|
||||||
|
var oss = scope.ServiceProvider.GetRequiredService<IOSSService>();
|
||||||
|
|
||||||
|
var file = await _fileUploadRecordRepository.FirstOrDefaultAsync(t => t.Id == id);
|
||||||
|
|
||||||
|
// ✅ 不要 return
|
||||||
|
if (file == null || file.IsNeedSync != true || syncConfig.IsOpenStoreSync == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncConfig.SyncConfigList.Any(t => t.UploadRegion == file.UploadRegion && t.IsOpenSync == false))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果发现系统配置某一边同步进行了关闭,那么就直接返回,不执行任务
|
||||||
|
if (syncConfig.SyncConfigList.Any(t => t.UploadRegion == file.UploadRegion && t.IsOpenSync == false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = new UploadFileSyncRecord
|
||||||
|
{
|
||||||
|
FileUploadRecordId = id,
|
||||||
|
StartTime = DateTime.Now,
|
||||||
|
JobState = jobState.RUNNING
|
||||||
|
};
|
||||||
|
|
||||||
|
await _uploadFileSyncRecordRepository.AddAsync(log);
|
||||||
|
await _uploadFileSyncRecordRepository.SaveChangesAsync(stoppingToken);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await oss.SyncFileAsync(file.Path.TrimStart('/'), file.UploadRegion == "CN" ? ObjectStoreUse.AliyunOSS : ObjectStoreUse.AWS, file.UploadRegion == "CN" ? ObjectStoreUse.AWS : ObjectStoreUse.AliyunOSS);
|
||||||
|
|
||||||
|
file.IsSync = true;
|
||||||
|
file.SyncFinishedTime = DateTime.Now;
|
||||||
|
|
||||||
|
log.JobState = jobState.SUCCESS;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.JobState = jobState.FAILED;
|
||||||
|
|
||||||
|
log.Msg = ex.Message.Length > 300 ? ex.Message.Substring(0, 300) : ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.EndTime = DateTime.Now;
|
||||||
|
|
||||||
|
await _uploadFileSyncRecordRepository.SaveChangesAsync(stoppingToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Sync failed {Id}", id);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// ⭐⭐⭐ 永远执行
|
||||||
|
_fileSyncQueue.Complete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,34 +1,32 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.5" />
|
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="11.0.0" />
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.416.8" />
|
<PackageReference Include="AWSSDK.S3" Version="4.0.24" />
|
||||||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.401.81" />
|
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
|
||||||
<PackageReference Include="DistributedLock.Core" Version="1.0.8" />
|
<PackageReference Include="DistributedLock.Core" Version="1.0.9" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.2.4" />
|
<PackageReference Include="fo-dicom" Version="5.2.6" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.4" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.4" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||||
<PackageReference Include="Minio" Version="6.0.3" />
|
<PackageReference Include="Minio" Version="7.0.0" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.1.2" />
|
<PackageReference Include="Serilog.Enrichers.ClientInfo" Version="2.9.0" />
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="10.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ using IRaCIS.Core.SCP.Service;
|
|||||||
using MassTransit;
|
using MassTransit;
|
||||||
using MassTransit.NewIdProviders;
|
using MassTransit.NewIdProviders;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Panda.DynamicWebApi;
|
using Panda.DynamicWebApi;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
@@ -63,11 +62,15 @@ builder.Host
|
|||||||
#region 配置服务
|
#region 配置服务
|
||||||
var _configuration = builder.Configuration;
|
var _configuration = builder.Configuration;
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<FileSyncQueue>();
|
||||||
|
builder.Services.AddHostedService<SyncFileRecoveryService>();
|
||||||
|
builder.Services.AddHostedService<FileSyncWorker>();
|
||||||
|
|
||||||
//健康检查
|
//健康检查
|
||||||
builder.Services.AddHealthChecks();
|
builder.Services.AddHealthChecks();
|
||||||
|
|
||||||
//本地化
|
//本地化
|
||||||
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
|
||||||
|
|
||||||
|
|
||||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using IRaCIS.Core.Infra.EFCore;
|
|||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using IRaCIS.Core.SCP.Service;
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using MassTransit;
|
||||||
using Medallion.Threading;
|
using Medallion.Threading;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -95,7 +96,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
|
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
|
||||||
{
|
{
|
||||||
|
|
||||||
_upload = new SCPImageUpload() { StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
|
_upload = new SCPImageUpload() { Id = NewId.NextSequentialGuid(), StartTime = DateTime.Now, CallingAE = association.CallingAE, CalledAE = association.CalledAE, CallingAEIP = association.RemoteHost };
|
||||||
|
|
||||||
|
|
||||||
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
|
Log.Logger.Warning($"接收到来自{association.CallingAE}的连接");
|
||||||
@@ -540,12 +541,12 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
|
|
||||||
//保留原始偏移表
|
//保留原始偏移表
|
||||||
|
|
||||||
if (originOffsetTable.Count == pixelData.NumberOfFrames)
|
//if (originOffsetTable.Count == pixelData.NumberOfFrames)
|
||||||
{
|
//{
|
||||||
newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
|
// newFragments.OffsetTable.AddRange(originOffsetTable.ToArray());
|
||||||
|
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
{
|
||||||
newFragments.OffsetTable.AddRange(bot.ToArray());
|
newFragments.OffsetTable.AddRange(bot.ToArray());
|
||||||
|
|
||||||
@@ -644,7 +645,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
|
|
||||||
//irc 从路径最后一截取Guid
|
//irc 从路径最后一截取Guid
|
||||||
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false);
|
storeRelativePath = await ossService.UploadToOSSAsync(ms, ossFolderPath, instanceId.ToString(), false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive, UploadBatchId = _upload.Id.ToString() });
|
||||||
|
|
||||||
fileSize = ms.Length;
|
fileSize = ms.Length;
|
||||||
|
|
||||||
@@ -674,7 +675,7 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
|
|
||||||
// 上传缩略图到 OSS
|
// 上传缩略图到 OSS
|
||||||
|
|
||||||
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, $"{seriesId.ToString()}_{instanceId.ToString()}.preview.jpg", false);
|
var seriesPath = await ossService.UploadToOSSAsync(memoryStream, ossFolderPath, $"{seriesId.ToString()}_{instanceId.ToString()}.preview.jpg", false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = _trialId, BatchDataType = BatchDataType.PACSReceive });
|
||||||
|
|
||||||
|
|
||||||
series.ImageResizePath = seriesPath;
|
series.ImageResizePath = seriesPath;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ public static class CacheKeys
|
|||||||
public static string UserMFAVerifyPass(Guid userId, string browserFingerprint) => $"UserMFAVerifyPass:{userId}:{browserFingerprint}";
|
public static string UserMFAVerifyPass(Guid userId, string browserFingerprint) => $"UserMFAVerifyPass:{userId}:{browserFingerprint}";
|
||||||
|
|
||||||
public static string TrialSiteInfo(Guid trialSiteId) => $"{trialSiteId}TrialSiteInfo";
|
public static string TrialSiteInfo(Guid trialSiteId) => $"{trialSiteId}TrialSiteInfo";
|
||||||
|
|
||||||
|
public static string TrialDataStoreType(Guid trialId) => $"TrialDataStoreType:{trialId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CacheHelper
|
public static class CacheHelper
|
||||||
|
|||||||
@@ -204,6 +204,12 @@ namespace IRaCIS.Core.SCP.Service
|
|||||||
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
AcquisitionNumber = dataset.GetSingleValueOrDefault(DicomTag.AcquisitionNumber, string.Empty),
|
||||||
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
TriggerTime = dataset.GetSingleValueOrDefault(DicomTag.TriggerTime, string.Empty),
|
||||||
|
|
||||||
|
RadionuclideTotalDose= dataset.GetSingleValueOrDefault(DicomTag.RadionuclideTotalDose, string.Empty),
|
||||||
|
|
||||||
|
RadionuclideHalfLife= dataset.GetSingleValueOrDefault(DicomTag.RadionuclideHalfLife, string.Empty),
|
||||||
|
RadiopharmaceuticalStartTime = dataset.GetSingleValueOrDefault(DicomTag.RadiopharmaceuticalStartTime, string.Empty),
|
||||||
|
|
||||||
|
|
||||||
Manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty),
|
Manufacturer = dataset.GetSingleValueOrDefault(DicomTag.Manufacturer, string.Empty),
|
||||||
ManufacturerModelName = dataset.GetSingleValueOrDefault(DicomTag.ManufacturerModelName, string.Empty),
|
ManufacturerModelName = dataset.GetSingleValueOrDefault(DicomTag.ManufacturerModelName, string.Empty),
|
||||||
DeviceSerialNumber = dataset.GetSingleValueOrDefault(DicomTag.DeviceSerialNumber, string.Empty),
|
DeviceSerialNumber = dataset.GetSingleValueOrDefault(DicomTag.DeviceSerialNumber, string.Empty),
|
||||||
|
|||||||
@@ -0,0 +1,334 @@
|
|||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||||
|
// 生成时间 2026-03-10 06:15:17Z
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
using AutoMapper;
|
||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using IRaCIS.Core.SCP;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.SCP.Service;
|
||||||
|
|
||||||
|
public class FileUploadRecordAddOrEdit
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
public long FileSize { get; set; }
|
||||||
|
|
||||||
|
public string FileType { get; set; }
|
||||||
|
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string UploadBatchId { get; set; }
|
||||||
|
public BatchDataType BatchDataType { get; set; }
|
||||||
|
|
||||||
|
public string StudyCode { get; set; }
|
||||||
|
|
||||||
|
public Guid? TrialId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectVisitId { get; set; }
|
||||||
|
|
||||||
|
public Guid? DicomStudyId { get; set; }
|
||||||
|
|
||||||
|
public Guid? NoneDicomStudyId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string FileMarkId { get; set; }
|
||||||
|
|
||||||
|
public int? Priority { get; set; }
|
||||||
|
public string IP { get; set; }
|
||||||
|
public bool? IsNeedSync { get; set; }
|
||||||
|
public string UploadRegion { get; set; }
|
||||||
|
public string TargetRegion { get; set; }
|
||||||
|
|
||||||
|
public bool? IsSync { get; set; }
|
||||||
|
}
|
||||||
|
public interface IFileUploadRecordService
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[ApiExplorerSettings(GroupName = "Common")]
|
||||||
|
public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRecordRepository,
|
||||||
|
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<ObjectStoreServiceOptions> options,
|
||||||
|
IFusionCache _fusionCache, IRepository<Trial> _trialRepository, FileSyncQueue _fileSyncQueue) : BaseService, IFileUploadRecordService
|
||||||
|
{
|
||||||
|
|
||||||
|
ObjectStoreServiceOptions ObjectStoreServiceConfig = options.CurrentValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord)
|
||||||
|
{
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IP = _userInfo.IP;
|
||||||
|
|
||||||
|
if (ObjectStoreServiceConfig.IsOpenStoreSync && _userInfo.Domain.IsNotNullOrEmpty())
|
||||||
|
{
|
||||||
|
var find = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.Domain == _userInfo.Domain);
|
||||||
|
if (find != null)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.UploadRegion = find.UploadRegion;
|
||||||
|
addOrEditFileUploadRecord.TargetRegion = find.TargetRegion;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//前后端调试的时候,上传的时候域名不对应,自动按照后端配置设置上传区域和同步区域
|
||||||
|
var apiDefalut = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.UploadRegion == ObjectStoreServiceConfig.ApiDeployRegion);
|
||||||
|
|
||||||
|
if (apiDefalut != null)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.UploadRegion = apiDefalut.UploadRegion;
|
||||||
|
addOrEditFileUploadRecord.TargetRegion = apiDefalut.TargetRegion;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SCP推送过来IP为空,后端归档的,设置区域
|
||||||
|
if (_userInfo.IP.IsNullOrEmpty() && _userInfo.Domain.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
var apiDefalut = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.UploadRegion == ObjectStoreServiceConfig.ApiDeployRegion);
|
||||||
|
|
||||||
|
if (apiDefalut != null)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.UploadRegion = apiDefalut.UploadRegion;
|
||||||
|
addOrEditFileUploadRecord.TargetRegion = apiDefalut.TargetRegion;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addOrEditFileUploadRecord.TrialId != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
var trialDataStore = await _fusionCache.GetOrSetAsync(CacheKeys.TrialDataStoreType(addOrEditFileUploadRecord.TrialId.Value), async _ =>
|
||||||
|
{
|
||||||
|
return await _trialRepository.Where(t => t.Id == addOrEditFileUploadRecord.TrialId).Select(t => t.TrialDataStoreType)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
},
|
||||||
|
TimeSpan.FromDays(7)
|
||||||
|
);
|
||||||
|
|
||||||
|
//项目配置了,那么就设置需要同步
|
||||||
|
if (trialDataStore == TrialDataStore.MUtiCenter)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IsSync = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = false;
|
||||||
|
|
||||||
|
//addOrEditFileUploadRecord.TargetRegion = "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//系统文件,默认同步
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IsSync = false;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true);
|
||||||
|
|
||||||
|
if (addOrEditFileUploadRecord.IsNeedSync == true)
|
||||||
|
{
|
||||||
|
_fileSyncQueue.Enqueue(entity.Id, addOrEditFileUploadRecord.Priority ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class FileSyncQueue
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 优先级队列(仅负责排序)
|
||||||
|
/// </summary>
|
||||||
|
private readonly PriorityQueue<Guid, int> _queue = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前等待中的任务(唯一真实数据)
|
||||||
|
/// key = Guid
|
||||||
|
/// value = 最新 priority
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<Guid, int> _waiting = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正在执行的任务(防止重复执行)
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<Guid> _running = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// worker 等待信号
|
||||||
|
/// </summary>
|
||||||
|
private readonly SemaphoreSlim _signal = new(0);
|
||||||
|
|
||||||
|
|
||||||
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Enqueue
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 入队(同 Guid 会覆盖优先级)
|
||||||
|
/// </summary>
|
||||||
|
public void Enqueue(Guid id, int priority)
|
||||||
|
{
|
||||||
|
bool needSignal = false;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
// 如果正在执行,忽略(防止重复)
|
||||||
|
if (_running.Contains(id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 是否新任务(用于减少 signal 风暴)
|
||||||
|
if (!_waiting.ContainsKey(id))
|
||||||
|
needSignal = true;
|
||||||
|
|
||||||
|
// 更新为最新优先级(最后一次为准)
|
||||||
|
_waiting[id] = priority; //等价于添加或者更新
|
||||||
|
|
||||||
|
// PriorityQueue 无法更新节点
|
||||||
|
// 允许旧节点存在,Dequeue 时过滤
|
||||||
|
_queue.Enqueue(id, -priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有新增任务才唤醒 worker
|
||||||
|
if (needSignal)
|
||||||
|
_signal.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Dequeue
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取一个待执行任务(无任务时自动等待)
|
||||||
|
/// </summary>
|
||||||
|
public async Task<Guid> DequeueAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await _signal.WaitAsync(ct);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
while (_queue.Count > 0)
|
||||||
|
{
|
||||||
|
var id = _queue.Dequeue();
|
||||||
|
|
||||||
|
// 已被覆盖或取消
|
||||||
|
if (!_waiting.TryGetValue(id, out _))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 标记为运行中
|
||||||
|
_waiting.Remove(id);
|
||||||
|
_running.Add(id);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Complete
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务执行完成(必须调用)
|
||||||
|
/// </summary>
|
||||||
|
public void Complete(Guid id)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_running.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Snapshot
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前等待中的任务快照
|
||||||
|
/// </summary>
|
||||||
|
public Guid[] Snapshot()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _waiting.Keys.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 状态信息(调试用)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public int WaitingCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _waiting.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RunningCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _running.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1434
-107
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.SCP.Service;
|
||||||
|
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Service
|
||||||
|
{
|
||||||
|
public class CommonConfig : Profile
|
||||||
|
{
|
||||||
|
public CommonConfig()
|
||||||
|
{
|
||||||
|
CreateMap<FileUploadRecordAddOrEdit, FileUploadRecord>().ReverseMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
||||||
|
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
||||||
|
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
||||||
|
"BucketName": "tl-med-irc-event-store",
|
||||||
|
"ViewEndpoint": "https://tl-med-irc-event-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,26 @@
|
|||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "eiirc.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
@@ -19,6 +39,18 @@
|
|||||||
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"Region": "oss-cn-shanghai",
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||||
|
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||||
|
"BucketName": "ei-med-s3-irc-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.test.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-test-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
// 使用的对象存储服务类型
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.test.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.test.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
@@ -29,6 +50,27 @@
|
|||||||
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
"secretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||||
"bucketName": "hir-test",
|
"bucketName": "hir-test",
|
||||||
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
"viewEndpoint": "http://106.14.89.110:9001/hir-test/"
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.test.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-test-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,38 @@
|
|||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AWS",
|
"ObjectStoreUse": "AWS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "US",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "eilili.elevateimaging.ai",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.elevateimaging.ai",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
|
"BucketName": "zy-lili-store",
|
||||||
|
"ViewEndpoint": "https://zy-lili-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"Region": "us-east-1",
|
"Region": "us-east-1",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
|
"BucketName": "zy-irc-test-store",
|
||||||
|
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HeAnShu;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server101.132.253.119,1435;Database=Uat_HeAnShu_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,17 +8,58 @@
|
|||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
"BucketName": "tl-med-irc-uat-store",
|
"BucketName": "zy-irc-test-store",
|
||||||
"ViewEndpoint": "https://tl-med-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
"Region": "oss-cn-shanghai",
|
"Region": "oss-cn-shanghai",
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
||||||
|
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
||||||
|
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-uat-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
// AWS S3 对象存储服务的配置
|
||||||
|
"AWS": {
|
||||||
|
// AWS S3 的Region
|
||||||
|
"Region": "us-east-1",
|
||||||
|
// AWS S3 的内部访问端点
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
// 是否使用 SSL
|
||||||
|
"UseSSL": true,
|
||||||
|
// AWS S3 的角色 ARN
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
// AWS S3 的访问密钥 ID
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
// AWS S3 的访问密钥 Secret
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
// AWS S3 的Bucket名称
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
// AWS S3 的访问端点
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
|
// AWS S3 的持续数秒
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server101.132.253.119,1435;Database=Uat_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"DicomSCPServiceConfig": {
|
||||||
|
"CalledAEList": [
|
||||||
|
"STORESCP"
|
||||||
|
],
|
||||||
|
"ServerPort": 11112
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,42 +1,21 @@
|
|||||||
using AlibabaCloud.SDK.Sts20150401;
|
using AlibabaCloud.SDK.Sts20150401;
|
||||||
using Amazon.Auth.AccessControlPolicy;
|
|
||||||
using Amazon.SecurityToken;
|
using Amazon.SecurityToken;
|
||||||
using AutoMapper;
|
|
||||||
using Azure.Core;
|
|
||||||
using IdentityModel.Client;
|
|
||||||
using IdentityModel.OidcClient;
|
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using IRaCIS.Core.Application.Auth;
|
using IRaCIS.Core.Application.Auth;
|
||||||
using IRaCIS.Core.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.Service;
|
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using MassTransit.Futures.Contracts;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Org.BouncyCastle.Tls;
|
using Serilog;
|
||||||
using RestSharp;
|
|
||||||
using RestSharp.Authenticators;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using ZiggyCreatures.Caching.Fusion;
|
|
||||||
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
|
||||||
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
|
||||||
|
|
||||||
namespace IRaCIS.Api.Controllers
|
namespace IRaCIS.Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -137,9 +116,14 @@ namespace IRaCIS.Api.Controllers
|
|||||||
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
|
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
|
||||||
{
|
{
|
||||||
|
|
||||||
var result = _oSSService.GetObjectStoreTempToken();
|
var domain = HttpContext.Request.Host.Host;
|
||||||
|
|
||||||
//result.AWS = await GetAWSTemToken(options.CurrentValue);
|
|
||||||
|
var result = _oSSService.GetObjectStoreTempToken(domain);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Log.Logger.Information($"使用域名:{domain}请求token.返回{result.ToJsonStr()}");
|
||||||
|
|
||||||
return ResponseOutput.Ok(result);
|
return ResponseOutput.Ok(result);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
ITrialDocumentService _trialDocumentService,
|
ITrialDocumentService _trialDocumentService,
|
||||||
IReadingImageTaskService _iReadingImageTaskService,
|
IReadingImageTaskService _iReadingImageTaskService,
|
||||||
ITrialConfigService _trialConfigService,
|
ITrialConfigService _trialConfigService,
|
||||||
|
IStudyService _studyService,
|
||||||
IClinicalAnswerService _clinicalAnswerService,
|
IClinicalAnswerService _clinicalAnswerService,
|
||||||
IReadingClinicalDataService _readingClinicalDataService,
|
IReadingClinicalDataService _readingClinicalDataService,
|
||||||
IQCOperationService _qCOperationService,
|
IQCOperationService _qCOperationService,
|
||||||
@@ -146,6 +147,26 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修正患者基本信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost, Route("Inspection/Study/AmendmentPatientInfo")]
|
||||||
|
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
public async Task<IResponseOutput> AmendmentPatientInfo(DataInspectionDto<EditPatientInfoCommand> opt)
|
||||||
|
{
|
||||||
|
|
||||||
|
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||||
|
var result = await _studyService.AmendmentPatientInfo(opt.Data);
|
||||||
|
await _inspectionService.CompletedSign(singid, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 医学审核完成
|
/// 医学审核完成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -155,10 +176,19 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||||||
|
|
||||||
[UnitOfWork]
|
[UnitOfWork]
|
||||||
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt)
|
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<CloseAndFinishMedicalReview> opt)
|
||||||
{
|
{
|
||||||
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||||
var result = await _readingMedicalReviewService.FinishMedicalReview(opt.Data);
|
|
||||||
|
await _readingMedicalReviewService.ClosedMedicalReviewDialog(new ClosedMedicalReviewDialogInDto() {
|
||||||
|
DialogCloseReason=opt.Data.DialogCloseReason,
|
||||||
|
IsClosedDialog=opt.Data.IsClosedDialog,
|
||||||
|
MedicalDialogCloseEnum=opt.Data.MedicalDialogCloseEnum,
|
||||||
|
TaskMedicalReviewId=opt.Data.TaskMedicalReviewId
|
||||||
|
});
|
||||||
|
var result = await _readingMedicalReviewService.FinishMedicalReview(new FinishMedicalReviewInDto() {
|
||||||
|
TaskMedicalReviewId=opt.Data.TaskMedicalReviewId
|
||||||
|
});
|
||||||
await _inspectionService.CompletedSign(singid, result);
|
await _inspectionService.CompletedSign(singid, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -321,6 +351,23 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交阅片裁判表单
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opt"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeForm")]
|
||||||
|
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
|
||||||
|
public async Task<IResponseOutput> SubmitJudgeForm(DataInspectionDto<SetJudgeFormInDto> opt)
|
||||||
|
{
|
||||||
|
var singid = await _inspectionService.RecordSing(opt.SignInfo);
|
||||||
|
var result = await _iReadingImageTaskService.SubmitJudgeForm(opt.Data);
|
||||||
|
await _inspectionService.CompletedSign(singid, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置 基础逻辑信息并确认
|
/// 配置 基础逻辑信息并确认
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using ExcelDataReader;
|
using ExcelDataReader;
|
||||||
using IRaCIS.Application.Interfaces;
|
|
||||||
using IRaCIS.Core.Application.BusinessFilter;
|
using IRaCIS.Core.Application.BusinessFilter;
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Contracts.Dicom;
|
using IRaCIS.Core.Application.Contracts.Dicom;
|
||||||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||||||
using IRaCIS.Core.Application.Filter;
|
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.MassTransit.Command;
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Core.Application.Service;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
@@ -16,8 +15,6 @@ using IRaCIS.Core.Infrastructure;
|
|||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using MassTransit.Mediator;
|
using MassTransit.Mediator;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
@@ -26,21 +23,15 @@ using Microsoft.AspNetCore.StaticFiles;
|
|||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using MiniExcelLibs;
|
using MiniExcelLibs;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SharpCompress.Archives;
|
using SharpCompress.Archives;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API.Controllers
|
namespace IRaCIS.Core.API.Controllers
|
||||||
@@ -131,7 +122,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
//处理压缩文件
|
//处理压缩文件
|
||||||
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
|
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var archive = ArchiveFactory.Open(section.Body);
|
var archive = ArchiveFactory.OpenArchive(section.Body);
|
||||||
|
|
||||||
foreach (var entry in archive.Entries)
|
foreach (var entry in archive.Entries)
|
||||||
{
|
{
|
||||||
@@ -212,7 +203,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
//处理压缩文件
|
//处理压缩文件
|
||||||
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
|
if (fileName.Contains(".Zip", StringComparison.OrdinalIgnoreCase) || fileName.Contains(".rar", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var archive = ArchiveFactory.Open(section.Body);
|
var archive = ArchiveFactory.OpenArchive(section.Body);
|
||||||
|
|
||||||
foreach (var entry in archive.Entries)
|
foreach (var entry in archive.Entries)
|
||||||
{
|
{
|
||||||
@@ -598,7 +589,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
templateFileStream.Seek(0, SeekOrigin.Begin);
|
templateFileStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
|
||||||
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", realFileName);
|
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", realFileName, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.DataReconciliation });
|
||||||
|
|
||||||
var addEntity = await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
var addEntity = await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
||||||
|
|
||||||
@@ -856,7 +847,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_TemplateUploadData"]);
|
throw new BusinessValidationFailedException(_localizer["UploadDownLoad_TemplateUploadData"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/SiteSurvey", realFileName);
|
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId.ToString()}/InspectionUpload/SiteSurvey", realFileName, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.SiteUserSurvey });
|
||||||
|
|
||||||
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = realFileName, RelativePath = ossRelativePath, TrialId = trialId }, true);
|
||||||
|
|
||||||
@@ -932,7 +923,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
//处理好 用户类型 和用户类型枚举
|
//处理好 用户类型 和用户类型枚举
|
||||||
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
|
var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList();
|
||||||
var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId = t.Id }).ToList();
|
var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, TrialSiteId = t.Id, t.Country }).ToList();
|
||||||
|
|
||||||
foreach (var item in excelList)
|
foreach (var item in excelList)
|
||||||
{
|
{
|
||||||
@@ -954,6 +945,8 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).TrialSiteId;
|
item.TrialSiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).TrialSiteId;
|
||||||
|
|
||||||
|
item.Country = siteList.FirstOrDefault(t => t.TrialSiteCode.Trim().ToUpper() == item.TrialSiteCode.Trim().ToUpper()).Country;
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
|
var list = excelList.Where(t => t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.CRA).ToList();
|
||||||
@@ -1008,7 +1001,7 @@ namespace IRaCIS.Core.API.Controllers
|
|||||||
|
|
||||||
Other = 6,
|
Other = 6,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.Service;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.API.HostService;
|
||||||
|
|
||||||
|
|
||||||
|
public class SyncFileRecoveryService(IServiceScopeFactory _scopeFactory, FileSyncQueue _fileSyncQueue) : BackgroundService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly int _pageSize = 500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 多个程序,如果恢复同一份数据,造成重复同步,SCP服务不恢复任务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stoppingToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
//在本地调试的时候,不干涉部署同步任务
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
var fileUploadRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<FileUploadRecord>>();
|
||||||
|
|
||||||
|
// 延迟启动,保证主机快速启动
|
||||||
|
await Task.Delay(5000, stoppingToken);
|
||||||
|
|
||||||
|
int page = 0;
|
||||||
|
|
||||||
|
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
// 分页获取未入队任务
|
||||||
|
var pending = await fileUploadRecordRepository
|
||||||
|
.Where(x => x.IsNeedSync == true && (x.IsSync == false || x.IsSync == null))
|
||||||
|
.OrderByDescending(x => x.Priority)
|
||||||
|
.Select(t => new { t.Id, t.Priority })
|
||||||
|
.Skip(page * _pageSize)
|
||||||
|
.Take(_pageSize)
|
||||||
|
.ToListAsync(stoppingToken);
|
||||||
|
|
||||||
|
if (!pending.Any())
|
||||||
|
break; // 扫描完毕,退出循环
|
||||||
|
|
||||||
|
foreach (var file in pending)
|
||||||
|
{
|
||||||
|
//file.IsQueued = true; // 避免重复入队
|
||||||
|
_fileSyncQueue.Enqueue(file.Id, file.Priority ?? 0); // 放入队列
|
||||||
|
}
|
||||||
|
|
||||||
|
page++; // 下一页
|
||||||
|
await Task.Delay(200, stoppingToken); // 缓解数据库压力
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileSyncWorker(IServiceScopeFactory _scopeFactory, ILogger<FileSyncWorker> _logger, FileSyncQueue _fileSyncQueue) : BackgroundService
|
||||||
|
{
|
||||||
|
|
||||||
|
// ⭐ 自动根据服务器CPU
|
||||||
|
private readonly int _workerCount = Math.Max(1, Environment.ProcessorCount - 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _workerCount; i++)
|
||||||
|
Task.Run(() => WorkerLoop(stoppingToken));
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task WorkerLoop(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var id = await _fileSyncQueue.DequeueAsync(stoppingToken);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
var _fileUploadRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<FileUploadRecord>>();
|
||||||
|
var _uploadFileSyncRecordRepository = scope.ServiceProvider.GetRequiredService<IRepository<UploadFileSyncRecord>>();
|
||||||
|
|
||||||
|
var syncConfig = (scope.ServiceProvider.GetRequiredService<IOptionsMonitor<ObjectStoreServiceOptions>>()).CurrentValue;
|
||||||
|
|
||||||
|
var oss = scope.ServiceProvider.GetRequiredService<IOSSService>();
|
||||||
|
|
||||||
|
var file = await _fileUploadRecordRepository.FirstOrDefaultAsync(t => t.Id == id);
|
||||||
|
|
||||||
|
// ✅ 不要 return
|
||||||
|
if (file == null || file.IsNeedSync != true || syncConfig.IsOpenStoreSync == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncConfig.SyncConfigList.Any(t => t.UploadRegion == file.UploadRegion && t.IsOpenSync == false))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果发现系统配置某一边同步进行了关闭,那么就直接返回,不执行任务
|
||||||
|
if (syncConfig.SyncConfigList.Any(t => t.UploadRegion == file.UploadRegion && t.IsOpenSync == false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = new UploadFileSyncRecord
|
||||||
|
{
|
||||||
|
FileUploadRecordId = id,
|
||||||
|
StartTime = DateTime.Now,
|
||||||
|
JobState = jobState.RUNNING
|
||||||
|
};
|
||||||
|
|
||||||
|
await _uploadFileSyncRecordRepository.AddAsync(log);
|
||||||
|
await _uploadFileSyncRecordRepository.SaveChangesAsync(stoppingToken);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await oss.SyncFileAsync(file.Path.TrimStart('/'), file.UploadRegion == "CN" ? ObjectStoreUse.AliyunOSS : ObjectStoreUse.AWS, file.UploadRegion == "CN" ? ObjectStoreUse.AWS : ObjectStoreUse.AliyunOSS);
|
||||||
|
|
||||||
|
file.IsSync = true;
|
||||||
|
file.SyncFinishedTime = DateTime.Now;
|
||||||
|
|
||||||
|
log.JobState = jobState.SUCCESS;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.JobState = jobState.FAILED;
|
||||||
|
|
||||||
|
log.Msg = ex.Message.Length > 300 ? ex.Message.Substring(0, 300) : ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.EndTime = DateTime.Now;
|
||||||
|
|
||||||
|
await _uploadFileSyncRecordRepository.SaveChangesAsync(stoppingToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Sync failed {Id}", id);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// ⭐⭐⭐ 永远执行
|
||||||
|
_fileSyncQueue.Complete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
<UserSecretsId>354572d4-9e15-4099-807c-63a2d29ff9f2</UserSecretsId>
|
||||||
<LangVersion>default</LangVersion>
|
<LangVersion>default</LangVersion>
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
<Company>上海展影医疗科技有限公司</Company>
|
<Company>上海展影医疗科技有限公司</Company>
|
||||||
<Product>IRC影像系统 (EICS)</Product>
|
<Product>IRC影像系统 (EICS)</Product>
|
||||||
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
<Copyright>上海展影医疗科技有限公司版权所有</Copyright>
|
||||||
|
<NoWarn>$(NoWarn);NU1903</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@@ -69,22 +69,21 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
<PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
|
<PackageReference Include="ConfigMapFileProvider" Version="2.0.1" />
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.20" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.23" />
|
||||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||||
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
|
<PackageReference Include="Hangfire.InMemory" Version="1.0.0" />
|
||||||
<PackageReference Include="Hangfire.SqlServer" Version="1.8.20" />
|
<PackageReference Include="Hangfire.SqlServer" Version="1.8.23" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
|
||||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Email" Version="4.1.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="10.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -136,7 +136,14 @@
|
|||||||
<param name="opt"></param>
|
<param name="opt"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.FinishMedicalReview(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.FinishMedicalReviewInDto})">
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.AmendmentPatientInfo(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Contracts.EditPatientInfoCommand})">
|
||||||
|
<summary>
|
||||||
|
修正患者基本信息
|
||||||
|
</summary>
|
||||||
|
<param name="opt"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.FinishMedicalReview(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.CloseAndFinishMedicalReview})">
|
||||||
<summary>
|
<summary>
|
||||||
医学审核完成
|
医学审核完成
|
||||||
</summary>
|
</summary>
|
||||||
@@ -206,6 +213,13 @@
|
|||||||
<param name="opt"></param>
|
<param name="opt"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.SubmitJudgeForm(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Service.Reading.Dto.SetJudgeFormInDto})">
|
||||||
|
<summary>
|
||||||
|
提交阅片裁判表单
|
||||||
|
</summary>
|
||||||
|
<param name="opt"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.ConfigTrialBasicInfoConfirm(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Contracts.BasicTrialConfig})">
|
<member name="M:IRaCIS.Core.API.Controllers.InspectionController.ConfigTrialBasicInfoConfirm(IRaCIS.Core.Application.Service.Inspection.DTO.DataInspectionDto{IRaCIS.Core.Application.Contracts.BasicTrialConfig})">
|
||||||
<summary>
|
<summary>
|
||||||
配置 基础逻辑信息并确认
|
配置 基础逻辑信息并确认
|
||||||
@@ -344,6 +358,13 @@
|
|||||||
</summary>
|
</summary>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IRaCIS.Core.API.HostService.SyncFileRecoveryService.ExecuteAsync(System.Threading.CancellationToken)">
|
||||||
|
<summary>
|
||||||
|
多个程序,如果恢复同一份数据,造成重复同步,SCP服务不恢复任务
|
||||||
|
</summary>
|
||||||
|
<param name="stoppingToken"></param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="T:IRaCIS.Core.API.IpPolicyRateLimitSetup">
|
<member name="T:IRaCIS.Core.API.IpPolicyRateLimitSetup">
|
||||||
<summary>
|
<summary>
|
||||||
IPLimit限流 启动服务
|
IPLimit限流 启动服务
|
||||||
@@ -364,6 +385,11 @@
|
|||||||
LowerCamelCaseJsonAttribute 可以设置类小写返回给前端
|
LowerCamelCaseJsonAttribute 可以设置类小写返回给前端
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="T:Program">
|
||||||
|
<summary>
|
||||||
|
Auto-generated public partial Program class for top-level statement apps.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
<member name="T:ZhaoXi._001.NET5Demo.Practice.WebApi.Utility.Jwt.CustomHSJWTService">
|
||||||
<summary>
|
<summary>
|
||||||
对称可逆加密
|
对称可逆加密
|
||||||
@@ -399,5 +425,49 @@
|
|||||||
<param name="withPrivate"></param>
|
<param name="withPrivate"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type)">
|
||||||
|
<summary>
|
||||||
|
Generates a documentation comment ID for a type.
|
||||||
|
Example: T:Namespace.Outer+Inner`1 becomes T:Namespace.Outer.Inner`1
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.PropertyInfo)">
|
||||||
|
<summary>
|
||||||
|
Generates a documentation comment ID for a property.
|
||||||
|
Example: P:Namespace.ContainingType.PropertyName or for an indexer P:Namespace.ContainingType.Item(System.Int32)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Type,System.String)">
|
||||||
|
<summary>
|
||||||
|
Generates a documentation comment ID for a property given its container type and property name.
|
||||||
|
Example: P:Namespace.ContainingType.PropertyName
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.CreateDocumentationId(System.Reflection.MethodInfo)">
|
||||||
|
<summary>
|
||||||
|
Generates a documentation comment ID for a method (or constructor).
|
||||||
|
For example:
|
||||||
|
M:Namespace.ContainingType.MethodName(ParamType1,ParamType2)~ReturnType
|
||||||
|
M:Namespace.ContainingType.#ctor(ParamType)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.GetTypeDocId(System.Type,System.Boolean,System.Boolean)">
|
||||||
|
<summary>
|
||||||
|
Generates a documentation ID string for a type.
|
||||||
|
This method handles nested types (replacing '+' with '.'),
|
||||||
|
generic types, arrays, pointers, by-ref types, and generic parameters.
|
||||||
|
The <paramref name="includeGenericArguments"/> flag controls whether
|
||||||
|
constructed generic type arguments are emitted, while <paramref name="omitGenericArity"/>
|
||||||
|
controls whether the generic arity marker (e.g. "`1") is appended.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:Microsoft.AspNetCore.OpenApi.Generated.DocumentationCommentIdHelper.NormalizeDocId(System.String)">
|
||||||
|
<summary>
|
||||||
|
Normalizes a documentation comment ID to match the compiler-style format.
|
||||||
|
Strips the return type suffix for ordinary methods but retains it for conversion operators.
|
||||||
|
</summary>
|
||||||
|
<param name="docId">The documentation comment ID to normalize.</param>
|
||||||
|
<returns>The normalized documentation comment ID.</returns>
|
||||||
|
</member>
|
||||||
</members>
|
</members>
|
||||||
</doc>
|
</doc>
|
||||||
|
|||||||
+14
-17
@@ -1,31 +1,19 @@
|
|||||||
using IRaCIS.Core.API;
|
using FellowOakDicom;
|
||||||
|
using IRaCIS.Core.API;
|
||||||
using IRaCIS.Core.API.HostService;
|
using IRaCIS.Core.API.HostService;
|
||||||
using IRaCIS.Core.Application.BusinessFilter;
|
using IRaCIS.Core.Application.BusinessFilter;
|
||||||
using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api;
|
using IRaCIS.Core.Application.BusinessFilter.LegacyController.Database.Api;
|
||||||
using IRaCIS.Core.Application.Filter;
|
using IRaCIS.Core.Application.Filter;
|
||||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
|
||||||
using IRaCIS.Core.Application.Service;
|
using IRaCIS.Core.Application.Service;
|
||||||
using IRaCIS.Core.Application.Service.BusinessFilter;
|
|
||||||
using IRaCIS.Core.Infra.EFCore;
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using MassTransit.NewIdProviders;
|
using MassTransit.NewIdProviders;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using UAParser;
|
||||||
|
|
||||||
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||||
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
||||||
@@ -63,7 +51,8 @@ SerilogExtension.AddSerilogSetup(enviromentName);
|
|||||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||||
{
|
{
|
||||||
|
|
||||||
EnvironmentName = enviromentName
|
EnvironmentName = enviromentName,
|
||||||
|
Args = args
|
||||||
});
|
});
|
||||||
|
|
||||||
#region 主机配置
|
#region 主机配置
|
||||||
@@ -88,6 +77,12 @@ builder.Services.ConfigureServices(_configuration);
|
|||||||
|
|
||||||
builder.Services.AddHostedService<HangfireHostService>();
|
builder.Services.AddHostedService<HangfireHostService>();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<FileSyncQueue>();
|
||||||
|
builder.Services.AddHostedService<SyncFileRecoveryService>();
|
||||||
|
builder.Services.AddHostedService<FileSyncWorker>();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton(_ => Parser.GetDefault());
|
||||||
|
|
||||||
//minimal api 异常处理
|
//minimal api 异常处理
|
||||||
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
||||||
//builder.Services.AddProblemDetails();
|
//builder.Services.AddProblemDetails();
|
||||||
@@ -96,7 +91,7 @@ builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
|
|||||||
builder.Services.AddHealthChecks();
|
builder.Services.AddHealthChecks();
|
||||||
builder.Services.AddSerilog();
|
builder.Services.AddSerilog();
|
||||||
//本地化
|
//本地化
|
||||||
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
builder.Services.AddJsonLocalization(options => options.ResourcesPath = new[] { "Resources" });
|
||||||
|
|
||||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||||
builder.Services.AddControllers(options =>
|
builder.Services.AddControllers(options =>
|
||||||
@@ -173,6 +168,7 @@ var env = app.Environment;
|
|||||||
|
|
||||||
#region 配置中间件
|
#region 配置中间件
|
||||||
|
|
||||||
|
DicomSetupBuilder.UseServiceProvider(app.Services);
|
||||||
|
|
||||||
app.UseMiddleware<EncryptionRequestMiddleware>();
|
app.UseMiddleware<EncryptionRequestMiddleware>();
|
||||||
|
|
||||||
@@ -278,6 +274,7 @@ try
|
|||||||
#region 运行环境 部署平台
|
#region 运行环境 部署平台
|
||||||
|
|
||||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||||
|
Log.Logger.Warning($".NET 运行时版本:{Environment.Version}");
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,24 @@
|
|||||||
},
|
},
|
||||||
"applicationUrl": "http://0.0.0.0:6100"
|
"applicationUrl": "http://0.0.0.0:6100"
|
||||||
},
|
},
|
||||||
|
"IRaCIS.Test_Rayplus": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Test_Rayplus",
|
||||||
|
"ASPNETCORE_OpenSwagger": "true"
|
||||||
|
},
|
||||||
|
"applicationUrl": "http://0.0.0.0:6100"
|
||||||
|
},
|
||||||
|
"IRaCIS.Uat_Rayplus": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Uat_Rayplus",
|
||||||
|
"ASPNETCORE_OpenSwagger": "true"
|
||||||
|
},
|
||||||
|
"applicationUrl": "http://0.0.0.0:6100"
|
||||||
|
},
|
||||||
"IRaCIS.Test_IRC_PGSQL": {
|
"IRaCIS.Test_IRC_PGSQL": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
@@ -33,11 +51,11 @@
|
|||||||
},
|
},
|
||||||
"applicationUrl": "http://0.0.0.0:6100"
|
"applicationUrl": "http://0.0.0.0:6100"
|
||||||
},
|
},
|
||||||
"IRaCIS.Event_IRC": {
|
"IRaCIS.Prod_Event_IRC": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Event_IRC"
|
"ASPNETCORE_ENVIRONMENT": "Prod_Event_IRC"
|
||||||
},
|
},
|
||||||
"applicationUrl": "http://0.0.0.0:6100"
|
"applicationUrl": "http://0.0.0.0:6100"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using UAParser;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API
|
namespace IRaCIS.Core.API
|
||||||
{
|
{
|
||||||
@@ -17,11 +18,14 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
app.UseMiddleware<RequestResponseLoggingMiddleware>();
|
app.UseMiddleware<RequestResponseLoggingMiddleware>();
|
||||||
|
|
||||||
|
// 从 DI 容器中获取 Parser 实例
|
||||||
|
var uaParser = app.ApplicationServices.GetRequiredService<Parser>();
|
||||||
|
|
||||||
app.UseSerilogRequestLogging(opts
|
app.UseSerilogRequestLogging(opts
|
||||||
=>
|
=>
|
||||||
{
|
{
|
||||||
|
|
||||||
opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
opts.MessageTemplate = "{FullName} {UserType} {UserIp} {Host} {RequestMethod} {RequestPath}{QueryString} {RequestBody} {OS} {Browser} {DeviceType} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||||
|
|
||||||
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
|
opts.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
|
||||||
{
|
{
|
||||||
@@ -33,10 +37,9 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
|
|
||||||
// Only set it if available. You're not sending sensitive data in a querystring right?!
|
// Only set it if available. You're not sending sensitive data in a querystring right?!
|
||||||
if (request.QueryString.HasValue)
|
|
||||||
{
|
diagnosticContext.Set("QueryString", request.QueryString.Value ?? "");
|
||||||
diagnosticContext.Set("QueryString", request.QueryString.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnosticContext.Set("FullName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.FullName)?.Value);
|
diagnosticContext.Set("FullName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.FullName)?.Value);
|
||||||
|
|
||||||
@@ -52,6 +55,38 @@ namespace IRaCIS.Core.API
|
|||||||
|
|
||||||
diagnosticContext.Set("UserIp", clientIp);
|
diagnosticContext.Set("UserIp", clientIp);
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== 新增:解析 User-Agent ====================
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(userAgent))
|
||||||
|
{
|
||||||
|
var clientInfo = uaParser.Parse(userAgent);
|
||||||
|
|
||||||
|
diagnosticContext.Set("OS", clientInfo.OS.ToString());
|
||||||
|
diagnosticContext.Set("Browser", clientInfo.UA.ToString());
|
||||||
|
//diagnosticContext.Set("DeviceType", clientInfo.Device.ToString());
|
||||||
|
diagnosticContext.Set("DeviceType", userAgent.Contains("Mobile") ? "Mobile": "Desktop");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diagnosticContext.Set("OS", "Unknown");
|
||||||
|
diagnosticContext.Set("Browser", "Unknown");
|
||||||
|
diagnosticContext.Set("DeviceType", "Unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 解析失败时记录异常,但不要影响主流程
|
||||||
|
diagnosticContext.Set("OS", "ParseError");
|
||||||
|
diagnosticContext.Set("Browser", "ParseError");
|
||||||
|
diagnosticContext.Set("DeviceType", "ParseError");
|
||||||
|
}
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
#region 非必要不记录
|
#region 非必要不记录
|
||||||
//diagnosticContext.Set("Protocol", request.Protocol);
|
//diagnosticContext.Set("Protocol", request.Protocol);
|
||||||
//diagnosticContext.Set("Scheme", request.Scheme);
|
//diagnosticContext.Set("Scheme", request.Scheme);
|
||||||
|
|||||||
@@ -8,13 +8,21 @@ namespace IRaCIS.Core.API
|
|||||||
{
|
{
|
||||||
public static void AddDicomSetup(this IServiceCollection services)
|
public static void AddDicomSetup(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// ⭐ 先做全局 DICOM 配置
|
||||||
new DicomSetupBuilder()
|
new DicomSetupBuilder()
|
||||||
.RegisterServices(s => s.AddFellowOakDicom()
|
.SkipValidation() // 👈 在这里设置
|
||||||
.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
.Build();
|
||||||
.AddImageManager<ImageSharpImageManager>()
|
|
||||||
)
|
services.AddFellowOakDicom().AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>().AddImageManager<ImageSharpImageManager>();
|
||||||
.SkipValidation()
|
|
||||||
.Build();
|
// new DicomSetupBuilder()
|
||||||
|
// .RegisterServices(s => s.AddFellowOakDicom()
|
||||||
|
//.AddTranscoderManager<FellowOakDicom.Imaging.NativeCodec.NativeTranscoderManager>()
|
||||||
|
// .AddImageManager<ImageSharpImageManager>()
|
||||||
|
// )
|
||||||
|
// .SkipValidation()
|
||||||
|
// .Build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ namespace IRaCIS.Core.API
|
|||||||
var dbType = configuration.GetSection("ConnectionStrings:Db_Type").Value;
|
var dbType = configuration.GetSection("ConnectionStrings:Db_Type").Value;
|
||||||
if (!string.IsNullOrWhiteSpace(dbType) && dbType == "pgsql")
|
if (!string.IsNullOrWhiteSpace(dbType) && dbType == "pgsql")
|
||||||
{
|
{
|
||||||
options.UseNpgsql(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure());
|
options.UseNpgsql(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure().CommandTimeout(90));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()/*.CommandTimeout(60)*/);
|
options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure().CommandTimeout(90));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,19 +46,19 @@ namespace IRaCIS.Core.API
|
|||||||
var emailConfig = new SystemEmailSendConfig();
|
var emailConfig = new SystemEmailSendConfig();
|
||||||
configuration.GetSection("SystemEmailSendConfig").Bind(emailConfig);
|
configuration.GetSection("SystemEmailSendConfig").Bind(emailConfig);
|
||||||
|
|
||||||
if (emailConfig.IsOpenErrorNoticeEmail)
|
//if (emailConfig.IsOpenErrorNoticeEmail)
|
||||||
{
|
//{
|
||||||
config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions()
|
// config.WriteTo.Email(options: new Serilog.Sinks.Email.EmailSinkOptions()
|
||||||
{
|
// {
|
||||||
From = emailConfig.FromEmail,
|
// From = emailConfig.FromEmail,
|
||||||
To = emailConfig.ErrorNoticeEmailList,
|
// To = emailConfig.ErrorNoticeEmailList,
|
||||||
Host = emailConfig.Host,
|
// Host = emailConfig.Host,
|
||||||
Port = emailConfig.Port,
|
// Port = emailConfig.Port,
|
||||||
Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"),
|
// Subject = new MessageTemplateTextFormatter("Log Alert - 系统发生了异常,请核查"),
|
||||||
Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode)
|
// Credentials = new NetworkCredential(emailConfig.FromEmail, emailConfig.AuthorizationCode)
|
||||||
|
|
||||||
}, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
|
// }, restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error);
|
||||||
}
|
//}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
Log.Logger = config.CreateLogger();
|
Log.Logger = config.CreateLogger();
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.OpenApi;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using Swashbuckle.AspNetCore.Filters;
|
using Swashbuckle.AspNetCore.Filters;
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
|
||||||
using Swashbuckle.AspNetCore.SwaggerUI;
|
using Swashbuckle.AspNetCore.SwaggerUI;
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace IRaCIS.Core.API;
|
namespace IRaCIS.Core.API;
|
||||||
@@ -52,18 +44,21 @@ public static class SwaggerSetup
|
|||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
|
|
||||||
typeof(SwaggerVersion).GetFields(BindingFlags.Public | BindingFlags.Static).ToList()
|
// 使用反射获取字段并动态创建 Swagger 文档
|
||||||
.ForEach(field =>
|
typeof(SwaggerVersion).GetFields(BindingFlags.Public | BindingFlags.Static)
|
||||||
{
|
.ToList()
|
||||||
var description = field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? field.Name;
|
.ForEach(field =>
|
||||||
options.SwaggerDoc(field.Name, new Microsoft.OpenApi.Models.OpenApiInfo
|
{
|
||||||
{
|
var description = field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? field.Name;
|
||||||
Version = field.Name,
|
options.SwaggerDoc(field.Name, new OpenApiInfo
|
||||||
Description = $"{field.Name} API",
|
{
|
||||||
Title = description // 使用Description作为Title
|
Version = field.Name,
|
||||||
});
|
Description = $"{field.Name} API",
|
||||||
});
|
Title = description // 使用 Description 作为 Title
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// 接口排序
|
// 接口排序
|
||||||
options.OrderActionsBy(o => o.GroupName);
|
options.OrderActionsBy(o => o.GroupName);
|
||||||
|
|
||||||
@@ -116,6 +111,9 @@ public static class SwaggerSetup
|
|||||||
//DocExpansion设置为none可折叠所有方法
|
//DocExpansion设置为none可折叠所有方法
|
||||||
options.DocExpansion(DocExpansion.None);
|
options.DocExpansion(DocExpansion.None);
|
||||||
|
|
||||||
|
// 开启Swagger UI的搜索/过滤功能
|
||||||
|
options.EnableFilter();
|
||||||
|
|
||||||
//DefaultModelsExpandDepth设置为 - 1 可不显示models
|
//DefaultModelsExpandDepth设置为 - 1 可不显示models
|
||||||
options.DefaultModelsExpandDepth(-1);
|
options.DefaultModelsExpandDepth(-1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft": "Warning",
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ConnectionStrings": {
|
|
||||||
"RemoteNew": "Server=101.132.253.119,1435;Database=irc_Prpd_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
|
||||||
"Hangfire": "Server=101.132.253.119,1435;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
|
||||||
},
|
|
||||||
"ObjectStoreService": {
|
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
|
||||||
"AliyunOSS": {
|
|
||||||
"RegionId": "cn-shanghai",
|
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
|
||||||
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
|
||||||
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
|
||||||
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
|
||||||
"BucketName": "tl-med-irc-event-store",
|
|
||||||
"ViewEndpoint": "https://tl-med-irc-event-store.oss-cn-shanghai.aliyuncs.com",
|
|
||||||
"Region": "oss-cn-shanghai",
|
|
||||||
"DurationSeconds": 7200
|
|
||||||
},
|
|
||||||
"MinIO": {
|
|
||||||
"endpoint": "http://192.168.3.68",
|
|
||||||
"port": "8001",
|
|
||||||
"useSSL": false,
|
|
||||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
|
||||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
|
||||||
"bucketName": "test"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"BasicSystemConfig": {
|
|
||||||
// 启用质控风险控制功能
|
|
||||||
"QCRiskControl": true,
|
|
||||||
"OpenUserComplexPassword": true,
|
|
||||||
|
|
||||||
"OpenSignDocumentBeforeWork": true,
|
|
||||||
|
|
||||||
"OpenLoginLimit": true,
|
|
||||||
"LoginMaxFailCount": 5,
|
|
||||||
|
|
||||||
"LoginFailLockMinutes": 30,
|
|
||||||
"AutoLoginOutMinutes": 60,
|
|
||||||
|
|
||||||
"ContinuousReadingTimeMin": 120,
|
|
||||||
|
|
||||||
"ReadingRestTimeMin": 10,
|
|
||||||
|
|
||||||
"IsNeedChangePassWord": true,
|
|
||||||
|
|
||||||
"ChangePassWordDays": 90,
|
|
||||||
|
|
||||||
// 模板类型 1 Elevate 2 Extensive
|
|
||||||
"TemplateType": 2,
|
|
||||||
|
|
||||||
"UserMFAVerifyMinutes": 1440
|
|
||||||
},
|
|
||||||
"SystemEmailSendConfig": {
|
|
||||||
"Port": 465,
|
|
||||||
"Host": "smtp.qiye.aliyun.com",
|
|
||||||
"Imap": "imap.qiye.aliyun.com",
|
|
||||||
"ImapPort": 993,
|
|
||||||
"FromEmail": "uat@extimaging.com",
|
|
||||||
"FromName": "UAT_IRC",
|
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
|
||||||
"SiteUrl": "http://irc.event.extimaging.com/login",
|
|
||||||
"CompanyName": "Extensive Imaging",
|
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
|
||||||
"CompanyShortName": "Extensive Imaging",
|
|
||||||
"CompanyShortNameCN": "展影医疗",
|
|
||||||
"IsEnv_US": false
|
|
||||||
},
|
|
||||||
"RequestDuplicationOptions": {
|
|
||||||
"IsEnabled": true,
|
|
||||||
"DuplicationWindowMs": 200,
|
|
||||||
"CacheTimeSeconds": 5,
|
|
||||||
"ExcludedPaths": [
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.193.237,1433;Database=Prod_IRC_pidr_restore;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=101.132.193.237,1433;Database=irc_Hangfire_bak;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||||
|
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"WeComNoticeConfig": {
|
||||||
|
"IsOpenWeComNotice": true,
|
||||||
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "eiirc.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
|
"BucketName": "zy-irc-store",
|
||||||
|
"ViewEndpoint": "https://zy-irc-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||||
|
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||||
|
"BucketName": "ei-med-s3-irc-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
// 启用质控风险控制功能
|
||||||
|
"QCRiskControl": true,
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 120,
|
||||||
|
|
||||||
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
// 模板类型 1 Elevate 2 Extensive
|
||||||
|
"TemplateType": 2,
|
||||||
|
//MFA免验证发送天数
|
||||||
|
"UserMFAVerifyMinutes": 1440
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
"ImapPort": 993,
|
||||||
|
"FromEmail": "irc@extimaging.com",
|
||||||
|
"FromName": "EIC Imaging System",
|
||||||
|
"AuthorizationCode": "ExtImg@2022",
|
||||||
|
"SiteUrl": "http://irc.event.extimaging.com/login",
|
||||||
|
|
||||||
|
"PlatformName": "EICS",
|
||||||
|
"PlatformNameCN": "展影云平台",
|
||||||
|
"SystemShortName": "IRC",
|
||||||
|
"OrganizationName": "ExtImaging",
|
||||||
|
"OrganizationNameCN": "ExtImaging",
|
||||||
|
"CompanyName": "Extensive Imaging",
|
||||||
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
|
"CompanyShortName": "Extensive Imaging",
|
||||||
|
"CompanyShortNameCN": "展影医疗",
|
||||||
|
"IsEnv_US": false,
|
||||||
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
|
},
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "101.132.193.237"
|
||||||
|
},
|
||||||
|
"RequestDuplicationOptions": {
|
||||||
|
"IsEnabled": true,
|
||||||
|
"DuplicationWindowMs": 500,
|
||||||
|
"CacheTimeSeconds": 5,
|
||||||
|
"ExcludedPaths": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,19 +7,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"RemoteNew": "Server=101.132.193.237,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
//"RemoteNew": "Server=10.10.10.49,1434;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||||
"Hangfire": "Server=101.132.193.237,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
//"Hangfire": "Server=10.10.10.49,1434;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||||
//"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_IRC;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||||
//"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_IRC_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||||
},
|
},
|
||||||
"WeComNoticeConfig": {
|
"WeComNoticeConfig": {
|
||||||
"IsOpenWeComNotice": true,
|
"IsOpenWeComNotice": true,
|
||||||
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
"APINoticeUserList": [ "u", "wait..." ],
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621697b96f74e6f3d" ]
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "eiirc.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
@@ -32,13 +52,16 @@
|
|||||||
"Region": "oss-cn-shanghai",
|
"Region": "oss-cn-shanghai",
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
},
|
},
|
||||||
"MinIO": {
|
"AWS": {
|
||||||
"endpoint": "http://192.168.3.68",
|
"Region": "us-east-1",
|
||||||
"port": "8001",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"useSSL": false,
|
"UseSSL": true,
|
||||||
"accessKey": "IDFkwEpWej0b4DtiuThL",
|
"RoleArn": "arn:aws:iam::471112624751:role/lili_s3_access",
|
||||||
"secretKey": "Lhuu83yMhVwu7c1SnjvGY6lq74jzpYqifK6Qtj4h",
|
"AccessKeyId": "AKIAW3MEAFJXZ2TZK7GM",
|
||||||
"bucketName": "test"
|
"SecretAccessKey": "9MLQCQ1HifEVW1gf068zBRAOb4wNnfrOkvBVByth",
|
||||||
|
"BucketName": "ei-med-s3-irc-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-irc-store.s3.amazonaws.com",
|
||||||
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
@@ -71,7 +94,7 @@
|
|||||||
"Imap": "imap.qiye.aliyun.com",
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
"ImapPort": 993,
|
"ImapPort": 993,
|
||||||
"FromEmail": "irc@extimaging.com",
|
"FromEmail": "irc@extimaging.com",
|
||||||
"FromName": "IRC Imaging System",
|
"FromName": "EIC Imaging System",
|
||||||
"AuthorizationCode": "ExtImg@2022",
|
"AuthorizationCode": "ExtImg@2022",
|
||||||
"SiteUrl": "http://irc.extimaging.com/login",
|
"SiteUrl": "http://irc.extimaging.com/login",
|
||||||
|
|
||||||
@@ -85,10 +108,8 @@
|
|||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"IsEnv_US": false,
|
"IsEnv_US": false,
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
"CronEmailDefaultCulture": "zh-CN",
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
"Port": "11113",
|
"Port": "11113",
|
||||||
@@ -96,7 +117,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=prod_mssql_standard,1433;Database=Prod_Rayplus_Hangfire;User ID=sa;Password=zhanying@2021;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"WeComNoticeConfig": {
|
||||||
|
"IsOpenWeComNotice": true,
|
||||||
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
|
"port": "80",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||||
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
|
"bucketName": "irc-uat"
|
||||||
|
|
||||||
|
},
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
// 启用质控风险控制功能
|
||||||
|
"QCRiskControl": true,
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 120,
|
||||||
|
|
||||||
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
// 模板类型 1 Elevate 2 Extensive
|
||||||
|
"TemplateType": 2,
|
||||||
|
//MFA免验证发送天数
|
||||||
|
"UserMFAVerifyMinutes": 1440
|
||||||
|
|
||||||
|
},
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
"ImapPort": 993,
|
||||||
|
"FromEmail": "irc@mail.rayplus.net",
|
||||||
|
"FromName": "RayPlus Imaging System",
|
||||||
|
"AuthorizationCode": "QWE1zxcv7632",
|
||||||
|
"SiteUrl": "https://irc.rayplus.net/login",
|
||||||
|
|
||||||
|
"PlatformName": "RayPlus",
|
||||||
|
"PlatformNameCN": "睿佳影像云平台",
|
||||||
|
"SystemShortName": "RayPlus",
|
||||||
|
"OrganizationName": "RayPlus",
|
||||||
|
"OrganizationNameCN": "RayPlus",
|
||||||
|
"CompanyName": "RayPlus",
|
||||||
|
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
|
||||||
|
"CompanyShortName": "RayPlus",
|
||||||
|
"CompanyShortNameCN": "睿佳",
|
||||||
|
"IsEnv_US": false,
|
||||||
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "47.117.165.18"
|
||||||
|
},
|
||||||
|
"RequestDuplicationOptions": {
|
||||||
|
"IsEnabled": true,
|
||||||
|
"DuplicationWindowMs": 200,
|
||||||
|
"CacheTimeSeconds": 5,
|
||||||
|
"ExcludedPaths": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,193 +1,132 @@
|
|||||||
{
|
{
|
||||||
// 日志信息
|
|
||||||
"Logging": {
|
"Logging": {
|
||||||
// 日志等级
|
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
// 默认日志等级
|
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
// 调试日志等级
|
|
||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
// ASP.NET Core 日志等级
|
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 数据库链接字符串
|
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
// 本地数据库链接字符串
|
|
||||||
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_IRC;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
// Hangfire 定时任务数据库链接字符串
|
|
||||||
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_IRC_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
},
|
},
|
||||||
"WeComNoticeConfig": {
|
"WeComNoticeConfig": {
|
||||||
"IsOpenWeComNotice": true,
|
"IsOpenWeComNotice": true,
|
||||||
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449",
|
||||||
"APINoticeUserList": [ "u", "wait..." ],
|
"APINoticeUserList": [
|
||||||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621697b96f74e6f3d" ]
|
"u",
|
||||||
|
"wait..."
|
||||||
|
],
|
||||||
|
"VueNoticeUserList": [
|
||||||
|
"wangxiaoshuang",
|
||||||
|
"6b7717a31647293621b97b96f74e6f3d"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
// 对象存储服务配置
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
// 使用的对象存储服务类型
|
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
// 阿里云对象存储服务的配置
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.test.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.test.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
// 阿里云 OSS 的 Region ID
|
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
// 阿里云 OSS 的内部访问端点
|
|
||||||
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
// 阿里云 OSS 的外部访问端点
|
|
||||||
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
// 阿里云 OSS 的访问密钥 ID
|
|
||||||
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
// 阿里云 OSS 的访问密钥 Secret
|
|
||||||
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
// 阿里云 OSS 的角色 ARN
|
|
||||||
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
// 阿里云 OSS 的Bucket名称
|
|
||||||
"BucketName": "zy-irc-test-store",
|
"BucketName": "zy-irc-test-store",
|
||||||
// 阿里云 OSS 的访问端点
|
|
||||||
"ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com",
|
"ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
// 阿里云 OSS 的预览端点
|
|
||||||
"Region": "oss-cn-shanghai",
|
"Region": "oss-cn-shanghai",
|
||||||
// 阿里云 OSS 的临时访问凭证有效时间(秒)
|
|
||||||
"DurationSeconds": 7200,
|
"DurationSeconds": 7200,
|
||||||
// 阿里云 OSS 的预览端点
|
|
||||||
"PreviewEndpoint": "https://test-oss.test.extimaging.com"
|
"PreviewEndpoint": "https://test-oss.test.extimaging.com"
|
||||||
},
|
},
|
||||||
// MinIO 对象存储服务的配置
|
|
||||||
"MinIO": {
|
"MinIO": {
|
||||||
// MinIO 的访问端点
|
|
||||||
"EndPoint": "hir-oss.test.extimaging.com",
|
"EndPoint": "hir-oss.test.extimaging.com",
|
||||||
// MinIO 的端口
|
|
||||||
"Port": "443",
|
"Port": "443",
|
||||||
// 是否使用 SSL
|
|
||||||
"UseSSL": true,
|
"UseSSL": true,
|
||||||
// MinIO 的角色 ARN
|
|
||||||
"AccessKey": "fbStsVYCIPKHQneeqMwD",
|
"AccessKey": "fbStsVYCIPKHQneeqMwD",
|
||||||
// MinIO 的访问密钥
|
|
||||||
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
"SecretKey": "TzgvyA3zGXMUnpilJNUlyMYHfosl1hBMl6lxPmjy",
|
||||||
// MinIO 的BucketName
|
|
||||||
"BucketName": "irc-test",
|
"BucketName": "irc-test",
|
||||||
// MinIO 的访问端点
|
|
||||||
"ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
"ViewEndpoint": "https://hir-oss.test.extimaging.com/irc-test"
|
||||||
},
|
},
|
||||||
// AWS S3 对象存储服务的配置
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
// AWS S3 的Region
|
|
||||||
"Region": "us-east-1",
|
"Region": "us-east-1",
|
||||||
// AWS S3 的内部访问端点
|
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
// 是否使用 SSL
|
|
||||||
"UseSSL": true,
|
"UseSSL": true,
|
||||||
// AWS S3 的角色 ARN
|
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
// AWS S3 的访问密钥 ID
|
|
||||||
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
// AWS S3 的访问密钥 Secret
|
|
||||||
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
// AWS S3 的Bucket名称
|
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
// AWS S3 的访问端点
|
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com",
|
||||||
// AWS S3 的持续数秒
|
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 系统配置
|
|
||||||
"BasicSystemConfig": {
|
"BasicSystemConfig": {
|
||||||
// 启用质控风险控制功能
|
|
||||||
"QCRiskControl": true,
|
"QCRiskControl": true,
|
||||||
// 打开用户复杂密码
|
|
||||||
"OpenUserComplexPassword": false,
|
"OpenUserComplexPassword": false,
|
||||||
// 是否在开始工作前强制签署电子知情同意书
|
|
||||||
"OpenSignDocumentBeforeWork": false,
|
"OpenSignDocumentBeforeWork": false,
|
||||||
// 是否启用登录失败次数限制(防暴力破解)
|
|
||||||
"OpenLoginLimit": false,
|
"OpenLoginLimit": false,
|
||||||
// 连续登录失败多少次后触发锁定
|
|
||||||
"LoginMaxFailCount": 5,
|
"LoginMaxFailCount": 5,
|
||||||
// 触发锁定后账号锁定时长(分钟)
|
|
||||||
"LoginFailLockMinutes": 1,
|
"LoginFailLockMinutes": 1,
|
||||||
// 无操作自动登出的超时时间(分钟)
|
|
||||||
"AutoLoginOutMinutes": 10,
|
"AutoLoginOutMinutes": 10,
|
||||||
// 是否启用多因子登录认证(MFA)
|
|
||||||
"OpenLoginMFA": false,
|
"OpenLoginMFA": false,
|
||||||
// 连续阅片的最长工作时间(分钟),超时后强制休息
|
|
||||||
"ContinuousReadingTimeMin": 120,
|
"ContinuousReadingTimeMin": 120,
|
||||||
// 强制休息时长(分钟)
|
|
||||||
"ReadingRestTimeMin": 10,
|
"ReadingRestTimeMin": 10,
|
||||||
// 是否强制用户定期修改密码
|
|
||||||
"IsNeedChangePassWord": true,
|
"IsNeedChangePassWord": true,
|
||||||
// 密码有效期(天),到期后必须修改
|
|
||||||
"ChangePassWordDays": 90,
|
"ChangePassWordDays": 90,
|
||||||
// 模板类型 1 Elevate(LiLi) 2 Extensive(展影)
|
|
||||||
"TemplateType": 2,
|
"TemplateType": 2,
|
||||||
// 是否打开项目关联删除
|
"OpenTrialRelationDelete": false,
|
||||||
"OpenTrialRelationDelete": true,
|
|
||||||
// 转换PDF服务配置
|
|
||||||
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf",
|
"ThirdPdfUrl": "http://106.14.89.110:30088/api/v1/convert/file/pdf",
|
||||||
//MFA免验证发送天数
|
|
||||||
"UserMFAVerifyMinutes": 1440
|
"UserMFAVerifyMinutes": 1440
|
||||||
},
|
},
|
||||||
// 邮件服务配置(用于系统通知、找回密码、错误报警等)
|
|
||||||
"SystemEmailSendConfig": {
|
"SystemEmailSendConfig": {
|
||||||
// SMTP端口
|
|
||||||
"Port": 465,
|
|
||||||
// 企业邮箱SMTP服务器地址
|
|
||||||
"Host": "smtp.qiye.aliyun.com",
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Port": 465,
|
||||||
"Imap": "imap.qiye.aliyun.com",
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
|
||||||
"ImapPort": 993,
|
"ImapPort": 993,
|
||||||
// 发件人邮箱地址
|
|
||||||
"FromEmail": "test@extimaging.com",
|
"FromEmail": "test@extimaging.com",
|
||||||
// 发件人显示名称
|
"FromName": "Test EIC Imaging System",
|
||||||
"FromName": "Test IRC Imaging System",
|
|
||||||
// SMTP授权码
|
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
"AuthorizationCode": "SHzyyl2021",
|
||||||
// 系统对外访问地址
|
|
||||||
"SiteUrl": "http://irc.test.extimaging.com/login",
|
"SiteUrl": "http://irc.test.extimaging.com/login",
|
||||||
|
"SystemShortName": "IRC",
|
||||||
|
"OrganizationName": "ExtImaging",
|
||||||
|
"OrganizationNameCN": "ExtImaging",
|
||||||
"PlatformName": "EICS",
|
"PlatformName": "EICS",
|
||||||
"PlatformNameCN": "展影云平台",
|
"PlatformNameCN": "展影云平台",
|
||||||
// 系统简称一致性核查使用
|
|
||||||
"SystemShortName": "IRC",
|
|
||||||
// 组织英文名称
|
|
||||||
"OrganizationName": "ExtImaging",
|
|
||||||
// 组织中文名称
|
|
||||||
"OrganizationNameCN": "ExtImaging",
|
|
||||||
// 公司英文全称
|
|
||||||
"CompanyName": "Extensive Imaging",
|
"CompanyName": "Extensive Imaging",
|
||||||
// 公司中文全称
|
|
||||||
"CompanyNameCN": "上海展影医疗科技有限公司",
|
"CompanyNameCN": "上海展影医疗科技有限公司",
|
||||||
// 公司英文简称
|
|
||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
// 公司中文简称
|
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
// 是否为国际版环境
|
|
||||||
"IsEnv_US": false,
|
"IsEnv_US": false,
|
||||||
// 是否开启系统异常邮件报警
|
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
// 邮箱格式校验正则表达式
|
|
||||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
"CronEmailDefaultCulture": "zh-CN",
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
// 接收系统异常报警的邮箱列表
|
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
// PACS 连接配置
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
// PACS服务器端口
|
|
||||||
"Port": "11113",
|
"Port": "11113",
|
||||||
// PACS服务器IP地址
|
|
||||||
"IP": "106.14.89.110"
|
"IP": "106.14.89.110"
|
||||||
},
|
},
|
||||||
// 重复请求配置
|
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
// 是否启用重复请求检测
|
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
// 重复请求时间窗口(毫秒)
|
"DuplicationWindowMs": 500,
|
||||||
"DuplicationWindowMs": 200,
|
|
||||||
// 缓存请求时间(秒)
|
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": []
|
||||||
]
|
},
|
||||||
}
|
"FrontWebConfig": "222"
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=106.14.89.110,1435;Database=Test_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=106.14.89.110,1435;Database=Test_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"WeComNoticeConfig": {
|
||||||
|
"IsOpenWeComNotice": true,
|
||||||
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.test.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tRRZehUp2V9pyTPtAJm",
|
||||||
|
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-test-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-test-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
|
"port": "80",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||||
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
|
"bucketName": "irc-uat"
|
||||||
|
|
||||||
|
},
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
// 启用质控风险控制功能
|
||||||
|
"QCRiskControl": true,
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 120,
|
||||||
|
|
||||||
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
// 模板类型 1 Elevate 2 Extensive
|
||||||
|
"TemplateType": 2,
|
||||||
|
//MFA免验证发送天数
|
||||||
|
"UserMFAVerifyMinutes": 1440
|
||||||
|
|
||||||
|
},
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
"ImapPort": 993,
|
||||||
|
"FromEmail": "test_irc@mail.rayplus.net",
|
||||||
|
"FromName": "Test RayPlus Imaging System",
|
||||||
|
"AuthorizationCode": "QWE1zxcv7632",
|
||||||
|
"SiteUrl": "https://irc.test.rayplus.net/login",
|
||||||
|
|
||||||
|
"PlatformName": "RayPlus",
|
||||||
|
"PlatformNameCN": "睿佳影像云平台",
|
||||||
|
"SystemShortName": "RayPlus",
|
||||||
|
"OrganizationName": "RayPlus",
|
||||||
|
"OrganizationNameCN": "RayPlus",
|
||||||
|
"CompanyName": "RayPlus",
|
||||||
|
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
|
||||||
|
"CompanyShortName": "RayPlus",
|
||||||
|
"CompanyShortNameCN": "睿佳",
|
||||||
|
"IsEnv_US": false,
|
||||||
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "101.132.253.119"
|
||||||
|
},
|
||||||
|
"RequestDuplicationOptions": {
|
||||||
|
"IsEnabled": true,
|
||||||
|
"DuplicationWindowMs": 200,
|
||||||
|
"CacheTimeSeconds": 5,
|
||||||
|
"ExcludedPaths": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,20 +16,42 @@
|
|||||||
"IsOpenWeComNotice": true,
|
"IsOpenWeComNotice": true,
|
||||||
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
"APINoticeUserList": [ "u", "wait..." ],
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621697b96f74e6f3d" ]
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
"ObjectStoreUse": "AWS",
|
"ObjectStoreUse": "AWS",
|
||||||
"MinIO": {
|
"IsOpenStoreSync": true,
|
||||||
"endPoint": "44.210.231.169",
|
"ApiDeployRegion": "US",
|
||||||
"port": "9001",
|
"SyncConfigList": [
|
||||||
"useSSL": false,
|
{
|
||||||
"accessKey": "e9bT1isTOqSAUxb6wd4n",
|
"Domain": "eilili.elevateimaging.ai",
|
||||||
"secretKey": "b5TaDzNdQCBtCvfm8eZ3dR6yY7tfZu2JYze2Po1i",
|
"Primary": "AliyunOSS",
|
||||||
"bucketName": "prod-irc-us",
|
"Target": "AWS",
|
||||||
"viewEndpoint": "http://44.210.231.169:9001/prod-irc-us/"
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.elevateimaging.ai",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tNRTsqL6aWmHkDmTwoH",
|
||||||
|
"AccessKeySecret": "7mtGz3qrYWI6JMMBZiLeC119VWicZH",
|
||||||
|
"RoleArn": "acs:ram::1899121822495495:role/irc-oss-access",
|
||||||
|
"BucketName": "zy-lili-store",
|
||||||
|
"ViewEndpoint": "https://zy-lili-cache.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
},
|
},
|
||||||
|
|
||||||
"AWS": {
|
"AWS": {
|
||||||
"Region": "us-east-1",
|
"Region": "us-east-1",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
@@ -90,10 +112,8 @@
|
|||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.elevateimaging.ai/login",
|
||||||
"IsEnv_US": true,
|
"IsEnv_US": true,
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
"CronEmailDefaultCulture": "en-US",
|
"CronEmailDefaultCulture": "en-US"
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
@@ -102,7 +122,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -93,9 +93,7 @@
|
|||||||
"CompanyShortName": "Elevate Imaging",
|
"CompanyShortName": "Elevate Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.test.elevateimaging.ai/login",
|
||||||
"IsEnv_US": true,
|
"IsEnv_US": true
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
@@ -104,7 +102,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"IsOpenWeComNotice": true,
|
"IsOpenWeComNotice": true,
|
||||||
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
"APINoticeUserList": [ "u", "wait..." ],
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621697b96f74e6f3d" ]
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
},
|
},
|
||||||
|
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
@@ -97,10 +97,8 @@
|
|||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"SiteUrl": "https://lili.uat.elevateimaging.ai/login",
|
"SiteUrl": "https://lili.uat.elevateimaging.ai/login",
|
||||||
"IsEnv_US": true,
|
"IsEnv_US": true,
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
"CronEmailDefaultCulture": "en-US",
|
"CronEmailDefaultCulture": "en-US"
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
@@ -109,7 +107,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_HeAnShu;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_HeAnShu_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"WeComNoticeConfig": {
|
||||||
|
"IsOpenWeComNotice": true,
|
||||||
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
||||||
|
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
||||||
|
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
||||||
|
"BucketName": "heanshu-irc-uat-store",
|
||||||
|
"ViewEndpoint": "https://heanshu-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
|
"port": "80",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||||
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
|
"bucketName": "irc-uat"
|
||||||
|
|
||||||
|
},
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
// 启用质控风险控制功能
|
||||||
|
"QCRiskControl": true,
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 120,
|
||||||
|
|
||||||
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
// 模板类型 1 Elevate 2 Extensive
|
||||||
|
"TemplateType": 2,
|
||||||
|
//MFA免验证发送天数
|
||||||
|
"UserMFAVerifyMinutes": 1440
|
||||||
|
|
||||||
|
},
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
//"Port": 465,
|
||||||
|
//"Host": "smtp.qiye.163.com",
|
||||||
|
//"Imap": "imap.qiye.163.com",
|
||||||
|
//"ImapPort": 993,
|
||||||
|
//"FromEmail": "service@heanshu.com",
|
||||||
|
//"FromName": "Uat HeAnShu Imaging System",
|
||||||
|
//"AuthorizationCode": "j#cAPU%XgvcHWn3N",
|
||||||
|
//"SiteUrl": "https://irc.uat.heanshu.com",
|
||||||
|
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
"ImapPort": 993,
|
||||||
|
"FromEmail": "service@mail.rayplus.net",
|
||||||
|
"FromName": "Uat HeAnShu Imaging System",
|
||||||
|
"AuthorizationCode": "crefHpx3WtenFr6X",
|
||||||
|
"SiteUrl": "https://irc.uat.heanshu.com",
|
||||||
|
|
||||||
|
"PlatformName": "HeAnShu",
|
||||||
|
"PlatformNameCN": "禾安枢影像云平台",
|
||||||
|
"SystemShortName": "HeAnShu",
|
||||||
|
"OrganizationName": "HeAnShu",
|
||||||
|
"OrganizationNameCN": "HeAnShu",
|
||||||
|
"CompanyName": "HeAnShu",
|
||||||
|
"CompanyNameCN": "禾安枢软件科技有限公司",
|
||||||
|
"CompanyShortName": "HeAnShu",
|
||||||
|
"CompanyShortNameCN": "禾安枢",
|
||||||
|
"IsEnv_US": false,
|
||||||
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "101.132.253.119"
|
||||||
|
},
|
||||||
|
"RequestDuplicationOptions": {
|
||||||
|
"IsEnabled": true,
|
||||||
|
"DuplicationWindowMs": 200,
|
||||||
|
"CacheTimeSeconds": 5,
|
||||||
|
"ExcludedPaths": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,11 +14,31 @@
|
|||||||
"IsOpenWeComNotice": true,
|
"IsOpenWeComNotice": true,
|
||||||
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
"APINoticeUserList": [ "u", "wait..." ],
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621697b96f74e6f3d" ]
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
},
|
},
|
||||||
"ObjectStoreService": {
|
"ObjectStoreService": {
|
||||||
|
|
||||||
"ObjectStoreUse": "AliyunOSS",
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.extimaging.com",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
"AliyunOSS": {
|
"AliyunOSS": {
|
||||||
"RegionId": "cn-shanghai",
|
"RegionId": "cn-shanghai",
|
||||||
@@ -50,9 +70,9 @@
|
|||||||
"Region": "us-east-1",
|
"Region": "us-east-1",
|
||||||
"EndPoint": "s3.us-east-1.amazonaws.com",
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
"UseSSL": true,
|
"UseSSL": true,
|
||||||
"RoleArn": "arn:aws:iam::471112624751:role/sts_s3_upload",
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
"AccessKeyId": "AKIAW3MEAFJXWRCGSX5Z",
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
"SecretAccessKey": "miais4jQGSd37A+TfBEP11AQM5u/CvotSmznJd8k",
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
"BucketName": "ei-med-s3-lili-uat-store",
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
"DurationSeconds": 7200
|
"DurationSeconds": 7200
|
||||||
@@ -90,7 +110,7 @@
|
|||||||
"Imap": "imap.qiye.aliyun.com",
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
"ImapPort": 993,
|
"ImapPort": 993,
|
||||||
"FromEmail": "uat@extimaging.com",
|
"FromEmail": "uat@extimaging.com",
|
||||||
"FromName": "Uat IRC Imaging System",
|
"FromName": "Uat EIC Imaging System",
|
||||||
"AuthorizationCode": "SHzyyl2021",
|
"AuthorizationCode": "SHzyyl2021",
|
||||||
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
"SiteUrl": "http://irc.uat.extimaging.com/login",
|
||||||
|
|
||||||
@@ -104,10 +124,8 @@
|
|||||||
"CompanyShortName": "Extensive Imaging",
|
"CompanyShortName": "Extensive Imaging",
|
||||||
"CompanyShortNameCN": "展影医疗",
|
"CompanyShortNameCN": "展影医疗",
|
||||||
"IsEnv_US": false,
|
"IsEnv_US": false,
|
||||||
"IsOpenErrorNoticeEmail": false,
|
|
||||||
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
"CronEmailDefaultCulture": "zh-CN",
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
"ErrorNoticeEmailList": [ "872297557@qq.com" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"SystemPacsConfig": {
|
"SystemPacsConfig": {
|
||||||
@@ -116,7 +134,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"RemoteNew": "Server=101.132.253.119,1435;Database=Uat_Rayplus;User ID=sa;Password=xc@123456;TrustServerCertificate=true",
|
||||||
|
"Hangfire": "Server=101.132.253.119,1435;Database=Uat_Rayplus_Hangfire;User ID=sa;Password=xc@123456;TrustServerCertificate=true"
|
||||||
|
},
|
||||||
|
"WeComNoticeConfig": {
|
||||||
|
"IsOpenWeComNotice": true,
|
||||||
|
"WebhookUrl": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4355b98e-1e72-4678-8dfb-2fc6ad0bf449", //4355b98e-1e72-4678-8dfb-2fc6ad0bf449 //cdd97aab-d256-4f07-9145-a0a2b1555322
|
||||||
|
"APINoticeUserList": [ "u", "wait..." ],
|
||||||
|
"VueNoticeUserList": [ "wangxiaoshuang", "6b7717a31647293621b97b96f74e6f3d" ]
|
||||||
|
},
|
||||||
|
"ObjectStoreService": {
|
||||||
|
|
||||||
|
"ObjectStoreUse": "AliyunOSS",
|
||||||
|
"IsOpenStoreSync": true,
|
||||||
|
"ApiDeployRegion": "CN",
|
||||||
|
"SyncConfigList": [
|
||||||
|
{
|
||||||
|
"Domain": "irc.uat.rayplus.net",
|
||||||
|
"Primary": "AliyunOSS",
|
||||||
|
"Target": "AWS",
|
||||||
|
"UploadRegion": "CN",
|
||||||
|
"TargetRegion": "US",
|
||||||
|
"IsOpenSync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "lili.uat.extimaging.com",
|
||||||
|
"Primary": "AWS",
|
||||||
|
"Target": "AliyunOSS",
|
||||||
|
"UploadRegion": "US",
|
||||||
|
"TargetRegion": "CN",
|
||||||
|
"IsOpenSync": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"AliyunOSS": {
|
||||||
|
"RegionId": "cn-shanghai",
|
||||||
|
"InternalEndpoint": "https://oss-cn-shanghai-internal.aliyuncs.com",
|
||||||
|
"EndPoint": "https://oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"AccessKeyId": "LTAI5tFUCCmz5TwghZHsj45Y",
|
||||||
|
"AccessKeySecret": "8evrBy1fVfzJG25i67Jm0xqn9Xcw2T",
|
||||||
|
"RoleArn": "acs:ram::1078130221702011:role/uat-oss-access",
|
||||||
|
"BucketName": "rayplus-irc-uat-store",
|
||||||
|
"ViewEndpoint": "https://rayplus-irc-uat-store.oss-cn-shanghai.aliyuncs.com",
|
||||||
|
"Region": "oss-cn-shanghai",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
},
|
||||||
|
|
||||||
|
"MinIO": {
|
||||||
|
"endPoint": "hir-oss.uat.extimaging.com",
|
||||||
|
"port": "80",
|
||||||
|
"useSSL": false,
|
||||||
|
"viewEndpoint": "http://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
//"port": "443",
|
||||||
|
//"useSSL": true,
|
||||||
|
//"viewEndpoint": "https://hir-oss.uat.extimaging.com/irc-uat",
|
||||||
|
"accessKey": "b9Ul0e98xPzt6PwRXA1Q",
|
||||||
|
"secretKey": "DzMaU2L4OXl90uytwOmDXF2encN0Jf4Nxu2XkYqQ",
|
||||||
|
"bucketName": "irc-uat"
|
||||||
|
|
||||||
|
},
|
||||||
|
"AWS": {
|
||||||
|
"Region": "us-east-1",
|
||||||
|
"EndPoint": "s3.us-east-1.amazonaws.com",
|
||||||
|
"UseSSL": true,
|
||||||
|
"RoleArn": "arn:aws:iam::471112624751:role/uat_s3_access",
|
||||||
|
"AccessKeyId": "AKIAW3MEAFJX7IPXISP4",
|
||||||
|
"SecretAccessKey": "Pgrg3le5jPxZQ7MR1yYNS30J0XRyJeKVyIIjElXc",
|
||||||
|
"BucketName": "ei-med-s3-lili-uat-store",
|
||||||
|
"ViewEndpoint": "https://ei-med-s3-lili-uat-store.s3.amazonaws.com/",
|
||||||
|
"DurationSeconds": 7200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"BasicSystemConfig": {
|
||||||
|
// 启用质控风险控制功能
|
||||||
|
"QCRiskControl": true,
|
||||||
|
"OpenUserComplexPassword": true,
|
||||||
|
"OpenSignDocumentBeforeWork": true,
|
||||||
|
|
||||||
|
"OpenLoginLimit": true,
|
||||||
|
"LoginMaxFailCount": 5,
|
||||||
|
|
||||||
|
"LoginFailLockMinutes": 30,
|
||||||
|
"AutoLoginOutMinutes": 120,
|
||||||
|
|
||||||
|
"OpenLoginMFA": false,
|
||||||
|
|
||||||
|
"ContinuousReadingTimeMin": 120,
|
||||||
|
"ReadingRestTimeMin": 10,
|
||||||
|
|
||||||
|
"IsNeedChangePassWord": true,
|
||||||
|
"ChangePassWordDays": 90,
|
||||||
|
// 模板类型 1 Elevate 2 Extensive
|
||||||
|
"TemplateType": 2,
|
||||||
|
//MFA免验证发送天数
|
||||||
|
"UserMFAVerifyMinutes": 1440
|
||||||
|
|
||||||
|
},
|
||||||
|
"SystemEmailSendConfig": {
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "smtp.qiye.aliyun.com",
|
||||||
|
"Imap": "imap.qiye.aliyun.com",
|
||||||
|
"ImapPort": 993,
|
||||||
|
"FromEmail": "uat@mail.rayplus.net",
|
||||||
|
"FromName": "Uat RayPlus Imaging System",
|
||||||
|
"AuthorizationCode": "QWE1zxcv7632",
|
||||||
|
"SiteUrl": "https://irc.uat.rayplus.net/login",
|
||||||
|
|
||||||
|
"PlatformName": "RayPlus",
|
||||||
|
"PlatformNameCN": "睿佳影像云平台",
|
||||||
|
"SystemShortName": "RayPlus",
|
||||||
|
"OrganizationName": "RayPlus",
|
||||||
|
"OrganizationNameCN": "RayPlus",
|
||||||
|
"CompanyName": "RayPlus",
|
||||||
|
"CompanyNameCN": "睿佳(武汉)软件科技有限公司",
|
||||||
|
"CompanyShortName": "RayPlus",
|
||||||
|
"CompanyShortNameCN": "睿佳",
|
||||||
|
"IsEnv_US": false,
|
||||||
|
"EmailRegexStr": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
|
||||||
|
"CronEmailDefaultCulture": "zh-CN"
|
||||||
|
},
|
||||||
|
|
||||||
|
"SystemPacsConfig": {
|
||||||
|
"Port": "11113",
|
||||||
|
"IP": "101.132.253.119"
|
||||||
|
},
|
||||||
|
"RequestDuplicationOptions": {
|
||||||
|
"IsEnabled": true,
|
||||||
|
"DuplicationWindowMs": 200,
|
||||||
|
"CacheTimeSeconds": 5,
|
||||||
|
"ExcludedPaths": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
},
|
},
|
||||||
"RequestDuplicationOptions": {
|
"RequestDuplicationOptions": {
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"DuplicationWindowMs": 200,
|
"DuplicationWindowMs": 500,
|
||||||
"CacheTimeSeconds": 5,
|
"CacheTimeSeconds": 5,
|
||||||
"ExcludedPaths": [
|
"ExcludedPaths": [
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- HTML for static distribution bundle build -->
|
<!-- HTML for static distribution bundle build -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -112,8 +112,23 @@
|
|||||||
}, info: function () {
|
}, info: function () {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
fn: {
|
||||||
|
opsFilter: function (taggedOps, phrase) {
|
||||||
|
var normalPhrase = phrase.toLowerCase();
|
||||||
|
return taggedOps.map(function (tagObj, tag) {
|
||||||
|
var operations = tagObj.get("operations").filter(function (op) {
|
||||||
|
var summary = op.getIn(["operation", "summary"]) || "";
|
||||||
|
var path = op.get("path") || "";
|
||||||
|
var tagMatch = tag.toLowerCase().indexOf(normalPhrase) !== -1;
|
||||||
|
return tagMatch || summary.toLowerCase().indexOf(normalPhrase) !== -1 || path.toLowerCase().indexOf(normalPhrase) !== -1;
|
||||||
|
});
|
||||||
|
return tagObj.set("operations", operations);
|
||||||
|
}).filter(function (tagObj) {
|
||||||
|
return tagObj.get("operations").size > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
new Claim(JwtIRaCISClaimType.UserTypeShortName,user.UserTypeShortName),
|
new Claim(JwtIRaCISClaimType.UserTypeShortName,user.UserTypeShortName),
|
||||||
new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr),
|
new Claim(JwtIRaCISClaimType.PermissionStr,user.PermissionStr),
|
||||||
new Claim(JwtIRaCISClaimType.IsZhiZhun,user.IsZhiZhun.ToString()),
|
new Claim(JwtIRaCISClaimType.IsZhiZhun,user.IsZhiZhun.ToString()),
|
||||||
new Claim(JwtIRaCISClaimType.IsTestUser,user.IsTestUser.ToString())
|
new Claim(JwtIRaCISClaimType.IsTestUser,user.IsTestUser.ToString()),
|
||||||
|
new Claim(JwtIRaCISClaimType.UserWorkLanguage,user.UserWorkLanguage.ToString())
|
||||||
};
|
};
|
||||||
|
|
||||||
////创建令牌
|
////创建令牌
|
||||||
|
|||||||
@@ -23,5 +23,7 @@ namespace IRaCIS.Core.Application.Auth
|
|||||||
public bool IsZhiZhun { get; set; }
|
public bool IsZhiZhun { get; set; }
|
||||||
|
|
||||||
public string UserTypeShortName { get; set; } = string.Empty;
|
public string UserTypeShortName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public UserWorkLanguage UserWorkLanguage { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+58
-10
@@ -8,6 +8,8 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
{
|
{
|
||||||
using Database.Api;
|
using Database.Api;
|
||||||
using DocumentFormat.OpenXml.InkML;
|
using DocumentFormat.OpenXml.InkML;
|
||||||
|
using global::MassTransit;
|
||||||
|
using IRaCIS.Core.Application.Helper.OtherTool;
|
||||||
using IRaCIS.Core.Application.Service.Common;
|
using IRaCIS.Core.Application.Service.Common;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
@@ -17,6 +19,7 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
@@ -35,7 +38,7 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logger">logger</param>
|
/// <param name="logger">logger</param>
|
||||||
/// <param name="accessor">loggerHelper</param>
|
/// <param name="accessor">loggerHelper</param>
|
||||||
public class RequestDuplicationFilter(ILogger<RequestDuplicationFilter> logger, IHttpContextAccessor accessor, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<RequestDuplicationOptions> RequestDuplicationOptionsMonitor) : ExceptionFilterAttribute, IAsyncActionFilter
|
public class RequestDuplicationFilter(ILogger<RequestDuplicationFilter> logger, IHttpContextAccessor accessor, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<RequestDuplicationOptions> RequestDuplicationOptionsMonitor, IConfiguration _config) : ExceptionFilterAttribute, IAsyncActionFilter
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 传入的参数
|
/// 传入的参数
|
||||||
@@ -70,6 +73,10 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
{
|
{
|
||||||
this.RequestDuplication();
|
this.RequestDuplication();
|
||||||
}
|
}
|
||||||
|
catch (BusinessValidationFailedException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -89,8 +96,12 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
{
|
{
|
||||||
var requestPath = accessor?.HttpContext?.Request?.Path.ToString() ?? string.Empty;
|
var requestPath = accessor?.HttpContext?.Request?.Path.ToString() ?? string.Empty;
|
||||||
|
|
||||||
|
var httpMethod = accessor?.HttpContext?.Request?.Method?.ToUpper() ?? string.Empty;
|
||||||
|
|
||||||
// 验证请求频繁情况
|
// 验证请求频繁情况
|
||||||
if (
|
if (
|
||||||
|
!httpMethod.Equals("GET", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
|
||||||
!requestPath
|
!requestPath
|
||||||
.Split("/", StringSplitOptions.RemoveEmptyEntries)
|
.Split("/", StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Any(segment => segment.StartsWith("get", StringComparison.OrdinalIgnoreCase)) &&
|
.Any(segment => segment.StartsWith("get", StringComparison.OrdinalIgnoreCase)) &&
|
||||||
@@ -106,17 +117,54 @@ namespace IRaCIS.Core.Application.BusinessFilter.LegacyController
|
|||||||
RequestTime = DateTime.Now
|
RequestTime = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
IRCSystemInfo.RequestRecordList= IRCSystemInfo.RequestRecordList.Where(x => x.RequestTime >= DateTime.Now.AddSeconds(-RequestDuplicationOptionsMonitor.CurrentValue.CacheTimeSeconds)).ToList();
|
var isAdded = IRCSystemInfo.TryAddRequestRecord(
|
||||||
|
requestInfo,
|
||||||
|
RequestDuplicationOptionsMonitor.CurrentValue.CacheTimeSeconds,
|
||||||
var requestsTimes = IRCSystemInfo.RequestRecordList.Any(x=>
|
RequestDuplicationOptionsMonitor.CurrentValue.DuplicationWindowMs);
|
||||||
x.RequestTime>= requestInfo.RequestTime.AddMilliseconds(-RequestDuplicationOptionsMonitor.CurrentValue.DuplicationWindowMs)&&
|
if (!isAdded)
|
||||||
x.RequestKey== requestInfo.RequestKey);
|
|
||||||
if (requestsTimes)
|
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException(_localizer["RequestDuplicationFilter_RequestDuplication"], ApiResponseCodeEnum.BusinessValidationFailed);
|
SendRequestDuplicationWeComNotice(requestPath);
|
||||||
|
logger.LogError($"重复请求出现错误:{this.Intoparam}");
|
||||||
|
throw new BusinessValidationFailedException(_localizer["RequestDuplicationFilter_RequestDuplication"], ApiResponseCodeEnum.NotRemind);
|
||||||
}
|
}
|
||||||
IRCSystemInfo.RequestRecordList.Add(requestInfo);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendRequestDuplicationWeComNotice(string requestPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool isOpenWeComNotice = _config.GetValue<bool>("WeComNoticeConfig:IsOpenWeComNotice");
|
||||||
|
|
||||||
|
if (isOpenWeComNotice)
|
||||||
|
{
|
||||||
|
string webhook = _config["WeComNoticeConfig:WebhookUrl"] ?? string.Empty;
|
||||||
|
|
||||||
|
var uri = new Uri(_config["SystemEmailSendConfig:SiteUrl"]);
|
||||||
|
var baseUrl = uri.GetLeftPart(UriPartial.Authority);
|
||||||
|
|
||||||
|
var userList = _config.GetSection("WeComNoticeConfig:VueNoticeUserList").Get<string[]>();
|
||||||
|
|
||||||
|
var request = accessor?.HttpContext?.Request;
|
||||||
|
|
||||||
|
_ = WeComNotifier.SendAlertAsync(
|
||||||
|
webhook: webhook,
|
||||||
|
alert: new WeComAlert
|
||||||
|
{
|
||||||
|
Env = baseUrl,
|
||||||
|
UserName = _userInfo.UserName.IsNotNullOrEmpty() ? $"{_userInfo.UserName}({_userInfo.UserTypeShortName})" : "匿名",
|
||||||
|
Api = $"{request?.Method} {requestPath}",
|
||||||
|
Message = "重复请求拦截",
|
||||||
|
JsonData = this.Intoparam,
|
||||||
|
Stack = string.Empty,
|
||||||
|
AtUsers = userList ?? []
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError($"重复请求过滤器里发送企业微信出现错误:{ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -29,11 +29,11 @@ public class TrialGlobalLimitActionFilter(IFusionCache _fusionCache, IUserInfo _
|
|||||||
var requestHost = context.HttpContext.Request.Host;
|
var requestHost = context.HttpContext.Request.Host;
|
||||||
|
|
||||||
// 检查请求是否来自 localhost:6100
|
// 检查请求是否来自 localhost:6100
|
||||||
//if (requestHost.Host == "localhost" && (requestHost.Port == 6100 || requestHost.Port == 3305))
|
if (requestHost.Host == "localhost" && (requestHost.Port == 6100 || requestHost.Port == 3305))
|
||||||
//{
|
{
|
||||||
// await next();
|
await next();
|
||||||
// return;
|
return;
|
||||||
//}
|
}
|
||||||
|
|
||||||
#region 特殊用户类型拦截
|
#region 特殊用户类型拦截
|
||||||
// 用户类型检查
|
// 用户类型检查
|
||||||
|
|||||||
@@ -79,11 +79,12 @@ public class SystemEmailSendConfig
|
|||||||
|
|
||||||
public bool IsEnv_US { get; set; }
|
public bool IsEnv_US { get; set; }
|
||||||
|
|
||||||
public bool IsOpenErrorNoticeEmail { get; set; }
|
|
||||||
|
|
||||||
public string EmailRegexStr { get; set; }
|
public string EmailRegexStr { get; set; }
|
||||||
|
|
||||||
public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
|
//public bool IsOpenErrorNoticeEmail { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
//public List<string> ErrorNoticeEmailList { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SystemEmailSendConfigView
|
public class SystemEmailSendConfigView
|
||||||
@@ -145,6 +146,31 @@ public class RequestDuplicationOptions
|
|||||||
public static class IRCSystemInfo
|
public static class IRCSystemInfo
|
||||||
{
|
{
|
||||||
public static List<RequestInfo> RequestRecordList { get; set; } = new List<RequestInfo>();
|
public static List<RequestInfo> RequestRecordList { get; set; } = new List<RequestInfo>();
|
||||||
|
|
||||||
|
private static readonly object requestRecordLock = new object();
|
||||||
|
|
||||||
|
public static bool TryAddRequestRecord(RequestInfo requestInfo, int cacheTimeSeconds, int duplicationWindowMs)
|
||||||
|
{
|
||||||
|
lock (requestRecordLock)
|
||||||
|
{
|
||||||
|
var now = DateTime.Now;
|
||||||
|
RequestRecordList = RequestRecordList
|
||||||
|
.Where(x => x.RequestTime >= now.AddSeconds(-cacheTimeSeconds))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var isDuplicate = RequestRecordList.Any(x =>
|
||||||
|
x.RequestTime >= requestInfo.RequestTime.AddMilliseconds(-duplicationWindowMs) &&
|
||||||
|
x.RequestKey == requestInfo.RequestKey);
|
||||||
|
|
||||||
|
if (isDuplicate)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestRecordList.Add(requestInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RequestInfo
|
public class RequestInfo
|
||||||
@@ -235,4 +261,4 @@ public static class AppSettings
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace IRaCIS.Core.Application.Helper;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Helper;
|
||||||
|
|
||||||
|
|
||||||
public static class CacheKeys
|
public static class CacheKeys
|
||||||
@@ -6,6 +8,8 @@ public static class CacheKeys
|
|||||||
//项目缓存
|
//项目缓存
|
||||||
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
|
||||||
|
|
||||||
|
public static string TrialVisitTaskMaxCode(Guid trialId) => $"TrialVisitTaskMaxCode:{trialId}";
|
||||||
|
|
||||||
//检查编号递增锁
|
//检查编号递增锁
|
||||||
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
public static string TrialStudyMaxCode(Guid trialId) => $"TrialStudyMaxCode:{trialId}";
|
||||||
|
|
||||||
@@ -66,6 +70,10 @@ public static class CacheKeys
|
|||||||
|
|
||||||
public static string UserMFATag(Guid userId) => $"UserMFAVerifyPass:{userId}";
|
public static string UserMFATag(Guid userId) => $"UserMFAVerifyPass:{userId}";
|
||||||
|
|
||||||
|
public static string TrialDataStoreType(Guid trialId) => $"TrialDataStoreType:{trialId}";
|
||||||
|
|
||||||
|
|
||||||
|
public static string UserQCSkipTask(Guid userId) => $"UserSKipQCTask:{userId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CacheHelper
|
public static class CacheHelper
|
||||||
@@ -77,6 +85,9 @@ public static class CacheHelper
|
|||||||
return statusStr;
|
return statusStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
public static async Task<List<SystemAnonymization>> GetSystemAnonymizationListAsync(IRepository<SystemAnonymization> _systemAnonymizationRepository)
|
||||||
{
|
{
|
||||||
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
var list = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
using DocumentFormat.OpenXml.Office.CustomUI;
|
using FellowOakDicom;
|
||||||
using FellowOakDicom;
|
|
||||||
using FellowOakDicom.Media;
|
using FellowOakDicom.Media;
|
||||||
using System;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper
|
namespace IRaCIS.Core.Application.Helper
|
||||||
{
|
{
|
||||||
@@ -58,7 +53,11 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
var mappings = new List<string>();
|
var mappings = new List<string>();
|
||||||
int index = 1;
|
int index = 1;
|
||||||
|
|
||||||
var studyUid=list.FirstOrDefault()?.StudyInstanceUid;
|
var trialId = Guid.Empty;
|
||||||
|
|
||||||
|
Guid.TryParse(ossFolder.Split('/', StringSplitOptions.RemoveEmptyEntries)[0], out trialId);
|
||||||
|
|
||||||
|
var studyUid = list.FirstOrDefault()?.StudyInstanceUid;
|
||||||
|
|
||||||
var dicomDir = new DicomDirectory();
|
var dicomDir = new DicomDirectory();
|
||||||
|
|
||||||
@@ -130,9 +129,9 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
// 重置流位置
|
// 重置流位置
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
var relativePath= await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", true);
|
var relativePath = await _oSSService.UploadToOSSAsync(memoryStream, ossFolder, "DICOMDIR", true, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.DICOMDIR });
|
||||||
|
|
||||||
dic.Add($"{studyUid}_DICOMDIR" , relativePath.Split('/').Last());
|
dic.Add($"{studyUid}_DICOMDIR", relativePath.Split('/').Last());
|
||||||
}
|
}
|
||||||
|
|
||||||
//清理临时文件
|
//清理临时文件
|
||||||
@@ -146,7 +145,7 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
var mappingText = string.Join(Environment.NewLine, mappings);
|
var mappingText = string.Join(Environment.NewLine, mappings);
|
||||||
await using var mappingStream = new MemoryStream(Encoding.UTF8.GetBytes(mappingText));
|
await using var mappingStream = new MemoryStream(Encoding.UTF8.GetBytes(mappingText));
|
||||||
|
|
||||||
await _oSSService.UploadToOSSAsync(mappingStream, ossFolder, $"Download_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", false);
|
await _oSSService.UploadToOSSAsync(mappingStream, ossFolder, $"Download_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}", false, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.DICOMDIR });
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -154,6 +153,91 @@ namespace IRaCIS.Core.Application.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static async Task GenerateStudyDIR(List<StudyDIRInfo> list, Dictionary<string, string> dic, string? dirSavePath = null, Stream? outputStream = null)
|
||||||
|
{
|
||||||
|
var mappings = new List<string>();
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
var trialId = Guid.Empty;
|
||||||
|
|
||||||
|
|
||||||
|
var studyUid = list.FirstOrDefault()?.StudyInstanceUid;
|
||||||
|
|
||||||
|
var dicomDir = new DicomDirectory();
|
||||||
|
|
||||||
|
foreach (var item in list.OrderBy(t => t.SeriesNumber).ThenBy(t => t.InstanceNumber))
|
||||||
|
{
|
||||||
|
var dicomUid = DicomUID.Enumerate().FirstOrDefault(uid => uid.UID == item.TransferSytaxUID);
|
||||||
|
|
||||||
|
if (dicomUid != null)
|
||||||
|
{
|
||||||
|
var ts = DicomTransferSyntax.Query(dicomUid);
|
||||||
|
|
||||||
|
var dataset = new DicomDataset(ts)
|
||||||
|
{
|
||||||
|
{ DicomTag.PatientID, item.PatientId ?? string.Empty },
|
||||||
|
{ DicomTag.PatientName, item.PatientName ?? string.Empty },
|
||||||
|
{ DicomTag.PatientBirthDate, item.PatientBirthDate ?? string.Empty },
|
||||||
|
{ DicomTag.PatientSex, item.PatientSex ?? string.Empty },
|
||||||
|
|
||||||
|
{ DicomTag.StudyInstanceUID, item.StudyInstanceUid ?? string.Empty },
|
||||||
|
{ DicomTag.StudyID, item.StudyId ?? string.Empty },
|
||||||
|
{ DicomTag.StudyDate, item.DicomStudyDate ?? string.Empty },
|
||||||
|
{ DicomTag.StudyTime, item.DicomStudyTime ?? string.Empty },
|
||||||
|
{ DicomTag.AccessionNumber, item.AccessionNumber ?? string.Empty },
|
||||||
|
{ DicomTag.StudyDescription, item.StudyDescription ?? string.Empty },
|
||||||
|
|
||||||
|
{ DicomTag.SeriesInstanceUID, item.SeriesInstanceUid ?? string.Empty },
|
||||||
|
{ DicomTag.Modality, item.Modality ?? string.Empty },
|
||||||
|
{ DicomTag.SeriesDate, item.DicomSeriesDate ?? string.Empty },
|
||||||
|
{ DicomTag.SeriesTime, item.DicomSeriesTime ?? string.Empty },
|
||||||
|
{ DicomTag.SeriesNumber, item.SeriesNumber.ToString() ?? string.Empty },
|
||||||
|
{ DicomTag.SeriesDescription, item.SeriesDescription ?? string.Empty },
|
||||||
|
|
||||||
|
{ DicomTag.SOPInstanceUID, item.SopInstanceUid ?? string.Empty },
|
||||||
|
{ DicomTag.SOPClassUID, item.SOPClassUID ?? string.Empty },
|
||||||
|
{ DicomTag.InstanceNumber, item.InstanceNumber.ToString() ?? string.Empty },
|
||||||
|
{ DicomTag.MediaStorageSOPClassUID, item.MediaStorageSOPClassUID ?? string.Empty },
|
||||||
|
{ DicomTag.MediaStorageSOPInstanceUID, item.MediaStorageSOPInstanceUID ?? string.Empty },
|
||||||
|
{ DicomTag.TransferSyntaxUID, item.TransferSytaxUID ?? string.Empty },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dicomFile = new DicomFile(dataset);
|
||||||
|
|
||||||
|
// 文件名递增格式:IM_00001, IM_00002, ...
|
||||||
|
string filename = $@"IMAGE\IM_{index:D5}"; // :D5 表示补足5位
|
||||||
|
|
||||||
|
mappings.Add($"{filename} => {item.InstanceId}");
|
||||||
|
|
||||||
|
dic.Add(item.InstanceId.ToString(), filename.TrimEnd('/', '\\').Split('/', '\\').Last());
|
||||||
|
|
||||||
|
dicomDir.AddFile(dicomFile, filename);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//有实际的文件
|
||||||
|
if (mappings.Count > 0)
|
||||||
|
{
|
||||||
|
// 保存 DICOMDIR 到临时文件 不能直接写入到流种
|
||||||
|
|
||||||
|
if (dirSavePath.IsNotNullOrEmpty())
|
||||||
|
{
|
||||||
|
await dicomDir.SaveAsync(dirSavePath);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await dicomDir.SaveAsync(outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile)
|
public static StudyDIRInfo ReadDicomDIRInfo(DicomFile dicomFile)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public static class SendEmailHelper
|
|||||||
|
|
||||||
//没有收件人 那么不发送
|
//没有收件人 那么不发送
|
||||||
if (messageToSend.To.Count == 0)
|
if (messageToSend.To.Count == 0)
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +62,15 @@ public static class SendEmailHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public static async Task<string> SendEmailAsync(MimeMessage messageToSend, Trial trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
/// 发送项目邮件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageToSend"></param>
|
||||||
|
/// <param name="trial"></param>
|
||||||
|
/// <param name="messageSentSuccess"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public static async Task<string> SendTrialEmailAsync(MimeMessage messageToSend, Trial trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
// 项目的需要重设 发件地址与邮件地址
|
// 项目的需要重设 发件地址与邮件地址
|
||||||
@@ -78,12 +85,39 @@ public static class SendEmailHelper
|
|||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
result = messageToSend.MessageId;
|
result = messageToSend.MessageId;
|
||||||
|
|
||||||
|
|
||||||
//没有收件人 那么不发送
|
//没有收件人 那么不发送
|
||||||
if (messageToSend.To.Count == 0)
|
if (messageToSend.To.Count == 0)
|
||||||
{
|
{
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 替换邮件标题
|
||||||
|
if (!string.IsNullOrEmpty(messageToSend.Subject))
|
||||||
|
{
|
||||||
|
foreach (var item in trial.TrialObjectNameList)
|
||||||
|
{
|
||||||
|
// 把标题里的占位符替换成真实名称
|
||||||
|
messageToSend.Subject = messageToSend.Subject.Replace(item.Name, item.TrialName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建替换字典
|
||||||
|
var replacements = new Dictionary<string, string>();
|
||||||
|
foreach (var item in trial.TrialObjectNameList)
|
||||||
|
{
|
||||||
|
replacements[item.Name] = item.TrialName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 安全替换 HTML
|
||||||
|
ReplaceHtmlContent(messageToSend.Body, replacements);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
|
using (var smtp = new MailKit.Net.Smtp.SmtpClient())
|
||||||
@@ -128,6 +162,27 @@ public static class SendEmailHelper
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 遍历邮件体,找到 HTML 部分并替换
|
||||||
|
public static void ReplaceHtmlContent(MimeEntity entity, Dictionary<string, string> replacements)
|
||||||
|
{
|
||||||
|
if (entity is Multipart multipart)
|
||||||
|
{
|
||||||
|
foreach (var part in multipart)
|
||||||
|
{
|
||||||
|
ReplaceHtmlContent(part, replacements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (entity is TextPart textPart && textPart.IsHtml)
|
||||||
|
{
|
||||||
|
// 只有这里才是真正的 HTML
|
||||||
|
foreach (var kv in replacements)
|
||||||
|
{
|
||||||
|
textPart.Text = textPart.Text.Replace(kv.Key, kv.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
public static async Task<bool> TestEmailConfigAsync(SystemEmailSendConfig _systemEmailConfig)
|
||||||
{
|
{
|
||||||
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
|
||||||
@@ -147,7 +202,7 @@ public static class SendEmailHelper
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig,Trial? trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
public static async Task SendEmailAsync(SMTPEmailConfig sMTPEmailConfig, Trial? trial, EventHandler<MessageSentEventArgs>? messageSentSuccess = null)
|
||||||
{
|
{
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
@@ -161,8 +216,9 @@ public static class SendEmailHelper
|
|||||||
|
|
||||||
if (sMTPEmailConfig.ToMailAddressList.Count == 0)
|
if (sMTPEmailConfig.ToMailAddressList.Count == 0)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
//---没有收件人
|
//---没有收件人
|
||||||
throw new ArgumentException(I18n.T("SendEmail_NoRecipient"));
|
//throw new ArgumentException(I18n.T("SendEmail_NoRecipient"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,4 @@
|
|||||||
using IRaCIS.Core.Domain.Share;
|
using System.Globalization;
|
||||||
using NPOI.XWPF.UserModel;
|
|
||||||
using System.Globalization;
|
|
||||||
using Xceed.Document.NET;
|
using Xceed.Document.NET;
|
||||||
using Xceed.Words.NET;
|
using Xceed.Words.NET;
|
||||||
|
|
||||||
@@ -54,42 +52,42 @@ public static class WordTempleteHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
//public static void Npoi_GetInternationalTempleteStream(string filePath, Stream memoryStream)
|
||||||
{
|
//{
|
||||||
|
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
// var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
// using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||||
{
|
// {
|
||||||
XWPFDocument doc = new XWPFDocument(fs);
|
// XWPFDocument doc = new XWPFDocument(fs);
|
||||||
|
|
||||||
// 查找包含指定书签的段落及其索引
|
// // 查找包含指定书签的段落及其索引
|
||||||
var bookmarkParagraph = doc.Paragraphs
|
// var bookmarkParagraph = doc.Paragraphs
|
||||||
.FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
// .FirstOrDefault(p => p.GetCTP().GetBookmarkStartList().Any(b => b.name == StaticData.CultureInfo.en_US_bookMark));
|
||||||
|
|
||||||
if (bookmarkParagraph != null)
|
// if (bookmarkParagraph != null)
|
||||||
{
|
// {
|
||||||
int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
// int bookmarkIndex = doc.Paragraphs.IndexOf(bookmarkParagraph);
|
||||||
|
|
||||||
if (isEn_US)
|
// if (isEn_US)
|
||||||
{
|
// {
|
||||||
// 从书签所在段落开始,删除之前的所有段落
|
// // 从书签所在段落开始,删除之前的所有段落
|
||||||
for (int i = bookmarkIndex - 1; i >= 0; i--)
|
// for (int i = bookmarkIndex - 1; i >= 0; i--)
|
||||||
{
|
// {
|
||||||
doc.RemoveBodyElement(i);
|
// doc.RemoveBodyElement(i);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
// 删除书签之后的所有段落
|
// // 删除书签之后的所有段落
|
||||||
for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
// for (int i = doc.Paragraphs.Count - 1; i >= bookmarkIndex; i--)
|
||||||
{
|
// {
|
||||||
doc.RemoveBodyElement(i);
|
// doc.RemoveBodyElement(i);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
doc.Write(memoryStream);
|
// doc.Write(memoryStream);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ using Amazon.S3;
|
|||||||
using Amazon.S3.Model;
|
using Amazon.S3.Model;
|
||||||
using Amazon.SecurityToken;
|
using Amazon.SecurityToken;
|
||||||
using Amazon.SecurityToken.Model;
|
using Amazon.SecurityToken.Model;
|
||||||
|
using DocumentFormat.OpenXml.Bibliography;
|
||||||
|
using IRaCIS.Application.Contracts;
|
||||||
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
|
using IRaCIS.Core.Infrastructure.NewtonsoftJson;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
@@ -16,6 +20,8 @@ using Minio;
|
|||||||
using Minio.DataModel;
|
using Minio.DataModel;
|
||||||
using Minio.DataModel.Args;
|
using Minio.DataModel.Args;
|
||||||
using Minio.Exceptions;
|
using Minio.Exceptions;
|
||||||
|
using Serilog.Parsing;
|
||||||
|
using SkiaSharp;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -80,6 +86,28 @@ public class ObjectStoreServiceOptions
|
|||||||
|
|
||||||
public AWSOptions AWS { get; set; }
|
public AWSOptions AWS { get; set; }
|
||||||
|
|
||||||
|
public bool IsOpenStoreSync { get; set; }
|
||||||
|
|
||||||
|
public string ApiDeployRegion { get; set; }
|
||||||
|
|
||||||
|
public List<SyncStoreConfig> SyncConfigList { get; set; } = new List<SyncStoreConfig>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SyncStoreConfig
|
||||||
|
{
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
|
public string UploadRegion { get; set; }
|
||||||
|
|
||||||
|
public string TargetRegion { get; set; }
|
||||||
|
|
||||||
|
public string Primary { get; set; }
|
||||||
|
|
||||||
|
public string Target { get; set; }
|
||||||
|
|
||||||
|
public bool IsOpenSync { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ObjectStoreDTO
|
public class ObjectStoreDTO
|
||||||
@@ -93,6 +121,10 @@ public class ObjectStoreDTO
|
|||||||
|
|
||||||
public AWSTempToken AWS { get; set; }
|
public AWSTempToken AWS { get; set; }
|
||||||
|
|
||||||
|
public bool IsOpenStoreSync { get; set; }
|
||||||
|
|
||||||
|
public List<SyncStoreConfig> SyncConfigList { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LowerCamelCaseJson]
|
[LowerCamelCaseJson]
|
||||||
@@ -137,6 +169,7 @@ public enum ObjectStoreUse
|
|||||||
AWS = 2,
|
AWS = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
|
// aws 参考链接 https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/S3/S3_Basics
|
||||||
@@ -147,8 +180,8 @@ public interface IOSSService
|
|||||||
public Task RestoreFilesByPrefixAsync(string prefix, int restoreDays = 3, int batchSize = 100);
|
public Task RestoreFilesByPrefixAsync(string prefix, int restoreDays = 3, int batchSize = 100);
|
||||||
|
|
||||||
|
|
||||||
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true);
|
public Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true, FileUploadRecordAddOrEdit? uploadInfo = null);
|
||||||
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false);
|
public Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false, FileUploadRecordAddOrEdit? uploadInfo = null);
|
||||||
|
|
||||||
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
public Task DownLoadFromOSSAsync(string ossRelativePath, string localFilePath);
|
||||||
|
|
||||||
@@ -164,28 +197,30 @@ public interface IOSSService
|
|||||||
|
|
||||||
List<string> GetRootFolderNames();
|
List<string> GetRootFolderNames();
|
||||||
|
|
||||||
public ObjectStoreDTO GetObjectStoreTempToken();
|
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null);
|
||||||
|
|
||||||
public Task MoveObject(string sourcePath, string destPath, bool overwrite = true);
|
public Task MoveObject(string sourcePath, string destPath, bool overwrite = true);
|
||||||
|
|
||||||
public Task<long> GetObjectSizeAsync(string sourcePath);
|
public Task<long> GetObjectSizeAsync(string sourcePath);
|
||||||
|
|
||||||
|
public Task SyncFileAsync(string objectKey, ObjectStoreUse source, ObjectStoreUse destination, CancellationToken ct = default);
|
||||||
|
|
||||||
|
public void ConvertPrefixToStandard(string prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class OSSService : IOSSService
|
public class OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options,
|
||||||
|
IFileUploadRecordService _fileUploadRecordService) : IOSSService
|
||||||
{
|
{
|
||||||
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; }
|
public ObjectStoreServiceOptions ObjectStoreServiceOptions { get; set; } = options.CurrentValue;
|
||||||
|
|
||||||
private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
|
private AliyunOSSTempToken AliyunOSSTempToken { get; set; }
|
||||||
|
|
||||||
private AWSTempToken AWSTempToken { get; set; }
|
private AWSTempToken AWSTempToken { get; set; }
|
||||||
|
public object result { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public OSSService(IOptionsMonitor<ObjectStoreServiceOptions> options)
|
private static readonly object _tokenLock = new();
|
||||||
{
|
|
||||||
ObjectStoreServiceOptions = options.CurrentValue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将指定前缀下的所有现有文件立即转为目标存储类型
|
/// 将指定前缀下的所有现有文件立即转为目标存储类型
|
||||||
@@ -506,8 +541,8 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region),
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
using var client = new AmazonS3Client(credentials, clientConfig);
|
using var client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -620,6 +655,90 @@ public class OSSService : IOSSService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将某个路径下的归档的文件 转为标准存储
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
public void ConvertPrefixToStandard(string prefix)
|
||||||
|
{
|
||||||
|
|
||||||
|
BackBatchGetToken();
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
var _ossClient = new OssClient(
|
||||||
|
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint,
|
||||||
|
AliyunOSSTempToken.AccessKeyId,
|
||||||
|
AliyunOSSTempToken.AccessKeySecret,
|
||||||
|
AliyunOSSTempToken.SecurityToken
|
||||||
|
);
|
||||||
|
var bucketName = aliConfig.BucketName;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ObjectListing objectListing = null;
|
||||||
|
string nextMarker = null;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
|
||||||
|
objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(bucketName)
|
||||||
|
{
|
||||||
|
Prefix = prefix,
|
||||||
|
MaxKeys = 1000,
|
||||||
|
Marker = nextMarker
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var obj in objectListing.ObjectSummaries)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 👇 跳过已经是标准存储的(优化)
|
||||||
|
if (obj.StorageClass == StorageClass.Standard.ToString())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var metadata = new ObjectMetadata();
|
||||||
|
|
||||||
|
// 👇 关键:手动加 Header
|
||||||
|
metadata.AddHeader("x-oss-storage-class", "Standard");
|
||||||
|
|
||||||
|
var copyRequest = new Aliyun.OSS.CopyObjectRequest(bucketName, obj.Key, bucketName, obj.Key) { NewObjectMetadata = metadata };
|
||||||
|
|
||||||
|
|
||||||
|
_ossClient.CopyObject(copyRequest);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Logger.Error($"❌ 失败: {obj.Key}, 错误: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 设置 NextMarker 以获取下一页的数据
|
||||||
|
nextMarker = objectListing.NextMarker;
|
||||||
|
|
||||||
|
} while (objectListing.IsTruncated);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Logger.Error($"Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 坑方法,会清空之前的规则
|
/// 坑方法,会清空之前的规则
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -686,8 +805,8 @@ public class OSSService : IOSSService
|
|||||||
//提供awsEndPoint(域名)进行访问配置
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -700,6 +819,9 @@ public class OSSService : IOSSService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
/// oosFolderPath 不要 "/ "开头 应该: TempFolder/ChildFolder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -707,8 +829,9 @@ public class OSSService : IOSSService
|
|||||||
/// <param name="oosFolderPath"></param>
|
/// <param name="oosFolderPath"></param>
|
||||||
/// <param name="fileRealName"></param>
|
/// <param name="fileRealName"></param>
|
||||||
/// <param name="isFileNameAddGuid"></param>
|
/// <param name="isFileNameAddGuid"></param>
|
||||||
|
/// <param name="uploadInfo"> 只用赋值业务参数Id 和批次信息即可,其他信息不用传递</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true)
|
public async Task<string> UploadToOSSAsync(Stream fileStream, string oosFolderPath, string fileRealName, bool isFileNameAddGuid = true, FileUploadRecordAddOrEdit? uploadInfo = null)
|
||||||
{
|
{
|
||||||
BackBatchGetToken();
|
BackBatchGetToken();
|
||||||
|
|
||||||
@@ -716,74 +839,68 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var memoryStream = new MemoryStream())
|
if (fileStream.CanSeek)
|
||||||
{
|
|
||||||
fileStream.Seek(0, SeekOrigin.Begin);
|
fileStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
fileStream.CopyTo(memoryStream);
|
|
||||||
|
|
||||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
|
{
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
|
||||||
|
|
||||||
|
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
|
||||||
|
// 上传文件
|
||||||
|
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, fileStream);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
|
{
|
||||||
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
|
|
||||||
|
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
|
||||||
|
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var putObjectArgs = new PutObjectArgs()
|
||||||
|
.WithBucket(minIOConfig.BucketName)
|
||||||
|
.WithObject(ossRelativePath)
|
||||||
|
.WithStreamData(fileStream)
|
||||||
|
.WithObjectSize(fileStream.Length);
|
||||||
|
|
||||||
|
await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
}
|
||||||
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
|
{
|
||||||
|
var awsConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
|
//,UseHttp = true,
|
||||||
|
};
|
||||||
|
|
||||||
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
|
|
||||||
|
var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
|
||||||
|
|
||||||
// 上传文件
|
|
||||||
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, memoryStream);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
|
||||||
{
|
{
|
||||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
BucketName = awsConfig.BucketName,
|
||||||
|
InputStream = fileStream,
|
||||||
|
Key = ossRelativePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
await amazonS3Client.PutObjectAsync(putObjectRequest);
|
||||||
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
|
}
|
||||||
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
|
else
|
||||||
.Build();
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
var putObjectArgs = new PutObjectArgs()
|
|
||||||
.WithBucket(minIOConfig.BucketName)
|
|
||||||
.WithObject(ossRelativePath)
|
|
||||||
.WithStreamData(memoryStream)
|
|
||||||
.WithObjectSize(memoryStream.Length);
|
|
||||||
|
|
||||||
await minioClient.PutObjectAsync(putObjectArgs);
|
|
||||||
}
|
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
|
||||||
{
|
|
||||||
var awsConfig = ObjectStoreServiceOptions.AWS;
|
|
||||||
|
|
||||||
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//提供awsEndPoint(域名)进行访问配置
|
|
||||||
var clientConfig = new AmazonS3Config
|
|
||||||
{
|
|
||||||
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
|
||||||
//,UseHttp = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
|
||||||
|
|
||||||
var putObjectRequest = new Amazon.S3.Model.PutObjectRequest()
|
|
||||||
{
|
|
||||||
BucketName = awsConfig.BucketName,
|
|
||||||
InputStream = memoryStream,
|
|
||||||
Key = ossRelativePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
await amazonS3Client.PutObjectAsync(putObjectRequest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -793,42 +910,76 @@ public class OSSService : IOSSService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var returnPath = "/" + ossRelativePath;
|
||||||
|
|
||||||
|
|
||||||
return "/" + ossRelativePath;
|
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
|
||||||
|
{
|
||||||
|
uploadInfo.FileSize = fileStream.CanSeek ? fileStream.Length : 0;
|
||||||
|
uploadInfo.Path = returnPath;
|
||||||
|
uploadInfo.FileName = fileRealName;
|
||||||
|
uploadInfo.FileType = Path.GetExtension(returnPath).TrimStart('.');
|
||||||
|
|
||||||
|
|
||||||
|
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return returnPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//后端批量上传 或者下载,不每个文件获取临时token
|
//后端批量上传 或者下载,不每个文件获取临时token
|
||||||
private void BackBatchGetToken()
|
private void BackBatchGetToken()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// 过期时间 ≤ 当前时间 + 15分钟 时需要续期
|
||||||
|
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
{
|
{
|
||||||
if (AliyunOSSTempToken == null)
|
if (AliyunOSSTempToken != null && AliyunOSSTempToken.Expiration > DateTime.Now.AddMinutes(15))
|
||||||
{
|
{
|
||||||
GetObjectStoreTempToken();
|
return; // 还有15分钟以上,不需要续期
|
||||||
}
|
|
||||||
//token 过期了
|
|
||||||
if (AliyunOSSTempToken?.Expiration.AddSeconds(10) <= DateTime.Now)
|
|
||||||
{
|
|
||||||
GetObjectStoreTempToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock (_tokenLock)
|
||||||
|
{
|
||||||
|
if (AliyunOSSTempToken == null ||
|
||||||
|
AliyunOSSTempToken.Expiration <= DateTime.Now.AddMinutes(15))
|
||||||
|
{
|
||||||
|
GetObjectStoreTempToken();
|
||||||
|
|
||||||
|
Log.Logger.Warning("后端获取阿里云临时 Token");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
{
|
{
|
||||||
if (AWSTempToken == null)
|
|
||||||
|
|
||||||
|
if (AWSTempToken != null && AWSTempToken.Expiration > DateTime.Now.AddMinutes(15))
|
||||||
{
|
{
|
||||||
GetObjectStoreTempToken();
|
return;
|
||||||
}
|
}
|
||||||
//token 过期了
|
|
||||||
if (AWSTempToken.Expiration?.AddSeconds(10) <= DateTime.Now)
|
lock (_tokenLock)
|
||||||
{
|
{
|
||||||
GetObjectStoreTempToken();
|
if (AWSTempToken == null ||
|
||||||
|
AWSTempToken.Expiration <= DateTime.Now.AddMinutes(15))
|
||||||
|
{
|
||||||
|
GetObjectStoreTempToken();
|
||||||
|
|
||||||
|
Log.Logger.Warning("后端获取s3 临时 Token");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -841,10 +992,12 @@ public class OSSService : IOSSService
|
|||||||
/// <param name="randomFileName">随机文件名</param>
|
/// <param name="randomFileName">随机文件名</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false)
|
public async Task<string> UploadToOSSAsync(string localFilePath, string oosFolderPath, bool isFileNameAddGuid = true, bool randomFileName = false, FileUploadRecordAddOrEdit? uploadInfo = null)
|
||||||
{
|
{
|
||||||
BackBatchGetToken();
|
BackBatchGetToken();
|
||||||
|
|
||||||
|
long fileSize = 0;
|
||||||
|
|
||||||
var localFileName = Path.GetFileName(localFilePath);
|
var localFileName = Path.GetFileName(localFilePath);
|
||||||
|
|
||||||
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
var ossRelativePath = isFileNameAddGuid ? $"{oosFolderPath}/{Guid.NewGuid()}_{localFileName}" : $"{oosFolderPath}/{localFileName}";
|
||||||
@@ -864,6 +1017,8 @@ public class OSSService : IOSSService
|
|||||||
// 上传文件
|
// 上传文件
|
||||||
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
|
var result = _ossClient.PutObject(aliConfig.BucketName, ossRelativePath, localFilePath);
|
||||||
|
|
||||||
|
fileSize = result.ContentLength;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
{
|
{
|
||||||
@@ -879,7 +1034,9 @@ public class OSSService : IOSSService
|
|||||||
.WithObject(ossRelativePath)
|
.WithObject(ossRelativePath)
|
||||||
.WithFileName(localFilePath);
|
.WithFileName(localFilePath);
|
||||||
|
|
||||||
await minioClient.PutObjectAsync(putObjectArgs);
|
var result = await minioClient.PutObjectAsync(putObjectArgs);
|
||||||
|
|
||||||
|
fileSize = result.Size;
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
||||||
{
|
{
|
||||||
@@ -904,14 +1061,30 @@ public class OSSService : IOSSService
|
|||||||
Key = ossRelativePath,
|
Key = ossRelativePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
await amazonS3Client.PutObjectAsync(putObjectRequest);
|
var result = await amazonS3Client.PutObjectAsync(putObjectRequest);
|
||||||
|
fileSize = result.ContentLength;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
}
|
}
|
||||||
return "/" + ossRelativePath;
|
|
||||||
|
var returnPath = "/" + ossRelativePath;
|
||||||
|
|
||||||
|
|
||||||
|
if (ObjectStoreServiceOptions.IsOpenStoreSync && uploadInfo != null)
|
||||||
|
{
|
||||||
|
uploadInfo.FileSize = fileSize;
|
||||||
|
uploadInfo.Path = returnPath;
|
||||||
|
uploadInfo.FileName = Path.GetFileName(localFilePath);
|
||||||
|
uploadInfo.FileType = Path.GetExtension(returnPath).TrimStart(".");
|
||||||
|
|
||||||
|
|
||||||
|
await _fileUploadRecordService.AddOrUpdateFileUploadRecord(uploadInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return returnPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,6 +1093,13 @@ public class OSSService : IOSSService
|
|||||||
{
|
{
|
||||||
BackBatchGetToken();
|
BackBatchGetToken();
|
||||||
|
|
||||||
|
// 确保目标目录存在
|
||||||
|
string directory = Path.GetDirectoryName(localFilePath);
|
||||||
|
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
ossRelativePath = ossRelativePath.TrimStart('/');
|
ossRelativePath = ossRelativePath.TrimStart('/');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1023,11 +1203,6 @@ public class OSSService : IOSSService
|
|||||||
// 直接返回流
|
// 直接返回流
|
||||||
return result.Content;
|
return result.Content;
|
||||||
|
|
||||||
//// 将OSS返回的流复制到内存流中并返回
|
|
||||||
//var memoryStream = new MemoryStream();
|
|
||||||
//await result.Content.CopyToAsync(memoryStream);
|
|
||||||
//memoryStream.Position = 0; // 重置位置以便读取
|
|
||||||
//return memoryStream;
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
||||||
{
|
{
|
||||||
@@ -1076,8 +1251,8 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -1093,10 +1268,6 @@ public class OSSService : IOSSService
|
|||||||
// ⭐ 直接返回流
|
// ⭐ 直接返回流
|
||||||
return response.ResponseStream;
|
return response.ResponseStream;
|
||||||
|
|
||||||
//var memoryStream = new MemoryStream();
|
|
||||||
//await response.ResponseStream.CopyToAsync(memoryStream);
|
|
||||||
//memoryStream.Position = 0;
|
|
||||||
//return memoryStream;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1337,8 +1508,8 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
var clientConfig = new AmazonS3Config
|
var clientConfig = new AmazonS3Config
|
||||||
{
|
{
|
||||||
RegionEndpoint = RegionEndpoint.USEast1,
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
UseHttp = true,
|
//,UseHttp = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
@@ -1440,9 +1611,36 @@ public class OSSService : IOSSService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task DeleteFromPrefix(string prefix, bool isCache = false)
|
public async Task DeleteFromPrefix(string prefix, bool isCache = false)
|
||||||
{
|
{
|
||||||
GetObjectStoreTempToken();
|
if (prefix.StartsWith("/"))
|
||||||
|
{
|
||||||
|
prefix = prefix.TrimStart("/");
|
||||||
|
}
|
||||||
|
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
//打开了同步的,删除的时候,一起删除
|
||||||
|
if (ObjectStoreServiceOptions.IsOpenStoreSync && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.IsOpenSync))
|
||||||
|
{
|
||||||
|
foreach (var config in ObjectStoreServiceOptions.SyncConfigList.Where(t => t.IsOpenSync))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
GetObjectStoreTempToken(objectUse: config.Primary);
|
||||||
|
|
||||||
|
await DeleteFromPrefixInternal(config.Primary, prefix, isCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetObjectStoreTempToken();
|
||||||
|
|
||||||
|
await DeleteFromPrefixInternal(ObjectStoreServiceOptions.ObjectStoreUse, prefix, isCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task DeleteFromPrefixInternal(string objectUse, string prefix, bool isCache = false)
|
||||||
|
{
|
||||||
|
if (objectUse == "AliyunOSS")
|
||||||
{
|
{
|
||||||
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
@@ -1498,7 +1696,7 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
else if (objectUse == "MinIO")
|
||||||
{
|
{
|
||||||
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
var minIOConfig = ObjectStoreServiceOptions.MinIO;
|
||||||
|
|
||||||
@@ -1535,7 +1733,7 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
else if (objectUse == "AWS")
|
||||||
{
|
{
|
||||||
|
|
||||||
var awsConfig = ObjectStoreServiceOptions.AWS;
|
var awsConfig = ObjectStoreServiceOptions.AWS;
|
||||||
@@ -1591,8 +1789,31 @@ public class OSSService : IOSSService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task DeleteObjects(List<string> objectKeys, bool isCache = false)
|
public async Task DeleteObjects(List<string> objectKeys, bool isCache = false)
|
||||||
{
|
{
|
||||||
|
//打开了同步的,删除的时候,一起删除
|
||||||
|
if (ObjectStoreServiceOptions.IsOpenStoreSync && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.IsOpenSync))
|
||||||
|
{
|
||||||
|
foreach (var config in ObjectStoreServiceOptions.SyncConfigList.Where(t => t.IsOpenSync))
|
||||||
|
{
|
||||||
|
|
||||||
|
GetObjectStoreTempToken(objectUse: config.Primary);
|
||||||
|
|
||||||
|
await DeleteObjectsInternal(objectKeys, isCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetObjectStoreTempToken();
|
||||||
|
|
||||||
|
await DeleteObjectsInternal(objectKeys, isCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task DeleteObjectsInternal(List<string> objectKeys, bool isCache = false)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
GetObjectStoreTempToken();
|
GetObjectStoreTempToken();
|
||||||
|
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
||||||
@@ -1755,13 +1976,42 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ObjectStoreDTO GetObjectStoreTempToken()
|
public ObjectStoreDTO GetObjectStoreTempToken(string? domain = null, bool? isGetAllTempToken = null, string? objectUse = null)
|
||||||
{
|
{
|
||||||
|
string objectStoreUse = string.Empty;
|
||||||
var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
|
//使用指定配置
|
||||||
|
if (objectUse != null)
|
||||||
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
|
|
||||||
{
|
{
|
||||||
|
objectStoreUse = objectUse?.Trim() ?? string.Empty;
|
||||||
|
}
|
||||||
|
//根据域名动态判断
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//如果传递了域名,并且打开了存储同步,根据域名使用的具体存储覆盖之前的配置,否则就用固定的配置
|
||||||
|
if (ObjectStoreServiceOptions.IsOpenStoreSync && domain.IsNotNullOrEmpty() && ObjectStoreServiceOptions.SyncConfigList.Any(t => t.Domain == domain))
|
||||||
|
{
|
||||||
|
|
||||||
|
var find = ObjectStoreServiceOptions.SyncConfigList.FirstOrDefault(t => t.Domain == domain);
|
||||||
|
if (find != null)
|
||||||
|
{
|
||||||
|
objectStoreUse = find.Primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//兜底,如果是本地测试环境,那就使用部署默认配置
|
||||||
|
objectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var objectStoreDTO = new ObjectStoreDTO() { ObjectStoreUse = objectStoreUse, IsOpenStoreSync = ObjectStoreServiceOptions.IsOpenStoreSync, SyncConfigList = ObjectStoreServiceOptions.SyncConfigList };
|
||||||
|
|
||||||
|
if (objectStoreUse == "AliyunOSS" || isGetAllTempToken == true)
|
||||||
|
{
|
||||||
|
var ossOptions = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
|
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
|
||||||
{
|
{
|
||||||
AccessKeyId = ossOptions.AccessKeyId,
|
AccessKeyId = ossOptions.AccessKeyId,
|
||||||
@@ -1803,13 +2053,14 @@ public class OSSService : IOSSService
|
|||||||
|
|
||||||
AliyunOSSTempToken = tempToken;
|
AliyunOSSTempToken = tempToken;
|
||||||
|
|
||||||
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AliyunOSS = tempToken };
|
objectStoreDTO.AliyunOSS = tempToken;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
|
if (objectStoreUse == "MinIO")
|
||||||
{
|
{
|
||||||
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, MinIO = ObjectStoreServiceOptions.MinIO };
|
objectStoreDTO.MinIO = ObjectStoreServiceOptions.MinIO;
|
||||||
}
|
}
|
||||||
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
|
if (objectStoreUse == "AWS" || isGetAllTempToken == true)
|
||||||
{
|
{
|
||||||
var awsOptions = ObjectStoreServiceOptions.AWS;
|
var awsOptions = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
@@ -1851,12 +2102,111 @@ public class OSSService : IOSSService
|
|||||||
};
|
};
|
||||||
|
|
||||||
AWSTempToken = tempToken;
|
AWSTempToken = tempToken;
|
||||||
return new ObjectStoreDTO() { ObjectStoreUse = ObjectStoreServiceOptions.ObjectStoreUse, AWS = tempToken };
|
|
||||||
|
objectStoreDTO.AWS = tempToken;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (objectStoreUse.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
throw new BusinessValidationFailedException("未定义的存储介质类型");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return objectStoreDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task SyncFileAsync(string objectKey, ObjectStoreUse source, ObjectStoreUse destination, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
var tempConfig = GetObjectStoreTempToken(isGetAllTempToken: true);
|
||||||
|
|
||||||
|
|
||||||
|
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
|
||||||
|
|
||||||
|
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
|
||||||
|
|
||||||
|
var awsConfig = ObjectStoreServiceOptions.AWS;
|
||||||
|
|
||||||
|
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
|
||||||
|
|
||||||
|
//提供awsEndPoint(域名)进行访问配置
|
||||||
|
var clientConfig = new AmazonS3Config
|
||||||
|
{
|
||||||
|
RegionEndpoint = RegionEndpoint.GetBySystemName(awsConfig.Region)
|
||||||
|
};
|
||||||
|
|
||||||
|
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
|
||||||
|
|
||||||
|
// ⭐ 关键变量
|
||||||
|
IDisposable? owner = null;
|
||||||
|
Stream sourceStream;
|
||||||
|
long contentLength;
|
||||||
|
|
||||||
|
// ========= 获取流 + 长度 =========
|
||||||
|
switch (source)
|
||||||
|
{
|
||||||
|
case ObjectStoreUse.AliyunOSS:
|
||||||
|
{
|
||||||
|
|
||||||
|
var obj = _ossClient.GetObject(
|
||||||
|
aliConfig.BucketName,
|
||||||
|
objectKey);
|
||||||
|
|
||||||
|
owner = obj;
|
||||||
|
sourceStream = obj.Content;
|
||||||
|
contentLength = obj.ContentLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ObjectStoreUse.AWS:
|
||||||
|
{
|
||||||
|
var response = await amazonS3Client.GetObjectAsync(
|
||||||
|
awsConfig.BucketName,
|
||||||
|
objectKey,
|
||||||
|
ct);
|
||||||
|
|
||||||
|
owner = response;
|
||||||
|
sourceStream = response.ResponseStream;
|
||||||
|
contentLength = response.Headers.ContentLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new BusinessValidationFailedException("未定义的同步类型");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ========= 上传 =========
|
||||||
|
if (destination == ObjectStoreUse.AWS)
|
||||||
|
{
|
||||||
|
var putRequest = new Amazon.S3.Model.PutObjectRequest
|
||||||
|
{
|
||||||
|
BucketName = awsConfig.BucketName,
|
||||||
|
Key = objectKey,
|
||||||
|
InputStream = sourceStream,
|
||||||
|
Headers = { ContentLength = contentLength }
|
||||||
|
};
|
||||||
|
|
||||||
|
await amazonS3Client.PutObjectAsync(putRequest, ct);
|
||||||
|
}
|
||||||
|
else if (destination == ObjectStoreUse.AliyunOSS)
|
||||||
|
{
|
||||||
|
_ossClient.PutObject(
|
||||||
|
aliConfig.BucketName,
|
||||||
|
objectKey,
|
||||||
|
sourceStream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new BusinessValidationFailedException("未定义的同步类型");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// ⭐⭐⭐ 真正释放 HTTP 连接
|
||||||
|
owner?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,11 @@ using FellowOakDicom.Imaging;
|
|||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using SixLabors.ImageSharp.Drawing.Processing;
|
||||||
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper;
|
|
||||||
|
|
||||||
public static class ImageHelper
|
public static class ImageHelper
|
||||||
{
|
{
|
||||||
@@ -28,7 +31,7 @@ public static class ImageHelper
|
|||||||
image.Save(fileStorePath, new JpegEncoder());
|
image.Save(fileStorePath, new JpegEncoder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,6 +63,36 @@ public static class ImageHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class ImageMaskHelper
|
||||||
|
{
|
||||||
|
public static async Task MaskAsync(Stream input, Stream output, IEnumerable<MaskRegion> regions)
|
||||||
|
{
|
||||||
|
// 确保输入流从起始位置读取
|
||||||
|
if (input.CanSeek && input.Position != 0)
|
||||||
|
{
|
||||||
|
input.Position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var image = await Image.LoadAsync(input);
|
||||||
|
|
||||||
|
// 保存原始图片的编码格式
|
||||||
|
var originalFormat = image.Metadata.DecodedImageFormat;
|
||||||
|
|
||||||
|
image.Mutate(ctx =>
|
||||||
|
{
|
||||||
|
foreach (var r in regions)
|
||||||
|
{
|
||||||
|
ctx.Fill(Color.Black, new Rectangle(r.X, r.Y, r.Width, r.Height));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用原始格式保存,保持格式不变
|
||||||
|
await image.SaveAsync(output, originalFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
using System;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Security;
|
|
||||||
using System.Net;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper.OtherTool
|
namespace IRaCIS.Core.Application.Helper.OtherTool
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
using System;
|
using IdentityModel;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IdentityModel;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Helper.OtherTool;
|
namespace IRaCIS.Core.Application.Helper.OtherTool;
|
||||||
|
|
||||||
@@ -31,6 +32,13 @@ public static class WeComNotifier
|
|||||||
|
|
||||||
public static async Task SendAlertAsync(string webhook, WeComAlert alert)
|
public static async Task SendAlertAsync(string webhook, WeComAlert alert)
|
||||||
{
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
await Task.CompletedTask;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = new RestClient();
|
var client = new RestClient();
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>default</LangVersion>
|
<LangVersion>default</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -12,6 +10,7 @@
|
|||||||
<OutputPath>..\bin\</OutputPath>
|
<OutputPath>..\bin\</OutputPath>
|
||||||
<DocumentationFile>.\IRaCIS.Core.Application.xml</DocumentationFile>
|
<DocumentationFile>.\IRaCIS.Core.Application.xml</DocumentationFile>
|
||||||
<NoWarn>1701;1702;1591</NoWarn>
|
<NoWarn>1701;1702;1591</NoWarn>
|
||||||
|
<NoWarn>$(NoWarn);NU1903</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
@@ -32,38 +31,39 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ClosedXML" Version="0.105.0" />
|
||||||
<PackageReference Include="IdentityModel.OidcClient" Version="6.0.0" />
|
<PackageReference Include="IdentityModel.OidcClient" Version="6.0.0" />
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.1.6" />
|
<PackageReference Include="AlibabaCloud.SDK.Sts20150401" Version="1.2.0" />
|
||||||
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.1.3" />
|
|
||||||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.14.1" />
|
||||||
<PackageReference Include="AWSSDK.S3" Version="4.0.4.1" />
|
<PackageReference Include="AWSSDK.S3" Version="4.0.24" />
|
||||||
<PackageReference Include="DocX" Version="4.0.25105.5786" />
|
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.7" />
|
||||||
<PackageReference Include="FreeSpire.Doc" Version="12.2.0" />
|
<PackageReference Include="DocX" Version="5.0.0" />
|
||||||
<PackageReference Include="ExcelDataReader" Version="3.7.0" />
|
<PackageReference Include="FreeSpire.Doc" Version="14.4.0" />
|
||||||
<PackageReference Include="ExcelDataReader.DataSet" Version="3.7.0" />
|
<PackageReference Include="ExcelDataReader" Version="3.8.0" />
|
||||||
<PackageReference Include="DistributedLock.Redis" Version="1.1.0" />
|
<PackageReference Include="ExcelDataReader.DataSet" Version="3.8.0" />
|
||||||
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.6" />
|
<PackageReference Include="DistributedLock.Redis" Version="1.1.1" />
|
||||||
<PackageReference Include="fo-dicom" Version="5.2.2" />
|
<PackageReference Include="DistributedLock.SqlServer" Version="1.0.7" />
|
||||||
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.2" />
|
<PackageReference Include="fo-dicom" Version="5.2.6" />
|
||||||
<PackageReference Include="fo-dicom.Codecs" Version="5.16.4" />
|
<PackageReference Include="fo-dicom.Imaging.ImageSharp" Version="5.2.6" />
|
||||||
<PackageReference Include="IP2Region.Net" Version="2.0.2" />
|
<PackageReference Include="fo-dicom.Codecs" Version="5.16.7" />
|
||||||
<PackageReference Include="MailKit" Version="4.11.0" />
|
<PackageReference Include="IP2Region.Net" Version="3.0.2" />
|
||||||
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0" />
|
<PackageReference Include="MailKit" Version="4.17.0" />
|
||||||
<PackageReference Include="MaxMind.GeoIP2" Version="5.3.0" />
|
<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
|
<PackageReference Include="MaxMind.GeoIP2" Version="6.0.0" />
|
||||||
<PackageReference Include="MimeKit" Version="4.11.0" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
|
||||||
<PackageReference Include="MiniExcel" Version="1.41.2" />
|
<PackageReference Include="MimeKit" Version="4.17.0" />
|
||||||
<PackageReference Include="Minio" Version="6.0.3" />
|
<PackageReference Include="MiniExcel" Version="1.44.1" />
|
||||||
|
<PackageReference Include="Minio" Version="7.0.0" />
|
||||||
<PackageReference Include="MiniWord" Version="0.9.2" />
|
<PackageReference Include="MiniWord" Version="0.9.2" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||||
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
|
<PackageReference Include="My.Extensions.Localization.Json" Version="4.0.0">
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<TreatAsUsed>true</TreatAsUsed>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="NPOI" Version="2.7.4" />
|
|
||||||
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
<PackageReference Include="Panda.DynamicWebApi" Version="1.2.2" />
|
||||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
<PackageReference Include="RestSharp" Version="114.0.0" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="10.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,8 @@ namespace IRaCIS.Core.Application.MassTransit.Command
|
|||||||
public Guid SubjectVisitId { get; set; }
|
public Guid SubjectVisitId { get; set; }
|
||||||
|
|
||||||
public Guid StudyId { get; set; }
|
public Guid StudyId { get; set; }
|
||||||
|
|
||||||
|
public string SiteCounty { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FullCheckResult: CheckViewModel
|
public class FullCheckResult: CheckViewModel
|
||||||
@@ -62,7 +64,7 @@ namespace IRaCIS.Core.Application.MassTransit.Command
|
|||||||
|
|
||||||
//[Required(ErrorMessage = "受试者筛选号不能为空")]
|
//[Required(ErrorMessage = "受试者筛选号不能为空")]
|
||||||
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
|
//[ImporterHeader(Name = "Subject ID", AutoTrim = true)]
|
||||||
[ExcelColumnName("Subject ID")]
|
[ExcelColumnName("Participant ID")]
|
||||||
public string SubjectCode { get; set; } = string.Empty;
|
public string SubjectCode { get; set; } = string.Empty;
|
||||||
|
|
||||||
//[Required(ErrorMessage = "访视名称不能为空")]
|
//[Required(ErrorMessage = "访视名称不能为空")]
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ public static class CommonEmailHelper
|
|||||||
/// <param name="configInfo"></param>
|
/// <param name="configInfo"></param>
|
||||||
/// <param name="messageToSend"></param>
|
/// <param name="messageToSend"></param>
|
||||||
/// <param name="emailFunc"></param>
|
/// <param name="emailFunc"></param>
|
||||||
|
/// <param name="userWorkLanguage"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailNoticeConfig configInfo, MimeMessage messageToSend,
|
public static async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailNoticeConfig configInfo, MimeMessage messageToSend,
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
|
||||||
{
|
{
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
bool isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
||||||
|
|
||||||
@@ -60,13 +62,14 @@ Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr
|
|||||||
/// <param name="configInfo"></param>
|
/// <param name="configInfo"></param>
|
||||||
/// <param name="messageToSend"></param>
|
/// <param name="messageToSend"></param>
|
||||||
/// <param name="emailFunc"></param>
|
/// <param name="emailFunc"></param>
|
||||||
|
/// <param name="userWorkLanguage"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="BusinessValidationFailedException"></exception>
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
public static async Task<TrialEmailNoticeConfig> GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(TrialEmailNoticeConfig configInfo, MimeMessage messageToSend,
|
public static async Task<TrialEmailNoticeConfig> GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(TrialEmailNoticeConfig configInfo, MimeMessage messageToSend,
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
|
||||||
{
|
{
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
|
||||||
|
|
||||||
|
bool isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
var (topicStr, htmlBodyStr) = isEn_US ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
||||||
|
|
||||||
@@ -94,12 +97,20 @@ Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr
|
|||||||
return configInfo;
|
return configInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ReplacePlatformName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt, UserWorkLanguage? userWorkLanguage = null)
|
||||||
|
|
||||||
|
|
||||||
public static string ReplaceCompanyName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt)
|
|
||||||
{
|
{
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
var platformName = isEn_US ? _systemEmailConfig.PlatformName : _systemEmailConfig.PlatformNameCN;
|
||||||
|
|
||||||
|
var str = needDealtxt.Replace("{platformName}", platformName);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string ReplaceCompanyName(SystemEmailSendConfig _systemEmailConfig, string needDealtxt, UserWorkLanguage? userWorkLanguage = null)
|
||||||
|
{
|
||||||
|
var isEn_US = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var str = needDealtxt.Replace("{company}", isEn_US ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
|
var str = needDealtxt.Replace("{company}", isEn_US ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
|
||||||
.Replace("{company abbreviation}", isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
|
.Replace("{company abbreviation}", isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ using IRaCIS.Core.Application.Contracts;
|
|||||||
using IRaCIS.Core.Application.Contracts.DTO;
|
using IRaCIS.Core.Application.Contracts.DTO;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.MassTransit.Command;
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
|
using MaxMind.GeoIP2.Model;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -78,6 +81,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
Modality = study.ModalityForEdit,
|
Modality = study.ModalityForEdit,
|
||||||
SubjectCode = subject.Code,
|
SubjectCode = subject.Code,
|
||||||
VisitName = sv.VisitName,
|
VisitName = sv.VisitName,
|
||||||
|
|
||||||
|
SiteCounty = sv.TrialSite.Country,
|
||||||
};
|
};
|
||||||
|
|
||||||
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
|
||||||
@@ -92,6 +97,8 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
Modality = noneDicomStudy.Modality,
|
Modality = noneDicomStudy.Modality,
|
||||||
SubjectCode = subject.Code,
|
SubjectCode = subject.Code,
|
||||||
VisitName = sv.VisitName,
|
VisitName = sv.VisitName,
|
||||||
|
|
||||||
|
SiteCounty = sv.TrialSite.Country,
|
||||||
};
|
};
|
||||||
|
|
||||||
var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();
|
var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();
|
||||||
@@ -119,6 +126,21 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
|
|
||||||
var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
||||||
|
|
||||||
|
//设置当前中心语言
|
||||||
|
|
||||||
|
var isEn_us = dbVisitStudyList.First().SiteCounty == StaticData.SiteCountry.US;
|
||||||
|
|
||||||
|
var cultureInfoName = StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
if (isEn_us == false)
|
||||||
|
{
|
||||||
|
cultureInfoName = StaticData.CultureInfo.zh_CN;
|
||||||
|
}
|
||||||
|
|
||||||
|
CultureInfo.CurrentCulture = new CultureInfo(cultureInfoName);
|
||||||
|
CultureInfo.CurrentUICulture = new CultureInfo(cultureInfoName);
|
||||||
|
|
||||||
|
|
||||||
//找到etc 当前visit site 和subject 一致的检查列表
|
//找到etc 当前visit site 和subject 一致的检查列表
|
||||||
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
|
||||||
|
|
||||||
@@ -320,7 +342,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
join study in _studyRepository.AsQueryable() on sv.Id equals study.SubjectVisitId
|
join study in _studyRepository.AsQueryable() on sv.Id equals study.SubjectVisitId
|
||||||
select new CheckDBModel()
|
select new CheckDBModel()
|
||||||
{
|
{
|
||||||
SubjectStatus = sv.Subject.Status,
|
SubjectStatus = sv.Subject.Status,
|
||||||
SubjectVisitId = sv.Id,
|
SubjectVisitId = sv.Id,
|
||||||
SiteCode = sv.TrialSite.TrialSiteCode,
|
SiteCode = sv.TrialSite.TrialSiteCode,
|
||||||
StudyDate = study.StudyTime == null ? string.Empty : ((DateTime)study.StudyTime).ToString("yyyy-MM-dd"),
|
StudyDate = study.StudyTime == null ? string.Empty : ((DateTime)study.StudyTime).ToString("yyyy-MM-dd"),
|
||||||
@@ -403,7 +425,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
{
|
{
|
||||||
SubjectStatus = dbCurrentVisitFirst.SubjectStatus,
|
SubjectStatus = dbCurrentVisitFirst.SubjectStatus,
|
||||||
CheckTime = DateTime.Now,
|
CheckTime = DateTime.Now,
|
||||||
CheckState=CheckStateEnum.CVPassed,
|
CheckState = CheckStateEnum.CVPassed,
|
||||||
SiteCode = dbCurrentVisitFirst.SiteCode,
|
SiteCode = dbCurrentVisitFirst.SiteCode,
|
||||||
SubjectCode = dbCurrentVisitFirst.SubjectCode,
|
SubjectCode = dbCurrentVisitFirst.SubjectCode,
|
||||||
VisitName = dbCurrentVisitFirst.VisitName,
|
VisitName = dbCurrentVisitFirst.VisitName,
|
||||||
@@ -448,7 +470,7 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer
|
|||||||
|
|
||||||
var fileStreamResult = (FileStreamResult)await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialConsistentFUllCheckList_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(FullCheckResult));
|
var fileStreamResult = (FileStreamResult)await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialConsistentFUllCheckList_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(FullCheckResult));
|
||||||
|
|
||||||
var ossRelativePath = await _oSSService.UploadToOSSAsync(fileStreamResult.FileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", "DataReconciliation");
|
var ossRelativePath = await _oSSService.UploadToOSSAsync(fileStreamResult.FileStream, $"{trialId.ToString()}/InspectionUpload/DataReconciliation", "DataReconciliation", uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.DataReconciliation });
|
||||||
|
|
||||||
|
|
||||||
//var add = await _inspectionFileRepository.FindAsync(inspectionFileId);
|
//var add = await _inspectionFileRepository.FindAsync(inspectionFileId);
|
||||||
|
|||||||
@@ -27,5 +27,16 @@ namespace IRaCIS.Core.Application.MassTransit.Consumer.Dto
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SendEmailUserDto
|
||||||
|
{
|
||||||
|
public UserTypeEnum UserTypeEnum { get; set; }
|
||||||
|
|
||||||
|
public string FullName { get; set; }
|
||||||
|
|
||||||
|
public UserWorkLanguage UserWorkLanguage { get; set; }
|
||||||
|
|
||||||
|
public string EMail { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,15 +273,30 @@ public class ImageConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 根据不同场景获取不同角色的用户 先排除CRC和CRA
|
// 根据不同场景获取不同角色的用户 先排除CRC和CRA
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted && !filterUserTypeList.Contains(x.UserRole.UserTypeEnum) ).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted && !filterUserTypeList.Contains(x.UserRole.UserTypeEnum) ).Include(x => x.UserRole).Select(x => x.UserRole)
|
||||||
|
.Select(x => new SendEmailUserDto()
|
||||||
|
{
|
||||||
|
UserTypeEnum = x.UserTypeEnum,
|
||||||
|
FullName = x.FullName,
|
||||||
|
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
|
||||||
|
EMail=x.EMail,
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
// CRC和CRA单独取
|
// CRC和CRA单独取
|
||||||
var crcAndcraUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole)).ToListAsync();
|
var crcAndcraUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole))
|
||||||
|
.Select(x => new SendEmailUserDto()
|
||||||
|
{
|
||||||
|
UserTypeEnum = x.UserTypeEnum,
|
||||||
|
FullName = x.FullName,
|
||||||
|
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
|
||||||
|
EMail = x.EMail,
|
||||||
|
}).ToListAsync();
|
||||||
trialUserList.AddRange(crcAndcraUserList);
|
trialUserList.AddRange(crcAndcraUserList);
|
||||||
|
|
||||||
// 根据场景确定收件人
|
// 根据场景确定收件人
|
||||||
List<UserRole> toUserList = new List<UserRole>();
|
List<SendEmailUserDto> toUserList = new List<SendEmailUserDto>();
|
||||||
List<UserRole> ccUserList = new List<UserRole>();
|
List<SendEmailUserDto> ccUserList = new List<SendEmailUserDto>();
|
||||||
|
|
||||||
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync();
|
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync();
|
||||||
var userTypeEnumList = emailNoticeUserList.Select(x => x.UserType).ToList();
|
var userTypeEnumList = emailNoticeUserList.Select(x => x.UserType).ToList();
|
||||||
@@ -334,42 +349,55 @@ public class ImageConsumer(
|
|||||||
DictionaryList = dictionaryDtos
|
DictionaryList = dictionaryDtos
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var userinfo in toUserList)
|
|
||||||
|
var userWorkLanguageList = toUserList.Select(x => x.UserWorkLanguage).Distinct().ToList();
|
||||||
|
|
||||||
|
foreach (var workLanguage in userWorkLanguageList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var userinfoList = toUserList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
// 发件地址
|
// 发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 添加抄送
|
// 添加抄送
|
||||||
foreach (var ccUser in ccUserList)
|
foreach (var ccUser in ccUserList)
|
||||||
{
|
{
|
||||||
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userNames = userinfoList.Select(x => x.FullName).ToList();
|
||||||
|
|
||||||
// 格式化邮件内容
|
// 格式化邮件内容
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var subjectCode = inDto.SubjectVisit.Subject.Code;
|
var subjectCode = inDto.SubjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
string.Join(',', userNames), // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
inDto.SubjectVisit.VisitName, // 访视 {3}
|
inDto.SubjectVisit.VisitName, // 访视 {3}
|
||||||
dictionValue[0], // 是否加急 {4}
|
dictionValue[0], // 是否加急 {4}
|
||||||
dictionValue[1], // 审批结果 {5}
|
dictionValue[1], // 审批结果 {5}
|
||||||
_systemEmailConfig.SiteUrl // 链接 {6}
|
_systemEmailConfig.SiteUrl // 链接 {6}
|
||||||
);
|
);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,11 +474,19 @@ public class ImageConsumer(
|
|||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
// 根据不同场景获取不同角色的用户
|
// 根据不同场景获取不同角色的用户
|
||||||
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole)
|
||||||
|
.Select(x => new SendEmailUserDto()
|
||||||
|
{
|
||||||
|
UserTypeEnum = x.UserTypeEnum,
|
||||||
|
FullName = x.FullName,
|
||||||
|
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
|
||||||
|
EMail = x.EMail,
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
// 根据场景确定收件人
|
// 根据场景确定收件人
|
||||||
List<UserRole> toUserList = new List<UserRole>();
|
List<SendEmailUserDto> toUserList = new List<SendEmailUserDto>();
|
||||||
List<UserRole> ccUserList = new List<UserRole>();
|
List<SendEmailUserDto> ccUserList = new List<SendEmailUserDto>();
|
||||||
|
|
||||||
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync();
|
var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync();
|
||||||
|
|
||||||
@@ -469,12 +505,19 @@ public class ImageConsumer(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var userinfo in toUserList)
|
var userWorkLanguageList = toUserList.Select(x => x.UserWorkLanguage).Distinct().ToList();
|
||||||
|
|
||||||
|
foreach (var workLanguage in userWorkLanguageList)
|
||||||
{
|
{
|
||||||
|
var userinfoList = toUserList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
// 发件地址
|
// 发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
// 添加抄送
|
// 添加抄送
|
||||||
foreach (var ccUser in ccUserList)
|
foreach (var ccUser in ccUserList)
|
||||||
@@ -482,13 +525,15 @@ public class ImageConsumer(
|
|||||||
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
messageToSend.Cc.Add(new MailboxAddress(ccUser.FullName, ccUser.EMail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userNames = userinfoList.Select(x => x.FullName).ToList();
|
||||||
|
|
||||||
// 格式化邮件内容
|
// 格式化邮件内容
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
string.Join(',', userNames), // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
"", // 受试者 {2} - 阅片人筛选不涉及受试者
|
"", // 受试者 {2} - 阅片人筛选不涉及受试者
|
||||||
"", // 访视 {3} - 阅片人筛选不涉及访视
|
"", // 访视 {3} - 阅片人筛选不涉及访视
|
||||||
@@ -500,9 +545,9 @@ public class ImageConsumer(
|
|||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.MassTransit.Command;
|
using IRaCIS.Core.Application.MassTransit.Command;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Consumer.Dto;
|
||||||
using IRaCIS.Core.Domain;
|
using IRaCIS.Core.Domain;
|
||||||
using IRaCIS.Core.Domain.BaseModel;
|
using IRaCIS.Core.Domain.BaseModel;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
@@ -68,7 +69,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||||||
|
|
||||||
|
|
||||||
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
||||||
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
|
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
|
||||||
|
|
||||||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
||||||
|
|
||||||
@@ -78,7 +79,8 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
@@ -86,14 +88,14 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
{
|
{
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
DictionaryRepository = _dictionaryRepository,
|
||||||
IsEn_US = isEn_US,
|
IsEn_US = userIsEn_US,
|
||||||
|
|
||||||
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
DictionaryList = new List<DictionaryDto>()
|
||||||
@@ -110,7 +112,7 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||||||
var subjectName = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
var subjectName = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectName, taskInfo.TaskBlindName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectName, taskInfo.TaskBlindName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
userinfo.FullName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
criterion.CriterionName, // 阅片标准 {2}
|
criterion.CriterionName, // 阅片标准 {2}
|
||||||
@@ -126,9 +128,9 @@ public class UrgentMedicalReviewAddedEventConsumer(
|
|||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +179,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||||||
|
|
||||||
|
|
||||||
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
||||||
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).FirstOrDefaultAsync();
|
var userinfo = await _userRoleRepository.Where(x => x.Id == medicalReview.MedicalManagerUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
|
||||||
|
|
||||||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
||||||
|
|
||||||
@@ -187,6 +189,8 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
@@ -195,14 +199,14 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
{
|
{
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
DictionaryRepository = _dictionaryRepository,
|
||||||
IsEn_US = isEn_US,
|
IsEn_US = userIsEn_US,
|
||||||
|
|
||||||
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
DictionaryList = new List<DictionaryDto>()
|
||||||
@@ -219,7 +223,7 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||||||
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
userinfo.FullName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
criterion.CriterionName, // 阅片标准 {2}
|
criterion.CriterionName, // 阅片标准 {2}
|
||||||
@@ -234,9 +238,9 @@ public class UrgentIRRepliedMedicalReviewConsumer(
|
|||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -293,7 +297,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||||||
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
var criterion = await _readingQuestionCriterionTrialRepository.FirstOrDefaultAsync(x => x.Id == medicalReview.VisitTask.TrialReadingCriterionId);
|
||||||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
var taskInfo = await _visitTaskRepository.Where(x => x.Id == medicalReview.VisitTaskId).Include(x => x.SourceSubjectVisit).Include(x => x.ReadModule).Include(x => x.Subject).FirstNotNullAsync();
|
||||||
|
|
||||||
var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
|
var userinfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).Include(x => x.IdentityUser).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -303,6 +307,9 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
var workLanguage = userinfo.IdentityUser?.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage.HasValue ? workLanguage.Value == UserWorkLanguage.US : isEn_US;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
@@ -311,14 +318,14 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == medicalReview.TrialId);
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
{
|
{
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
DictionaryRepository = _dictionaryRepository,
|
||||||
IsEn_US = isEn_US,
|
IsEn_US = userIsEn_US,
|
||||||
|
|
||||||
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
DictionaryList = new List<DictionaryDto>()
|
||||||
@@ -335,7 +342,7 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||||||
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
userinfo.FullName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
@@ -352,8 +359,8 @@ public class UrgentMIMRepliedMedicalReviewConsumer(
|
|||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -399,7 +406,15 @@ public class UrgentIRApplyedReReadingConsumer(
|
|||||||
|
|
||||||
var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
|
var doctorInfo = await _userRoleRepository.Where(x => x.Id == taskInfo.DoctorUserId).FirstOrDefaultAsync();
|
||||||
|
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId && x.TrialUser.IsDeleted==false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == taskInfo.TrialId && x.TrialUser.IsDeleted==false).Include(x => x.UserRole).Select(x => x.UserRole)
|
||||||
|
.Select(x => new SendEmailUserDto()
|
||||||
|
{
|
||||||
|
UserTypeEnum = x.UserTypeEnum,
|
||||||
|
FullName = x.FullName,
|
||||||
|
UserWorkLanguage = x.IdentityUser.UserWorkLanguage,
|
||||||
|
EMail = x.EMail,
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList();
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList();
|
||||||
if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
|
if (context.Message.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
|
||||||
@@ -412,37 +427,48 @@ public class UrgentIRApplyedReReadingConsumer(
|
|||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == visitid).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
var userWorkLanguageList = userinfoList.Select(x => x.UserWorkLanguage).Distinct().ToList();
|
||||||
|
|
||||||
|
foreach (var workLanguage in userWorkLanguageList)
|
||||||
{
|
{
|
||||||
var messageToSend = new MimeMessage();
|
var langUserinfoList = userinfoList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
|
||||||
//发件地址
|
if (!langUserinfoList.Any()) continue;
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == taskInfo.TrialId);
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
|
var userIsEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
{
|
{
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
DictionaryRepository = _dictionaryRepository,
|
||||||
IsEn_US = isEn_US,
|
IsEn_US = userIsEn_US,
|
||||||
DictionaryList = new List<DictionaryDto>()
|
DictionaryList = new List<DictionaryDto>()
|
||||||
{
|
{
|
||||||
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), }, //任务类型
|
new DictionaryDto (){DictionaryCode= "ReadingCategory",EnumValue=taskInfo.ReadingCategory.GetEnumInt(), }, //任务类型
|
||||||
new DictionaryDto (){DictionaryCode= "RequestReReadingResult",EnumValue="0", }, //审批结果 都是待审批
|
new DictionaryDto (){DictionaryCode= "RequestReReadingResult",EnumValue="0", }, //审批结果 都是待审批
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
//发件地址
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
foreach (var userinfo in langUserinfoList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
var userNames = langUserinfoList.Select(x => x.FullName).ToList();
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
var subjectCode = taskInfo.BlindSubjectCode.IsNullOrEmpty() ? taskInfo.Subject.Code : taskInfo.BlindSubjectCode;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, taskInfo.TaskBlindName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
string.Join(',', userNames), // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
taskInfo.TaskBlindName, // 访视 {3}
|
taskInfo.TaskBlindName, // 访视 {3}
|
||||||
@@ -451,18 +477,14 @@ public class UrgentIRApplyedReReadingConsumer(
|
|||||||
criterion.CriterionName, // 阅片标准 {6}
|
criterion.CriterionName, // 阅片标准 {6}
|
||||||
dictionValue[1], // 审批结果 {7}
|
dictionValue[1], // 审批结果 {7}
|
||||||
_systemEmailConfig.SiteUrl // 链接 {8}
|
_systemEmailConfig.SiteUrl // 链接 {8}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,9 @@
|
|||||||
using DocumentFormat.OpenXml.Office2013.Excel;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
|
||||||
using DocumentFormat.OpenXml.Vml;
|
|
||||||
using DocumentFormat.OpenXml.Wordprocessing;
|
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Helper;
|
|
||||||
using IRaCIS.Core.Application.MassTransit.Command;
|
|
||||||
using IRaCIS.Core.Domain;
|
using IRaCIS.Core.Domain;
|
||||||
using IRaCIS.Core.Domain.BaseModel;
|
|
||||||
using IRaCIS.Core.Domain.Models;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using NPOI.Util;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
namespace IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
|
|
||||||
@@ -57,73 +39,85 @@ public class UserSiteSurveySubmitedEventConsumer(
|
|||||||
if (emailConfig != null)
|
if (emailConfig != null)
|
||||||
{
|
{
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
||||||
|
|
||||||
|
|
||||||
var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId && t.TrialUser.IsDeleted == false)
|
var trialUserList = await _trialUserRoleRepository.Where(t => t.TrialId == siteSurveyInfo.TrialId && t.TrialUser.IsDeleted == false)
|
||||||
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
|
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
|
||||||
.Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum }).ToListAsync();
|
.Select(t => new { t.UserRole.FullName, t.UserRole.IdentityUser.EMail, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
|
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
|
||||||
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
|
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
|
|
||||||
var toUserName = string.Empty;
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
//有SPM 并且参与
|
|
||||||
if (trialInfo.IsSPMJoinSiteSurvey && sPMOrCPMList.Count > 0)
|
|
||||||
{
|
{
|
||||||
foreach (var user in sPMOrCPMList)
|
//重新设置当前发送邮件的语言
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
|
var toUserName = string.Empty;
|
||||||
|
|
||||||
|
//有SPM 并且参与
|
||||||
|
if (trialInfo.IsSPMJoinSiteSurvey && sPMOrCPMList.Count > 0)
|
||||||
{
|
{
|
||||||
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
var lan_SPMOrCPMList = sPMOrCPMList.Where(t => t.UserWorkLanguage == workLanguage);
|
||||||
|
|
||||||
|
foreach (var user in lan_SPMOrCPMList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
toUserName = string.Join('、', lan_SPMOrCPMList.Select(t => t.FullName));
|
||||||
|
|
||||||
|
foreach (var user in pmAndAPMList)
|
||||||
|
{
|
||||||
|
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lan_pmAndAPMList = pmAndAPMList.Where(t => t.UserWorkLanguage == workLanguage);
|
||||||
|
|
||||||
|
foreach (var user in lan_pmAndAPMList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
toUserName = string.Join('、', lan_pmAndAPMList.Select(t => t.FullName));
|
||||||
}
|
}
|
||||||
|
|
||||||
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
|
//发件地址
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
foreach (var user in pmAndAPMList)
|
|
||||||
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
||||||
}
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
toUserName,
|
||||||
|
siteInfo.TrialSiteCode,
|
||||||
|
siteInfo.TrialSiteAliasName,
|
||||||
|
|
||||||
|
siteSurveyInfo.UserName,
|
||||||
|
siteSurveyInfo.Email,
|
||||||
|
siteSurveyInfo.Phone,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var user in pmAndAPMList)
|
|
||||||
{
|
|
||||||
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
|
||||||
}
|
|
||||||
|
|
||||||
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
|
|
||||||
}
|
|
||||||
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
|
|
||||||
|
|
||||||
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
toUserName,
|
|
||||||
siteInfo.TrialSiteCode,
|
|
||||||
siteInfo.TrialSiteAliasName,
|
|
||||||
|
|
||||||
siteSurveyInfo.UserName,
|
|
||||||
siteSurveyInfo.Email,
|
|
||||||
siteSurveyInfo.Phone,
|
|
||||||
_systemEmailConfig.SiteUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -152,61 +146,74 @@ public class SiteSurveySPMSubmitedEventConsumer(
|
|||||||
|
|
||||||
var trialId = siteSurveyInfo.TrialId;
|
var trialId = siteSurveyInfo.TrialId;
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
|
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
||||||
|
|
||||||
|
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
|
||||||
|
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToList();
|
||||||
|
|
||||||
var scenario = EmailBusinessScenario.Approval_SubmitSiteSurvey;
|
var scenario = EmailBusinessScenario.Approval_SubmitSiteSurvey;
|
||||||
|
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
|
||||||
if (emailConfig != null)
|
if (emailConfig != null)
|
||||||
{
|
{
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
|
|
||||||
var trialUserList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM || t.UserRole.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserRole.UserTypeEnum == UserTypeEnum.APM)
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
|
|
||||||
|
|
||||||
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
|
|
||||||
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
|
|
||||||
|
|
||||||
var toUserName = string.Empty;
|
|
||||||
|
|
||||||
foreach (var item in pmAndAPMList)
|
|
||||||
{
|
{
|
||||||
messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail));
|
//重新设置当前发送邮件的语言
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
|
var sPMOrCPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.SPM || t.UserTypeEnum == UserTypeEnum.CPM).ToList();
|
||||||
|
var pmAndAPMList = trialUserList.Where(t => t.UserTypeEnum == UserTypeEnum.ProjectManager || t.UserTypeEnum == UserTypeEnum.APM).ToList();
|
||||||
|
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
|
var toUserName = string.Empty;
|
||||||
|
|
||||||
|
var lan_pmAndAPMList = pmAndAPMList.Where(t => t.UserWorkLanguage == workLanguage);
|
||||||
|
|
||||||
|
foreach (var item in lan_pmAndAPMList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(item.FullName, item.EMail));
|
||||||
|
|
||||||
|
toUserName = string.Join('、', lan_pmAndAPMList.Select(t => t.FullName));
|
||||||
|
}
|
||||||
|
|
||||||
|
//发件地址
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
||||||
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
toUserName,
|
||||||
|
siteInfo.TrialSiteCode, //中心编号
|
||||||
|
siteInfo.TrialSiteAliasName,//中心名称
|
||||||
|
|
||||||
|
siteSurveyInfo.UserName, //联系人
|
||||||
|
siteSurveyInfo.Email, //联系邮箱
|
||||||
|
siteSurveyInfo.Phone, //联系电话
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
toUserName = string.Join('、', pmAndAPMList.Select(t => t.FullName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
|
||||||
|
|
||||||
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
toUserName,
|
|
||||||
siteInfo.TrialSiteCode, //中心编号
|
|
||||||
siteInfo.TrialSiteAliasName,//中心名称
|
|
||||||
|
|
||||||
siteSurveyInfo.UserName, //联系人
|
|
||||||
siteSurveyInfo.Email, //联系邮箱
|
|
||||||
siteSurveyInfo.Phone, //联系电话
|
|
||||||
_systemEmailConfig.SiteUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -235,92 +242,136 @@ public class SiteSurverRejectedEventConsumer(
|
|||||||
|
|
||||||
var trialSiteSurveyId = context.Message.TrialSiteSurveyId;
|
var trialSiteSurveyId = context.Message.TrialSiteSurveyId;
|
||||||
|
|
||||||
var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId ,ignoreQueryFilters:true).FirstOrDefault().IfNullThrowException();
|
var siteSurveyInfo = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId, ignoreQueryFilters: true).FirstOrDefault().IfNullThrowException();
|
||||||
|
|
||||||
var trialId = siteSurveyInfo.TrialId;
|
var trialId = siteSurveyInfo.TrialId;
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
|
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
||||||
|
|
||||||
var scenario = EmailBusinessScenario.SiteSurveyReject;
|
var scenario = EmailBusinessScenario.SiteSurveyReject;
|
||||||
|
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
|
||||||
if (emailConfig != null)
|
if (emailConfig != null)
|
||||||
{
|
{
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
|
|
||||||
var toUserName = siteSurveyInfo.UserName;
|
|
||||||
|
|
||||||
if (context.Message.IsHaveSPMOrCPM)
|
|
||||||
{
|
{
|
||||||
//PM 驳回到SPM
|
//重新设置当前发送邮件的语言
|
||||||
if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted)
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
|
var toUserName = siteSurveyInfo.UserName;
|
||||||
|
|
||||||
|
if (context.Message.IsHaveSPMOrCPM)
|
||||||
{
|
{
|
||||||
//var user = await _userRoleRepository.FirstOrDefaultAsync(t => t.Id == siteSurveyInfo.PreliminaryUserId);
|
////PM 驳回到SPM
|
||||||
|
//if (siteSurveyInfo.State == TrialSiteSurveyEnum.CRCSubmitted)
|
||||||
|
//{
|
||||||
|
|
||||||
//name = user.FullName;
|
// var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
|
||||||
|
// .Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
|
||||||
|
// .Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToList();
|
||||||
|
|
||||||
var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
|
// var lan_SPMOrCPMList = sPMOrCPMList.Where(t => t.UserWorkLanguage == workLanguage);
|
||||||
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
|
|
||||||
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum }).ToList();
|
|
||||||
|
|
||||||
|
// foreach (var user in lan_SPMOrCPMList)
|
||||||
|
// {
|
||||||
|
// messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
|
// }
|
||||||
|
|
||||||
foreach (var user in sPMOrCPMList)
|
// toUserName = string.Join('、', lan_SPMOrCPMList.Select(t => t.FullName));
|
||||||
|
|
||||||
|
//}
|
||||||
|
////SPM 驳回到CRC
|
||||||
|
//else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
|
||||||
|
//{
|
||||||
|
// //使用中心国家语言 一致才发送
|
||||||
|
// if ((siteInfo.Country == StaticData.SiteCountry.US && isEn_US) || (siteInfo.Country == StaticData.SiteCountry.CN && isEn_US == false))
|
||||||
|
// {
|
||||||
|
// messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// PM 驳回到CRC
|
||||||
|
if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
|
||||||
{
|
{
|
||||||
messageToSend.To.Add(new MailboxAddress(user.FullName, user.EMail));
|
//使用中心国家语言 一致才发送
|
||||||
|
if ((siteInfo.Country == StaticData.SiteCountry.US && isEn_US) || (siteInfo.Country == StaticData.SiteCountry.CN && isEn_US == false))
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var sPMOrCPMList = _trialUserRoleRepository.Where(t => t.TrialId == trialId && t.TrialUser.IsDeleted == false)
|
||||||
|
.Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.SPM || t.UserRole.UserTypeEnum == UserTypeEnum.CPM)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToList();
|
||||||
|
|
||||||
|
var lan_SPMOrCPMList = sPMOrCPMList.Where(t => t.UserWorkLanguage == workLanguage);
|
||||||
|
|
||||||
|
foreach (var user in lan_SPMOrCPMList)
|
||||||
|
{
|
||||||
|
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toUserName = string.Join('、', sPMOrCPMList.Select(t => t.FullName));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//SPM 驳回到CRC
|
else
|
||||||
else if (siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit)
|
|
||||||
{
|
{
|
||||||
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
|
//没有SPM PM驳回到CRC
|
||||||
|
|
||||||
|
//使用中心国家语言 一致才发送
|
||||||
|
if ((siteInfo.Country == StaticData.SiteCountry.US && isEn_US) || (siteInfo.Country == StaticData.SiteCountry.CN && isEn_US == false))
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(toUserName, siteSurveyInfo.Email));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Uri uri = new Uri(_systemEmailConfig.SiteUrl);
|
||||||
else
|
|
||||||
{
|
// 获取 Scheme + Host(不包含路径)
|
||||||
//没有SPM PM驳回到CRC
|
string baseUrl = uri.GetLeftPart(UriPartial.Authority);
|
||||||
|
|
||||||
|
//发件地址
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
toUserName,
|
||||||
|
trialInfo.TrialCode,
|
||||||
|
trialInfo.ResearchProgramNo,
|
||||||
|
trialInfo.ExperimentName,
|
||||||
|
|
||||||
|
siteInfo.TrialSiteCode, //中心编号
|
||||||
|
siteInfo.TrialSiteAliasName,//中心名称
|
||||||
|
siteSurveyInfo.LatestBackReason, //驳回原因
|
||||||
|
$"{baseUrl}/researchLogin?trialId={trialId}", //链接
|
||||||
|
(siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none"),
|
||||||
|
trialInfo.LinkVerificationCode.IsNullOrEmpty()? trialInfo.ResearchProgramNo: trialInfo.LinkVerificationCode
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
messageToSend.To.Add(new MailboxAddress(siteSurveyInfo.UserName, siteSurveyInfo.Email));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
|
||||||
|
|
||||||
var siteInfo = await _trialSiteRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.Id == siteSurveyInfo.TrialSiteId, true);
|
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(input.topicStr, companyName,trialInfo.ResearchProgramNo);
|
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
toUserName,
|
|
||||||
trialInfo.TrialCode,
|
|
||||||
trialInfo.ResearchProgramNo,
|
|
||||||
trialInfo.ExperimentName,
|
|
||||||
|
|
||||||
siteInfo.TrialSiteCode, //中心编号
|
|
||||||
siteInfo.TrialSiteAliasName,//中心名称
|
|
||||||
siteSurveyInfo.LatestBackReason, //驳回原因
|
|
||||||
_systemEmailConfig.SiteUrl, //链接
|
|
||||||
(siteSurveyInfo.State == TrialSiteSurveyEnum.ToSubmit ? "inline - block" : "none")
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<CRCSubmitedAndQCToAuditEvent> context)
|
public async Task Consume(ConsumeContext<CRCSubmitedAndQCToAuditEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(005,006) 【加急项目所有IQC待领取质控任务】邮件!!!");
|
Log.Logger.Warning("发送(005,006) 【加急项目所有IQC待领取质控任务】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var subjectVisitId = context.Message.SubjectVisitId;
|
var subjectVisitId = context.Message.SubjectVisitId;
|
||||||
@@ -49,80 +49,91 @@ public class CRCSubmitedAndQCToAuditEventConsumer(
|
|||||||
|
|
||||||
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
|
||||||
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
if (trialEmailConfig != null)
|
if (trialEmailConfig != null)
|
||||||
{
|
{
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
|
||||||
|
|
||||||
var auditStateCode = "AuditStatePE";
|
|
||||||
|
|
||||||
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
|
|
||||||
{
|
{
|
||||||
auditStateCode = "AuditStateRC";
|
//重新设置当前发送邮件的语言
|
||||||
}
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
|
var iqcList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).Where(t => t.UserWorkLanguage == workLanguage).ToList();
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
|
||||||
{
|
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
||||||
IsEn_US = isEn_US,
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
|
||||||
|
var auditStateCode = "AuditStatePE";
|
||||||
|
|
||||||
|
if (trialInfo.QCProcessEnum == TrialQCProcess.DoubleAudit)
|
||||||
|
{
|
||||||
|
auditStateCode = "AuditStateRC";
|
||||||
|
}
|
||||||
|
|
||||||
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
|
{
|
||||||
|
|
||||||
|
DictionaryRepository = _dictionaryRepository,
|
||||||
|
IsEn_US = isEn_US,
|
||||||
|
DictionaryList = new List<DictionaryDto>()
|
||||||
{
|
{
|
||||||
new DictionaryDto (){DictionaryCode= auditStateCode,EnumValue=subjectVisit.AuditState.GetEnumInt(), }, //审核状态
|
new DictionaryDto (){DictionaryCode= auditStateCode,EnumValue=subjectVisit.AuditState.GetEnumInt(), }, //审核状态
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var userinfo in iqcList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
var userNames = iqcList.Select(x => x.FullName).ToList();
|
||||||
|
|
||||||
|
foreach (var pm in pmandAPm)
|
||||||
|
{
|
||||||
|
messageToSend.Cc.Add(new MailboxAddress(pm.FullName, pm.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
|
var htmlBodyStr = string.Format(
|
||||||
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
string.Join(',', userNames), // 用户名 {0}
|
||||||
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
|
subjectCode, // 受试者 {2}
|
||||||
|
subjectVisit.VisitName, // 访视 {3}
|
||||||
|
dictionValue[0], // 审核状态 {4}
|
||||||
|
_systemEmailConfig.SiteUrl // 链接 {5}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
|
||||||
{
|
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var userNames = userinfoList.Select(x => x.FullName).ToList();
|
|
||||||
|
|
||||||
foreach (var pm in pmandAPm)
|
|
||||||
{
|
|
||||||
messageToSend.Cc.Add(new MailboxAddress(pm.FullName, pm.EMail));
|
|
||||||
}
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var subjectCode = subjectVisit.Subject.Code;
|
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
|
||||||
var htmlBodyStr = string.Format(
|
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
string.Join(',', userNames), // 用户名 {0}
|
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
|
||||||
subjectCode, // 受试者 {2}
|
|
||||||
subjectVisit.VisitName, // 访视 {3}
|
|
||||||
dictionValue[0], // 审核状态 {4}
|
|
||||||
_systemEmailConfig.SiteUrl // 链接 {5}
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -147,7 +158,7 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<CRCRepliedQCChallengeEvent> context)
|
public async Task Consume(ConsumeContext<CRCRepliedQCChallengeEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(Code012,013) 【CRC 回复质控质疑 通知QC】邮件!!!");
|
Log.Logger.Warning("发送(Code012,013) 【CRC 回复质控质疑 通知QC】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var subjectVisitId = context.Message.SubjectVisitId;
|
var subjectVisitId = context.Message.SubjectVisitId;
|
||||||
@@ -158,26 +169,29 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||||||
|
|
||||||
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending;
|
var scenario = context.Message.IsPd ? EmailBusinessScenario.PDVerification_UnderQCQuery : EmailBusinessScenario.EligibilityVerification_Pending;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
|
||||||
if (trialEmailConfig != null)
|
if (trialEmailConfig != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync();
|
var qCChallengeDialog = await _qCChallengeDialogRepository.Where(x => x.Id == context.Message.QCChallengeDialogId).Include(x => x.QCChallenge).FirstNotNullAsync();
|
||||||
|
|
||||||
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList();
|
||||||
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
var pmandAPm = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
||||||
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
|
|
||||||
var userinfo = subjectVisit.CurrentActionUser;
|
var userinfo = subjectVisit.CurrentActionUser;
|
||||||
|
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = _userRoleRepository.Where(t => t.Id == userinfo.Id).Select(t => t.IdentityUser.UserWorkLanguage).First();
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -207,7 +221,7 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
userinfo.FullName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
@@ -219,9 +233,9 @@ public class CRCRepliedQCChallengeEventConsumer(
|
|||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +258,7 @@ public class QCRepliedQCChallengeEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<QCRepliedQCChallengeEvent> context)
|
public async Task Consume(ConsumeContext<QCRepliedQCChallengeEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(014,015) 【 QC回复 质控质疑,通知CRC】邮件!!!");
|
Log.Logger.Warning("发送(014,015) 【 QC回复 质控质疑,通知CRC】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var subjectVisitId = context.Message.SubjectVisitId;
|
var subjectVisitId = context.Message.SubjectVisitId;
|
||||||
@@ -277,54 +291,61 @@ public class QCRepliedQCChallengeEventConsumer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
|
|
||||||
|
|
||||||
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
|
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
DictionaryRepository = _dictionaryRepository,
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
IsEn_US = isEn_US,
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
|
||||||
{
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Where(t => t.UserWorkLanguage == workLanguage).ToList();
|
||||||
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=isclose.ToString().ToLower(), }, //是否关闭
|
|
||||||
|
var craInfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).ToList();
|
||||||
}
|
|
||||||
});
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
|
{
|
||||||
|
|
||||||
|
DictionaryRepository = _dictionaryRepository,
|
||||||
|
IsEn_US = isEn_US,
|
||||||
|
DictionaryList = new List<DictionaryDto>()
|
||||||
|
{
|
||||||
|
new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=isclose.ToString().ToLower(), }, //是否关闭
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
|
||||||
{
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
if (craInfo != null)
|
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
|
||||||
|
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
{
|
{
|
||||||
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var user in craInfoList)
|
||||||
|
{
|
||||||
|
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
}
|
}
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
toUserName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
subjectVisit.VisitName, // 访视 {3}
|
subjectVisit.VisitName, // 访视 {3}
|
||||||
@@ -337,10 +358,13 @@ public class QCRepliedQCChallengeEventConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,7 +388,7 @@ public class CRCRepliedCheckChallengeEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<CRCRepliedCheckChallengeEvent> context)
|
public async Task Consume(ConsumeContext<CRCRepliedCheckChallengeEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(019,020) 【 CRC 回复一致性核查质疑 通知PM】邮件!!!");
|
Log.Logger.Warning("发送(019,020) 【 CRC 回复一致性核查质疑 通知PM】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
|
||||||
@@ -383,49 +407,58 @@ public class CRCRepliedCheckChallengeEventConsumer(
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
DictionaryRepository = _dictionaryRepository,
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
IsEn_US = isEn_US,
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
|
||||||
{
|
|
||||||
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
|
{
|
||||||
}
|
|
||||||
});
|
DictionaryRepository = _dictionaryRepository,
|
||||||
|
IsEn_US = isEn_US,
|
||||||
|
DictionaryList = new List<DictionaryDto>()
|
||||||
|
{
|
||||||
|
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager)
|
||||||
|
.Where(t => t.UserWorkLanguage == workLanguage).ToList();
|
||||||
|
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
|
||||||
{
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail));
|
|
||||||
|
|
||||||
|
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
toUserName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
subjectVisit.VisitName, // 访视 {3}
|
subjectVisit.VisitName, // 访视 {3}
|
||||||
@@ -437,10 +470,17 @@ public class CRCRepliedCheckChallengeEventConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -466,12 +506,12 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<PMRepliedCheckChallengeEvent> context)
|
public async Task Consume(ConsumeContext<PMRepliedCheckChallengeEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(016,017) 【 PM 一致性核查 通知CRC】邮件!!!");
|
Log.Logger.Warning("发送(016,017) 【 PM 一致性核查 通知CRC】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
var subjectVisitId = context.Message.SubjectVisitId;
|
var subjectVisitId = context.Message.SubjectVisitId;
|
||||||
|
|
||||||
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.NoneDicomStudyList).Include(x => x.StudyList).Include(x => x.Subject).FirstNotNullAsync();
|
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.NoneDicomStudyList).Include(x => x.StudyList).Include(x => x.Subject).Include(t => t.TrialSite).FirstNotNullAsync();
|
||||||
|
|
||||||
var trialId = subjectVisit.TrialId;
|
var trialId = subjectVisit.TrialId;
|
||||||
|
|
||||||
@@ -486,11 +526,11 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||||||
var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync();
|
var checkChallengeDialog = await _checkChallengeDialogRepository.Where(x => x.Id == context.Message.CheckChallengeDialogId).FirstNotNullAsync();
|
||||||
|
|
||||||
|
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList();
|
|
||||||
|
|
||||||
var craInfo = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).FirstOrDefault();
|
var craInfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.CRA).ToList();
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
@@ -499,28 +539,46 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||||||
modalities = subjectVisit.NoneDicomStudyList.Select(t => t.Modality)
|
modalities = subjectVisit.NoneDicomStudyList.Select(t => t.Modality)
|
||||||
.Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList();
|
.Union(subjectVisit.StudyList.Select(k => k.ModalityForEdit)).ToList();
|
||||||
|
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
|
||||||
|
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
//foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
isEn_US = subjectVisit.TrialSite.Country == StaticData.SiteCountry.US;
|
||||||
IsEn_US = isEn_US,
|
|
||||||
DictionaryList = new List<DictionaryDto>()
|
|
||||||
{
|
|
||||||
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //核查状态
|
|
||||||
|
|
||||||
}
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
});
|
|
||||||
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Where(t => t.UserWorkLanguage == workLanguage).ToList();
|
||||||
|
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
DictionaryRepository = _dictionaryRepository,
|
||||||
|
IsEn_US = isEn_US,
|
||||||
|
DictionaryList = new List<DictionaryDto>()
|
||||||
|
{
|
||||||
|
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //核查状态
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
|
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
if (craInfo != null)
|
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
{
|
{
|
||||||
messageToSend.Cc.Add(new MailboxAddress(craInfo.FullName, craInfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var user in craInfoList)
|
||||||
|
{
|
||||||
|
messageToSend.Cc.Add(new MailboxAddress(user.FullName, user.EMail));
|
||||||
}
|
}
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
@@ -531,8 +589,8 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
toUserName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
|
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
@@ -547,10 +605,11 @@ public class PMRepliedCheckChallengeEventConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -592,49 +651,57 @@ public class CheckStateChangedToAuditEventConsumer(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync();
|
var trialUserList = await _trialUseRoleRepository.Where(x => x.TrialId == subjectVisit.TrialId && x.TrialUser.IsDeleted == false)
|
||||||
|
.Select(t => new { t.UserRole.IdentityUser.EMail, t.UserRole.FullName, t.UserRole.UserTypeEnum, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == subjectVisit.TrialId);
|
||||||
|
|
||||||
|
|
||||||
|
// 遍历语言枚举 在底层判断收件人是否为空,决定是否跳过邮件发送,避免每个邮件场景的地方都重复判断
|
||||||
|
foreach (UserWorkLanguage workLanguage in Enum.GetValues<UserWorkLanguage>())
|
||||||
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
DictionaryRepository = _dictionaryRepository,
|
var userinfoList = trialUserList.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager)
|
||||||
IsEn_US = isEn_US,
|
.Where(t => t.UserWorkLanguage == workLanguage).ToList();
|
||||||
DictionaryList = new List<DictionaryDto>()
|
|
||||||
{
|
|
||||||
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
|
|
||||||
|
|
||||||
}
|
var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto()
|
||||||
});
|
{
|
||||||
|
|
||||||
|
DictionaryRepository = _dictionaryRepository,
|
||||||
|
IsEn_US = isEn_US,
|
||||||
|
DictionaryList = new List<DictionaryDto>()
|
||||||
|
{
|
||||||
|
new DictionaryDto (){DictionaryCode= "CheckState",EnumValue=subjectVisit.CheckState.GetEnumInt(), }, //审核状态
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
foreach (var userinfo in userinfoList)
|
|
||||||
{
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
var toUserName = string.Join('、', userinfoList.Select(t => t.FullName));
|
||||||
|
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
|
{
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 姓名 {0}
|
toUserName, // 姓名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
subjectCode, // 受试者 {2}
|
subjectCode, // 受试者 {2}
|
||||||
subjectVisit.VisitName, // 访视 {3}
|
subjectVisit.VisitName, // 访视 {3}
|
||||||
@@ -646,10 +713,11 @@ public class CheckStateChangedToAuditEventConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,7 +739,7 @@ public class QCClaimTaskEventConsumer(
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<QCClaimTaskEvent> context)
|
public async Task Consume(ConsumeContext<QCClaimTaskEvent> context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("发送(Code007,008) 【QC 领取了质控任务】邮件!!!");
|
Log.Logger.Warning("发送(Code007,008) 【QC 领取了质控任务】邮件!!!");
|
||||||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
|
|
||||||
@@ -703,6 +771,14 @@ public class QCClaimTaskEventConsumer(
|
|||||||
|
|
||||||
|
|
||||||
var userinfo = subjectVisit.CurrentActionUser;
|
var userinfo = subjectVisit.CurrentActionUser;
|
||||||
|
if (userinfo == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = _userRoleRepository.Where(t => t.Id == userinfo.Id).Select(t => t.IdentityUser.UserWorkLanguage).First();
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
@@ -741,7 +817,7 @@ public class QCClaimTaskEventConsumer(
|
|||||||
var subjectCode = subjectVisit.Subject.Code;
|
var subjectCode = subjectVisit.Subject.Code;
|
||||||
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName);
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.FullName, // 用户名 {0}
|
userinfo.FullName, // 用户名 {0}
|
||||||
trialInfo.ExperimentName, // 项目 {1}
|
trialInfo.ExperimentName, // 项目 {1}
|
||||||
string.Join(',', subjectcodes), // 受试者 {2}
|
string.Join(',', subjectcodes), // 受试者 {2}
|
||||||
@@ -755,9 +831,9 @@ public class QCClaimTaskEventConsumer(
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using System.Globalization;
|
using IRaCIS.Core.Domain.BaseModel;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using IRaCIS.Core.Domain.BaseModel;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using NPOI.SS.Formula.Functions;
|
using System.Globalization;
|
||||||
|
|
||||||
public class CultureInfoFilter<T> (IRepository<EventStoreRecord> _eventStoreRecordRepository) : IFilter<ConsumeContext<T>> where T : DomainEvent
|
public class CultureInfoFilter<T> (IRepository<EventStoreRecord> _eventStoreRecordRepository) : IFilter<ConsumeContext<T>> where T : DomainEvent
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,13 +74,17 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
t.UserRole.IdentityUser.EMail,
|
t.UserRole.IdentityUser.EMail,
|
||||||
t.UserRole.IdentityUser.UserName,
|
t.UserRole.IdentityUser.UserName,
|
||||||
t.Trial.TrialCode,
|
t.Trial.TrialCode,
|
||||||
t.Trial.ResearchProgramNo
|
t.Trial.ResearchProgramNo,
|
||||||
|
t.UserRole.IdentityUser.UserWorkLanguage
|
||||||
//TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList()
|
//TrialReadingCriterionList = t.Trial.TrialReadingCriterionList.Select(t => new { t.CriterionName, TrialReadingCriterionId = t.Id }).ToList()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
foreach (var trialUser in trialUserList)
|
foreach (var trialUser in trialUserList)
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = trialUser.UserWorkLanguage;
|
||||||
|
isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var userId = trialUser.UserId;
|
var userId = trialUser.UserId;
|
||||||
|
|
||||||
@@ -153,7 +157,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, emailContent, workLanguage),
|
||||||
trialUser.FullName,
|
trialUser.FullName,
|
||||||
|
|
||||||
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
@@ -167,9 +171,9 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc);
|
await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
//处理标记已通知的任务
|
//处理标记已通知的任务
|
||||||
|
|
||||||
|
|||||||
@@ -44,12 +44,17 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
|
|||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
||||||
|
|
||||||
//找到 该项目的CRC 用户Id
|
//找到 该项目的CRC 用户Id
|
||||||
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync();
|
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
|
|
||||||
foreach (var user in userList)
|
foreach (var user in userList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = user.UserWorkLanguage;
|
||||||
|
isEn_us = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var userId = user.UserId;
|
var userId = user.UserId;
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
var query = _trialRepository.Where(t => t.Id == trialId)
|
var query = _trialRepository.Where(t => t.Id == trialId)
|
||||||
@@ -72,7 +77,7 @@ public class QCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRepo
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
|
||||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr, isEn_us, userId);
|
return (topicStr, htmlBodyStr, isEn_us, userId);
|
||||||
@@ -116,12 +121,17 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
|
|||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync();
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstNotNullAsync();
|
||||||
|
|
||||||
//找到 该项目的IQC 用户Id
|
//找到 该项目的IQC 用户Id
|
||||||
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync();
|
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
|
|
||||||
foreach (var user in userList)
|
foreach (var user in userList)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = user.UserWorkLanguage;
|
||||||
|
isEn_us = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var userId = user.UserId;
|
var userId = user.UserId;
|
||||||
|
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
@@ -147,7 +157,7 @@ public class CRCImageQuestionRecurringEventConsumer(IRepository<Trial> _trialRep
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
|
||||||
|
|
||||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
@@ -181,7 +191,7 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
|||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context)
|
public async Task Consume(ConsumeContext<ImageQCRecurringEvent> context)
|
||||||
{
|
{
|
||||||
var trialId=context.Message.TrialId;
|
var trialId = context.Message.TrialId;
|
||||||
|
|
||||||
var isEn_us = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
|
var isEn_us = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
|
||||||
|
|
||||||
@@ -192,13 +202,17 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
|||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
|
||||||
|
|
||||||
//找到 该项目的IQC 用户Id
|
//找到 该项目的IQC 用户Id
|
||||||
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName }).ToListAsync();
|
var userList = await _trialUserRoleRepository.Where(t => t.TrialId == trialId).Where(t => t.UserRole.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.UserRole.FullName, t.UserRole.IdentityUser.UserWorkLanguage }).ToListAsync();
|
||||||
|
|
||||||
//判断是否任务可以领取 ,可以的话 发送邮件
|
//判断是否任务可以领取 ,可以的话 发送邮件
|
||||||
var userIdList = userList.Select(t => t.UserId).ToList();
|
var userIdList = userList.Select(t => t.UserId).ToList();
|
||||||
|
|
||||||
foreach (var user in userList)
|
foreach (var user in userList)
|
||||||
{
|
{
|
||||||
|
//重新设置当前发送邮件的语言
|
||||||
|
var workLanguage = user.UserWorkLanguage;
|
||||||
|
isEn_us = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var userId = user.UserId;
|
var userId = user.UserId;
|
||||||
|
|
||||||
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
|
||||||
@@ -222,11 +236,11 @@ public class ImageQCRecurringEventConsumer(IRepository<Trial> _trialRepository,
|
|||||||
|
|
||||||
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
var htmlContent = isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN;
|
||||||
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, htmlContent, workLanguage),
|
||||||
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
user.FullName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr, false, userId);
|
return (topicStr, htmlBodyStr, false, userId);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using IRaCIS.Core.Application.Helper;
|
|||||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
@@ -50,11 +51,13 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
|
|
||||||
var systemDocQuery =
|
var systemDocQuery =
|
||||||
from sysDoc in _systemDocumentRepository.AsQueryable(false)
|
from sysDoc in _systemDocumentRepository.AsQueryable(false)
|
||||||
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.Status == UserStateEnum.Enable).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
||||||
join confirmc in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirmc.ConfirmUserId, confirmc.SystemDocumentId } into cc
|
join confirmc in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirmc.ConfirmUserId, confirmc.SystemDocumentId } into cc
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
select new TriaAndSystemlSignDocView()
|
||||||
{
|
{
|
||||||
|
DocLanguageType=sysDoc.DocLanguageType,
|
||||||
|
UserWorkLanguage=identityUser.UserWorkLanguage,
|
||||||
IsSystemDoc = true,
|
IsSystemDoc = true,
|
||||||
Id = sysDoc.Id,
|
Id = sysDoc.Id,
|
||||||
CreateTime = sysDoc.CreateTime,
|
CreateTime = sysDoc.CreateTime,
|
||||||
@@ -78,209 +81,211 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
};
|
};
|
||||||
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null)
|
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
|
datalist = datalist
|
||||||
|
.Where(x=>x.DocLanguageType == DocLanguageType.CN_US || (int)x.DocLanguageType == (int)x.UserWorkLanguage)
|
||||||
|
.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
|
||||||
.Where(x => x.IsNeedSendEmial).ToList();
|
.Where(x => x.IsNeedSendEmial).ToList();
|
||||||
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
||||||
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
||||||
|
|
||||||
Console.WriteLine("发送定时过期提醒:人员数量" + userinfoList.Count);
|
Console.WriteLine("发送定时过期提醒:人员数量" + userinfoList.Count);
|
||||||
int index = 1;
|
|
||||||
foreach (var userinfo in userinfoList)
|
var scenario = EmailBusinessScenario.GeneralTraining_ExpirationNotification;
|
||||||
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
if (emailConfig == null)
|
||||||
{
|
{
|
||||||
try
|
return;
|
||||||
{
|
|
||||||
Console.WriteLine($"{index}发送定时过期提醒,邮箱:{userinfo.EMail},姓名{userinfo.UserName}");
|
|
||||||
index++;
|
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(
|
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
userinfo.UserName, // 用户名 {0}
|
|
||||||
_systemEmailConfig.SiteUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
var scenario = EmailBusinessScenario.GeneralTraining_ExpirationNotification;
|
|
||||||
|
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
|
||||||
|
|
||||||
if (emailConfig != null)
|
|
||||||
{
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userWorkLanguageList = userinfoList.Select(x => x.UserWorkLanguage).Distinct().ToList();
|
||||||
|
foreach (var workLanguage in userWorkLanguageList)
|
||||||
|
{
|
||||||
|
var langUserInfoList = userinfoList.Where(x => x.UserWorkLanguage == workLanguage).ToList();
|
||||||
|
if (!langUserInfoList.Any())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userIsEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
foreach (var userinfo in langUserInfoList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(
|
||||||
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
userinfo.FullName,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生效通知
|
/// 生效通知
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SystemDocumentPublishEventConsumer(
|
public class SystemDocumentPublishEventConsumer(
|
||||||
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
|
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
|
||||||
IRepository<VisitTask> _visitTaskRepository,
|
IRepository<VisitTask> _visitTaskRepository,
|
||||||
IRepository<SystemDocument> _systemDocumentRepository,
|
IRepository<SystemDocument> _systemDocumentRepository,
|
||||||
IRepository<IdentityUser> _identityUserRepository,
|
IRepository<IdentityUser> _identityUserRepository,
|
||||||
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
|
IRepository<SystemDocConfirmedIdentityUser> _systemDocConfirmedUserRepository,
|
||||||
IRepository<Dictionary> _dictionaryRepository,
|
IRepository<Dictionary> _dictionaryRepository,
|
||||||
IRepository<TrialUserRole> _trialUserRoleRepository,
|
IRepository<TrialUserRole> _trialUserRoleRepository,
|
||||||
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
|
IRepository<EmailNoticeConfig> _emailNoticeConfigrepository,
|
||||||
|
|
||||||
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentPublishEvent>
|
IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig) : IConsumer<SystemDocumentPublishEvent>
|
||||||
{
|
|
||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
|
||||||
|
|
||||||
public async Task Consume(ConsumeContext<SystemDocumentPublishEvent> context)
|
|
||||||
{
|
{
|
||||||
var isEn_US = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
|
|
||||||
//设置当前事件传递过来的语言
|
public async Task Consume(ConsumeContext<SystemDocumentPublishEvent> context)
|
||||||
var culture = context.Message.CultureInfoName;
|
|
||||||
CultureInfo.CurrentCulture = new CultureInfo(culture);
|
|
||||||
|
|
||||||
// 记录是否只发送给新增角色的日志
|
|
||||||
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
|
||||||
{
|
{
|
||||||
Console.WriteLine($"只发送给新增的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
|
var isEn_US = context.Message.CultureInfoName == StaticData.CultureInfo.en_US;
|
||||||
}
|
|
||||||
// 构建查询
|
|
||||||
IQueryable<UnionDocumentWithConfirmInfoView> systemDocQuery;
|
|
||||||
|
|
||||||
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
//设置当前事件传递过来的语言
|
||||||
{
|
var culture = context.Message.CultureInfoName;
|
||||||
// 只查询新增角色的用户
|
CultureInfo.CurrentCulture = new CultureInfo(culture);
|
||||||
systemDocQuery =
|
|
||||||
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
// 记录是否只发送给新增角色的日志
|
||||||
from identityUser in _identityUserRepository.AsQueryable(false)
|
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
||||||
.Where(t => t.Status == UserStateEnum.Enable &&
|
|
||||||
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
|
|
||||||
.Any(t => context.Message.NewUserTypeIds.Contains(t.UserTypeId) &&
|
|
||||||
sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
|
||||||
{
|
{
|
||||||
IsSystemDoc = true,
|
Console.WriteLine($"只发送给新增的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
|
||||||
Id = sysDoc.Id,
|
}
|
||||||
CreateTime = sysDoc.CreateTime,
|
// 构建查询
|
||||||
IsDeleted = sysDoc.IsDeleted,
|
IQueryable<TriaAndSystemlSignDocView> systemDocQuery;
|
||||||
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
|
|
||||||
Name = sysDoc.Name,
|
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
||||||
Path = sysDoc.Path,
|
|
||||||
FileTypeId = sysDoc.FileTypeId,
|
|
||||||
UpdateTime = sysDoc.UpdateTime,
|
|
||||||
ConfirmUserId = identityUser.Id,
|
|
||||||
RealName = identityUser.FullName,
|
|
||||||
UserName = identityUser.UserName,
|
|
||||||
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
|
|
||||||
FullFilePath = sysDoc.Path
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 查询所有相关角色的用户
|
|
||||||
systemDocQuery =
|
|
||||||
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
|
||||||
from identityUser in _identityUserRepository.AsQueryable(false)
|
|
||||||
.Where(t => t.Status == UserStateEnum.Enable &&
|
|
||||||
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
|
|
||||||
.Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
|
||||||
{
|
{
|
||||||
IsSystemDoc = true,
|
// 只查询新增角色的用户
|
||||||
Id = sysDoc.Id,
|
systemDocQuery =
|
||||||
CreateTime = sysDoc.CreateTime,
|
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
||||||
IsDeleted = sysDoc.IsDeleted,
|
from identityUser in _identityUserRepository.AsQueryable(false)
|
||||||
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
|
.Where(t => t.Status == UserStateEnum.Enable &&
|
||||||
Name = sysDoc.Name,
|
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
|
||||||
Path = sysDoc.Path,
|
.Any(t => context.Message.NewUserTypeIds.Contains(t.UserTypeId) &&
|
||||||
FileTypeId = sysDoc.FileTypeId,
|
sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
||||||
UpdateTime = sysDoc.UpdateTime,
|
select new TriaAndSystemlSignDocView()
|
||||||
ConfirmUserId = identityUser.Id,
|
|
||||||
RealName = identityUser.FullName,
|
|
||||||
UserName = identityUser.UserName,
|
|
||||||
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
|
|
||||||
FullFilePath = sysDoc.Path
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(x => x.IsNeedSendEmial).ToListAsync();
|
|
||||||
|
|
||||||
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
|
||||||
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
|
||||||
int index = 1;
|
|
||||||
foreach (var userinfo in userinfoList)
|
|
||||||
{
|
|
||||||
string msg = $"{index}生效通知,邮箱:{userinfo.EMail},姓名{userinfo.UserName},";
|
|
||||||
index++;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
DocLanguageType = sysDoc.DocLanguageType,
|
||||||
|
UserWorkLanguage = identityUser.UserWorkLanguage,
|
||||||
var htmlBodyStr = string.Format(
|
IsSystemDoc = true,
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
Id = sysDoc.Id,
|
||||||
userinfo.UserName, // 用户名 {0}
|
CreateTime = sysDoc.CreateTime,
|
||||||
_systemEmailConfig.SiteUrl
|
IsDeleted = sysDoc.IsDeleted,
|
||||||
);
|
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
|
||||||
|
Name = sysDoc.Name,
|
||||||
return (topicStr, htmlBodyStr);
|
Path = sysDoc.Path,
|
||||||
|
FileTypeId = sysDoc.FileTypeId,
|
||||||
|
UpdateTime = sysDoc.UpdateTime,
|
||||||
|
ConfirmUserId = identityUser.Id,
|
||||||
|
RealName = identityUser.FullName,
|
||||||
|
UserName = identityUser.UserName,
|
||||||
|
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
|
||||||
|
FullFilePath = sysDoc.Path
|
||||||
};
|
};
|
||||||
|
}
|
||||||
var scenario = EmailBusinessScenario.GeneralTraining_EffectiveNotification;
|
else
|
||||||
|
{
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
// 查询所有相关角色的用户
|
||||||
|
systemDocQuery =
|
||||||
if (emailConfig != null)
|
from sysDoc in _systemDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
||||||
|
from identityUser in _identityUserRepository.AsQueryable(false)
|
||||||
|
.Where(t => t.Status == UserStateEnum.Enable &&
|
||||||
|
t.UserRoleList.Where(t => t.IsUserRoleDisabled == false)
|
||||||
|
.Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
|
||||||
|
select new TriaAndSystemlSignDocView()
|
||||||
{
|
{
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
DocLanguageType = sysDoc.DocLanguageType,
|
||||||
|
UserWorkLanguage = identityUser.UserWorkLanguage,
|
||||||
|
IsSystemDoc = true,
|
||||||
|
Id = sysDoc.Id,
|
||||||
|
CreateTime = sysDoc.CreateTime,
|
||||||
|
IsDeleted = sysDoc.IsDeleted,
|
||||||
|
SignViewMinimumMinutes = sysDoc.SignViewMinimumMinutes,
|
||||||
|
Name = sysDoc.Name,
|
||||||
|
Path = sysDoc.Path,
|
||||||
|
FileTypeId = sysDoc.FileTypeId,
|
||||||
|
UpdateTime = sysDoc.UpdateTime,
|
||||||
|
ConfirmUserId = identityUser.Id,
|
||||||
|
RealName = identityUser.FullName,
|
||||||
|
UserName = identityUser.UserName,
|
||||||
|
IsNeedSendEmial = identityUser.IsZhiZhun || (!identityUser.IsZhiZhun && sysDoc.DocUserSignType == DocUserSignType.InnerAndOuter),
|
||||||
|
FullFilePath = sysDoc.Path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var datalist = await systemDocQuery.IgnoreQueryFilters().Where(x => x.IsNeedSendEmial).ToListAsync();
|
||||||
|
datalist = datalist.Where(x => x.DocLanguageType == DocLanguageType.CN_US || (int)x.DocLanguageType == (int)x.UserWorkLanguage).ToList();
|
||||||
|
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
||||||
|
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
||||||
|
|
||||||
|
var scenario = EmailBusinessScenario.GeneralTraining_EffectiveNotification;
|
||||||
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
if (emailConfig == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var userinfo in userinfoList)
|
||||||
|
{
|
||||||
|
string msg = $"{userinfo.UserName}生效通知,";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
|
var workLanguage = userinfo.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(
|
||||||
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
userinfo.FullName,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
msg += "发送成功";
|
msg += "发送成功";
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
msg += "发送失败";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
Console.WriteLine(msg);
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
msg += "发送失败";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
using DocumentFormat.OpenXml;
|
using DocumentFormat.OpenXml;
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.MassTransit.Consumer;
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using MimeKit;
|
using MimeKit;
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
using System.Reactive.Joins;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.MassTransit.Recurring
|
namespace IRaCIS.Core.Application.MassTransit.Recurring
|
||||||
{
|
{
|
||||||
@@ -60,7 +52,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
|
|
||||||
var trialDocQuery =
|
var trialDocQuery =
|
||||||
from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
from trialDoc in _trialDocumentRepository.AsQueryable(true)
|
||||||
|
join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
|
||||||
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
||||||
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
||||||
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
||||||
@@ -72,15 +64,18 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
|
|
||||||
from confirm in cc.DefaultIfEmpty()
|
from confirm in cc.DefaultIfEmpty()
|
||||||
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
||||||
select new TrialSignDocView()
|
select new TriaAndSystemlSignDocView()
|
||||||
{
|
{
|
||||||
|
|
||||||
TrialCode = trialDoc.Trial.TrialCode,
|
TrialCode = trialDoc.Trial.TrialCode,
|
||||||
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
ResearchProgramNo = trialDoc.Trial.ResearchProgramNo,
|
||||||
ExperimentName = trialDoc.Trial.ExperimentName,
|
ExperimentName = trialDoc.Trial.ExperimentName,
|
||||||
CurrentStaffTrainDays = trialDoc.CurrentStaffTrainDays,
|
CurrentStaffTrainDays = trialDoc.CurrentStaffTrainDays,
|
||||||
NewStaffTrainDays = trialDoc.NewStaffTrainDays,
|
NewStaffTrainDays = trialDoc.NewStaffTrainDays,
|
||||||
Id = trialDoc.Id,
|
Id = trialDoc.Id,
|
||||||
TrialId= trialDoc.TrialId,
|
TrialType= trial.TrialType,
|
||||||
|
IsTestUser= identityUser.IsTestUser,
|
||||||
|
TrialId = trialDoc.TrialId,
|
||||||
IsSystemDoc = false,
|
IsSystemDoc = false,
|
||||||
CreateTime = trialDoc.CreateTime,
|
CreateTime = trialDoc.CreateTime,
|
||||||
FullFilePath = trialDoc.Path,
|
FullFilePath = trialDoc.Path,
|
||||||
@@ -102,57 +97,79 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
};
|
};
|
||||||
var datalist = await trialDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null&&t.ConfirmTime==null)
|
var datalist = await trialDocQuery.IgnoreQueryFilters().Where(t => t.IsDeleted == false && t.ConfirmTime == null&&t.ConfirmTime==null)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
datalist = datalist.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
|
|
||||||
|
|
||||||
|
datalist = datalist
|
||||||
|
.Where(x=>((x.TrialType== TrialType.OfficialTrial|| x.TrialType== TrialType.Training) && !x.IsTestUser) || (x.TrialType==TrialType.NoneOfficial &&x.IsTestUser))
|
||||||
|
.Where(x => x.SuggestFinishTime != null && x.SuggestFinishTime.Value.Date == DateTime.Now.Date)
|
||||||
.ToList();
|
.ToList();
|
||||||
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
||||||
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
||||||
|
|
||||||
Console.WriteLine("发送定时项目过期提醒:人员数量" + userinfoList.Count);
|
Console.WriteLine("发送定时项目过期提醒:人员数量" + userinfoList.Count);
|
||||||
int index = 1;
|
|
||||||
foreach (var userinfo in userinfoList)
|
var scenario = EmailBusinessScenario.TrialTraining_ExpirationNotification;
|
||||||
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
||||||
|
if (emailConfig == null)
|
||||||
{
|
{
|
||||||
try
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
|
||||||
|
var userWithTrialList = (from ut in userTrialIdList
|
||||||
|
join u in userinfoList on ut.ConfirmUserId equals u.Id
|
||||||
|
select new { ut.TrialId, User = u }).ToList();
|
||||||
|
|
||||||
|
var groupedList = userWithTrialList.GroupBy(x => new { x.TrialId, x.User.UserWorkLanguage }).ToList();
|
||||||
|
foreach (var groupItem in groupedList)
|
||||||
|
{
|
||||||
|
var langUserInfoList = groupItem.Select(x => x.User).Distinct().ToList();
|
||||||
|
if (!langUserInfoList.Any())
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{index}发送定时过期提醒,邮箱:{userinfo.EMail},姓名{userinfo.UserName}");
|
continue;
|
||||||
index++;
|
|
||||||
var trialInfo = _trialRepository.Where(x => x.Id == userinfo.TrialId).FirstOrDefault();
|
|
||||||
var messageToSend = new MimeMessage();
|
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
|
||||||
{
|
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(
|
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
|
||||||
userinfo.UserName, // 用户名 {0}
|
|
||||||
_systemEmailConfig.SiteUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
var scenario = EmailBusinessScenario.TrialTraining_ExpirationNotification;
|
|
||||||
|
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault();
|
|
||||||
|
|
||||||
if (emailConfig != null)
|
|
||||||
{
|
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
Console.WriteLine($"发送定时过期提醒,数量:{langUserInfoList.Count}");
|
||||||
|
|
||||||
|
var trialInfo = await _trialRepository.Where(x => x.Id == groupItem.Key.TrialId).FirstOrDefaultAsync();
|
||||||
|
if (trialInfo == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var workLanguage = groupItem.Key.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
|
foreach (var userinfo in langUserInfoList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var messageToSend = new MimeMessage();
|
||||||
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
|
{
|
||||||
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
|
var htmlBodyStr = string.Format(
|
||||||
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
userinfo.FullName,
|
||||||
|
_systemEmailConfig.SiteUrl
|
||||||
|
);
|
||||||
|
|
||||||
|
return (topicStr, htmlBodyStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -193,20 +210,21 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
Console.WriteLine($"只发送给新增项目的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
|
Console.WriteLine($"只发送给新增项目的角色,角色数量: {context.Message.NewUserTypeIds.Count}");
|
||||||
}
|
}
|
||||||
// 构建查询
|
// 构建查询
|
||||||
IQueryable<UnionDocumentWithConfirmInfoView> systemDocQuery;
|
IQueryable<TriaAndSystemlSignDocView> trialDocQuery;
|
||||||
|
|
||||||
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
if (context.Message.NewUserTypeIds != null && context.Message.NewUserTypeIds.Any())
|
||||||
{
|
{
|
||||||
// 只查询新增角色的用户
|
// 只查询新增角色的用户
|
||||||
systemDocQuery =
|
trialDocQuery =
|
||||||
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
||||||
|
join trial in _trialRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trial.Id
|
||||||
join trialIdentityUser in _trialIdentityUserRepository.Where(x=>x.IsDeleted==false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
join trialIdentityUser in _trialIdentityUserRepository.Where(x=>x.IsDeleted==false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
||||||
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
join trialUserRole in _trialUserRoleRepository.Where(x => x.IsDeleted == false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
||||||
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
join identityUser in _identityUserRepository.AsQueryable(false).Where(u => u.Status == UserStateEnum.Enable)
|
||||||
on trialIdentityUser.IdentityUserId equals identityUser.Id
|
on trialIdentityUser.IdentityUserId equals identityUser.Id
|
||||||
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && context.Message.NewUserTypeIds.Contains(ur.UserRole.UserTypeId) && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted && context.Message.NewUserTypeIds.Contains(ur.UserRole.UserTypeId) && trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
||||||
|
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
select new TriaAndSystemlSignDocView()
|
||||||
{
|
{
|
||||||
IsSystemDoc = true,
|
IsSystemDoc = true,
|
||||||
Id = trialDoc.Id,
|
Id = trialDoc.Id,
|
||||||
@@ -214,6 +232,8 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
CreateTime = trialDoc.CreateTime,
|
CreateTime = trialDoc.CreateTime,
|
||||||
IsDeleted = trialDoc.IsDeleted,
|
IsDeleted = trialDoc.IsDeleted,
|
||||||
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
||||||
|
TrialType = trial.TrialType,
|
||||||
|
IsTestUser = identityUser.IsTestUser,
|
||||||
Name = trialDoc.Name,
|
Name = trialDoc.Name,
|
||||||
Path = trialDoc.Path,
|
Path = trialDoc.Path,
|
||||||
FileTypeId = trialDoc.FileTypeId,
|
FileTypeId = trialDoc.FileTypeId,
|
||||||
@@ -228,8 +248,9 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 查询所有相关角色的用户
|
// 查询所有相关角色的用户
|
||||||
systemDocQuery =
|
trialDocQuery =
|
||||||
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
from trialDoc in _trialDocumentRepository.AsQueryable(false).Where(x => context.Message.Ids.Contains(x.Id))
|
||||||
|
|
||||||
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
join trialIdentityUser in _trialIdentityUserRepository.Where(x => x.IsDeleted == false) on trialDoc.TrialId equals trialIdentityUser.TrialId
|
||||||
join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
join trialUserRole in _trialUserRoleRepository.Where(x=>x.IsDeleted==false) on trialIdentityUser.Id equals trialUserRole.TrialUserId
|
||||||
|
|
||||||
@@ -239,7 +260,7 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
where trialIdentityUser.TrialUserRoleList.Any(ur => !ur.IsDeleted &&trialDoc.NeedConfirmedUserTypeList.Any(c => c.NeedConfirmUserTypeId == ur.UserRole.UserTypeId))
|
||||||
|
|
||||||
|
|
||||||
select new UnionDocumentWithConfirmInfoView()
|
select new TriaAndSystemlSignDocView()
|
||||||
{
|
{
|
||||||
IsSystemDoc = false,
|
IsSystemDoc = false,
|
||||||
Id = trialDoc.Id,
|
Id = trialDoc.Id,
|
||||||
@@ -248,6 +269,8 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
CreateTime = trialDoc.CreateTime,
|
CreateTime = trialDoc.CreateTime,
|
||||||
IsDeleted = trialDoc.IsDeleted,
|
IsDeleted = trialDoc.IsDeleted,
|
||||||
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
SignViewMinimumMinutes = trialDoc.SignViewMinimumMinutes,
|
||||||
|
TrialType = trial.TrialType,
|
||||||
|
IsTestUser = identityUser.IsTestUser,
|
||||||
Name = trialDoc.Name,
|
Name = trialDoc.Name,
|
||||||
Path = trialDoc.Path,
|
Path = trialDoc.Path,
|
||||||
FileTypeId = trialDoc.FileTypeId,
|
FileTypeId = trialDoc.FileTypeId,
|
||||||
@@ -260,56 +283,60 @@ namespace IRaCIS.Core.Application.MassTransit.Recurring
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var datalist = await systemDocQuery.IgnoreQueryFilters().ToListAsync();
|
var datalist = await trialDocQuery.IgnoreQueryFilters().ToListAsync();
|
||||||
|
datalist = datalist.Where(x => ((x.TrialType == TrialType.OfficialTrial || x.TrialType == TrialType.Training) && !x.IsTestUser) || (x.TrialType == TrialType.NoneOfficial && x.IsTestUser)).ToList();
|
||||||
|
|
||||||
|
|
||||||
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
var confirmUserIdList = datalist.Select(t => t.ConfirmUserId).Distinct().ToList();
|
||||||
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
var userinfoList = await _identityUserRepository.Where(x => confirmUserIdList.Contains(x.Id)).ToListAsync();
|
||||||
int index = 1;
|
|
||||||
foreach (var userinfo in userinfoList)
|
var scenario = EmailBusinessScenario.TrialTraining_EffectiveNotification;
|
||||||
|
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable).FirstOrDefault();
|
||||||
|
if (emailConfig == null)
|
||||||
{
|
{
|
||||||
string msg = $"{index}项目生效通知,邮箱:{userinfo.EMail},姓名{userinfo.UserName},";
|
return;
|
||||||
index++;
|
}
|
||||||
|
|
||||||
|
var userTrialIdList = datalist.Select(t => new { t.ConfirmUserId, t.TrialId }).Distinct().ToList();
|
||||||
|
var userWithTrialList = (from ut in userTrialIdList
|
||||||
|
join u in userinfoList on ut.ConfirmUserId equals u.Id
|
||||||
|
select new { ut.TrialId, User = u }).ToList();
|
||||||
|
|
||||||
|
foreach (var userWithTrial in userWithTrialList)
|
||||||
|
{
|
||||||
|
var userinfo = userWithTrial.User;
|
||||||
|
string msg = $"{userinfo.UserName}项目生效通知,";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
messageToSend.To.Add(new MailboxAddress(userinfo.FullName, userinfo.EMail));
|
||||||
|
|
||||||
|
var workLanguage = userinfo.UserWorkLanguage;
|
||||||
|
var userIsEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = userIsEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(
|
var htmlBodyStr = string.Format(
|
||||||
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr),
|
CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userinfo.UserName, // 用户名 {0}
|
userinfo.FullName,
|
||||||
_systemEmailConfig.SiteUrl
|
_systemEmailConfig.SiteUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
var scenario = EmailBusinessScenario.TrialTraining_EffectiveNotification;
|
var trialInfo = await _trialRepository.Where(x => x.Id == userWithTrial.TrialId).FirstOrDefaultAsync();
|
||||||
|
if (trialInfo == null)
|
||||||
var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable).FirstOrDefault();
|
|
||||||
|
|
||||||
if (emailConfig != null)
|
|
||||||
{
|
{
|
||||||
await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailConfig, messageToSend, emailConfigFunc);
|
continue;
|
||||||
|
|
||||||
var trial = datalist.Where(x => x.ConfirmUserId == userinfo.Id).FirstOrDefault();
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.Where(x=>x.Id==trial.TrialId).FirstNotNullAsync();
|
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
|
||||||
msg += "发送成功";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
msg += "发送成功";
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|||||||
@@ -439,6 +439,8 @@ namespace IRaCIS.Core.Application.ViewModel
|
|||||||
|
|
||||||
public string TaskName { get; set; } = String.Empty;
|
public string TaskName { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public string TaskBlindName { get; set; } = String.Empty;
|
||||||
|
|
||||||
public Guid? DoctorUserId { get; set; }
|
public Guid? DoctorUserId { get; set; }
|
||||||
|
|
||||||
public ReadingCategory? ReadingCategory { get; set; }
|
public ReadingCategory? ReadingCategory { get; set; }
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
|
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
|
||||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||||
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
|
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
|
||||||
.WhereIf(inQuery.IsHaveQuestion != null, t => t.IsHaveQuestion == inQuery.IsHaveQuestion)
|
.WhereIf(inQuery.IsHaveQuestion != null, t => t.IsHaveQuestion == inQuery.IsHaveQuestion)
|
||||||
|
|
||||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
|
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
|
||||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
|
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
|
||||||
@@ -211,23 +211,23 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
|
.WhereIf(inQuery.SubjectId != null, t => t.VisitTask.SubjectId == inQuery.SubjectId)
|
||||||
.WhereIf(inQuery.TrialSiteId != null, t => t.VisitTask.Subject.TrialSiteId == inQuery.TrialSiteId)
|
.WhereIf(inQuery.TrialSiteId != null, t => t.VisitTask.Subject.TrialSiteId == inQuery.TrialSiteId)
|
||||||
.WhereIf(inQuery.IsUrgent != null, t => t.VisitTask.IsUrgent == inQuery.IsUrgent)
|
.WhereIf(inQuery.IsUrgent != null, t => t.VisitTask.IsUrgent == inQuery.IsUrgent)
|
||||||
.WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState)
|
.WhereIf(inQuery.AuditState != null, t => t.AuditState == inQuery.AuditState)
|
||||||
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
|
.WhereIf(inQuery.DoctorUserIdeaEnum != null, t => t.DoctorUserIdeaEnum == inQuery.DoctorUserIdeaEnum)
|
||||||
.WhereIf(inQuery.TaskState != null, t => t.VisitTask.TaskState == inQuery.TaskState)
|
.WhereIf(inQuery.TaskState != null, t => t.VisitTask.TaskState == inQuery.TaskState)
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.VisitTask.Subject.Code.Contains(inQuery.SubjectCode) || t.VisitTask.Subject.MedicalNo.Contains(inQuery.SubjectCode))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.VisitTask.TaskName.Contains(inQuery.TaskName) || t.VisitTask.TaskBlindName.Contains(inQuery.TaskName))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.VisitTask.TaskName.Contains(inQuery.TaskName) || t.VisitTask.TaskBlindName.Contains(inQuery.TaskName))
|
||||||
.WhereIf(inQuery.DoctorUserId != null, t => t.VisitTask.DoctorUserId == inQuery.DoctorUserId)
|
.WhereIf(inQuery.DoctorUserId != null, t => t.VisitTask.DoctorUserId == inQuery.DoctorUserId)
|
||||||
.WhereIf(inQuery.ReadingCategory != null, t => t.VisitTask.ReadingCategory == inQuery.ReadingCategory)
|
.WhereIf(inQuery.ReadingCategory != null, t => t.VisitTask.ReadingCategory == inQuery.ReadingCategory)
|
||||||
.WhereIf(inQuery.ReadingTaskState != null, t => t.VisitTask.ReadingTaskState == inQuery.ReadingTaskState)
|
.WhereIf(inQuery.ReadingTaskState != null, t => t.VisitTask.ReadingTaskState == inQuery.ReadingTaskState)
|
||||||
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
|
.WhereIf(inQuery.IsInvalid != null, t => t.IsInvalid == inQuery.IsInvalid)
|
||||||
.WhereIf(inQuery.IsGetBeRead, x => !x.IsInvalid && x.AuditState != MedicalReviewAuditState.HaveSigned)
|
.WhereIf(inQuery.IsGetBeRead, x => !x.IsInvalid && x.AuditState != MedicalReviewAuditState.HaveSigned)
|
||||||
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.VisitTask.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
|
||||||
.WhereIf(inQuery.BeginAuditSignTime != null, t => t.AuditSignTime >= inQuery.BeginAuditSignTime)
|
.WhereIf(inQuery.BeginAuditSignTime != null, t => t.AuditSignTime >= inQuery.BeginAuditSignTime)
|
||||||
.WhereIf(inQuery.EndAuditSignTime != null, t => t.AuditSignTime <= inQuery.EndAuditSignTime)
|
.WhereIf(inQuery.EndAuditSignTime != null, t => t.AuditSignTime <= inQuery.EndAuditSignTime)
|
||||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
|
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime >= inQuery.BeginAllocateDate)
|
||||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
|
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime <= inQuery.EndAllocateDate)
|
||||||
|
|
||||||
.WhereIf(inQuery.ArmEnum != null, t => t.VisitTask.ArmEnum == inQuery.ArmEnum)
|
.WhereIf(inQuery.ArmEnum != null, t => t.VisitTask.ArmEnum == inQuery.ArmEnum)
|
||||||
.WhereIf(inQuery.MedicalManagerUserId != null, t => t.MedicalManagerUserId == inQuery.MedicalManagerUserId)
|
.WhereIf(inQuery.MedicalManagerUserId != null, t => t.MedicalManagerUserId == inQuery.MedicalManagerUserId)
|
||||||
.WhereIf(inQuery.BeginSignTime != null, t => t.VisitTask.SignTime > inQuery.BeginSignTime)
|
.WhereIf(inQuery.BeginSignTime != null, t => t.VisitTask.SignTime > inQuery.BeginSignTime)
|
||||||
.WhereIf(inQuery.EndSignTime != null, t => t.VisitTask.SignTime < inQuery.EndSignTime)
|
.WhereIf(inQuery.EndSignTime != null, t => t.VisitTask.SignTime < inQuery.EndSignTime)
|
||||||
|
|||||||
@@ -124,6 +124,45 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 获取随机编号
|
||||||
|
/// <summary>
|
||||||
|
/// 从 NewId 的后 3 个字节(24 位)生成一个 6 位十六进制字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GenerateTaskNo()
|
||||||
|
{
|
||||||
|
var bytes = NewId.Next().ToByteArray();
|
||||||
|
|
||||||
|
uint value =
|
||||||
|
BitConverter.ToUInt32(bytes, 0)
|
||||||
|
^ BitConverter.ToUInt32(bytes, 4)
|
||||||
|
^ BitConverter.ToUInt32(bytes, 8)
|
||||||
|
^ BitConverter.ToUInt32(bytes, 12);
|
||||||
|
|
||||||
|
return (value & 0xFFFFFF).ToString("X6");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetRandomTaskName(Guid trialId, List<string> existList)
|
||||||
|
{
|
||||||
|
var taskName = GenerateTaskNo();
|
||||||
|
|
||||||
|
while (existList.Any(t => t == taskName))
|
||||||
|
{
|
||||||
|
taskName = GenerateTaskNo();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (await _visitTaskRepository.AnyAsync(t => t.TaskBlindName == taskName && t.TrialId == trialId))
|
||||||
|
{
|
||||||
|
taskName = GenerateTaskNo();
|
||||||
|
}
|
||||||
|
|
||||||
|
existList.Add(taskName);
|
||||||
|
|
||||||
|
return taskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
//基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务)
|
//基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务)
|
||||||
public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List<Guid>? subjectVisitIdList = null)
|
public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List<Guid>? subjectVisitIdList = null)
|
||||||
@@ -151,11 +190,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
||||||
|
|
||||||
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialStudyMaxCode(trialId));
|
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialVisitTaskMaxCode(trialId));
|
||||||
|
|
||||||
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
|
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
|
||||||
|
|
||||||
|
var randomTaskBlindNameList = new List<string>();
|
||||||
|
|
||||||
foreach (var subjectGroup in needGenerateVisit.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() }))
|
foreach (var subjectGroup in needGenerateVisit.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() }))
|
||||||
{
|
{
|
||||||
@@ -173,6 +212,8 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var blindTaskName = string.Empty;
|
var blindTaskName = string.Empty;
|
||||||
|
|
||||||
|
var isRandom = false;
|
||||||
|
|
||||||
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
{
|
{
|
||||||
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0)
|
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0 && subjectVisit.VisitNum == 0)
|
||||||
@@ -185,6 +226,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.Random)
|
||||||
|
{
|
||||||
|
blindTaskName = await GetRandomTaskName(trialId, randomTaskBlindNameList);
|
||||||
|
|
||||||
|
isRandom = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blindTaskName = "Timepoint";
|
blindTaskName = "Timepoint";
|
||||||
@@ -258,12 +305,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
|
|
||||||
|
var blindTaskName2 = isRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : blindTaskName;
|
||||||
|
|
||||||
task2 = await _visitTaskRepository.AddAsync(new VisitTask()
|
task2 = await _visitTaskRepository.AddAsync(new VisitTask()
|
||||||
{
|
{
|
||||||
TrialId = trialId,
|
TrialId = trialId,
|
||||||
SubjectId = subjectVisit.SubjectId,
|
SubjectId = subjectVisit.SubjectId,
|
||||||
IsUrgent = subjectVisit.IsUrgent,
|
IsUrgent = subjectVisit.IsUrgent,
|
||||||
TaskBlindName = blindTaskName,
|
TaskBlindName = blindTaskName2,
|
||||||
TaskName = subjectVisit.VisitName,
|
TaskName = subjectVisit.VisitName,
|
||||||
TaskUrgentType = taskUrgentType,
|
TaskUrgentType = taskUrgentType,
|
||||||
IsCanEditUrgentState = isCanEditUrgentState,
|
IsCanEditUrgentState = isCanEditUrgentState,
|
||||||
@@ -283,7 +332,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -344,7 +393,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -590,11 +639,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
||||||
|
|
||||||
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialStudyMaxCode(trialId));
|
var cacheMaxCodeInt = _fusionCache.GetOrDefault<int>(CacheKeys.TrialVisitTaskMaxCode(trialId));
|
||||||
|
|
||||||
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
|
int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode;
|
||||||
|
|
||||||
|
var randomTaskBlindNameList = new List<string>();
|
||||||
|
|
||||||
|
|
||||||
switch (generateTaskCommand.ReadingCategory)
|
switch (generateTaskCommand.ReadingCategory)
|
||||||
@@ -654,7 +703,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false);
|
var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false);
|
||||||
|
|
||||||
|
|
||||||
var blindTaskName = string.Empty;
|
var blindTaskName = string.Empty;
|
||||||
|
var isFullRandom = false;
|
||||||
|
|
||||||
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
{
|
{
|
||||||
@@ -668,6 +719,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.Random)
|
||||||
|
{
|
||||||
|
blindTaskName = await GetRandomTaskName(trialId, randomTaskBlindNameList);
|
||||||
|
isFullRandom = true;
|
||||||
|
}
|
||||||
|
//受试者随机
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blindTaskName = "Timepoint";
|
blindTaskName = "Timepoint";
|
||||||
@@ -710,6 +767,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt, nameof(VisitTask)),
|
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt, nameof(VisitTask)),
|
||||||
ReadingCategory = ReadingCategory.Visit,
|
ReadingCategory = ReadingCategory.Visit,
|
||||||
|
|
||||||
|
|
||||||
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId,
|
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId,
|
||||||
IsNeedClinicalDataSign = isNeedClinicalDataSign,
|
IsNeedClinicalDataSign = isNeedClinicalDataSign,
|
||||||
IsClinicalDataSign = isClinicalDataSign,
|
IsClinicalDataSign = isClinicalDataSign,
|
||||||
@@ -721,11 +779,15 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
|
if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
|
||||||
{
|
{
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
|
var blindTaskName2 = isFullRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : blindTaskName;
|
||||||
|
|
||||||
|
|
||||||
task2 = await _visitTaskRepository.AddAsync(new VisitTask()
|
task2 = await _visitTaskRepository.AddAsync(new VisitTask()
|
||||||
{
|
{
|
||||||
TrialId = trialId,
|
TrialId = trialId,
|
||||||
SubjectId = subjectVisit.SubjectId,
|
SubjectId = subjectVisit.SubjectId,
|
||||||
TaskBlindName = blindTaskName,
|
TaskBlindName = blindTaskName2,
|
||||||
TaskName = subjectVisit.VisitName,
|
TaskName = subjectVisit.VisitName,
|
||||||
IsUrgent = subjectVisit.IsUrgent,
|
IsUrgent = subjectVisit.IsUrgent,
|
||||||
|
|
||||||
@@ -747,7 +809,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
|
|
||||||
#region 分配
|
#region 分配
|
||||||
@@ -873,7 +935,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
arm1.TaskAllocationState = TaskAllocationState.Allocated;
|
arm1.TaskAllocationState = TaskAllocationState.Allocated;
|
||||||
arm1.AllocateTime = DateTime.Now;
|
arm1.AllocateTime = DateTime.Now;
|
||||||
arm1.DoctorUserId = task1.DoctorUserId;
|
arm1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
|
||||||
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,14 +975,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
taskOne.TaskAllocationState = TaskAllocationState.Allocated;
|
taskOne.TaskAllocationState = TaskAllocationState.Allocated;
|
||||||
taskOne.AllocateTime = DateTime.Now;
|
taskOne.AllocateTime = DateTime.Now;
|
||||||
taskOne.DoctorUserId = task1!.DoctorUserId;
|
taskOne.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
|
||||||
taskOne.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
taskOne.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -944,7 +1006,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
arm2.TaskAllocationState = TaskAllocationState.Allocated;
|
arm2.TaskAllocationState = TaskAllocationState.Allocated;
|
||||||
arm2.AllocateTime = DateTime.Now;
|
arm2.AllocateTime = DateTime.Now;
|
||||||
arm2.DoctorUserId = task2.DoctorUserId;
|
arm2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
|
||||||
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,13 +1048,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
taskTwo.TaskAllocationState = TaskAllocationState.Allocated;
|
taskTwo.TaskAllocationState = TaskAllocationState.Allocated;
|
||||||
taskTwo.AllocateTime = DateTime.Now;
|
taskTwo.AllocateTime = DateTime.Now;
|
||||||
taskTwo.DoctorUserId = task2!.DoctorUserId;
|
taskTwo.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
|
||||||
taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,7 +1131,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
#region 分配
|
#region 分配
|
||||||
|
|
||||||
@@ -1197,7 +1259,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1277,6 +1339,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var reReadingVisitTask = generateTaskCommand.ReReadingTask;
|
var reReadingVisitTask = generateTaskCommand.ReReadingTask;
|
||||||
|
|
||||||
|
|
||||||
Guid? subjectVisitId = Guid.Empty;
|
Guid? subjectVisitId = Guid.Empty;
|
||||||
|
|
||||||
if (reReadingVisitTask.SourceSubjectVisitId == null)
|
if (reReadingVisitTask.SourceSubjectVisitId == null)
|
||||||
@@ -1317,6 +1380,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//&& t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId && t.TaskState == TaskState.Effect
|
//&& t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId && t.TaskState == TaskState.Effect
|
||||||
// && t.SourceSubjectVisitId == reReadingVisitTask.SourceSubjectVisitId && t.ArmEnum == reReadingVisitTask.ArmEnum && t.DoctorUserId == reReadingVisitTask.DoctorUserId).FirstOrDefault();
|
// && t.SourceSubjectVisitId == reReadingVisitTask.SourceSubjectVisitId && t.ArmEnum == reReadingVisitTask.ArmEnum && t.DoctorUserId == reReadingVisitTask.DoctorUserId).FirstOrDefault();
|
||||||
|
|
||||||
|
var isRandomReading = trialReadingCriterionConfigList.FirstOrDefault(t => t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId)?.IsReadingTaskViewInOrder == ReadingOrder.Random;
|
||||||
|
|
||||||
|
var taskBlindName = isRandomReading ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : reReadingVisitTask.TaskBlindName;
|
||||||
|
|
||||||
|
|
||||||
var newTask = await _visitTaskRepository.AddAsync(new VisitTask()
|
var newTask = await _visitTaskRepository.AddAsync(new VisitTask()
|
||||||
{
|
{
|
||||||
@@ -1325,7 +1392,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
SubjectId = reReadingVisitTask.SubjectId,
|
SubjectId = reReadingVisitTask.SubjectId,
|
||||||
ArmEnum = reReadingVisitTask.ArmEnum,
|
ArmEnum = reReadingVisitTask.ArmEnum,
|
||||||
TaskName = reReadingVisitTask.TaskName,
|
TaskName = reReadingVisitTask.TaskName,
|
||||||
TaskBlindName = reReadingVisitTask.TaskBlindName,
|
TaskBlindName = taskBlindName,
|
||||||
|
|
||||||
IsUrgent = reReadingVisitTask.IsAnalysisCreate ? false : subjectVisitUrgentInfo.IsUrgent,
|
IsUrgent = reReadingVisitTask.IsAnalysisCreate ? false : subjectVisitUrgentInfo.IsUrgent,
|
||||||
TaskUrgentType = reReadingVisitTask.IsAnalysisCreate ? null : taskUrgent,
|
TaskUrgentType = reReadingVisitTask.IsAnalysisCreate ? null : taskUrgent,
|
||||||
@@ -1355,6 +1422,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
// AllocateTime = DateTime.Now,
|
// AllocateTime = DateTime.Now,
|
||||||
//DoctorUserId = reReadingVisitTask.DoctorUserId,
|
//DoctorUserId = reReadingVisitTask.DoctorUserId,
|
||||||
|
|
||||||
|
IsIRImageDownloaded= reReadingVisitTask.IsIRImageDownloaded,
|
||||||
});
|
});
|
||||||
|
|
||||||
generateTaskCommand.Action(newTask);
|
generateTaskCommand.Action(newTask);
|
||||||
@@ -1386,7 +1454,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -1491,7 +1559,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1538,7 +1606,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1548,6 +1616,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm && x.IsConfirmed && x.TrialReadingCriterionId == firstTask.TrialReadingCriterionId).FirstOrDefaultAsync();
|
var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm && x.IsConfirmed && x.TrialReadingCriterionId == firstTask.TrialReadingCriterionId).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
|
var isRandom = trialReadingCriterionConfigList.FirstOrDefault(t => t.TrialReadingCriterionId == firstTask.TrialReadingCriterionId)?.IsReadingTaskViewInOrder == ReadingOrder.Random;
|
||||||
|
|
||||||
|
var blindName = isRandom ? await GetRandomTaskName(trialId, randomTaskBlindNameList) : firstTask.TaskBlindName;
|
||||||
|
|
||||||
VisitTask visitTask = new VisitTask()
|
VisitTask visitTask = new VisitTask()
|
||||||
{
|
{
|
||||||
ArmEnum = Arm.JudgeArm,
|
ArmEnum = Arm.JudgeArm,
|
||||||
@@ -1564,7 +1637,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
SouceReadModuleId = firstTask.SouceReadModuleId,
|
SouceReadModuleId = firstTask.SouceReadModuleId,
|
||||||
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
|
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
|
||||||
TaskState = TaskState.Effect,
|
TaskState = TaskState.Effect,
|
||||||
TaskBlindName = firstTask.TaskBlindName,
|
TaskBlindName = blindName,
|
||||||
DoctorUserId = subjectUser == null ? null : subjectUser.DoctorUserId,
|
DoctorUserId = subjectUser == null ? null : subjectUser.DoctorUserId,
|
||||||
TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated,
|
TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated,
|
||||||
AllocateTime = subjectUser == null ? null : DateTime.Now,
|
AllocateTime = subjectUser == null ? null : DateTime.Now,
|
||||||
@@ -1576,7 +1649,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
await _visitTaskRepository.AddAsync(visitTask);
|
await _visitTaskRepository.AddAsync(visitTask);
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
|
|
||||||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id), x => new VisitTask()
|
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id), x => new VisitTask()
|
||||||
{
|
{
|
||||||
@@ -1637,7 +1710,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
});
|
});
|
||||||
|
|
||||||
currentMaxCodeInt = currentMaxCodeInt + 1;
|
currentMaxCodeInt = currentMaxCodeInt + 1;
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,7 +1780,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
TrialId = originalTaskInfo.TrialId
|
TrialId = originalTaskInfo.TrialId
|
||||||
});
|
});
|
||||||
|
|
||||||
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
_fusionCache.Set<int>(CacheKeys.TrialVisitTaskMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
|
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
|
||||||
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
||||||
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
|
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
|
||||||
|
IRepository<Segment> _segmentRepository,
|
||||||
|
IRepository<Segmentation> _segmentationRepository,
|
||||||
|
IRepository<SegmentBinding> _segmentBindingRepository,
|
||||||
IRepository<DicomInstance> _dicomInstanceRepository,
|
IRepository<DicomInstance> _dicomInstanceRepository,
|
||||||
IRepository<DicomSeries> _dicomSeriesRepository,
|
IRepository<DicomSeries> _dicomSeriesRepository,
|
||||||
IRepository<SubjectCanceDoctor> _subjectCanceDoctorRepository,
|
IRepository<SubjectCanceDoctor> _subjectCanceDoctorRepository,
|
||||||
@@ -50,7 +53,11 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
IRepository<ReadingNoneDicomMark> _readingNoneDicomMarkRepository,
|
IRepository<ReadingNoneDicomMark> _readingNoneDicomMarkRepository,
|
||||||
IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository,
|
IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository,
|
||||||
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
|
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
|
||||||
//IRepository<ReadingCustomTag> _readingCustomTagRepository,
|
//IRepository<ReadingCustomTag> _readingCustomTagRepository,
|
||||||
|
IRepository<TaskStudy> _taskStudyRepository,
|
||||||
|
IRepository<TaskSeries> _taskSeriesRepository,
|
||||||
|
IRepository<TaskInstance> _taskInstanceRepository,
|
||||||
|
IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
|
||||||
IRepository<TaskInfluence> _taskInfluenceRepository,
|
IRepository<TaskInfluence> _taskInfluenceRepository,
|
||||||
IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
|
IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
|
||||||
ILogger<VisitTaskService> _logger,
|
ILogger<VisitTaskService> _logger,
|
||||||
@@ -88,6 +95,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
{
|
{
|
||||||
TrialReadingCriterionId = t.Id,
|
TrialReadingCriterionId = t.Id,
|
||||||
IsAutoCreate = t.IsAutoCreate,
|
IsAutoCreate = t.IsAutoCreate,
|
||||||
|
ReadingTool = t.ReadingTool,
|
||||||
IsAdditionalAssessment = t.IsAdditionalAssessment,
|
IsAdditionalAssessment = t.IsAdditionalAssessment,
|
||||||
TrialReadingCriterionName = t.CriterionName,
|
TrialReadingCriterionName = t.CriterionName,
|
||||||
CriterionType = t.CriterionType,
|
CriterionType = t.CriterionType,
|
||||||
@@ -846,7 +854,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
/// <param name="inQuery"></param>
|
/// <param name="inQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<PageOutput<ReReadingTaskView>> GetIRReReadingTaskList(VisitTaskQuery inQuery)
|
public async Task<IResponseOutput<PageOutput<ReReadingTaskView>>> GetIRReReadingTaskList(VisitTaskQuery inQuery)
|
||||||
{
|
{
|
||||||
|
|
||||||
var visitTaskQueryable = _visitTaskReReadingRepository
|
var visitTaskQueryable = _visitTaskReReadingRepository
|
||||||
@@ -870,6 +878,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.OriginalReReadingTask.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate) || (t.OriginalReReadingTask.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.OriginalReReadingTask.IsAnalysisCreate == false))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskName))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.OriginalReReadingTask.TaskName.Contains(inQuery.TaskName) || t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskBlindName), t => t.NewReReadingTask.TaskBlindName.Contains(inQuery.TaskBlindName))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.OriginalReReadingTask.Subject.Code.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate == false) || (t.OriginalReReadingTask.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.OriginalReReadingTask.IsAnalysisCreate))
|
||||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate)
|
.WhereIf(inQuery.BeginAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime > inQuery.BeginAllocateDate)
|
||||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
.WhereIf(inQuery.EndAllocateDate != null, t => t.OriginalReReadingTask.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
||||||
@@ -881,7 +890,11 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
|
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
|
||||||
|
|
||||||
return pageList;
|
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||||||
|
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(pageList, criterionInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1013,9 +1026,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
if (critrion.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
|
||||||
{
|
{
|
||||||
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.TrialExtraConfigJsonStr }).FirstOrDefault();
|
var extralObj = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.IsOpenLostVistRead }).FirstOrDefault();
|
||||||
|
|
||||||
var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
|
//var extralConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(extralObj?.TrialExtraConfigJsonStr) ?? new TrialExtraConfig();
|
||||||
|
|
||||||
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect && x.Subject.IsSubjectQuit == false)
|
var visitQuery = _visitTaskRepository.Where(x => x.TrialId == inQuery.TrialId && x.DoctorUserId == _userInfo.UserRoleId && x.TaskState == TaskState.Effect && x.Subject.IsSubjectQuit == false)
|
||||||
|
|
||||||
@@ -1024,7 +1037,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
.WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum))
|
.WhereIf(critrion.IsAutoCreate == false, t => !t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(f => f.IsGeneratedTask == false && t.VisitTaskNum > f.SubjectVisit.VisitNum))
|
||||||
|
|
||||||
// 前序 不存在 未一致性核查未通过的
|
// 前序 不存在 未一致性核查未通过的
|
||||||
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralConfig.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
|
.Where(t => !t.Subject.SubjectVisitList.Where(t => extralObj.IsOpenLostVistRead ? t.IsLostVisit == false : true).Any(sv => sv.CheckState != CheckStateEnum.CVPassed && t.VisitTaskNum >= sv.VisitNum))
|
||||||
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
|
//.WhereIf(critrion.IsAutoCreate == false, t => t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId).Any(t => t.IsGeneratedTask == false) ?
|
||||||
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
|
//t.VisitTaskNum <= t.Subject.SubjectCriteriaEvaluationVisitFilterList.Where(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.IsGeneratedTask == false).Min(t => t.SubjectVisit.VisitNum) : true)
|
||||||
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
|
//.Where(t => t.Subject.SubjectVisitList.Any(t => t.CheckState != CheckStateEnum.CVPassed) ? t.VisitTaskNum <= t.Subject.SubjectVisitList.Where(t => t.CheckState != CheckStateEnum.CVPassed).Min(t => t.VisitNum) : true)
|
||||||
@@ -1047,14 +1060,14 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
|
UnReadTaskCount = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned).Count(),
|
||||||
|
|
||||||
//未读 里可读任务量
|
//未读 里可读任务量
|
||||||
UnReadCanReadTaskCount = x.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
|
UnReadCanReadTaskCount = x.Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false).Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned && (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true)
|
||||||
//不能对包含聚合或子查询的表达式执行聚合函数
|
//不能对包含聚合或子查询的表达式执行聚合函数
|
||||||
//&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum )
|
//&& !x.Any(t => t.ReadingTaskState != ReadingTaskState.HaveSigned && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false && t.VisitTaskNum<y.VisitTaskNum )
|
||||||
).Count(),
|
).Count(),
|
||||||
|
|
||||||
|
|
||||||
UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
|
UnReadCanReadTaskList = x.Where(y => y.TrialReadingCriterionId == trialReadingCriterionId && y.ReadingTaskState != ReadingTaskState.HaveSigned)
|
||||||
.Where(t => extralConfig.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
|
.Where(t => extralObj.IsOpenLostVistRead ? true : t.IsFrontTaskNeedSignButNotSign == false)
|
||||||
.Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
|
.Where(y => /*y.IsFrontTaskNeedSignButNotSign == false &&*/ (y.IsNeedClinicalDataSign == false || y.IsClinicalDataSign == true))
|
||||||
.OrderBy(x => x.VisitTaskNum)
|
.OrderBy(x => x.VisitTaskNum)
|
||||||
.Select(u => new IRUnreadTaskView()
|
.Select(u => new IRUnreadTaskView()
|
||||||
@@ -1234,7 +1247,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
/// <param name="inQuery"></param>
|
/// <param name="inQuery"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<PageOutput<IRHaveReadView>> GetIRHaveReadTaskList(VisitTaskQuery inQuery)
|
public async Task<IResponseOutput<PageOutput<IRHaveReadView>>> GetIRHaveReadTaskList(VisitTaskQuery inQuery)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -1253,6 +1266,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
|
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskBlindName), t => t.TaskBlindName.Contains(inQuery.TaskBlindName))
|
||||||
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
|
||||||
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
|
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
|
||||||
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
|
||||||
@@ -1262,7 +1276,10 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
|
var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery, defalutSortArray);
|
||||||
|
|
||||||
return pageList;
|
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId)
|
||||||
|
.Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(pageList, criterionInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2071,29 +2088,37 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
//申请表 设置新任务Id
|
//申请表 设置新任务Id
|
||||||
visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id;
|
visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id;
|
||||||
|
|
||||||
//拷贝原始表单
|
|
||||||
if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id)
|
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
||||||
{
|
{
|
||||||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
CopyImages(newTask, influenceTask);
|
||||||
|
|
||||||
|
//拷贝原始表单
|
||||||
|
if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id)
|
||||||
{
|
{
|
||||||
CopyForms(newTask, origenalTask);
|
CopyForms(newTask, origenalTask);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//拷贝后续表单
|
||||||
|
if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
|
||||||
//拷贝后续表单
|
|
||||||
if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
|
|
||||||
{
|
|
||||||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
|
||||||
{
|
{
|
||||||
newTask.IsCopyLesionAnswer = true;
|
newTask.IsCopyLesionAnswer = true;
|
||||||
|
|
||||||
//CopyForms(newTask, origenalTask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (origenalTask.ReadingCategory == ReadingCategory.Judge)
|
||||||
|
{
|
||||||
|
//拷贝原始表单
|
||||||
|
if (visitTaskReReadingAppply.IsCopyOrigenalForms && influenceTask.Id == origenalTask.Id)
|
||||||
|
{
|
||||||
|
CopyForms(newTask, origenalTask);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2175,6 +2200,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
newTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
newTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
|
||||||
|
|
||||||
|
|
||||||
|
CopyImages(newTask, influenceTask);
|
||||||
|
|
||||||
|
|
||||||
//裁判任务 需要进行特殊处理 在重阅逻辑里面处理
|
//裁判任务 需要进行特殊处理 在重阅逻辑里面处理
|
||||||
|
|
||||||
if (visitTaskReReadingAppply != null)
|
if (visitTaskReReadingAppply != null)
|
||||||
@@ -2191,16 +2219,16 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//拷贝后续表单
|
////拷贝后续表单
|
||||||
if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
|
//if (visitTaskReReadingAppply.IsCopyFollowForms && origenalTask.VisitTaskNum != influenceTask.VisitTaskNum)
|
||||||
{
|
//{
|
||||||
if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
// if (origenalTask.ReadingCategory == ReadingCategory.Visit)
|
||||||
{
|
// {
|
||||||
newTask.IsCopyLesionAnswer = true;
|
// newTask.IsCopyLesionAnswer = true;
|
||||||
//CopyForms(newTask, origenalTask);
|
// //CopyForms(newTask, origenalTask);
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2220,6 +2248,83 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CopyImages(VisitTask newTask, VisitTask origenalTask)
|
||||||
|
{
|
||||||
|
//拷贝后处理绑定的的Dicom影像
|
||||||
|
|
||||||
|
var newTaskId = newTask.Id;
|
||||||
|
|
||||||
|
var taskStudyList = _taskStudyRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
|
var taskSeriesList = _taskSeriesRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
var taskInstanceList = _taskInstanceRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var taskStudy in taskStudyList)
|
||||||
|
{
|
||||||
|
var newStudyId = IdentifierHelper.CreateGuid(taskStudy.StudyInstanceUid, taskStudy.TrialId.ToString(), newTaskId.ToString());
|
||||||
|
|
||||||
|
var newStudy = taskStudy.Clone();
|
||||||
|
newStudy.Id = newStudyId;
|
||||||
|
newStudy.SeqId = NewId.NextSequentialGuid();
|
||||||
|
newStudy.VisitTaskId = newTaskId;
|
||||||
|
|
||||||
|
_ = _taskStudyRepository.AddAsync(newStudy).Result;
|
||||||
|
|
||||||
|
var studySeriesList = taskSeriesList.Where(t => t.StudyId == taskStudy.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var series in studySeriesList)
|
||||||
|
{
|
||||||
|
var newSeriesId = IdentifierHelper.CreateGuid(series.StudyInstanceUid, series.SeriesInstanceUid, series.TrialId.ToString(), newTaskId.ToString());
|
||||||
|
|
||||||
|
var newSeries = series.Clone();
|
||||||
|
newSeries.Id = newSeriesId;
|
||||||
|
newSeries.SeqId = NewId.NextSequentialGuid();
|
||||||
|
newSeries.StudyId = newStudyId;
|
||||||
|
newSeries.VisitTaskId = newTaskId;
|
||||||
|
|
||||||
|
|
||||||
|
_ = _taskSeriesRepository.AddAsync(newSeries).Result;
|
||||||
|
|
||||||
|
|
||||||
|
var studyInstanceList = taskInstanceList.Where(t => t.StudyId == taskStudy.Id && t.SeriesId == series.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var instance in studyInstanceList)
|
||||||
|
{
|
||||||
|
var newInstanceId = IdentifierHelper.CreateGuid(newStudy.StudyInstanceUid, newSeries.SeriesInstanceUid, instance.SopInstanceUid, newStudy.TrialId.ToString(), newTaskId.ToString());
|
||||||
|
|
||||||
|
var newInstance = instance.Clone();
|
||||||
|
|
||||||
|
newInstance.Id = newInstanceId;
|
||||||
|
newInstance.SeqId = NewId.NextSequentialGuid();
|
||||||
|
newInstance.StudyId = newStudyId;
|
||||||
|
newInstance.SeriesId = newSeriesId;
|
||||||
|
newInstance.VisitTaskId = newTaskId;
|
||||||
|
|
||||||
|
Console.WriteLine($"StudyInstanceUid:{newStudy.StudyInstanceUid} SeriesInstanceUid:{newSeries.SeriesInstanceUid} SopInstanceUid: {instance.SopInstanceUid},newInstanceId:{newInstanceId} ");
|
||||||
|
|
||||||
|
_ = _taskInstanceRepository.AddAsync(newInstance).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//拷贝后处理的NoneDicom
|
||||||
|
|
||||||
|
var fileList = _noneDicomStudyFileRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var file in fileList)
|
||||||
|
{
|
||||||
|
var newFile = file.Clone();
|
||||||
|
|
||||||
|
newFile.Id = NewId.NextSequentialGuid();
|
||||||
|
newFile.VisitTaskId = newTaskId;
|
||||||
|
|
||||||
|
_ = _noneDicomStudyFileRepository.AddAsync(newFile).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
private void CopyForms(VisitTask newTask, VisitTask origenalTask)
|
private void CopyForms(VisitTask newTask, VisitTask origenalTask)
|
||||||
{
|
{
|
||||||
newTask.IsCopyLesionAnswer = true;
|
newTask.IsCopyLesionAnswer = true;
|
||||||
@@ -2238,6 +2343,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
foreach (var item in readingTaskQuestionAnswerList)
|
foreach (var item in readingTaskQuestionAnswerList)
|
||||||
@@ -2294,6 +2402,64 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 分割
|
||||||
|
Dictionary<Guid, Guid> segmentationRelationship = new Dictionary<Guid, Guid>() { };
|
||||||
|
var segmentationList = _segmentationRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var item in segmentationList)
|
||||||
|
{
|
||||||
|
|
||||||
|
var newSegmentationId = NewId.NextSequentialGuid();
|
||||||
|
segmentationRelationship.Add(item.Id, newSegmentationId);
|
||||||
|
item.Id = newSegmentationId;
|
||||||
|
item.VisitTaskId = newTask.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<Guid, Guid> segmentRelationship = new Dictionary<Guid, Guid>() { };
|
||||||
|
var segmentList = _segmentRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
foreach (var item in segmentList)
|
||||||
|
{
|
||||||
|
var newSegmentationId = NewId.NextSequentialGuid();
|
||||||
|
segmentRelationship.Add(item.Id, newSegmentationId);
|
||||||
|
if (segmentationRelationship.ContainsKey(item.SegmentationId))
|
||||||
|
{
|
||||||
|
item.SegmentationId = segmentationRelationship[item.SegmentationId];
|
||||||
|
}
|
||||||
|
item.Id = newSegmentationId;
|
||||||
|
item.VisitTaskId = newTask.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
var segmentBindingList = _segmentBindingRepository.Where(x => x.VisitTaskId == origenalTask.Id).ToList();
|
||||||
|
|
||||||
|
foreach (var item in segmentBindingList)
|
||||||
|
{
|
||||||
|
if (segmentationRelationship.ContainsKey(item.SegmentationId))
|
||||||
|
{
|
||||||
|
item.SegmentationId = segmentationRelationship[item.SegmentationId];
|
||||||
|
}
|
||||||
|
if (segmentRelationship.ContainsKey(item.SegmentId))
|
||||||
|
{
|
||||||
|
item.SegmentId = segmentRelationship[item.SegmentId];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.RowId != null && lesionRelationship.ContainsKey(item.RowId.Value))
|
||||||
|
{
|
||||||
|
item.RowId = lesionRelationship[item.RowId.Value];
|
||||||
|
}
|
||||||
|
item.Id = NewId.NextSequentialGuid();
|
||||||
|
item.VisitTaskId = newTask.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_ = _segmentationRepository.AddRangeAsync(segmentationList).Result;
|
||||||
|
_ = _segmentRepository.AddRangeAsync(segmentList).Result;
|
||||||
|
_ = _segmentBindingRepository.AddRangeAsync(segmentBindingList).Result;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var item in readingTableAnswerRowInfoList)
|
foreach (var item in readingTableAnswerRowInfoList)
|
||||||
{
|
{
|
||||||
if (item.SplitRowId != null && lesionRelationship.ContainsKey(item.SplitRowId.Value))
|
if (item.SplitRowId != null && lesionRelationship.ContainsKey(item.SplitRowId.Value))
|
||||||
@@ -2654,6 +2820,19 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
|
|||||||
sv.ReviewAuditUserId = null;
|
sv.ReviewAuditUserId = null;
|
||||||
sv.SecondReviewState = SecondReviewState.None;
|
sv.SecondReviewState = SecondReviewState.None;
|
||||||
|
|
||||||
|
|
||||||
|
// 处理阅片期的临床数据
|
||||||
|
var readModuleIdList = await _readModuleRepository.Where(x => x.SubjectVisitId == sv.Id).Select(x => x.Id).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
|
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => readModuleIdList.Contains(t.ReadingId), c => new ReadingClinicalData()
|
||||||
|
{
|
||||||
|
IsSign = false,
|
||||||
|
ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (sv.IsBaseLine)
|
if (sv.IsBaseLine)
|
||||||
{
|
{
|
||||||
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && (t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit), c => new ReadingClinicalData() { IsSign = false, ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded });
|
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && (t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit), c => new ReadingClinicalData() { IsSign = false, ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded });
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ namespace IRaCIS.Application.Contracts
|
|||||||
public Guid? TrialReadingCriterionId { get; set; }
|
public Guid? TrialReadingCriterionId { get; set; }
|
||||||
|
|
||||||
public Guid? SystemReadingCriterionId { get; set; }
|
public Guid? SystemReadingCriterionId { get; set; }
|
||||||
|
|
||||||
|
public Guid? TrialId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||||
|
// 生成时间 2026-03-10 06:15:31Z
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
using IRaCIS.Core.Domain.Share;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
namespace IRaCIS.Core.Application.ViewModel;
|
||||||
|
|
||||||
|
public class SubjectFileUploadRecordView
|
||||||
|
{
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
public string StudyCode { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectVisitId { get; set; }
|
||||||
|
|
||||||
|
public int FileCount { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? UploadRegion { get; set; }
|
||||||
|
public string? TargetRegion { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
public DateTime? SyncFinishedTime { get; set; }
|
||||||
|
|
||||||
|
public bool IsSync { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileUploadRecordView : FileUploadRecordAddOrEdit
|
||||||
|
{
|
||||||
|
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Comment("同步结束时间-最后一个任务的时间")]
|
||||||
|
public DateTime? SyncFinishedTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class FileUploadRecordAddOrEdit
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
public long FileSize { get; set; }
|
||||||
|
|
||||||
|
public string FileType { get; set; }
|
||||||
|
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string UploadBatchId { get; set; }
|
||||||
|
public BatchDataType BatchDataType { get; set; }
|
||||||
|
|
||||||
|
public string StudyCode { get; set; }
|
||||||
|
|
||||||
|
public Guid? TrialId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectVisitId { get; set; }
|
||||||
|
|
||||||
|
public Guid? DicomStudyId { get; set; }
|
||||||
|
|
||||||
|
public Guid? NoneDicomStudyId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string FileMarkId { get; set; }
|
||||||
|
|
||||||
|
public int? Priority { get; set; }
|
||||||
|
public string IP { get; set; }
|
||||||
|
public bool? IsNeedSync { get; set; }
|
||||||
|
public string UploadRegion { get; set; }
|
||||||
|
public string TargetRegion { get; set; }
|
||||||
|
|
||||||
|
public bool? IsSync { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommonUploadRecordDto: CommonUploadRecordAddOrEdit
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommonUploadRecordAddOrEdit
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public string FileType { get; set; }
|
||||||
|
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
public long FileSize { get; set; }
|
||||||
|
|
||||||
|
public string Path { get; set; }
|
||||||
|
}
|
||||||
|
public class SubjectFileUploadRecordQuery : PageInput
|
||||||
|
{
|
||||||
|
public Guid TrialId { get; set; }
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
public string? StudyCode { get; set; }
|
||||||
|
|
||||||
|
public string? UploadRegion { get; set; }
|
||||||
|
public string? TargetRegion { get; set; }
|
||||||
|
|
||||||
|
public bool? IsSync { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FileUploadRecordQuery : PageInput
|
||||||
|
{
|
||||||
|
|
||||||
|
public BatchDataType? BatchDataType { get; set; }
|
||||||
|
|
||||||
|
public Guid? TrialId { get; set; }
|
||||||
|
|
||||||
|
public int? DataFileType { get; set; }
|
||||||
|
|
||||||
|
public string StudyCode { get; set; }
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid? SubjectId { get; set; }
|
||||||
|
|
||||||
|
public Guid? SubjectVisitId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public string? FileMarkId { get; set; }
|
||||||
|
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? FileType { get; set; }
|
||||||
|
|
||||||
|
public string? IP { get; set; }
|
||||||
|
|
||||||
|
public bool? IsNeedSync { get; set; }
|
||||||
|
|
||||||
|
public bool? IsSync { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? Path { get; set; }
|
||||||
|
|
||||||
|
public int? Priority { get; set; }
|
||||||
|
|
||||||
|
public string? TargetRegion { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string? UploadBatchId { get; set; }
|
||||||
|
|
||||||
|
public string? UploadRegion { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DateTime? SyncFinishedStartTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? SyncFinishedEndTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UploadStartTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UploadEndTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class UploadFileSyncRecordView
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public DateTime? StartTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime? EndTime { get; set; }
|
||||||
|
|
||||||
|
public jobState JobState { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string Msg { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public Guid? FileUploadRecordId { get; set; }
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
|
||||||
|
public string? FileType { get; set; }
|
||||||
|
|
||||||
|
public string? Path { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public string StudyCode { get; set; }
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UploadFileSyncRecordQuery : PageInput
|
||||||
|
{
|
||||||
|
|
||||||
|
public Guid? FileUploadRecordId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public jobState? JobState { get; set; }
|
||||||
|
|
||||||
|
public string? SubjectCode { get; set; }
|
||||||
|
|
||||||
|
public string? VisitName { get; set; }
|
||||||
|
|
||||||
|
public string? StudyCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BatchAddSyncFileCommand
|
||||||
|
{
|
||||||
|
public List<Guid> FileUploadRecordIdList { get; set; }
|
||||||
|
|
||||||
|
public int? Priority { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using IRaCIS.Application.Contracts;
|
||||||
|
using Medallion.Threading;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Service.Common;
|
||||||
|
|
||||||
|
[ApiExplorerSettings(GroupName = "Common")]
|
||||||
|
public class DeployConfigService(IMapper _mapper, IConfiguration _configuration, IDistributedLockProvider _distributedLockProvider, IUserInfo _userInfo, IWebHostEnvironment _hostEnvironment, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取系统基础配置信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<ServiceVerifyConfigOption> GetSystemBasicConfigInfo([FromServices] IOptionsMonitor<ServiceVerifyConfigOption> options)
|
||||||
|
{
|
||||||
|
//var config = _configuration.GetSection("BasicSystemConfig").Get<ServiceVerifyConfigOption>();
|
||||||
|
//return config;
|
||||||
|
|
||||||
|
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
|
||||||
|
var obj = JObject.Parse(json);
|
||||||
|
|
||||||
|
return obj["BasicSystemConfig"]!.ToObject<ServiceVerifyConfigOption>()!;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新系统基础配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="basicSystemConfigOption"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IResponseOutput> UpdateSystemBasicConfig(ServiceVerifyConfigOption basicSystemConfigOption)
|
||||||
|
{
|
||||||
|
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
|
||||||
|
|
||||||
|
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
|
||||||
|
|
||||||
|
|
||||||
|
using (await @lock.AcquireAsync())
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
string text = System.IO.File.ReadAllText(path);
|
||||||
|
|
||||||
|
// 修改
|
||||||
|
JObject obj = JObject.Parse(text);
|
||||||
|
// QCRiskControl 相关配置
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.QCRiskControl)] = basicSystemConfigOption.QCRiskControl;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenUserComplexPassword)] = basicSystemConfigOption.OpenUserComplexPassword;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenSignDocumentBeforeWork)] = basicSystemConfigOption.OpenSignDocumentBeforeWork;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenTrialRelationDelete)] = basicSystemConfigOption.OpenTrialRelationDelete;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginLimit)] = basicSystemConfigOption.OpenLoginLimit;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginMaxFailCount)] = basicSystemConfigOption.LoginMaxFailCount;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.LoginFailLockMinutes)] = basicSystemConfigOption.LoginFailLockMinutes;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.AutoLoginOutMinutes)] = basicSystemConfigOption.AutoLoginOutMinutes;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.OpenLoginMFA)] = basicSystemConfigOption.OpenLoginMFA;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ContinuousReadingTimeMin)] = basicSystemConfigOption.ContinuousReadingTimeMin;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ReadingRestTimeMin)] = basicSystemConfigOption.ReadingRestTimeMin;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.IsNeedChangePassWord)] = basicSystemConfigOption.IsNeedChangePassWord;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ChangePassWordDays)] = basicSystemConfigOption.ChangePassWordDays;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.TemplateType)] = ((int)basicSystemConfigOption.TemplateType); // 枚举需要转换为字符串
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.ThirdPdfUrl)] = basicSystemConfigOption.ThirdPdfUrl;
|
||||||
|
obj["BasicSystemConfig"][nameof(ServiceVerifyConfigOption.UserMFAVerifyMinutes)] = basicSystemConfigOption.UserMFAVerifyMinutes;
|
||||||
|
|
||||||
|
|
||||||
|
// 重新写入appsettings.json
|
||||||
|
string result = obj.ToString();
|
||||||
|
System.IO.File.WriteAllText(path, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取系统邮件配置信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<SystemEmailSendConfig> GetEmailConfigInfo([FromServices] IOptionsMonitor<SystemEmailSendConfig> options)
|
||||||
|
{
|
||||||
|
//两种方式都有问题
|
||||||
|
//var config = _configuration.GetSection("BasicSystemConfig").Get<SystemEmailSendConfig>();
|
||||||
|
//return config;
|
||||||
|
//return options.CurrentValue;
|
||||||
|
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
|
||||||
|
var obj = JObject.Parse(json);
|
||||||
|
|
||||||
|
return obj["SystemEmailSendConfig"]!.ToObject<SystemEmailSendConfig>()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新系统邮件配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="emailConfig"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IResponseOutput> UpdateSystemEmailConfig(SystemEmailSendConfig emailConfig)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
|
||||||
|
|
||||||
|
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
|
||||||
|
|
||||||
|
|
||||||
|
using (await @lock.AcquireAsync())
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
string text = System.IO.File.ReadAllText(path);
|
||||||
|
|
||||||
|
// 修改
|
||||||
|
JObject obj = JObject.Parse(text);
|
||||||
|
|
||||||
|
// SystemEmailSendConfig 相关配置
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Port)] = emailConfig.Port;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Host)] = emailConfig.Host;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.Imap)] = emailConfig.Imap;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.ImapPort)] = emailConfig.ImapPort;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromEmail)] = emailConfig.FromEmail;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.FromName)] = emailConfig.FromName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.AuthorizationCode)] = emailConfig.AuthorizationCode;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SiteUrl)] = emailConfig.SiteUrl;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformName)] = emailConfig.PlatformName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.PlatformNameCN)] = emailConfig.PlatformNameCN;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.SystemShortName)] = emailConfig.SystemShortName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationName)] = emailConfig.OrganizationName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.OrganizationNameCN)] = emailConfig.OrganizationNameCN;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyName)] = emailConfig.CompanyName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyNameCN)] = emailConfig.CompanyNameCN;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortName)] = emailConfig.CompanyShortName;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.CompanyShortNameCN)] = emailConfig.CompanyShortNameCN;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.IsEnv_US)] = emailConfig.IsEnv_US;
|
||||||
|
obj["SystemEmailSendConfig"][nameof(SystemEmailSendConfig.EmailRegexStr)] = emailConfig.EmailRegexStr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 重新写入appsettings.json
|
||||||
|
string result = obj.ToString();
|
||||||
|
System.IO.File.WriteAllText(path, result);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取前端配置
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<string> GetWebConfigInfo()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
|
||||||
|
var json = File.ReadAllText(path);
|
||||||
|
|
||||||
|
var obj = JObject.Parse(json);
|
||||||
|
|
||||||
|
return obj["FrontWebConfig"]!.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResponseOutput> UpdateWebConfigInfo(string configStr)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(_hostEnvironment.ContentRootPath, $"appsettings.{_hostEnvironment.EnvironmentName}.json");
|
||||||
|
//var path = $"appsettings.{_hostEnvironment.EnvironmentName}.json";
|
||||||
|
|
||||||
|
var @lock = _distributedLockProvider.CreateLock("WriteConfigFile");
|
||||||
|
|
||||||
|
using (await @lock.AcquireAsync())
|
||||||
|
{
|
||||||
|
string text = System.IO.File.ReadAllText(path);
|
||||||
|
// 修改
|
||||||
|
JObject obj = JObject.Parse(text);
|
||||||
|
|
||||||
|
// SystemEmailSendConfig 相关配置
|
||||||
|
obj["FrontWebConfig"] = configStr;
|
||||||
|
|
||||||
|
// 重新写入appsettings.json
|
||||||
|
string result = obj.ToString();
|
||||||
|
|
||||||
|
System.IO.File.WriteAllText(path, result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -452,14 +452,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
if (inDto.TrialReadingCriterionId == null && inDto.SystemReadingCriterionId == null)
|
if (inDto.TrialReadingCriterionId == null && inDto.SystemReadingCriterionId == null)
|
||||||
{
|
{
|
||||||
return result;
|
return await ChangeTrialObjectNameList(result,inDto.TrialId);
|
||||||
}
|
}
|
||||||
else if (inDto.TrialReadingCriterionId != null)
|
else if (inDto.TrialReadingCriterionId != null)
|
||||||
{
|
{
|
||||||
var trialCriterionType = await _readingQuestionCriterionTrial.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
|
var trialCriterionType = await _readingQuestionCriterionTrial.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
|
||||||
if (trialCriterionType == CriterionType.SelfDefine)
|
if (trialCriterionType == CriterionType.SelfDefine)
|
||||||
{
|
{
|
||||||
return result;
|
return await ChangeTrialObjectNameList(result, inDto.TrialId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -505,7 +505,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
result[item.Key] = item.Value;
|
result[item.Key] = item.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return await ChangeTrialObjectNameList(result, inDto.TrialId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -548,12 +548,76 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
result[item.Key] = item.Value;
|
result[item.Key] = item.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return await ChangeTrialObjectNameList(result, inDto.TrialId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 替换字典中的项目名称为试验对象名称 --New
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="trialId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task<Dictionary<string, List<BasicDicSelect>>> ChangeTrialObjectNameList(Dictionary<string, List<BasicDicSelect>> data,Guid? trialId)
|
||||||
|
{
|
||||||
|
if (!trialId.HasValue)
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 查询映射集合
|
||||||
|
var trialObjectNameList = await _trialRepository
|
||||||
|
.Where(x => x.Id == trialId)
|
||||||
|
.Select(x => x.TrialObjectNameList)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
// 无映射数据直接返回
|
||||||
|
if (trialObjectNameList == null || !trialObjectNameList.Any())
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 构建映射字典,过滤空名称,避免无效替换
|
||||||
|
var replaceDict = trialObjectNameList
|
||||||
|
.Where(m => !string.IsNullOrEmpty(m.Name))
|
||||||
|
.ToDictionary(m => m.Name, m => m.TrialName);
|
||||||
|
|
||||||
|
// 遍历替换
|
||||||
|
foreach (var (_, selectList) in data)
|
||||||
|
{
|
||||||
|
foreach (var selectItem in selectList)
|
||||||
|
{
|
||||||
|
// 替换Value,判null保护
|
||||||
|
if (selectItem.Value != null)
|
||||||
|
{
|
||||||
|
string tempVal = selectItem.Value;
|
||||||
|
foreach (var (oldStr, newStr) in replaceDict)
|
||||||
|
{
|
||||||
|
tempVal = tempVal.Replace(oldStr, newStr);
|
||||||
|
}
|
||||||
|
selectItem.Value = tempVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换中文名称ValueCN
|
||||||
|
if (selectItem.ValueCN != null)
|
||||||
|
{
|
||||||
|
string tempCn = selectItem.ValueCN;
|
||||||
|
foreach (var (oldStr, newStr) in replaceDict)
|
||||||
|
{
|
||||||
|
tempCn = tempCn.Replace(oldStr, newStr);
|
||||||
|
}
|
||||||
|
selectItem.ValueCN = tempCn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
#region 稽查相关
|
#region 稽查相关
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -155,7 +155,8 @@ public class EmailLogService(IRepository<EmailLog> _emailLogRepository,
|
|||||||
fileStream: decodeStream,
|
fileStream: decodeStream,
|
||||||
oosFolderPath: $"EmailAttachment/{emailInfo.Id}", // OSS 虚拟目录
|
oosFolderPath: $"EmailAttachment/{emailInfo.Id}", // OSS 虚拟目录
|
||||||
fileRealName: emaliAttachmentInfo.AttachmentName,
|
fileRealName: emaliAttachmentInfo.AttachmentName,
|
||||||
isFileNameAddGuid: true); // 让方法自己在文件名前加 Guid
|
isFileNameAddGuid: true,
|
||||||
|
uploadInfo: new FileUploadRecordAddOrEdit() {TrialId= inDto.TrialId, BatchDataType = BatchDataType.EmailAttach }); // 让方法自己在文件名前加 Guid
|
||||||
|
|
||||||
attachmentInfos.Add(emaliAttachmentInfo);
|
attachmentInfos.Add(emaliAttachmentInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,19 +4,13 @@
|
|||||||
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using MailKit;
|
using MailKit;
|
||||||
using MailKit.Net.Imap;
|
using MailKit.Net.Imap;
|
||||||
using MailKit.Search;
|
using MailKit.Search;
|
||||||
using MailKit.Security;
|
using MailKit.Security;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Contracts
|
namespace IRaCIS.Core.Application.Contracts
|
||||||
|
|||||||
@@ -1,27 +1,16 @@
|
|||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using ClosedXML.Excel;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using IRaCIS.Application.Contracts;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Interfaces;
|
|
||||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
||||||
using IRaCIS.Core.Application.Contracts;
|
using IRaCIS.Core.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Contracts.DTO;
|
using IRaCIS.Core.Application.Contracts.DTO;
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Models;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using IRaCIS.Core.Infra.EFCore.Common;
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
using IRaCIS.Core.Infra.EFCore.Migrations;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
using Newtonsoft.Json;
|
||||||
using NPOI.HPSF;
|
|
||||||
using NPOI.POIFS.Properties;
|
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using NPOI.XSSF.UserModel;
|
|
||||||
using System.ComponentModel.Design;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using static IRaCIS.Core.Application.Service.ExcelExportHelper;
|
using static IRaCIS.Core.Application.Service.ExcelExportHelper;
|
||||||
@@ -52,6 +41,191 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService
|
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#region 中心调研导出
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> GetTrialSiteSurveyList_Export(TrialSiteSurveyQueryDTO inQuery,
|
||||||
|
[FromServices] IRepository<TrialSiteSurvey> _trialSiteSurveyRepository,
|
||||||
|
[FromServices] IDictionaryService _dictionaryService)
|
||||||
|
{
|
||||||
|
var trialSiteSurveyQueryable = _trialSiteSurveyRepository.Where(t => t.TrialId == inQuery.TrialId).IgnoreQueryFilters()
|
||||||
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||||||
|
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
|
||||||
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserKeyInfo), t => t.UserName.Contains(inQuery.UserKeyInfo) || t.Phone.Contains(inQuery.UserKeyInfo) || t.Email.Contains(inQuery.UserKeyInfo))
|
||||||
|
.WhereIf(inQuery.State != null, t => t.State == inQuery.State)
|
||||||
|
.WhereIf(inQuery.UpdateTimeBegin != null, t => t.UpdateTime >= inQuery.UpdateTimeBegin)
|
||||||
|
.WhereIf(inQuery.UpdateTimeEnd != null, t => t.UpdateTime <= inQuery.UpdateTimeEnd)
|
||||||
|
|
||||||
|
.ProjectTo<TrialSiteSurveyView>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us })
|
||||||
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PreliminaryUserName), t => t.PreliminaryUser.RealName.Contains(inQuery.PreliminaryUserName))
|
||||||
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.ReviewerUserName), t => t.ReviewerUser.RealName.Contains(inQuery.ReviewerUserName))
|
||||||
|
;
|
||||||
|
|
||||||
|
//var defalutSortArray = new string[] { /*nameof(TrialSiteSurveyView.LanguageType) + " desc", nameof(TrialSiteSurveyView.ShowOrder)*/ };
|
||||||
|
|
||||||
|
|
||||||
|
var list = await trialSiteSurveyQueryable.SortToListAsync(inQuery /*,defalutSortArray*/);
|
||||||
|
|
||||||
|
var exportInfo = new ExcelExportInfo();
|
||||||
|
|
||||||
|
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||||
|
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||||
|
|
||||||
|
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSiteSurvey_BasicInfo_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TrialSiteSurveyView));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取中心设备信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> GetSiteSurveyEquipmentList_Export(SiteSurveyEquipmentQuery inQuery,
|
||||||
|
[FromServices] IRepository<TrialSiteEquipmentSurvey> _trialSiteEquipmentSurveyRepository,
|
||||||
|
[FromServices] IRepository<TrialSiteSurvey> _trialSiteSurveyRepository,
|
||||||
|
[FromServices] IDictionaryService _dictionaryService)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//找到该中心最新的调研记录
|
||||||
|
var groupSelectIdQuery =
|
||||||
|
_trialSiteSurveyRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||||
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||||||
|
.GroupBy(t => t.TrialSiteId)
|
||||||
|
.Select(g => g.OrderByDescending(u => u.CreateTime).Select(t => t.Id).First());
|
||||||
|
|
||||||
|
|
||||||
|
var query = _trialSiteEquipmentSurveyRepository.Where(t => t.TrialSiteSurvey.TrialId == inQuery.TrialId)
|
||||||
|
.IgnoreQueryFilters().Where(t => groupSelectIdQuery.Contains(t.TrialSiteSurveyId))
|
||||||
|
.WhereIf(inQuery.IsDeleted != null, t => t.TrialSiteSurvey.IsDeleted == inQuery.IsDeleted)
|
||||||
|
.WhereIf(inQuery.State != null, t => t.TrialSiteSurvey.State == inQuery.State)
|
||||||
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteSurvey.TrialSiteId == inQuery.TrialSiteId)
|
||||||
|
.WhereIf(inQuery.TrialSiteCode.IsNotNullOrEmpty(), t => t.TrialSiteSurvey.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode))
|
||||||
|
.WhereIf(inQuery.TrialSiteName.IsNotNullOrEmpty(), t => t.TrialSiteSurvey.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteName) ||
|
||||||
|
t.TrialSiteSurvey.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteName))
|
||||||
|
.ProjectTo<SiteSurveyEquipmentDto>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
var siteSurveryConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
|
||||||
|
|
||||||
|
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
|
||||||
|
|
||||||
|
|
||||||
|
var fields = new List<(string FieldName, int excelIndex)>()
|
||||||
|
{
|
||||||
|
|
||||||
|
("Parameters", 9),
|
||||||
|
("ManufacturerType", 10),
|
||||||
|
("ScannerType", 11),
|
||||||
|
("MagneticFieldStrengthType", 12),
|
||||||
|
("BodyCoilChannelCount", 13),
|
||||||
|
("HasDedicatedPdfFatQuantificationSequence", 14),
|
||||||
|
("PdfFatQuantificationSequenceType", 15),
|
||||||
|
//("OtherSequenceSpecification", 15),
|
||||||
|
("HasT2R2Correction", 16),
|
||||||
|
("CanFullyExportPdfParameterMapsAndRawDicom", 17),
|
||||||
|
("Note", 18),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var viewNameList = config.EquipmentControlFieldList.Where(t => t.IsView == true).Select(t => t.FiledName).ToList();
|
||||||
|
|
||||||
|
var columnsToDelete = fields.Where(f => !viewNameList.Any(t => f.FieldName == t)).Select(f => f.excelIndex).Distinct().OrderByDescending(i => i).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
//var defalutSortArray = new string[] { /*nameof(TrialSiteSurveyView.LanguageType) + " desc", nameof(TrialSiteSurveyView.ShowOrder)*/ };
|
||||||
|
|
||||||
|
|
||||||
|
var list = await query.SortToListAsync(inQuery /*,defalutSortArray*/);
|
||||||
|
|
||||||
|
var exportInfo = new ExcelExportInfo();
|
||||||
|
|
||||||
|
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||||
|
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||||
|
|
||||||
|
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSiteSurvey_Equipment_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SiteSurveyEquipmentDto), removeExcelIndexList: columnsToDelete);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 调研表基本信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> GetSiteSurveyInfoList_Export(SiteSurveyInfoQuery inQuery,
|
||||||
|
[FromServices] IRepository<TrialSiteSurvey> _trialSiteSurveyRepository,
|
||||||
|
[FromServices] IDictionaryService _dictionaryService)
|
||||||
|
{
|
||||||
|
|
||||||
|
//找到该中心最新的调研记录
|
||||||
|
var groupSelectIdQuery =
|
||||||
|
_trialSiteSurveyRepository.Where(t => t.TrialId == inQuery.TrialId)
|
||||||
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||||||
|
.GroupBy(t => t.TrialSiteId)
|
||||||
|
.Select(g => g.OrderByDescending(u => u.CreateTime).Select(t => t.Id).First());
|
||||||
|
|
||||||
|
var query = _trialSiteSurveyRepository.Where(t => t.TrialId == inQuery.TrialId).IgnoreQueryFilters()
|
||||||
|
.Where(t => groupSelectIdQuery.Contains(t.Id))
|
||||||
|
.WhereIf(inQuery.IsDeleted != null, t => t.IsDeleted == inQuery.IsDeleted)
|
||||||
|
.WhereIf(inQuery.State != null, t => t.State == inQuery.State)
|
||||||
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||||||
|
.WhereIf(inQuery.TrialSiteCode.IsNotNullOrEmpty(), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode))
|
||||||
|
.WhereIf(inQuery.TrialSiteName.IsNotNullOrEmpty(), t => t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteName) ||
|
||||||
|
t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteName))
|
||||||
|
|
||||||
|
.ProjectTo<TrialSiteSurveyView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
|
||||||
|
var siteSurveryConfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => t.TrialExtraConfigJsonStr).FirstOrDefault() ?? string.Empty;
|
||||||
|
|
||||||
|
var config = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
|
||||||
|
|
||||||
|
|
||||||
|
var fields = new List<(string FieldName, int excelIndex)>()
|
||||||
|
{
|
||||||
|
|
||||||
|
("AverageEngravingCycle", 8),
|
||||||
|
("IsRoutineMRIPDEE", 9),
|
||||||
|
("MRIPDFFScanTime", 10),
|
||||||
|
("MRIPDFFLeadTime", 11),
|
||||||
|
("MRIPDFFOther", 12),
|
||||||
|
("IsAuthorizeRadiologistsParticipate", 13),
|
||||||
|
("AssignFixedTechnologists", 14),
|
||||||
|
("IsConfirmImagingTechnologist", 15),
|
||||||
|
("NotConfirmReson", 16),
|
||||||
|
("EfficacyEvaluatorType", 17),
|
||||||
|
|
||||||
|
("IsFollowStudyParameters", 18),
|
||||||
|
("NotFollowReson", 19),
|
||||||
|
("ISStrictManualBurnFlag", 20),
|
||||||
|
("NotStrictManualBurnFlagReason",21)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//var viewNameList = config.NotShowFieldList;
|
||||||
|
|
||||||
|
var columnsToDelete = fields.Where(f => config.NotShowFieldList.Any(t => f.FieldName == t)).Select(f => f.excelIndex).Distinct().OrderByDescending(i => i).ToList();
|
||||||
|
|
||||||
|
|
||||||
|
//var defalutSortArray = new string[] { /*nameof(TrialSiteSurveyView.LanguageType) + " desc", nameof(TrialSiteSurveyView.ShowOrder)*/ };
|
||||||
|
|
||||||
|
|
||||||
|
var list = await query.SortToListAsync(inQuery /*,defalutSortArray*/);
|
||||||
|
|
||||||
|
var exportInfo = new ExcelExportInfo();
|
||||||
|
|
||||||
|
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
|
||||||
|
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||||
|
|
||||||
|
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialSiteSurvey_Info_Export, exportInfo, exportInfo.TrialCode, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(TrialSiteSurveyView), removeExcelIndexList: columnsToDelete);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 质控问题答案导出
|
/// 质控问题答案导出
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -153,9 +327,9 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
var dynamicColumnConfig = new DynamicColumnConfig()
|
var dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
AutoColumnTitleRowIndex = 2,
|
AutoColumnTitleRowIndex = 3, //2
|
||||||
AutoColumnStartIndex = 7,
|
AutoColumnStartIndex = 8, //7
|
||||||
TempalteLastColumnIndex = 6,
|
TempalteLastColumnIndex = 7, //6
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "Answer",
|
DynamicItemValueName = "Answer",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -167,7 +341,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(StaticData.Export.TrialQCResult_Export, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(QCQuestionResult_Export), dynamicColumnConfig: dynamicColumnConfig);
|
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(StaticData.Export.TrialQCResult_Export, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(QCQuestionResult_Export), dynamicColumnConfig: dynamicColumnConfig);
|
||||||
|
|
||||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||||
{
|
{
|
||||||
@@ -984,7 +1158,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
var query = _subjectVisitRepository.Where(x => x.TrialId == inQuery.TrialId)
|
var query = _subjectVisitRepository.Where(x => x.TrialId == inQuery.TrialId)
|
||||||
.Where(t => t.Subject.IsSubjectQuit == false || t.SubmitState >= SubmitStateEnum.ToSubmit)
|
.Where(t => t.Subject.IsSubjectQuit == false || t.SubmitState >= SubmitStateEnum.ToSubmit)
|
||||||
|
.WhereIf(inQuery.SubjectStatus != null, t => t.Subject.Status == inQuery.SubjectStatus)
|
||||||
.Where(t => t.Subject.FinalSubjectVisitId != null ? t.VisitNum <= t.Subject.FinalSubjectVisit.VisitNum : true)
|
.Where(t => t.Subject.FinalSubjectVisitId != null ? t.VisitNum <= t.Subject.FinalSubjectVisit.VisitNum : true)
|
||||||
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
|
||||||
.WhereIf(inQuery.SubjectId != null, t => t.Subject.Id == inQuery.SubjectId)
|
.WhereIf(inQuery.SubjectId != null, t => t.Subject.Id == inQuery.SubjectId)
|
||||||
@@ -1034,7 +1208,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
var query = _subjectVisitRepository.Where(x => x.TrialId == inQuery.TrialId)
|
var query = _subjectVisitRepository.Where(x => x.TrialId == inQuery.TrialId)
|
||||||
|
|
||||||
.Where(t => t.Subject.IsSubjectQuit == false || t.AuditState > AuditStateEnum.ToAudit)
|
.Where(t => t.Subject.IsSubjectQuit == false || t.AuditState > AuditStateEnum.ToAudit)
|
||||||
|
.WhereIf(inQuery.SubjectStatus != null, t => t.Subject.Status == inQuery.SubjectStatus)
|
||||||
.WhereIf(inQuery.VisitId != null, t => t.Id == inQuery.VisitId)
|
.WhereIf(inQuery.VisitId != null, t => t.Id == inQuery.VisitId)
|
||||||
.WhereIf(inQuery.CurrentActionUserId != null, t => t.CurrentActionUserId == inQuery.CurrentActionUserId)
|
.WhereIf(inQuery.CurrentActionUserId != null, t => t.CurrentActionUserId == inQuery.CurrentActionUserId)
|
||||||
.WhereIf(inQuery.ChallengeState != null, t => t.ChallengeState == inQuery.ChallengeState)
|
.WhereIf(inQuery.ChallengeState != null, t => t.ChallengeState == inQuery.ChallengeState)
|
||||||
@@ -1209,7 +1383,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.TaskAllocationState == TaskAllocationState.Allocated && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ?
|
t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.TaskAllocationState == TaskAllocationState.Allocated && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.ReadingTaskState == ReadingTaskState.HaveSigned).Count() == (int)trialReadingCriterion.ReadingType ?
|
||||||
ReadingStatusEnum.ReadCompleted : t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? ReadingStatusEnum.ImageReading :
|
ReadingStatusEnum.ReadCompleted : t.VisitTaskList.Where(t => t.TaskState == TaskState.Effect && t.TrialReadingCriterionId == dto.TrialReadingCriterionId && t.IsAnalysisCreate == false && t.ReadingCategory == ReadingCategory.Visit && t.TaskAllocationState == TaskAllocationState.Allocated).Count() == (int)trialReadingCriterion.ReadingType ? ReadingStatusEnum.ImageReading :
|
||||||
t.ReadingStatus
|
t.ReadingStatus
|
||||||
}).ToList(),
|
}).OrderBy(t => t.VisitTaskNum).ToList(),
|
||||||
|
|
||||||
ModuleList = subject.ReadModuleList.Where(t => t.TrialReadingCriterionId == dto.TrialReadingCriterionId).Select(t => new SubjectProgressDto.MouduleProgress()
|
ModuleList = subject.ReadModuleList.Where(t => t.TrialReadingCriterionId == dto.TrialReadingCriterionId).Select(t => new SubjectProgressDto.MouduleProgress()
|
||||||
{
|
{
|
||||||
@@ -1239,55 +1413,60 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
|
||||||
|
|
||||||
|
|
||||||
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(StaticData.Export.TrialSubjectProgressList_Export, exportInfo, /*"", */_commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SubjectProgressDto));
|
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(StaticData.Export.TrialSubjectProgressList_Export, exportInfo, /*"", */_commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(SubjectProgressDto));
|
||||||
|
|
||||||
|
|
||||||
// 使用NPOI 进行二次处理
|
// 使用 ClosedXML 进行二次处理
|
||||||
|
using var workbook = new XLWorkbook(memoryStream);
|
||||||
var wb = new XSSFWorkbook(memoryStream);
|
var worksheet = workbook.Worksheet(1); // 获取第一个工作表,索引从1开始
|
||||||
|
|
||||||
var sheet = wb.GetSheetAt(0);
|
|
||||||
|
|
||||||
foreach (var subject in list)
|
foreach (var subject in list)
|
||||||
{
|
{
|
||||||
var index = list.IndexOf(subject);
|
var index = list.IndexOf(subject);
|
||||||
var row = sheet.GetRow(index + 4);
|
|
||||||
|
// ClosedXML 行索引从1开始,原来 NPOI 从0开始,所以 +1
|
||||||
|
var row = worksheet.Row(index + 4 + 1); // NPOI: index + 4, ClosedXML: +1 = index + 5
|
||||||
|
|
||||||
|
|
||||||
foreach (var item in subject.TotalList)
|
foreach (var item in subject.TotalList)
|
||||||
{
|
{
|
||||||
//从第五列开始动态写
|
// 从第五列开始动态写(ClosedXML 列索引从1开始)
|
||||||
var visitIndex = subject.TotalList.IndexOf(item) + 4;
|
var visitIndex = subject.TotalList.IndexOf(item) + 4 + 1; // NPOI: +4, ClosedXML: +1 = +5
|
||||||
|
|
||||||
var cell = row.CreateCell(visitIndex);
|
var cell = row.Cell(visitIndex);
|
||||||
|
|
||||||
if (item.IsLostVisit == true)
|
if (item.IsLostVisit == true)
|
||||||
{
|
{
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(7).CellStyle;
|
//cell.CellStyle = sheet.GetRow(1).GetCell(7).CellStyle;
|
||||||
|
|
||||||
|
// 复制样式 - ClosedXML 需要先获取源样式,然后应用到目标单元格
|
||||||
|
var sourceCell = worksheet.Row(2).Cell(8); // 原 NPOI: GetRow(1).GetCell(7) -> +1 转换
|
||||||
|
|
||||||
|
cell.Style = sourceCell.Style;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (item.ReadingStatus)
|
switch (item.ReadingStatus)
|
||||||
{
|
{
|
||||||
case ReadingStatusEnum.ImageNotSubmit:
|
case ReadingStatusEnum.ImageNotSubmit:
|
||||||
|
cell.Style = worksheet.Row(2).Cell(2).Style; // NPOI: (1,1) -> ClosedXML: (2,2)
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(1).CellStyle;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ReadingStatusEnum.ImageQuality:
|
case ReadingStatusEnum.ImageQuality:
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(2).CellStyle;
|
cell.Style = worksheet.Row(2).Cell(3).Style; // (1,2) -> (2,3)
|
||||||
break;
|
break;
|
||||||
case ReadingStatusEnum.ConsistencyCheck:
|
case ReadingStatusEnum.ConsistencyCheck:
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(3).CellStyle;
|
cell.Style = worksheet.Row(2).Cell(4).Style; // (1,3) -> (2,4)
|
||||||
break;
|
break;
|
||||||
case ReadingStatusEnum.TaskAllocate:
|
case ReadingStatusEnum.TaskAllocate:
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(4).CellStyle;
|
cell.Style = worksheet.Row(2).Cell(5).Style;// (1,4) -> (2,5)
|
||||||
break;
|
break;
|
||||||
case ReadingStatusEnum.ImageReading:
|
case ReadingStatusEnum.ImageReading:
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(5).CellStyle;
|
cell.Style = worksheet.Row(2).Cell(6).Style;// (1,5) -> (2,6)
|
||||||
break;
|
break;
|
||||||
case ReadingStatusEnum.ReadCompleted:
|
case ReadingStatusEnum.ReadCompleted:
|
||||||
cell.CellStyle = sheet.GetRow(1).GetCell(6).CellStyle;
|
cell.Style = worksheet.Row(2).Cell(7).Style; // (1,6) -> (2,7)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1297,12 +1476,13 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cell.SetCellValue(item.TaskName);
|
cell.SetValue(item.TaskName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存到 MemoryStream
|
||||||
var memoryStream2 = new MemoryStream();
|
var memoryStream2 = new MemoryStream();
|
||||||
wb.Write(memoryStream2, true);
|
workbook.SaveAs(memoryStream2);
|
||||||
memoryStream2.Seek(0, SeekOrigin.Begin);
|
memoryStream2.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
return new FileStreamResult(memoryStream2, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||||
@@ -2709,9 +2889,10 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
var dynamicColumnConfig = new DynamicColumnConfig()
|
var dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
//可读的列表名行索引,不是{{}} 模板行索引
|
//可读的列表名行索引,不是{{}} 模板行索引
|
||||||
AutoColumnTitleRowIndex = 2,
|
AutoColumnTitleRowIndex = 3, //2
|
||||||
AutoColumnStartIndex = 5,
|
AutoColumnStartIndex = 6, //5
|
||||||
TempalteLastColumnIndex = 4,
|
TempalteLastColumnIndex = 5, //4
|
||||||
|
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "QuestionValue",
|
DynamicItemValueName = "QuestionValue",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -2722,7 +2903,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig);
|
var (memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(AnalysisDynamicCommonExport), criterion.CriterionType, dynamicColumnConfig);
|
||||||
|
|
||||||
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||||
{
|
{
|
||||||
@@ -2768,13 +2949,13 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
if (criterion.CriterionType == CriterionType.OCT)
|
if (criterion.CriterionType == CriterionType.OCT)
|
||||||
{
|
{
|
||||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
|
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export });
|
||||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_CDISC_Export, ExportCatogory = ExportResult.OCT_CDISC_Export });
|
//list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_CDISC_Export, ExportCatogory = ExportResult.OCT_CDISC_Export });
|
||||||
}
|
}
|
||||||
if (criterion.CriterionType == CriterionType.IVUS)
|
if (criterion.CriterionType == CriterionType.IVUS)
|
||||||
{
|
{
|
||||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.IVUS_CDISC_Export, ExportCatogory = ExportResult.IVUS_CDISC_Export });
|
//list.Add(new ExportDocumentDes() { Code = StaticData.Export.IVUS_CDISC_Export, ExportCatogory = ExportResult.IVUS_CDISC_Export });
|
||||||
}
|
}
|
||||||
if (criterion.CriterionGroup != CriterionGroup.Tumor && criterion.CriterionType != CriterionType.OCT && criterion.CriterionType != CriterionType.IVUS)
|
if (criterion.CriterionGroup != CriterionGroup.Tumor /*&& criterion.CriterionType != CriterionType.OCT && criterion.CriterionType != CriterionType.IVUS*/)
|
||||||
{
|
{
|
||||||
list.Add(new ExportDocumentDes() { Code = StaticData.Export.CDISC_Reading_Export, ExportCatogory = ExportResult.NoneTumorCDISC });
|
list.Add(new ExportDocumentDes() { Code = StaticData.Export.CDISC_Reading_Export, ExportCatogory = ExportResult.NoneTumorCDISC });
|
||||||
}
|
}
|
||||||
@@ -2867,7 +3048,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
if (!criterion.IsArbitrationReading)
|
if (!criterion.IsArbitrationReading)
|
||||||
{
|
{
|
||||||
//仲裁阅片 才有裁判阅片明细表 同时要把模板里面的三列给去掉
|
//仲裁阅片 才有裁判阅片明细表 同时要把模板里面的三列给去掉
|
||||||
removeColumnIndexList = new List<int>() { 6, 7, 8 };
|
//removeColumnIndexList = new List<int>() { 6, 7, 8 };
|
||||||
|
removeColumnIndexList = new List<int>() { 7, 8, 9 };
|
||||||
}
|
}
|
||||||
|
|
||||||
//阅片结果表 和阅片结果明细表 没有肿瘤学的时候需要移除肿瘤学三个字段
|
//阅片结果表 和阅片结果明细表 没有肿瘤学的时候需要移除肿瘤学三个字段
|
||||||
@@ -2876,7 +3058,8 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
{
|
{
|
||||||
if (inQuery.ReadingExportType == ExportResult.TableOfAssessmentResults || inQuery.ReadingExportType == ExportResult.DetailedTableOfAssessmentResults)
|
if (inQuery.ReadingExportType == ExportResult.TableOfAssessmentResults || inQuery.ReadingExportType == ExportResult.DetailedTableOfAssessmentResults)
|
||||||
{
|
{
|
||||||
removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 9, 10, 11 }).ToList();
|
//removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 9, 10, 11 }).ToList();
|
||||||
|
removeColumnIndexList = removeColumnIndexList.Union(new List<int>() { 10, 11, 12 }).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2903,7 +3086,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
//阅片结果表
|
//阅片结果表
|
||||||
export_Template = StaticData.Export.CommonReading_Export;
|
export_Template = StaticData.Export.CommonReading_Export;
|
||||||
}
|
}
|
||||||
//斑块表
|
//斑块表
|
||||||
else if (inQuery.ReadingExportType == ExportResult.OCT_ReadingLession_Export)
|
else if (inQuery.ReadingExportType == ExportResult.OCT_ReadingLession_Export)
|
||||||
{
|
{
|
||||||
//OCT
|
//OCT
|
||||||
@@ -2933,7 +3116,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
arbitrationRule = criterion.ArbitrationRule,
|
arbitrationRule = criterion.ArbitrationRule,
|
||||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||||
isEn_Us = _userInfo.IsEn_Us
|
isEn_Us = _userInfo.IsEn_Us
|
||||||
}).ToListAsync();
|
}).AsSplitQuery().ToListAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
//肿瘤标准 病灶明细表 按照病灶级别 (OCT 暂时不删除,先看是否能覆盖)
|
//肿瘤标准 病灶明细表 按照病灶级别 (OCT 暂时不删除,先看是否能覆盖)
|
||||||
@@ -2952,7 +3135,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
arbitrationRule = criterion.ArbitrationRule,
|
arbitrationRule = criterion.ArbitrationRule,
|
||||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||||
isEn_Us = _userInfo.IsEn_Us
|
isEn_Us = _userInfo.IsEn_Us
|
||||||
}).ToListAsync();
|
}).AsSplitQuery().ToListAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
// 非肿瘤标准 包括自定义,以及系统非肿瘤 会配置到表格层级 问题名称是 表格名称_表格子问题名
|
// 非肿瘤标准 包括自定义,以及系统非肿瘤 会配置到表格层级 问题名称是 表格名称_表格子问题名
|
||||||
@@ -2970,7 +3153,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
arbitrationRule = criterion.ArbitrationRule,
|
arbitrationRule = criterion.ArbitrationRule,
|
||||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||||
isEn_Us = _userInfo.IsEn_Us
|
isEn_Us = _userInfo.IsEn_Us
|
||||||
}).ToListAsync();
|
}).AsSplitQuery().ToListAsync();
|
||||||
|
|
||||||
}
|
}
|
||||||
// CDISC 导出 只管到 外层问题层级 和阅片结果表是保持一致
|
// CDISC 导出 只管到 外层问题层级 和阅片结果表是保持一致
|
||||||
@@ -2988,7 +3171,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
arbitrationRule = criterion.ArbitrationRule,
|
arbitrationRule = criterion.ArbitrationRule,
|
||||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||||
isEn_Us = _userInfo.IsEn_Us
|
isEn_Us = _userInfo.IsEn_Us
|
||||||
}).ToListAsync();
|
}).AsSplitQuery().ToListAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3000,7 +3183,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
arbitrationRule = criterion.ArbitrationRule,
|
arbitrationRule = criterion.ArbitrationRule,
|
||||||
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
trialReadingCriterionId = inQuery.TrialReadingCriterionId,
|
||||||
isEn_Us = _userInfo.IsEn_Us
|
isEn_Us = _userInfo.IsEn_Us
|
||||||
}).ToListAsync();
|
}).AsSplitQuery().ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3170,7 +3353,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion Type" : "病灶类型", QuestionValue = lession.LessionType, TranslateDicName = "LesionType" });
|
addLessionInfoList.Add(new CommonQuesionInfo() { QuestionName = _userInfo.IsEn_Us ? "Lesion Type" : "病灶类型", QuestionValue = lession.LessionType, TranslateDicName = "LesionType" });
|
||||||
}
|
}
|
||||||
|
|
||||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, OptionTypeEnum = t.OptionTypeEnum, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName ,Unit=t.Unit});
|
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionName = t.QuestionName, OptionTypeEnum = t.OptionTypeEnum, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, Unit = t.Unit });
|
||||||
|
|
||||||
//有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题
|
//有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题
|
||||||
var dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList();
|
var dynamicLessionInfoList = item.QuestionAnswerList.Union(addLessionInfoList).Union(dynamicPartialLessionInfoList).ToList();
|
||||||
@@ -3358,9 +3541,10 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
dynamicColumnConfig = new DynamicColumnConfig()
|
dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
AutoColumnTitleRowIndex = 2,
|
|
||||||
AutoColumnStartIndex = 6,
|
AutoColumnTitleRowIndex = 3, //2
|
||||||
TempalteLastColumnIndex = 11,
|
AutoColumnStartIndex = 7, //6
|
||||||
|
TempalteLastColumnIndex = 12,//11
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "QuestionValue",
|
DynamicItemValueName = "QuestionValue",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -3372,7 +3556,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
TranslateDicNameList = translateDicNameList
|
TranslateDicNameList = translateDicNameList
|
||||||
};
|
};
|
||||||
|
|
||||||
if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export || export_Template== StaticData.Export.OCT_ReadingLession_Export)
|
if (export_Template == StaticData.Export.ReadingLession_Export || export_Template == StaticData.Export.CommonJudgeReadingDetail_Export || export_Template == StaticData.Export.OCT_ReadingLession_Export)
|
||||||
{
|
{
|
||||||
dynamicColumnConfig.TempalteLastColumnIndex = 8;
|
dynamicColumnConfig.TempalteLastColumnIndex = 8;
|
||||||
}
|
}
|
||||||
@@ -3391,7 +3575,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
var trialConfigTableQuestionList = _trialReadingTableQuestionRepository.Where(t => t.TrialId == trialId && t.TrialCriterionId == trialReadingCriterionId).Where(t => t.ExportResultStr.Contains(((int)inQuery.ReadingExportType).ToString()))
|
var trialConfigTableQuestionList = _trialReadingTableQuestionRepository.Where(t => t.TrialId == trialId && t.TrialCriterionId == trialReadingCriterionId).Where(t => t.ExportResultStr.Contains(((int)inQuery.ReadingExportType).ToString()))
|
||||||
.Select(t => new ExportQuestionBasicInfo()
|
.Select(t => new ExportQuestionBasicInfo()
|
||||||
{
|
{
|
||||||
QuestionId = t.Id,
|
QuestionId = t.Id,
|
||||||
TableName = _userInfo.IsEn_Us ? t.ReadingQuestionTrial.QuestionEnName : t.ReadingQuestionTrial.QuestionName,
|
TableName = _userInfo.IsEn_Us ? t.ReadingQuestionTrial.QuestionEnName : t.ReadingQuestionTrial.QuestionName,
|
||||||
QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName,
|
QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName,
|
||||||
CDISCCode = t.CDISCCode,
|
CDISCCode = t.CDISCCode,
|
||||||
@@ -3435,7 +3619,7 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
var dynamicLessionInfoList = new List<CommonQuesionInfo>();
|
var dynamicLessionInfoList = new List<CommonQuesionInfo>();
|
||||||
|
|
||||||
|
|
||||||
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId,OptionTypeEnum=t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
|
var dynamicPartialLessionInfoList = lession.LessionAnswerList.Select(t => new CommonQuesionInfo() { QuestionId = t.TableQuesionId, OptionTypeEnum = t.OptionTypeEnum, QuestionName = t.QuestionName, QuestionValue = t.QuestionValue, TranslateDicName = t.TranslateDicName, CDISCCode = t.CDISCCode, Unit = t.Unit });
|
||||||
|
|
||||||
//两部分组成 外层问题+ 动态的表格问题
|
//两部分组成 外层问题+ 动态的表格问题
|
||||||
dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList();
|
dynamicLessionInfoList = item.QuestionAnswerList.Union(dynamicPartialLessionInfoList).ToList();
|
||||||
@@ -3458,9 +3642,9 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
dynamicColumnConfig = new DynamicColumnConfig()
|
dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
AutoColumnTitleRowIndex = 1,
|
AutoColumnTitleRowIndex = 2, //1
|
||||||
AutoColumnStartIndex = 6,
|
AutoColumnStartIndex = 7, //6
|
||||||
TempalteLastColumnIndex = 10,
|
TempalteLastColumnIndex = 11, //10
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "QuestionValue",
|
DynamicItemValueName = "QuestionValue",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -3543,9 +3727,9 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
dynamicColumnConfig = new DynamicColumnConfig()
|
dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
AutoColumnTitleRowIndex = 1,
|
AutoColumnTitleRowIndex = 2, //1
|
||||||
AutoColumnStartIndex = 6,
|
AutoColumnStartIndex = 7, //6
|
||||||
TempalteLastColumnIndex = 15,
|
TempalteLastColumnIndex = 16, //15
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "QuestionValue",
|
DynamicItemValueName = "QuestionValue",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -3578,9 +3762,9 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
dynamicColumnConfig = new DynamicColumnConfig()
|
dynamicColumnConfig = new DynamicColumnConfig()
|
||||||
{
|
{
|
||||||
AutoColumnTitleRowIndex = 1,
|
AutoColumnTitleRowIndex = 2, //1
|
||||||
AutoColumnStartIndex = 6,
|
AutoColumnStartIndex = 7, //6
|
||||||
TempalteLastColumnIndex = 10,
|
TempalteLastColumnIndex = 11, //10
|
||||||
DynamicItemDicName = "TranslateDicName",
|
DynamicItemDicName = "TranslateDicName",
|
||||||
DynamicItemValueName = "QuestionValue",
|
DynamicItemValueName = "QuestionValue",
|
||||||
DynamicItemTitleName = "QuestionName",
|
DynamicItemTitleName = "QuestionName",
|
||||||
@@ -3650,12 +3834,12 @@ namespace IRaCIS.Core.Application.Service.Common
|
|||||||
|
|
||||||
if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC)
|
if (inQuery.ReadingExportType == ExportResult.NoneTumorCDISC)
|
||||||
{
|
{
|
||||||
(memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
|
(memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(memoryStream, fileName) = await ExcelExportHelper.DataExport_NpoiTestAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
|
(memoryStream, fileName) = await ExcelExportHelper.DataExport_ClosedXMLAsync(export_Template, exportInfo, _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(CommonEvaluationExport), criterion.CriterionType, dynamicColumnConfig);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using IRaCIS.Core.Infra.EFCore.Common;
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
using IRaCIS.Core.Infrastructure.Extention;
|
|
||||||
using MassTransit;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MiniExcelLibs;
|
using MiniExcelLibs;
|
||||||
using MiniExcelLibs.OpenXml;
|
using MiniExcelLibs.OpenXml;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using Org.BouncyCastle.Asn1.X509;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.Common;
|
namespace IRaCIS.Core.Application.Service.Common;
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,9 @@
|
|||||||
using Amazon.Runtime.Internal.Transform;
|
using IRaCIS.Application.Contracts;
|
||||||
using DocumentFormat.OpenXml.Bibliography;
|
|
||||||
using DocumentFormat.OpenXml.Office2010.CustomUI;
|
|
||||||
using DocumentFormat.OpenXml.Office2021.DocumentTasks;
|
|
||||||
using DocumentFormat.OpenXml.Spreadsheet;
|
|
||||||
using IRaCIS.Application.Contracts;
|
|
||||||
using IRaCIS.Application.Interfaces;
|
using IRaCIS.Application.Interfaces;
|
||||||
using IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson;
|
|
||||||
using IRaCIS.Core.Application.Contracts;
|
|
||||||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
|
||||||
using IRaCIS.Core.Application.ViewModel;
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
using IRaCIS.Core.Domain.Models;
|
|
||||||
using IRaCIS.Core.Domain.Share;
|
|
||||||
using IRaCIS.Core.Infra.EFCore.Common;
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
using MailKit;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using NetTopologySuite.Triangulate.Tri;
|
|
||||||
using NPOI.OpenXmlFormats.Spreadsheet;
|
|
||||||
using NPOI.SS.Formula.Functions;
|
|
||||||
using NPOI.Util;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static IRaCIS.Core.Application.Service.ExcelExportHelper;
|
|
||||||
|
|
||||||
namespace IRaCIS.Core.Application.Service.Common;
|
namespace IRaCIS.Core.Application.Service.Common;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,604 @@
|
|||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||||
|
// 生成时间 2026-03-10 06:15:17Z
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
using DocumentFormat.OpenXml.Office2010.ExcelAc;
|
||||||
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.Interfaces;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
|
using IRaCIS.Core.Domain.Models;
|
||||||
|
using IRaCIS.Core.Infra.EFCore;
|
||||||
|
using IRaCIS.Core.Infra.EFCore.Common;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Spire.Doc.Interface;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace IRaCIS.Core.Application.Service;
|
||||||
|
|
||||||
|
[ApiExplorerSettings(GroupName = "Common")]
|
||||||
|
public class FileUploadRecordService(IRepository<FileUploadRecord> _fileUploadRecordRepository, IRepository<UploadFileSyncRecord> _uploadFileSyncRecordRepository,
|
||||||
|
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IOptionsMonitor<ObjectStoreServiceOptions> options,
|
||||||
|
IRepository<CommonUploadRecord> _commonUploadRecordRepository,
|
||||||
|
IFusionCache _fusionCache, IRepository<Trial> _trialRepository, FileSyncQueue _fileSyncQueue) : BaseService, IFileUploadRecordService
|
||||||
|
{
|
||||||
|
|
||||||
|
ObjectStoreServiceOptions ObjectStoreServiceConfig = options.CurrentValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传通用文件记录
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="addOrEditCommonUploadRecord"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<IResponseOutput> AddOrUpdateCommonUploadRecord(CommonUploadRecordAddOrEdit addOrEditCommonUploadRecord)
|
||||||
|
{
|
||||||
|
|
||||||
|
var entity = await _commonUploadRecordRepository.InsertOrUpdateAsync(addOrEditCommonUploadRecord, true);
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按照 subject visit studyCode 三个维度进行分组的查询列表 (subject相关)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<PageOutput<SubjectFileUploadRecordView>> GetSubjectUploadRecordList(SubjectFileUploadRecordQuery inQuery)
|
||||||
|
{
|
||||||
|
|
||||||
|
var query = _fileUploadRecordRepository.Where(t => t.TrialId == inQuery.TrialId && t.SubjectId != null)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.VisitName), t => t.SubjectVisit.VisitName.Contains(inQuery.VisitName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.StudyCode), t => t.StudyCode.Contains(inQuery.StudyCode))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.UploadRegion), t => t.UploadRegion == inQuery.UploadRegion)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TargetRegion), t => t.TargetRegion == inQuery.TargetRegion)
|
||||||
|
.WhereIf(inQuery.IsSync != null, t => t.IsSync == inQuery.IsSync)
|
||||||
|
.GroupBy(t => new { t.StudyCode, SubjectCode = t.Subject.Code, t.SubjectVisit.VisitName, t.SubjectId, t.SubjectVisitId })
|
||||||
|
.Select(g => new SubjectFileUploadRecordView()
|
||||||
|
{
|
||||||
|
SubjectCode = g.Key.SubjectCode,
|
||||||
|
VisitName = g.Key.VisitName,
|
||||||
|
StudyCode = g.Key.StudyCode,
|
||||||
|
SubjectId = g.Key.SubjectId,
|
||||||
|
SubjectVisitId = g.Key.SubjectVisitId,
|
||||||
|
|
||||||
|
FileCount = g.Count(),
|
||||||
|
|
||||||
|
CreateTime = g.Max(t => t.CreateTime),
|
||||||
|
|
||||||
|
SyncFinishedTime = g.Max(t => t.SyncFinishedTime),
|
||||||
|
|
||||||
|
UploadRegion = g.First().UploadRegion,
|
||||||
|
|
||||||
|
TargetRegion = g.First().TargetRegion,
|
||||||
|
|
||||||
|
IsSync = !g.Any(t => t.IsSync == false || t.IsSync == null)
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var pageList = await query.ToPagedListAsync(inQuery);
|
||||||
|
|
||||||
|
return pageList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传记录表--里面包含待同步任务 DataFileType= 0 :代表系统文件 1:Subject相关 2:项目相关,但是和subject 没关系
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<PageOutput<FileUploadRecordView>> GetFileUploadRecordList(FileUploadRecordQuery inQuery)
|
||||||
|
{
|
||||||
|
|
||||||
|
var fileUploadRecordQueryable = _fileUploadRecordRepository
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.FileName), t => t.FileName.Contains(inQuery.FileName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.FileType), t => t.FileType.Contains(inQuery.FileType))
|
||||||
|
.WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId)
|
||||||
|
|
||||||
|
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
|
||||||
|
.WhereIf(inQuery.SubjectVisitId != null, t => t.SubjectVisitId == inQuery.SubjectVisitId)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.StudyCode), t => t.StudyCode.Contains(inQuery.StudyCode))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.VisitName), t => t.SubjectVisit.VisitName.Contains(inQuery.VisitName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode))
|
||||||
|
|
||||||
|
.WhereIf(inQuery.DataFileType == 1 && inQuery.SubjectId != null && inQuery.SubjectVisitId == null, t => t.SubjectVisitId == null)
|
||||||
|
.WhereIf(inQuery.DataFileType == 1 && inQuery.SubjectVisitId != null && inQuery.StudyCode == "", t => t.StudyCode == "")
|
||||||
|
.WhereIf(inQuery.DataFileType == 1 && inQuery.SubjectCode.IsNotNullOrEmpty() && inQuery.VisitName.IsNullOrEmpty(), t => t.SubjectVisitId == null)
|
||||||
|
.WhereIf(inQuery.DataFileType == 1 && inQuery.VisitName.IsNotNullOrEmpty() && inQuery.StudyCode == "", t => t.StudyCode == "")
|
||||||
|
|
||||||
|
.WhereIf(inQuery.DataFileType == 0, t => t.TrialId == null)
|
||||||
|
.WhereIf(inQuery.DataFileType == 1, t => t.SubjectId != null)
|
||||||
|
.WhereIf(inQuery.DataFileType == 2, t => t.SubjectId == null)
|
||||||
|
|
||||||
|
.WhereIf(inQuery.IsNeedSync != null, t => t.IsNeedSync == inQuery.IsNeedSync)
|
||||||
|
|
||||||
|
.WhereIf(inQuery.IsSync != null, t => t.IsSync == inQuery.IsSync)
|
||||||
|
.WhereIf(inQuery.Priority != null, t => t.Priority == inQuery.Priority)
|
||||||
|
.WhereIf(inQuery.BatchDataType != null, t => t.BatchDataType == inQuery.BatchDataType)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.UploadRegion), t => t.UploadRegion == inQuery.UploadRegion)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.TargetRegion), t => t.TargetRegion == inQuery.TargetRegion)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.UploadBatchId), t => t.UploadBatchId.Contains(inQuery.UploadBatchId))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.Path), t => t.Path.Contains(inQuery.Path))
|
||||||
|
.WhereIf(inQuery.UploadStartTime != null, t => t.CreateTime >= inQuery.UploadStartTime)
|
||||||
|
.WhereIf(inQuery.UploadEndTime != null, t => t.CreateTime <= inQuery.UploadEndTime)
|
||||||
|
.WhereIf(inQuery.SyncFinishedStartTime != null, t => t.SyncFinishedTime >= inQuery.SyncFinishedStartTime)
|
||||||
|
.WhereIf(inQuery.SyncFinishedEndTime != null, t => t.SyncFinishedTime <= inQuery.SyncFinishedEndTime)
|
||||||
|
|
||||||
|
.ProjectTo<FileUploadRecordView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
var pageList = await fileUploadRecordQueryable.ToPagedListAsync(inQuery);
|
||||||
|
|
||||||
|
return pageList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务具体执行记录表
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inQuery"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<PageOutput<UploadFileSyncRecordView>> GetUploadFileSyncRecordList(UploadFileSyncRecordQuery inQuery)
|
||||||
|
{
|
||||||
|
|
||||||
|
var fileUploadRecordQueryable = _uploadFileSyncRecordRepository
|
||||||
|
.WhereIf(inQuery.JobState != null, t => t.JobState == inQuery.JobState)
|
||||||
|
.WhereIf(inQuery.FileUploadRecordId != null, t => t.FileUploadRecordId == inQuery.FileUploadRecordId)
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.StudyCode), t => t.FileUploadRecord.StudyCode.Contains(inQuery.StudyCode))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.VisitName), t => t.FileUploadRecord.SubjectVisit.VisitName.Contains(inQuery.VisitName))
|
||||||
|
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.FileUploadRecord.Subject.Code.Contains(inQuery.SubjectCode))
|
||||||
|
|
||||||
|
.ProjectTo<UploadFileSyncRecordView>(_mapper.ConfigurationProvider);
|
||||||
|
|
||||||
|
var pageList = await fileUploadRecordQueryable.ToPagedListAsync(inQuery);
|
||||||
|
|
||||||
|
return pageList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量设置为需要同步,并且设置优先级
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inComand"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<IResponseOutput> BatchAddSyncFileTask(BatchAddSyncFileCommand inComand)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
await _fileUploadRecordRepository.BatchUpdateNoTrackingAsync(t => inComand.FileUploadRecordIdList.Contains(t.Id), u => new FileUploadRecord() { IsNeedSync = true, Priority = inComand.Priority ?? 0 });
|
||||||
|
|
||||||
|
foreach (var item in inComand.FileUploadRecordIdList)
|
||||||
|
{
|
||||||
|
_fileSyncQueue.Enqueue(item, inComand.Priority ?? 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
await _fileUploadRecordRepository.SaveChangesAsync();
|
||||||
|
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord)
|
||||||
|
{
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IP = _userInfo.IP;
|
||||||
|
|
||||||
|
if (ObjectStoreServiceConfig.IsOpenStoreSync && _userInfo.Domain.IsNotNullOrEmpty())
|
||||||
|
{
|
||||||
|
var find = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.Domain == _userInfo.Domain);
|
||||||
|
if (find != null)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.UploadRegion = find.UploadRegion;
|
||||||
|
addOrEditFileUploadRecord.TargetRegion = find.TargetRegion;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//前后端调试的时候,上传的时候域名不对应,自动按照后端配置设置上传区域和同步区域
|
||||||
|
var apiDefalut = ObjectStoreServiceConfig.SyncConfigList.FirstOrDefault(t => t.UploadRegion == ObjectStoreServiceConfig.ApiDeployRegion);
|
||||||
|
|
||||||
|
if (apiDefalut != null)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.UploadRegion = apiDefalut.UploadRegion;
|
||||||
|
addOrEditFileUploadRecord.TargetRegion = apiDefalut.TargetRegion;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addOrEditFileUploadRecord.TrialId != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
var trialDataStore = await _fusionCache.GetOrSetAsync(CacheKeys.TrialDataStoreType(addOrEditFileUploadRecord.TrialId.Value), async _ =>
|
||||||
|
{
|
||||||
|
return await _trialRepository.Where(t => t.Id == addOrEditFileUploadRecord.TrialId).Select(t => t.TrialDataStoreType)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
},
|
||||||
|
TimeSpan.FromDays(7)
|
||||||
|
);
|
||||||
|
|
||||||
|
//项目配置了,那么就设置需要同步
|
||||||
|
if (trialDataStore == TrialDataStore.MUtiCenter)
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IsSync = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = false;
|
||||||
|
|
||||||
|
//addOrEditFileUploadRecord.TargetRegion = "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//系统文件,默认同步
|
||||||
|
addOrEditFileUploadRecord.IsNeedSync = true;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.IsSync = false;
|
||||||
|
|
||||||
|
addOrEditFileUploadRecord.Priority = addOrEditFileUploadRecord.Priority ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = await _fileUploadRecordRepository.InsertOrUpdateAsync(addOrEditFileUploadRecord, true);
|
||||||
|
|
||||||
|
if (addOrEditFileUploadRecord.IsNeedSync == true)
|
||||||
|
{
|
||||||
|
_fileSyncQueue.Enqueue(entity.Id, addOrEditFileUploadRecord.Priority ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseOutput.Ok(entity.Id.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpDelete("{fileUploadRecordId:guid}")]
|
||||||
|
public async Task<IResponseOutput> DeleteFileUploadRecord(Guid fileUploadRecordId)
|
||||||
|
{
|
||||||
|
var success = await _fileUploadRecordRepository.BatchDeleteNoTrackingAsync(t => t.Id == fileUploadRecordId);
|
||||||
|
return ResponseOutput.Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region 同步队列
|
||||||
|
|
||||||
|
|
||||||
|
public sealed class FileSyncQueue
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 优先级队列(仅负责排序)
|
||||||
|
/// </summary>
|
||||||
|
private readonly PriorityQueue<Guid, int> _queue = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前等待中的任务(唯一真实数据)
|
||||||
|
/// key = Guid
|
||||||
|
/// value = 最新 priority
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<Guid, int> _waiting = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正在执行的任务(防止重复执行)
|
||||||
|
/// </summary>
|
||||||
|
private readonly HashSet<Guid> _running = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// worker 等待信号
|
||||||
|
/// </summary>
|
||||||
|
private readonly SemaphoreSlim _signal = new(0);
|
||||||
|
|
||||||
|
|
||||||
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Enqueue
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 入队(同 Guid 会覆盖优先级)
|
||||||
|
/// </summary>
|
||||||
|
public void Enqueue(Guid id, int priority)
|
||||||
|
{
|
||||||
|
bool needSignal = false;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
// 如果正在执行,忽略(防止重复)
|
||||||
|
if (_running.Contains(id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 是否新任务(用于减少 signal 风暴)
|
||||||
|
if (!_waiting.ContainsKey(id))
|
||||||
|
needSignal = true;
|
||||||
|
|
||||||
|
// 更新为最新优先级(最后一次为准)
|
||||||
|
_waiting[id] = priority; //等价于添加或者更新
|
||||||
|
|
||||||
|
// PriorityQueue 无法更新节点
|
||||||
|
// 允许旧节点存在,Dequeue 时过滤
|
||||||
|
_queue.Enqueue(id, -priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有新增任务才唤醒 worker
|
||||||
|
if (needSignal)
|
||||||
|
_signal.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Dequeue
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取一个待执行任务(无任务时自动等待)
|
||||||
|
/// </summary>
|
||||||
|
public async Task<Guid> DequeueAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await _signal.WaitAsync(ct);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
while (_queue.Count > 0)
|
||||||
|
{
|
||||||
|
var id = _queue.Dequeue();
|
||||||
|
|
||||||
|
// 已被覆盖或取消 如果这个任务已经不是“当前最新版任务”,那它只是 PriorityQueue 里的垃圾数据,直接跳过。
|
||||||
|
if (!_waiting.TryGetValue(id, out _)) //能从等待任务中取到,那么就是有效的,不能取到那么就是覆盖的
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 标记为运行中
|
||||||
|
_waiting.Remove(id);
|
||||||
|
_running.Add(id);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Complete
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 任务执行完成(必须调用)
|
||||||
|
/// </summary>
|
||||||
|
public void Complete(Guid id)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_running.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Snapshot
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前等待中的任务快照
|
||||||
|
/// </summary>
|
||||||
|
public Guid[] Snapshot()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _waiting.Keys.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 状态信息(调试用)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
public int WaitingCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _waiting.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RunningCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _running.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 同步队列 信号量
|
||||||
|
///// </summary>
|
||||||
|
//public class FileSyncQueue
|
||||||
|
//{
|
||||||
|
// private readonly PriorityQueue<Guid, int> _queue = new();
|
||||||
|
// private readonly SemaphoreSlim _signal = new(0);
|
||||||
|
// private readonly object _lock = new();
|
||||||
|
|
||||||
|
// public void Enqueue(Guid id, int priority)
|
||||||
|
// {
|
||||||
|
// lock (_lock)
|
||||||
|
// {
|
||||||
|
// // priority 越大越优先
|
||||||
|
// _queue.Enqueue(id, -priority);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //类似于计数器,不会产生通知风暴,可消费资源 +1
|
||||||
|
// //if (有等待线程) 唤醒一个 else 仅增加计数
|
||||||
|
// _signal.Release(); // 唤醒一个 worker
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// 如果没有任务 → 挂起等待 有任务 → 被唤醒并返回
|
||||||
|
// /// </summary>
|
||||||
|
// /// <param name="ct"></param>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public async Task<Guid> DequeueAsync(CancellationToken ct)
|
||||||
|
// {
|
||||||
|
// await _signal.WaitAsync(ct);
|
||||||
|
|
||||||
|
// lock (_lock)
|
||||||
|
// {
|
||||||
|
// return _queue.Dequeue();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// 获取队列任务Id
|
||||||
|
// /// </summary>
|
||||||
|
// /// <returns></returns>
|
||||||
|
// public Guid[] Snapshot()
|
||||||
|
// {
|
||||||
|
// lock (_lock)
|
||||||
|
// {
|
||||||
|
// return _queue.UnorderedItems
|
||||||
|
// .Select(x => x.Element)
|
||||||
|
// .ToArray();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
#region 这里不用 SyncQueueUseChannel 和调度器 SyncScheduler
|
||||||
|
public class SyncQueueUseChannel
|
||||||
|
{
|
||||||
|
// 优先级队列(priority 越大越先执行)
|
||||||
|
private readonly PriorityQueue<Guid, int> _queue = new();
|
||||||
|
|
||||||
|
// Worker 唤醒信号
|
||||||
|
private readonly Channel<bool> _signal =
|
||||||
|
Channel.CreateUnbounded<bool>(new UnboundedChannelOptions
|
||||||
|
{
|
||||||
|
SingleReader = false,
|
||||||
|
SingleWriter = false
|
||||||
|
});
|
||||||
|
|
||||||
|
// 队列任务数量(不是CPU数量!)
|
||||||
|
private int _count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 入队任务
|
||||||
|
/// </summary>
|
||||||
|
public void Enqueue(Guid id, int priority)
|
||||||
|
{
|
||||||
|
bool needSignal = false;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
// priority 越大越优先 → 转负数
|
||||||
|
_queue.Enqueue(id, -priority);
|
||||||
|
|
||||||
|
// 只有从 0 → 1 才需要唤醒 worker
|
||||||
|
if (_count == 0)
|
||||||
|
needSignal = true;
|
||||||
|
|
||||||
|
_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 避免 signal 风暴
|
||||||
|
if (needSignal)
|
||||||
|
_signal.Writer.TryWrite(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Worker 等待并获取任务
|
||||||
|
/// </summary>
|
||||||
|
public async Task<Guid> DequeueAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 没任务时挂起(不会占CPU)
|
||||||
|
await _signal.Reader.ReadAsync(ct);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
var id = _queue.Dequeue();
|
||||||
|
|
||||||
|
_count--;
|
||||||
|
|
||||||
|
// 如果还有任务,继续唤醒下一个 worker
|
||||||
|
if (_count > 0)
|
||||||
|
_signal.Writer.TryWrite(true);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前排队数量(调试用)
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
return _count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步调度器
|
||||||
|
/// </summary>
|
||||||
|
public class FileSyncScheduler
|
||||||
|
{
|
||||||
|
private readonly FileSyncQueue _queue;
|
||||||
|
|
||||||
|
public FileSyncScheduler(FileSyncQueue queue)
|
||||||
|
{
|
||||||
|
_queue = queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enqueue(FileUploadRecord file)
|
||||||
|
{
|
||||||
|
if (file.IsNeedSync != true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_queue.Enqueue(file.Id, file.Priority ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 如果没有任务 → 挂起等待 有任务 → 被唤醒并返回
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ct"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task<Guid> WaitAsync(CancellationToken ct)
|
||||||
|
=> _queue.DequeueAsync(ct);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// 此代码由liquid模板自动生成 byzhouhang 20240909
|
||||||
|
// 生成时间 2026-03-10 06:15:31Z
|
||||||
|
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
using System;
|
||||||
|
using IRaCIS.Core.Infrastructure.Extention;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using IRaCIS.Core.Application.ViewModel;
|
||||||
|
namespace IRaCIS.Core.Application.Interfaces;
|
||||||
|
|
||||||
|
public interface IFileUploadRecordService
|
||||||
|
{
|
||||||
|
|
||||||
|
Task<PageOutput<FileUploadRecordView>> GetFileUploadRecordList(FileUploadRecordQuery inQuery);
|
||||||
|
|
||||||
|
Task<IResponseOutput> AddOrUpdateFileUploadRecord(FileUploadRecordAddOrEdit addOrEditFileUploadRecord);
|
||||||
|
|
||||||
|
Task<IResponseOutput> DeleteFileUploadRecord(Guid fileUploadRecordId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using IRaCIS.Application.Contracts;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
|
using IRaCIS.Application.Contracts;
|
||||||
using IRaCIS.Core.Application.Auth;
|
using IRaCIS.Core.Application.Auth;
|
||||||
using IRaCIS.Core.Application.Helper;
|
using IRaCIS.Core.Application.Helper;
|
||||||
|
using IRaCIS.Core.Application.MassTransit.Consumer;
|
||||||
using IRaCIS.Core.Domain.Models;
|
using IRaCIS.Core.Domain.Models;
|
||||||
using IRaCIS.Core.Domain.Share;
|
using IRaCIS.Core.Domain.Share;
|
||||||
using IRaCIS.Core.Infrastructure;
|
using IRaCIS.Core.Infrastructure;
|
||||||
@@ -66,7 +68,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl);
|
Task AddUserSendEmailAsync(Guid userId, string baseUrl, string routeUrl);
|
||||||
|
|
||||||
Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456", string baseUrl="");
|
Task AdminResetPwdSendEmailAsync(Guid userId, string pwdNotMd5 = "123456", string baseUrl = "");
|
||||||
|
|
||||||
Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string userTypes, string baseUrl, string rootUrl);
|
Task SiteSurveyUserJoinEmail(Guid trialId, Guid userId, string userTypes, string baseUrl, string rootUrl);
|
||||||
|
|
||||||
@@ -104,10 +106,18 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取邮件主题和html 通用封装 以用户语言为主,没有的就用当前的请求语言_userInfo.IsEn_Us
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scenario"></param>
|
||||||
|
/// <param name="messageToSend"></param>
|
||||||
|
/// <param name="emailFunc"></param>
|
||||||
|
/// <param name="userWorkLanguage"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
||||||
private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
|
private async Task<EmailNoticeConfig> GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario scenario, MimeMessage messageToSend,
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc)
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailFunc, UserWorkLanguage? userWorkLanguage = null)
|
||||||
{
|
{
|
||||||
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();
|
var configInfo = await _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario).FirstOrDefaultAsync();
|
||||||
|
|
||||||
@@ -119,7 +129,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var (topicStr, htmlBodyStr) = _userInfo.IsEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
bool isEn_Us = userWorkLanguage.HasValue ? userWorkLanguage.Value == UserWorkLanguage.US : _userInfo.IsEn_Us;
|
||||||
|
|
||||||
|
var (topicStr, htmlBodyStr) = isEn_Us ? (configInfo.EmailTopic, configInfo.EmailHtmlContent) : (configInfo.EmailTopicCN, configInfo.EmailHtmlContentCN);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -182,24 +194,16 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
return sucessHandle;
|
return sucessHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ReplaceCompanyName(string needDealtxt)
|
|
||||||
{
|
|
||||||
var str = needDealtxt.Replace("{company}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyName : _systemEmailConfig.CompanyNameCN)
|
|
||||||
.Replace("{company abbreviation}", _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ReplacePlatformName(string needDealtxt)
|
|
||||||
{
|
|
||||||
var platformName = _userInfo.IsEn_Us ? _systemEmailConfig.PlatformName : _systemEmailConfig.PlatformNameCN;
|
|
||||||
|
|
||||||
var str = needDealtxt.Replace("{platformName}", platformName);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
//MFA
|
//MFA
|
||||||
public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login)
|
public async Task SenMFAVerifyEmail(Guid userId, string userName, string emailAddress, int verificationCode, UserMFAType mfaType = UserMFAType.Login)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = _identityUserRepository.Where(t => t.Id == userId).Select(t => t.UserWorkLanguage).First();
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -207,13 +211,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(userName, emailAddress));
|
||||||
//主题---[来自{0}] 关于MFA邮箱验证的提醒
|
//主题---[来自{0}] 关于MFA邮箱验证的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userName,
|
userName,
|
||||||
verificationCode
|
verificationCode
|
||||||
);
|
);
|
||||||
@@ -222,7 +226,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(mfaType == UserMFAType.Login ? EmailBusinessScenario.MFALogin : EmailBusinessScenario.MFAUnlock, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
|
||||||
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
||||||
@@ -245,6 +249,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
public async Task SendEmailVerification(string emailAddress, int verificationCode)
|
public async Task SendEmailVerification(string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var isEn_US = _userInfo.IsEn_Us;
|
||||||
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -253,13 +262,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC]的提醒
|
//---[来自展影IRC]的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
"Sir/Madam",
|
"Sir/Madam",
|
||||||
//---您正在参与展影医疗IRC项目
|
//---您正在参与展影医疗IRC项目
|
||||||
@@ -271,7 +280,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.ReviewerLogin, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
//此时不知道用户
|
//此时不知道用户
|
||||||
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
@@ -286,8 +295,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//中心调研 登陆 发送验证码
|
//中心调研 登陆 发送验证码
|
||||||
public async Task AnolymousSendEmail(Guid trialId, string emailAddress, int verificationCode)
|
public async Task AnolymousSendEmail(Guid trialId, string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
//throw new BusinessValidationFailedException("模拟邮件取数据或者发送异常!!!");
|
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var isEn_US = _userInfo.IsEn_Us;
|
||||||
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
@@ -299,13 +310,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";
|
//$"[来自展影IRC] [{researchProgramNo}] 关于中心调研的提醒";
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
"Sir/Madam",
|
"Sir/Madam",
|
||||||
//---您正在参与展影医疗IRC项目中心调研工作
|
//---您正在参与展影医疗IRC项目中心调研工作
|
||||||
@@ -317,13 +328,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurveyLogin, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
//此时不知道用户
|
//此时不知道用户
|
||||||
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, sucessHandle);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo, sucessHandle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +346,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
@@ -349,20 +363,19 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new IdentityUser() { EmailToken = token });
|
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new IdentityUser() { EmailToken = token });
|
||||||
|
|
||||||
routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
routeUrl = routeUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&UserName=" + sysUserInfo.UserName + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
sysUserInfo.EMail,
|
sysUserInfo.EMail,
|
||||||
@@ -374,7 +387,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysCreateUser, messageToSend, emailConfigFunc, sysUserInfo.UserWorkLanguage);
|
||||||
|
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
@@ -385,6 +398,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).Include(t => t.UserRoleList).ThenInclude(c => c.UserTypeRole).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -393,13 +411,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置账户密码的提醒
|
//---[来自展影IRC] 关于重置账户密码的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
sysUserInfo.UserName,
|
sysUserInfo.UserName,
|
||||||
@@ -413,7 +431,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysResetPassword, messageToSend, emailConfigFunc, sysUserInfo.UserWorkLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
}
|
}
|
||||||
@@ -421,6 +439,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//用户重置邮箱
|
//用户重置邮箱
|
||||||
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
|
public async Task SendMailEditEmail(Guid userId, string userName, string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = _identityUserRepository.Where(t => t.Id == userId).Select(t => t.UserWorkLanguage).First();
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
@@ -430,13 +452,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
userName,
|
userName,
|
||||||
//---您正在进行邮箱重置操作
|
//---您正在进行邮箱重置操作
|
||||||
@@ -447,7 +469,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UserResetEmail, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
|
|
||||||
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
var sucessHandle = GetEmailSuccessHandle(userId, verificationCode, emailAddress);
|
||||||
@@ -460,6 +482,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//不登录 通过邮箱重置密码
|
//不登录 通过邮箱重置密码
|
||||||
public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode)
|
public async Task AnolymousSendEmailForResetAccount(string emailAddress, int verificationCode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var isEn_US = _userInfo.IsEn_Us;
|
||||||
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -467,13 +494,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
messageToSend.To.Add(new MailboxAddress(String.Empty, emailAddress));
|
||||||
|
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
"Sir/Madam",
|
"Sir/Madam",
|
||||||
//---您正在进行邮箱重置密码操作
|
//---您正在进行邮箱重置密码操作
|
||||||
@@ -484,7 +511,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.UnloginUseEmailResetPassword, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
////此时不知道用户
|
////此时不知道用户
|
||||||
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
var sucessHandle = GetEmailSuccessHandle(Guid.Empty, verificationCode, emailAddress);
|
||||||
@@ -500,6 +527,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -518,18 +550,18 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
@@ -544,9 +576,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,10 +587,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -575,20 +609,20 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
|
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
|
|
||||||
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
var redirectUrl = $"{domain}/api/User/UserRedirect?url={System.Web.HttpUtility.UrlEncode(routeUrl)}";
|
||||||
|
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
@@ -603,9 +637,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.SiteUseOrExternalUserFirstrJoinTrial : EmailBusinessScenario.SiteUserOrExternalUserExistJoinTrial, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,6 +678,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
saveItem.IsTestUser = true;
|
saveItem.IsTestUser = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//通过医生信息,设置工作语言
|
||||||
|
var nation = _doctorTypeRepository.Where(t => t.Id == doctorId).Select(t => t.Nation).FirstOrDefault();
|
||||||
|
saveItem.UserWorkLanguage = nation == DoctorNation.CN ? UserWorkLanguage.CN : UserWorkLanguage.US;
|
||||||
|
|
||||||
|
|
||||||
saveItem.UserCeateSource = UserCeateSource.ReviewerSelect;
|
saveItem.UserCeateSource = UserCeateSource.ReviewerSelect;
|
||||||
saveItem.TrialId = trialId;
|
saveItem.TrialId = trialId;
|
||||||
|
|
||||||
@@ -686,6 +726,11 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId);
|
||||||
|
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -701,7 +746,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
|
await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == sysUserInfo.Id, u => new Domain.Models.IdentityUser() { EmailToken = token });
|
||||||
}
|
}
|
||||||
|
|
||||||
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (_userInfo.IsEn_Us ? "en" : "zh") + "&access_token=" + token;
|
var routeUrl = rootUrl + "?UserId=" + sysUserInfo.Id + "&Email=" + sysUserInfo.EMail + "&lang=" + (isEn_US ? "en" : "zh") + "&access_token=" + token;
|
||||||
|
|
||||||
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
var domain = baseUrl.Substring(0, baseUrl.IndexOf("/login"));
|
||||||
|
|
||||||
@@ -711,13 +756,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
// $"[来自展影IRC] [{trialInfo.ResearchProgramNo}]邀请信";
|
||||||
|
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName,
|
sysUserInfo.FullName,
|
||||||
trialInfo.ExperimentName,
|
trialInfo.ExperimentName,
|
||||||
@@ -732,9 +777,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(sysUserInfo.IsFirstAdd ? EmailBusinessScenario.DoctorUserFirstJoinTrial : EmailBusinessScenario.DoctorUserExistJoinTrial, messageToSend, emailConfigFunc,workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo, null);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo, null);
|
||||||
|
|
||||||
//创建账号 和创建角色 一条,更新的时候才记录更新角色
|
//创建账号 和创建角色 一条,更新的时候才记录更新角色
|
||||||
if (isNeedCreateNewUser == false)
|
if (isNeedCreateNewUser == false)
|
||||||
@@ -754,6 +799,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUserRole.UserTypeRole).Include(t => t.CreateUserRole.IdentityUser).FirstNotNullAsync();
|
var feedBack = await _userFeedBackRepository.Where(t => t.Id == feedBackId).Include(t => t.CreateUserRole.UserTypeRole).Include(t => t.CreateUserRole.IdentityUser).FirstNotNullAsync();
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = _identityUserRepository.Where(t => t.Id == _userInfo.IdentityUserId).Select(t => t.UserWorkLanguage).First();
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -762,7 +811,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var trialinfo = await _trialRepository.Where(x => x.Id == feedBack.TrialId).FirstOrDefaultAsync();
|
var trialinfo = await _trialRepository.Where(x => x.Id == feedBack.TrialId).FirstOrDefaultAsync();
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack));
|
var emialScenario = feedBack.VisitTaskId != null ? EmailBusinessScenario.IRImageError : (feedBack.SubjectVisitId != null ? EmailBusinessScenario.TrialSubjectVisitFeedBack : (feedBack.TrialId != null ? EmailBusinessScenario.TrialFeedBack : EmailBusinessScenario.SysFeedBack));
|
||||||
|
|
||||||
@@ -785,7 +834,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
if (feedBack.VisitTaskId != null)
|
if (feedBack.VisitTaskId != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "FeedBackTypeToIR" && t.ParentId != null && t.Code == ((int)feedBack.QuestionType).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "FeedBackTypeToIR" && t.ParentId != null && t.Code == ((int)feedBack.QuestionType).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync();
|
var info = await _visitTaskRepository.Where(t => t.Id == feedBack.VisitTaskId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.SourceSubjectVisit.VisitName }).FirstNotNullAsync();
|
||||||
@@ -794,7 +843,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userNames,
|
userNames,
|
||||||
info.TrialCode,
|
info.TrialCode,
|
||||||
info.SubejctCode,
|
info.SubejctCode,
|
||||||
@@ -810,12 +859,12 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IRImageError, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (feedBack.SubjectVisitId != null)
|
else if (feedBack.SubjectVisitId != null)
|
||||||
{
|
{
|
||||||
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialSubjectVisitFeedBack).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync();
|
var info = await _subjectVisitRepository.Where(t => t.Id == feedBack.SubjectVisitId).Select(t => new { t.Trial.ResearchProgramNo, t.Trial.TrialCode, SubejctCode = t.Subject.Code, t.VisitName }).FirstNotNullAsync();
|
||||||
@@ -824,7 +873,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo, info.SubejctCode, info.VisitName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userNames,
|
userNames,
|
||||||
info.TrialCode,
|
info.TrialCode,
|
||||||
info.SubejctCode,
|
info.SubejctCode,
|
||||||
@@ -840,13 +889,13 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialSubjectVisitFeedBack, messageToSend, emailConfigFunc, workLanguage);
|
||||||
}
|
}
|
||||||
//项目相关的反馈 pm admin
|
//项目相关的反馈 pm admin
|
||||||
else if (feedBack.TrialId != null)
|
else if (feedBack.TrialId != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => _userInfo.IsEn_Us ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
var emailType = await _dictionaryRepository.Where(t => t.Parent.Code == "Email_BusinessScenario" && t.ParentId != null && t.Code == ((int)EmailBusinessScenario.TrialFeedBack).ToString()).Select(t => isEn_US ? t.Value : t.ValueCN).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
||||||
var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync();
|
var info = await _trialRepository.Where(t => t.Id == feedBack.TrialId).Select(t => new { t.ResearchProgramNo, t.TrialCode }).FirstNotNullAsync();
|
||||||
@@ -855,7 +904,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, info.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userNames,
|
userNames,
|
||||||
info.TrialCode,
|
info.TrialCode,
|
||||||
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
|
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
|
||||||
@@ -869,7 +918,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.TrialFeedBack, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
}
|
}
|
||||||
//项目无关的反馈 admin
|
//项目无关的反馈 admin
|
||||||
@@ -881,7 +930,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr);
|
var topicStr = string.Format(input.topicStr);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
userNames,
|
userNames,
|
||||||
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
|
feedBack.CreateUserRole.UserTypeRole.UserTypeShortName,
|
||||||
feedBack.CreateUserRole.IdentityUser.FullName,
|
feedBack.CreateUserRole.IdentityUser.FullName,
|
||||||
@@ -893,7 +942,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SysFeedBack, messageToSend, emailConfigFunc, workLanguage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trialinfo == null)
|
if (trialinfo == null)
|
||||||
@@ -902,9 +951,9 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialinfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,6 +964,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
var sysUserInfo = (await _identityUserRepository.Where(t => t.Id == userId).FirstOrDefaultAsync()).IfNullThrowException();
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var workLanguage = sysUserInfo.UserWorkLanguage;
|
||||||
|
var isEn_US = workLanguage == UserWorkLanguage.US;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -923,22 +976,23 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
var topicStr = string.Format(input.topicStr, companyName);
|
var topicStr = string.Format(input.topicStr, companyName);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplacePlatformName(ReplaceCompanyName(input.htmlBodyStr)) ,
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
|
|
||||||
sysUserInfo.FullName
|
sysUserInfo.FullName,
|
||||||
|
_systemEmailConfig.PlatformName
|
||||||
);
|
);
|
||||||
|
|
||||||
return (topicStr, htmlBodyStr);
|
return (topicStr, htmlBodyStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IdentityUser_ModifyPassword, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.IdentityUser_ModifyPassword, messageToSend, emailConfigFunc, workLanguage);
|
||||||
|
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig);
|
||||||
}
|
}
|
||||||
@@ -948,6 +1002,10 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
{
|
{
|
||||||
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync();
|
var trialInfo = await _trialRepository.Where(t => t.Id == trialId).FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var isEn_US = _userInfo.IsEn_Us;
|
||||||
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -956,14 +1014,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
name,
|
name,
|
||||||
trialInfo.TrialCode,
|
trialInfo.TrialCode,
|
||||||
trialInfo.ResearchProgramNo
|
trialInfo.ResearchProgramNo
|
||||||
@@ -974,14 +1032,20 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_CheckUser, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_CheckUser, messageToSend, emailConfigFunc);
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url)
|
public async Task SiteSuervyUpdateUser(Guid trialSiteId, string email, string name, string url)
|
||||||
{
|
{
|
||||||
var siteInfo = await _trialSiteRepository.Where(t => t.Id == trialSiteId).Include(x=>x.Trial).FirstOrDefaultAsync();
|
var siteInfo = await _trialSiteRepository.Where(t => t.Id == trialSiteId).Include(x => x.Trial).FirstOrDefaultAsync();
|
||||||
|
|
||||||
var trialInfo = siteInfo.Trial;
|
var trialInfo = siteInfo.Trial;
|
||||||
|
|
||||||
|
|
||||||
|
//设置工作语言
|
||||||
|
var isEn_US = _userInfo.IsEn_Us;
|
||||||
|
var workLanguage = isEn_US ? UserWorkLanguage.US : UserWorkLanguage.CN;
|
||||||
|
|
||||||
var messageToSend = new MimeMessage();
|
var messageToSend = new MimeMessage();
|
||||||
//发件地址
|
//发件地址
|
||||||
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail));
|
||||||
@@ -990,14 +1054,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//主题
|
//主题
|
||||||
//---[来自展影IRC] 关于重置邮箱的提醒
|
//---[来自展影IRC] 关于重置邮箱的提醒
|
||||||
|
|
||||||
var companyName = _userInfo.IsEn_Us ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
var companyName = isEn_US ? _systemEmailConfig.CompanyShortName : _systemEmailConfig.CompanyShortNameCN;
|
||||||
|
|
||||||
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
var topicStr = string.Format(input.topicStr, companyName, trialInfo.ResearchProgramNo);
|
||||||
|
|
||||||
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
|
var htmlBodyStr = string.Format(CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr, workLanguage),
|
||||||
name,
|
name,
|
||||||
trialInfo.TrialCode,
|
trialInfo.TrialCode,
|
||||||
siteInfo.TrialSiteCode,
|
siteInfo.TrialSiteCode,
|
||||||
@@ -1010,7 +1074,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
|
|
||||||
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_UpdateUser, messageToSend, emailConfigFunc);
|
await GetEmailSubejctAndHtmlInfoAndBuildAsync(EmailBusinessScenario.SiteSurvey_UpdateUser, messageToSend, emailConfigFunc);
|
||||||
await SendEmailHelper.SendEmailAsync(messageToSend, trialInfo);
|
await SendEmailHelper.SendTrialEmailAsync(messageToSend, trialInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
|
|
||||||
CreateMap<EmailLog, GetEmailInfoOutDto>()
|
CreateMap<EmailLog, GetEmailInfoOutDto>()
|
||||||
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList))
|
.ForMember(t => t.RecipientList, u => u.MapFrom(c => c.EmailRecipientLogList))
|
||||||
.ForMember(t => t.AttachmentList, u => u.MapFrom(c => c.AttachmentList));
|
.ForMember(t => t.AttachmentList, u => u.MapFrom(c => c.AttachmentList));
|
||||||
|
|
||||||
CreateMap<EmailLog, EmailLogAddOrEdit>().ReverseMap();
|
CreateMap<EmailLog, EmailLogAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.ForMember(t => t.EmailNoticeUserList, u => u.MapFrom(c => c.EmailNoticeUserTypeList));
|
.ForMember(t => t.EmailNoticeUserList, u => u.MapFrom(c => c.EmailNoticeUserTypeList));
|
||||||
|
|
||||||
CreateMap<EmailNoticeConfig, EmailNoticeConfigExportDto>();
|
CreateMap<EmailNoticeConfig, EmailNoticeConfigExportDto>();
|
||||||
|
|
||||||
|
|
||||||
CreateMap<Dictionary, DicView>()
|
CreateMap<Dictionary, DicView>()
|
||||||
.ForMember(t => t.ParentCode, u => u.MapFrom(c => c.Parent.Code));
|
.ForMember(t => t.ParentCode, u => u.MapFrom(c => c.Parent.Code));
|
||||||
@@ -89,14 +89,14 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
CreateMap<Internationalization, InternationalizationAddOrEdit>().ReverseMap();
|
CreateMap<Internationalization, InternationalizationAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<InternationalizationAddOrEdit, IRCGlobalInfoDTO>();
|
CreateMap<InternationalizationAddOrEdit, IRCGlobalInfoDTO>();
|
||||||
|
|
||||||
|
|
||||||
CreateMap<Internationalization, BatchInternationalizationDto>().ReverseMap();
|
CreateMap<Internationalization, BatchInternationalizationDto>().ReverseMap();
|
||||||
|
|
||||||
CreateMap<Internationalization, IRCGlobalInfoDTO>();
|
CreateMap<Internationalization, IRCGlobalInfoDTO>();
|
||||||
|
|
||||||
CreateMap<EventStoreRecord, EventStoreRecordView>();
|
CreateMap<EventStoreRecord, EventStoreRecordView>();
|
||||||
|
|
||||||
CreateMap<BatchAddInternationalizationDto, InternationalizationAddOrEdit>();
|
CreateMap<BatchAddInternationalizationDto, InternationalizationAddOrEdit>();
|
||||||
|
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.Subject.TrialSite.TrialSiteCode));
|
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.Subject.TrialSite.TrialSiteCode));
|
||||||
|
|
||||||
|
|
||||||
CreateMap<TumorExportBaseModel , TU_Export>();
|
CreateMap<TumorExportBaseModel, TU_Export>();
|
||||||
CreateMap<TumorExportBaseModel, TR_Export>();
|
CreateMap<TumorExportBaseModel, TR_Export>();
|
||||||
CreateMap<TumorExportBaseModel, RS_Export>();
|
CreateMap<TumorExportBaseModel, RS_Export>();
|
||||||
CreateMap<TumorExportBaseModel, CO_Export>();
|
CreateMap<TumorExportBaseModel, CO_Export>();
|
||||||
@@ -124,6 +124,26 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
CreateMap<IVUS_OCTBaseDto, IvusExportDto>();
|
CreateMap<IVUS_OCTBaseDto, IvusExportDto>();
|
||||||
CreateMap<IVUS_OCTBaseDto, OctExportDto>();
|
CreateMap<IVUS_OCTBaseDto, OctExportDto>();
|
||||||
|
|
||||||
|
|
||||||
|
CreateMap<FileUploadRecord, FileUploadRecordView>()
|
||||||
|
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code))
|
||||||
|
.ForMember(d => d.VisitName, u => u.MapFrom(s => s.SubjectVisit.VisitName));
|
||||||
|
CreateMap<FileUploadRecord, FileUploadRecordAddOrEdit>().ReverseMap();
|
||||||
|
|
||||||
|
|
||||||
|
CreateMap<CommonUploadRecordAddOrEdit, CommonUploadRecord>().ReverseMap();
|
||||||
|
|
||||||
|
CreateMap<CommonUploadRecord, CommonUploadRecordDto>();
|
||||||
|
|
||||||
|
|
||||||
|
CreateMap<UploadFileSyncRecord, UploadFileSyncRecordView>()
|
||||||
|
.ForMember(d => d.FileName, u => u.MapFrom(s => s.FileUploadRecord.FileName))
|
||||||
|
.ForMember(d => d.FileType, u => u.MapFrom(s => s.FileUploadRecord.FileType))
|
||||||
|
.ForMember(d => d.Path, u => u.MapFrom(s => s.FileUploadRecord.Path))
|
||||||
|
.ForMember(d => d.StudyCode, u => u.MapFrom(s => s.FileUploadRecord.StudyCode))
|
||||||
|
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.FileUploadRecord.Subject.Code))
|
||||||
|
.ForMember(d => d.VisitName, u => u.MapFrom(s => s.FileUploadRecord.SubjectVisit.VisitName));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace IRaCIS.Application.Contracts
|
|||||||
|
|
||||||
public bool? AcceptingNewTrial { get; set; }//是否接受新的项目
|
public bool? AcceptingNewTrial { get; set; }//是否接受新的项目
|
||||||
public bool? ActivelyReading { get; set; }// 是否接受新的读片任务
|
public bool? ActivelyReading { get; set; }// 是否接受新的读片任务
|
||||||
public int? Nation { get; set; }// 0-中国医生,2-美国医生,3-全部
|
public DoctorNation? Nation { get; set; }// 0-中国医生,2-美国医生,3-全部
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ namespace IRaCIS.Core.Application.Service
|
|||||||
//重新插入新的 Title记录
|
//重新插入新的 Title记录
|
||||||
updateModel.TitleIds.ForEach(titleId => adddata.Add(new DoctorDictionary() { DoctorId = updateModel.Id.Value, KeyName = StaticData.Title, DictionaryId = titleId }));
|
updateModel.TitleIds.ForEach(titleId => adddata.Add(new DoctorDictionary() { DoctorId = updateModel.Id.Value, KeyName = StaticData.Title, DictionaryId = titleId }));
|
||||||
|
|
||||||
|
indto.ReviewerCode = doctor.ReviewerCode;
|
||||||
await _doctorDictionaryRepository.AddRangeAsync(adddata);
|
await _doctorDictionaryRepository.AddRangeAsync(adddata);
|
||||||
|
|
||||||
_mapper.Map(indto, doctor);
|
_mapper.Map(indto, doctor);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user