Compare commits
602 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ecaf5e267 | |||
| 1ca4fb7dd4 | |||
| cb2fed1ad2 | |||
| 4c642cd814 | |||
| 9dcbad7616 | |||
| 197b3213e7 | |||
| 3bfda749d8 | |||
| 6f911d0d74 | |||
| 78f4a78994 | |||
| 4e1911223d | |||
| 7dd02e84aa | |||
| 7f260799d8 | |||
| 06c7a8126b | |||
| 78624d9cce | |||
| 6ecc0e58e9 | |||
| 84a81e1851 | |||
| b09209af31 | |||
| 9892070ccc | |||
| 63cbc8746f | |||
| fe64feac80 | |||
| dce7fd9737 | |||
| 6187c585ad | |||
| 22ac496d7b | |||
| 45c0e5030b | |||
| 36e23b8135 | |||
| b530f68446 | |||
| 383bfabae8 | |||
| 196ed7f993 | |||
| 70cc0027cd | |||
| 975b7d39a7 | |||
| 21bcd1fddb | |||
| 04bbde8583 | |||
| f3c4bedbfd | |||
| 835aedc800 | |||
| 9026b1d7fd | |||
| b8f96efa66 | |||
| 4c4f68dbd0 | |||
| 11c56d2f7a | |||
| a72521304e | |||
| 8baf6cb88f | |||
| 71e04c3bf1 | |||
| 1af9b48622 | |||
| 447b74fa55 | |||
| c633fbcf87 | |||
| 1cc57ad1d6 | |||
| f282fdfabc | |||
| d77c6ecf03 | |||
| 1db75cf4f7 | |||
| 7bc70bfd6c | |||
| 69ba30e5a9 | |||
| 18482ddaa9 | |||
| 14e2afcfee | |||
| 39dadbbf47 | |||
| d0ba340fea | |||
| 28ac64747b | |||
| 5e014120c1 | |||
| 76a937066d | |||
| 414af5db9e | |||
| 8cc04c8bcf | |||
| 3592fe7ec7 | |||
| 22705f6035 | |||
| 698dca94d4 | |||
| e1f3669aab | |||
| 8f2109b4cd | |||
| 433cfdc123 | |||
| a278b032e2 | |||
| 2ec96a82f0 | |||
| b7b763651f | |||
| a07cf5f4d0 | |||
| 77f0c91e74 | |||
| 54e9e6f6ad | |||
| ba71d73407 | |||
| 9a64fd1bfd | |||
| 9b7d9d3c88 | |||
| 5ec234c9dd | |||
| 4709125107 | |||
| 0bbf537ddf | |||
| aba5dec904 | |||
| b04530ddd2 | |||
| 27bacd95d2 | |||
| 9385b1f671 | |||
| cdcc98efeb | |||
| bb00ac10f8 | |||
| e184b5255d | |||
| 095536ca33 | |||
| 83a1d2d5a4 | |||
| e91ce47f28 | |||
| 02b153c524 | |||
| 2b93fd18ff | |||
| c80e7ca5a9 | |||
| e7562fbe83 | |||
| 92da42f010 | |||
| 92bc105281 | |||
| 105bd48201 | |||
| d57c3b5157 | |||
| 30fdd91764 | |||
| f03db6f995 | |||
| 022a2005f1 | |||
| e64498858d | |||
| ffbf12f845 | |||
| c0523e2855 | |||
| 794ebeb42c | |||
| ffdf3d2376 | |||
| f69a297b2b | |||
| 39bd20e880 | |||
| 8a5be1a0ea | |||
| b6f8b41615 | |||
| bddcadeb89 | |||
| 2e388db02c | |||
| 370f99eabc | |||
| e2bd9feae6 | |||
| abbc15cb09 | |||
| 87f088ac05 | |||
| 0971f2b922 | |||
| e93be4cf9c | |||
| 2fca310327 | |||
| 97411b7eaf | |||
| 0631af4d9b | |||
| 2794cabdc8 | |||
| 8203b3d738 | |||
| 4d16ebb488 | |||
| b241682fa9 | |||
| cb16658190 | |||
| 8b766672b5 | |||
| b7d45456a6 | |||
| a4241bccf7 | |||
| 212a545aa9 | |||
| 11c4df2852 | |||
| 05bcb982dd | |||
| af62056962 | |||
| de7cd64c9b | |||
| 83f73db692 | |||
| 71418c393e | |||
| 6629fc0a17 | |||
| b7c00a0b70 | |||
| 3907123c1d | |||
| e1822126bb | |||
| 05e9bbb050 | |||
| 6b1fffb800 | |||
| d0d8819ab4 | |||
| 0e430ef8c9 | |||
| 0b87a1845c | |||
| e7a13be6e4 | |||
| f7b5ab0281 | |||
| e3be28ca17 | |||
| ee34e6cdc2 | |||
| 8c83897c6e | |||
| 3a6956c031 | |||
| 73e7b4c3fa | |||
| 7f9080398a | |||
| 4c7c0cce47 | |||
| eda4b31dda | |||
| dc84d0e96f | |||
| 7fea4b938f | |||
| 7325760c23 | |||
| 1a26d3885a | |||
| f9c9d0be6d | |||
| ebfbe27d0c | |||
| 37257da722 | |||
| 6d214727b5 | |||
| 1db50cff3b | |||
| 6d17a1f3cd | |||
| f38f1f465a | |||
| db627afeda | |||
| fef7215bdb | |||
| 0718a70f91 | |||
| da21972c63 | |||
| 361ab4e2fd | |||
| 7a52507d27 | |||
| 83dc28008f | |||
| 323b76036a | |||
| 4b7bb8df95 | |||
| 46aa64365f | |||
| d2fae40100 | |||
| 4030b1c95b | |||
| d689c23f5a | |||
| 4a7f8a0a93 | |||
| 7daa7fda0c | |||
| b25426711a | |||
| f06f7827cf | |||
| 3ea46b5d1e | |||
| 72634c785d | |||
| 2dbf6a1fb3 | |||
| 755f305389 | |||
| 29a6870fb5 | |||
| 2d99e074b8 | |||
| 6e6e2d11d0 | |||
| 6b8711232e | |||
| eb0b9d6fb8 | |||
| 7ef1cafeff | |||
| 3ac3e41d0d | |||
| 1763e49650 | |||
| 016a5e93ea | |||
| e4d731222b | |||
| aeeba1dfb7 | |||
| d7ebed0b05 | |||
| 312e85d9b3 | |||
| 3ee32c2e56 | |||
| 2778b34f14 | |||
| 6736121309 | |||
| e48c00f817 | |||
| e5f7ad3b31 | |||
| b7a0a336dd | |||
| d83a086087 | |||
| d03ce19b02 | |||
| a2668b39be | |||
| a30fd58d79 | |||
| 31d0872653 | |||
| e63e38222e | |||
| 65d7a95d5f | |||
| 298619717a | |||
| d6713ba9a4 | |||
| 0e252b0377 | |||
| 52ab454860 | |||
| 0e2e57446b | |||
| 94b0354fe4 | |||
| 93ed9943fa | |||
| e04e94a792 | |||
| b7c57c3c27 | |||
| 015eb78b70 | |||
| 04580ed1bb | |||
| b6877d4fe8 | |||
| b53f566160 | |||
| c767004a2d | |||
| 3a546e6e89 | |||
| 6af2f0555e | |||
| a82526e21d | |||
| c65ad92d39 | |||
| 36d5661044 | |||
| feb94dc832 | |||
| 756750783c | |||
| db3f7b4cde | |||
| a9d62cf28d | |||
| 04014ab524 | |||
| 2a68b40875 | |||
| 375a7e7071 | |||
| efc3b03392 | |||
| 730a375509 | |||
| d34b4b796c | |||
| 427f060935 | |||
| 6a10cb1afe | |||
| 962ac2e693 | |||
| 3567f2d625 | |||
| bd980cd867 | |||
| 284432ffa4 | |||
| 16e2fbc8ff | |||
| ac6be424ee | |||
| 351b2a627f | |||
| dd919f123e | |||
| 3a33abf02e | |||
| 917373e081 | |||
| 632463327c | |||
| 59a14c0e37 | |||
| 511640f66f | |||
| c26f5df102 | |||
| 98e9af71a3 | |||
| b59e0c12f6 | |||
| fed2677689 | |||
| a55278e323 | |||
| 8f808d73b5 | |||
| 717c5a6529 | |||
| ec676d8d2b | |||
| 2ce14c6d72 | |||
| 10b5bba0dd | |||
| 159a36cd70 | |||
| 4a17946598 | |||
| d6f36cbbda | |||
| e6a15e35f6 | |||
| 27a9ccd3c2 | |||
| e8dda21459 | |||
| 7ebbfb9621 | |||
| 9da7c1a159 | |||
| 197f17fc99 | |||
| d680c57482 | |||
| 7266d0a4f5 | |||
| 3e19e85a8d | |||
| c9057e12cd | |||
| 10bac01371 | |||
| 67d54aedb7 | |||
| 1a21aa38f3 | |||
| 64f0998896 | |||
| 04d9a53a0e | |||
| fd0412004e | |||
| 64ef1e513c | |||
| a83349387a | |||
| 9500842628 | |||
| 998e340919 | |||
| 753127381f | |||
| a5c3dac047 | |||
| a7337a347b | |||
| 85b88d4564 | |||
| 763e00a6ca | |||
| 6a345e35cd | |||
| 09e9c62f3c | |||
| af97e2b4ed | |||
| e0dd443d84 | |||
| 1c0cdde9ad | |||
| e100d45bc1 | |||
| 49c7482d76 | |||
| 22b77ff70f | |||
| 3a35f4a966 | |||
| 8ff9e3b232 | |||
| e189080e5c | |||
| 07b1e5d1f9 | |||
| 2f92bf6dfb | |||
| 391e696d8a | |||
| 9ff7928b16 | |||
| 3c0971e961 | |||
| 1f20834dd3 | |||
| f34665fcb9 | |||
| 00e03c782d | |||
| 5e6c8e6936 | |||
| cd2c56c510 | |||
| ec7cb78018 | |||
| 6a65b6507f | |||
| d08df877d7 | |||
| 10a43d4c04 | |||
| a87769a60f | |||
| 4d808ed87c | |||
| 0a3a4e3bb4 | |||
| 0aab18924b | |||
| 2bf9b21f40 | |||
| 06d0ce2290 | |||
| 1b6e53819c | |||
| a59509dd7d | |||
| d88f7c43b2 | |||
| c3543e19c8 | |||
| 72b1a3906d | |||
| 06794447ec | |||
| 00c5570692 | |||
| cd2df6e576 | |||
| 52f9c17234 | |||
| 0b78561331 | |||
| c12da4de3e | |||
| 4f16060a46 | |||
| 212bd65bc1 | |||
| afc35daffa | |||
| 5bf8e7ecf6 | |||
| 192f7a3316 | |||
| d88535b75e | |||
| 128cdc0f75 | |||
| 4a8b1da094 | |||
| 728f3238ca | |||
| e245057bb2 | |||
| 7bf80c10eb | |||
| ecf4c8a2c7 | |||
| c532babf98 | |||
| 2fa54eaac6 | |||
| 50de867772 | |||
| 24a48e3d23 | |||
| 13429f45ed | |||
| 8545e8f1d6 | |||
| 619a7b2ee3 | |||
| 544f83d118 | |||
| 1541e3d353 | |||
| 7a454d09ff | |||
| 06f52f4f24 | |||
| 877e47ccb1 | |||
| c373b59f23 | |||
| 73e8f24c3d | |||
| 1e57777d3b | |||
| aca7f07d00 | |||
| 35e52fbdcf | |||
| aaeadbc440 | |||
| 60d3dfa6e7 | |||
| 417fefb04b | |||
| 27646e2c46 | |||
| 48b154bf87 | |||
| acfa552cbe | |||
| aa6a226ce1 | |||
| 09144f2b98 | |||
| 9b8c6788bf | |||
| 4aa1a05ea9 | |||
| 45790141df | |||
| 6804d909b8 | |||
| 1a1bf6810c | |||
| c9e7719c71 | |||
| 07b23fce1d | |||
| 9f5cbad22e | |||
| 3cf4f95770 | |||
| 5a01f10957 | |||
| 4ed0ebc913 | |||
| 9971c3ecca | |||
| 3c10ae73dd | |||
| 5cbd13cc3d | |||
| 7dcc524bd3 | |||
| bc4639a238 | |||
| 0f25958d9b | |||
| ff0d204612 | |||
| 91386589ae | |||
| b2a9f279a1 | |||
| b4fc5d970f | |||
| e046bffdbd | |||
| 38ea9ddb0b | |||
| 1194e56139 | |||
| 741c723bab | |||
| fea0047f58 | |||
| 5a943fbefe | |||
| 6c88af0a03 | |||
| 26412931a9 | |||
| 5a1b64a023 | |||
| 64d8c853b3 | |||
| 0261fb04c6 | |||
| ab372a9c29 | |||
| f7dd68f7f3 | |||
| 946203f124 | |||
| f0eb814492 | |||
| 6c36c48b82 | |||
| 47b05526a2 | |||
| f7afca6e73 | |||
| 04aa61658c | |||
| 86c506bc1d | |||
| 06959b4465 | |||
| 838ab975cc | |||
| 7aa33672a9 | |||
| 81297954d3 | |||
| 25e348f428 | |||
| c101302cca | |||
| c4fd8c3ea3 | |||
| a7e7419a20 | |||
| 55da1d9219 | |||
| 2a842fd2f8 | |||
| ca2e9e0253 | |||
| b4c06990f6 | |||
| 599fad48ba | |||
| 72b5d515ba | |||
| 608bd42836 | |||
| 040f66f182 | |||
| 7afbc360e5 | |||
| 74c5d032fb | |||
| 43aa371c36 | |||
| 398ec90fae | |||
| 890910a763 | |||
| 3b5ebfcba1 | |||
| b971235164 | |||
| e53a18f212 | |||
| 774f43a6d0 | |||
| 88f274ab89 | |||
| 3345a989ae | |||
| 11000ef9f8 | |||
| 57be74aea8 | |||
| 8724eeeafb | |||
| 7c71a6d342 | |||
| cb04be1b56 | |||
| 63709b414d | |||
| 7001bc9ec0 | |||
| c12833d283 | |||
| 22baa213ae | |||
| 09c1c3ff12 | |||
| 94f43f4b11 | |||
| 1a42cfd47c | |||
| b6b918efbf | |||
| a16d86d942 | |||
| 266698cc79 | |||
| eac6b25b9e | |||
| 47d7fb00e2 | |||
| 312ab754e1 | |||
| 0ff5a21d04 | |||
| 5a7fa1fb77 | |||
| 5289c156c0 | |||
| a68c27fd43 | |||
| 641c2e6ade | |||
| 5b4cc097bc | |||
| b1de662677 | |||
| d2d1063ed5 | |||
| 2bc4b32d3a | |||
| 366ec62cd7 | |||
| 866e2e5c6b | |||
| 16e2db37cd | |||
| ee6c5bf8a5 | |||
| 48cfe99f12 | |||
| f65264a2a6 | |||
| 769c5f8440 | |||
| 6321bddfd3 | |||
| e30fb2a041 | |||
| 478adcde21 | |||
| 34ce5142f2 | |||
| 3b993bcd46 | |||
| 3f2e39f46c | |||
| d317402f85 | |||
| 6cb63bdc59 | |||
| 8db641db16 | |||
| 9da9515930 | |||
| 2be119de6b | |||
| c9f9615488 | |||
| be137b3840 | |||
| d80101f86b | |||
| 3c0b084f7e | |||
| 8a88a64c36 | |||
| 3d538d6e67 | |||
| 67d2a83ec8 | |||
| 2efb229c96 | |||
| c930480336 | |||
| b39ea3a032 | |||
| ff5aea17a5 | |||
| 477b6935ff | |||
| 8b6432ad14 | |||
| ca35fe6df4 | |||
| 307c02725f | |||
| 72d0494baa | |||
| d1017bc565 | |||
| 76e6ef087f | |||
| c5c9e4364c | |||
| 920d0b21c6 | |||
| 3fe16b4166 | |||
| bc2d5463ff | |||
| c63811d55c | |||
| 832fa82d4b | |||
| b3ae801fe9 | |||
| 0dbd74270d | |||
| aae5968d74 | |||
| 79a7ad0cf7 | |||
| a35309d9b5 | |||
| a987ac086b | |||
| fdc2bc5f8a | |||
| 84f68c79f0 | |||
| b77dc34523 | |||
| 91554e0e30 | |||
| 2efb7fd36a | |||
| dbdec93efc | |||
| e631ce73f2 | |||
| 5931dcdc67 | |||
| b55ffc0821 | |||
| 8600054405 | |||
| 9a88539294 | |||
| 09211c8841 | |||
| 2724e0267f | |||
| a0e355d69b | |||
| 04a0a1ccc3 | |||
| c3e967acaa | |||
| 740a0aa221 | |||
| e8f95d09ba | |||
| 2c305af49e | |||
| 5c76bda1e7 | |||
| 0273601f7b | |||
| c3a154f762 | |||
| cdb97f6405 | |||
| 4794429a57 | |||
| 77a633d699 | |||
| 64d1ebf350 | |||
| 5336cb5353 | |||
| 0a288b9f47 | |||
| 674d483cbf | |||
| cbcb396441 | |||
| 9a3e972723 | |||
| b593615e9e | |||
| d30c9a5f3b | |||
| dd3d738eed | |||
| d9edaf4c27 | |||
| a5e0dd89ff | |||
| 73f8f816b7 | |||
| 19d5144b70 | |||
| e0ecd3f4ac | |||
| 30e0e374bc | |||
| 25b909c660 | |||
| 5cb3e8e606 | |||
| 619af2e874 | |||
| 43f1736b05 | |||
| c9be5678bd | |||
| 4e5ecb3938 | |||
| 7870c3d74b | |||
| d07adc4948 | |||
| 266886fa64 | |||
| e012eba0c2 | |||
| 75d296405b | |||
| 07c92c48a4 | |||
| b5427dd17b | |||
| 385643643e | |||
| 756f1293aa | |||
| eee19f0ae9 | |||
| 78c0910db7 | |||
| 18a71725f9 | |||
| 87332ae9d8 | |||
| 401762dca7 | |||
| 7b694d4afb | |||
| 6e285d900b | |||
| c5d3b44c2c | |||
| cf4dbc2914 | |||
| 3cef5afebd | |||
| 060b61eafb | |||
| 0d3571f672 | |||
| 8b3bd101b6 | |||
| da252ae4df | |||
| fdb7251b62 | |||
| 1f51bbd178 | |||
| 597ca07fcf | |||
| b43c75dd9f | |||
| 94f3e6c757 | |||
| 1d95cd15f2 | |||
| a1f9283262 | |||
| a0abba71dd | |||
| 02d85e19a6 | |||
| 9ad916f860 | |||
| e0094c01d8 | |||
| 0eb2135185 | |||
| 8ddfe34f72 | |||
| c603d10ff5 | |||
| 3fca2e76cb | |||
| c0ae4732fc | |||
| 4ec0a178b4 | |||
| 443a31df97 | |||
| d21c01076d |
@@ -1,4 +1,39 @@
|
|||||||
|
|
||||||
|
kind: pipeline
|
||||||
|
type: ssh
|
||||||
|
name: ssh-linux-uat-irc-publish
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: Linux
|
||||||
|
arch: 386
|
||||||
|
|
||||||
|
clone:
|
||||||
|
disable: true #禁用默认克隆
|
||||||
|
|
||||||
|
server:
|
||||||
|
host: 101.132.253.119
|
||||||
|
user: root
|
||||||
|
password:
|
||||||
|
from_secret: local_pwd
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: publish-uat-irc-web
|
||||||
|
commands:
|
||||||
|
- bash /opt/1panel/xc-deploy-new/devops-center/build-vue-then-publish.sh IRC_Web uat --mode uat
|
||||||
|
- name: notify-wecom
|
||||||
|
commands:
|
||||||
|
- echo $DRONE_COMMIT_AUTHOR "$DRONE_COMMIT_MESSAGE"
|
||||||
|
- bash /opt/1panel/xc-deploy-new/devops-center/drone-notify-wecom.sh "$DRONE_BUILD_STATUS" "$DRONE_REPO_NAME" "$DRONE_BRANCH" "$DRONE_BUILD_NUMBER" "4355b98e-1e72-4678-8dfb-2fc6ad0bf449" "$DRONE_COMMIT_MESSAGE" "$DRONE_COMMIT_AUTHOR" "Uat_IRC_WEB" "irc.uat.extimaging.com"
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
- failure
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- uat
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: ssh
|
type: ssh
|
||||||
name: ssh-linux-test-irc-publish
|
name: ssh-linux-test-irc-publish
|
||||||
@@ -33,6 +68,3 @@ trigger:
|
|||||||
- main
|
- main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -9,24 +9,25 @@
|
|||||||
"build:usa": "vue-cli-service build --mode usa",
|
"build:usa": "vue-cli-service build --mode usa",
|
||||||
"build:usa_prod": "vue-cli-service build --mode usa_prod",
|
"build:usa_prod": "vue-cli-service build --mode usa_prod",
|
||||||
"pre": "vue-cli-service build --mode pre",
|
"pre": "vue-cli-service build --mode pre",
|
||||||
|
"postinstall": "patch-package",
|
||||||
"i18n": "npm run i18n:zh && npm run i18n:en",
|
"i18n": "npm run i18n:zh && npm run i18n:en",
|
||||||
"i18n:zh": "node i18nGenerate.js lang=zh keyCol=5 valCol=6",
|
"i18n:zh": "node i18nGenerate.js lang=zh keyCol=5 valCol=6",
|
||||||
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
|
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.701.0",
|
"@aws-sdk/client-s3": "3.726.1",
|
||||||
"@cornerstonejs/adapters": "^2.19.7",
|
"@cornerstonejs/adapters": "^4.19.2",
|
||||||
"@cornerstonejs/calculate-suv": "^1.1.0",
|
"@cornerstonejs/calculate-suv": "^1.1.0",
|
||||||
"@cornerstonejs/core": "^2.19.7",
|
"@cornerstonejs/core": "^4.19.2",
|
||||||
"@cornerstonejs/dicom-image-loader": "^2.19.7",
|
"@cornerstonejs/dicom-image-loader": "^4.19.2",
|
||||||
"@cornerstonejs/tools": "^2.19.7",
|
"@cornerstonejs/polymorphic-segmentation": "^4.19.2",
|
||||||
|
"@cornerstonejs/tools": "^4.19.2",
|
||||||
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
||||||
"@icr/polyseg-wasm": "^0.4.0",
|
"@icr/polyseg-wasm": "^0.4.0",
|
||||||
"@microsoft/signalr": "^8.0.7",
|
"@microsoft/signalr": "^8.0.7",
|
||||||
"@riophae/vue-treeselect": "^0.4.0",
|
"@riophae/vue-treeselect": "^0.4.0",
|
||||||
"@vue-office/docx": "^1.6.2",
|
"@vue-office/docx": "^1.6.2",
|
||||||
"@vue-office/excel": "^1.7.11",
|
"@vue-office/excel": "^1.7.11",
|
||||||
"@vue/composition-api": "^1.7.2",
|
|
||||||
"ali-oss": "^6.17.1",
|
"ali-oss": "^6.17.1",
|
||||||
"axios": "^0.18.1",
|
"axios": "^0.18.1",
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
@@ -38,7 +39,8 @@
|
|||||||
"dcmjs": "^0.29.8",
|
"dcmjs": "^0.29.8",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"dicomedit": "^0.1.0",
|
"dicomedit": "^0.1.0",
|
||||||
"echarts": "^4.8.0",
|
"echarts": "^6.0.0",
|
||||||
|
"echarts-map": "^3.0.1",
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
@@ -60,11 +62,10 @@
|
|||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.5",
|
"sortablejs": "^1.15.5",
|
||||||
"streamsaver": "^2.0.6",
|
"streamsaver": "^2.0.6",
|
||||||
"svg-sprite-loader": "^4.1.3",
|
|
||||||
"svgo": "^1.2.2",
|
"svgo": "^1.2.2",
|
||||||
"v-viewer": "^1.7.4",
|
"v-viewer": "^1.7.4",
|
||||||
"vcrontab": "^0.3.5",
|
"vcrontab": "^0.3.5",
|
||||||
"vue": "^2.6.14",
|
"vue": "2.7.16",
|
||||||
"vue-clipboard2": "^0.3.3",
|
"vue-clipboard2": "^0.3.3",
|
||||||
"vue-contextmenujs": "^1.4.11",
|
"vue-contextmenujs": "^1.4.11",
|
||||||
"vue-count-to": "^1.0.13",
|
"vue-count-to": "^1.0.13",
|
||||||
@@ -95,12 +96,14 @@
|
|||||||
"html-webpack-plugin": "^5.6.3",
|
"html-webpack-plugin": "^5.6.3",
|
||||||
"mini-css-extract-plugin": "^2.9.2",
|
"mini-css-extract-plugin": "^2.9.2",
|
||||||
"node-polyfill-webpack-plugin": "^4.0.0",
|
"node-polyfill-webpack-plugin": "^4.0.0",
|
||||||
|
"patch-package": "^8.0.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"sass": "^1.63.2",
|
"sass": "^1.63.2",
|
||||||
"sass-loader": "^10.4.1",
|
"sass-loader": "^16.0.7",
|
||||||
|
"svg-sprite-loader": "^6.0.11",
|
||||||
"terser-webpack-plugin": "^5.3.10",
|
"terser-webpack-plugin": "^5.3.10",
|
||||||
"vue-template-compiler": "^2.6.14",
|
"vue-template-compiler": "2.7.16",
|
||||||
"webpack": "^5.96.1",
|
"webpack": "^5.96.1",
|
||||||
"webpack-bundle-analyzer": "^4.10.2"
|
"webpack-bundle-analyzer": "^4.10.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/node_modules/@cornerstonejs/dicom-image-loader/dist/esm/imageLoader/isColorConversionRequired.js b/node_modules/@cornerstonejs/dicom-image-loader/dist/esm/imageLoader/isColorConversionRequired.js
|
||||||
|
index 33469a3..f39736f 100644
|
||||||
|
--- a/node_modules/@cornerstonejs/dicom-image-loader/dist/esm/imageLoader/isColorConversionRequired.js
|
||||||
|
+++ b/node_modules/@cornerstonejs/dicom-image-loader/dist/esm/imageLoader/isColorConversionRequired.js
|
||||||
|
@@ -14,10 +14,7 @@ export default function isColorConversionRequired(imageFrame) {
|
||||||
|
(3 * Math.ceil(columns / 2) + Math.floor(columns / 2)) * rows);
|
||||||
|
}
|
||||||
|
else if (photometricInterpretation.endsWith('422')) {
|
||||||
|
- return (pixelDataLength ===
|
||||||
|
- (3 * Math.ceil(columns / 2) + Math.floor(columns / 2)) *
|
||||||
|
- Math.ceil(rows / 2) +
|
||||||
|
- Math.floor(rows / 2) * columns);
|
||||||
|
+ return pixelDataLength === rows * columns * 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return photometricInterpretation !== 'RGB' || planarConfiguration === 1;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
window.config = {
|
||||||
|
timeZone: false
|
||||||
|
}
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
num = e.data
|
num = e.data
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script src="/config.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app" style="position: relative">
|
<div id="app" style="position: relative" :class="{ mask: isLock }">
|
||||||
<router-view />
|
<router-view />
|
||||||
<div v-show="show" v-if="$route.matched.length > 0" v-adaptive @click="openI18n" style="
|
<div v-show="show" v-if="$route.matched.length > 0" v-adaptive @click="openI18n" style="
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
" size="mini"></el-input>
|
" size="mini"></el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="ValueCN" :label="$t('il8n:table:state')" sortable="custom">
|
<el-table-column prop="State" :label="$t('il8n:table:state')" sortable="custom">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-select v-model="scope.row.State" clearable filterable size="mini">
|
<el-select v-model="scope.row.State" clearable filterable size="mini">
|
||||||
<el-option v-for="item of $d.InternationalizationKeyState"
|
<el-option v-for="item of $d.InternationalizationKeyState"
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<feedBack v-if="$route.matched.length > 0" />
|
<feedBack v-if="$route.matched.length > 0" />
|
||||||
<timeTag />
|
<timeTag v-if="config.timeZone" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -97,9 +97,14 @@ import feedBack from '@/views/trials/trials-layout/components/feedBack'
|
|||||||
import timeTag from '@/components/timeTag'
|
import timeTag from '@/components/timeTag'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import i18n from './lang'
|
import i18n from './lang'
|
||||||
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
|
import WHITELIST from "./utils/whiteList"
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
components: { feedBack, timeTag },
|
components: {
|
||||||
|
feedBack,
|
||||||
|
timeTag
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawer: false,
|
drawer: false,
|
||||||
@@ -109,12 +114,17 @@ export default {
|
|||||||
arr: [],
|
arr: [],
|
||||||
il8nExternal: false,
|
il8nExternal: false,
|
||||||
State: null,
|
State: null,
|
||||||
|
config: window.config,
|
||||||
|
isLock: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
|
this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
|
||||||
this.show = false
|
|
||||||
Vue.prototype.$openI18n = this.openI18n
|
Vue.prototype.$openI18n = this.openI18n
|
||||||
|
this.getIsLock()
|
||||||
|
DicomEvent.$on("isLock", (isLock) => {
|
||||||
|
this.isLock = isLock
|
||||||
|
})
|
||||||
},
|
},
|
||||||
// watch: {
|
// watch: {
|
||||||
// '$route.query': {
|
// '$route.query': {
|
||||||
@@ -146,17 +156,30 @@ export default {
|
|||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
methods: {
|
methods: {
|
||||||
|
getIsLock() {
|
||||||
|
if (zzSessionStorage.getItem('isLock') === 'true' && !WHITELIST.includes(this.$route.path)) {
|
||||||
|
this.isLock = true
|
||||||
|
} else {
|
||||||
|
this.isLock = false
|
||||||
|
}
|
||||||
|
},
|
||||||
// 排序
|
// 排序
|
||||||
handleSortByColumn(column) {
|
handleSortByColumn(column) {
|
||||||
if (column.order === 'ascending') {
|
const { prop, order } = column
|
||||||
this.tableData.sort((a, b) =>
|
if (!prop || !order) {
|
||||||
a[column.prop].localeCompare(b[column.prop])
|
this.tableData = [...this.tableData]
|
||||||
)
|
return
|
||||||
} else {
|
|
||||||
this.tableData.sort((a, b) =>
|
|
||||||
b[column.prop].localeCompare(a[column.prop])
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const collator = new Intl.Collator('zh-Hans-CN', {
|
||||||
|
numeric: true,
|
||||||
|
sensitivity: 'base',
|
||||||
|
})
|
||||||
|
|
||||||
|
this.tableData.sort((a, b) => {
|
||||||
|
const result = collator.compare(a[prop], b[prop])
|
||||||
|
return order === 'ascending' ? result : -result
|
||||||
|
})
|
||||||
},
|
},
|
||||||
handleStateChange() {
|
handleStateChange() {
|
||||||
this.tableData.forEach((item) => {
|
this.tableData.forEach((item) => {
|
||||||
@@ -298,6 +321,23 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.mask {
|
||||||
|
position: relative;
|
||||||
|
filter: blur(5px);
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
background: rgba(255, 253, 253, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
$light_gray: #606266;
|
$light_gray: #606266;
|
||||||
|
|
||||||
.el-tooltip__popper {
|
.el-tooltip__popper {
|
||||||
|
|||||||
@@ -391,3 +391,35 @@ export function getReSendEmail(data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取系统基础配置
|
||||||
|
export function getSystemBasicConfigInfo() {
|
||||||
|
return request({
|
||||||
|
url: `/DeployConfig/getSystemBasicConfigInfo`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 更新系统基础配置
|
||||||
|
export function updateSystemBasicConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: `/DeployConfig/updateSystemBasicConfig`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取系统邮件配置
|
||||||
|
export function getEmailConfigInfo() {
|
||||||
|
return request({
|
||||||
|
url: `/DeployConfig/getEmailConfigInfo`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 更新系统邮件配置
|
||||||
|
export function updateSystemEmailConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: `/DeployConfig/updateSystemEmailConfig`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function addOrUpdateFileUploadRecord(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/addOrUpdateFileUploadRecord`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function batchAddSyncFileTask(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/batchAddSyncFileTask`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubjectUploadRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getSubjectUploadRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFileUploadRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getFileUploadRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUploadFileSyncRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getUploadFileSyncRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -319,3 +319,193 @@ export function getReportsChartData(param) {
|
|||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分割相关
|
||||||
|
// 获取分割组
|
||||||
|
export function getSegmentationList(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/getSegmentationList`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 新增修改分割组
|
||||||
|
export function addOrUpdateSegmentation(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/addOrUpdateSegmentation`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 删除分割组
|
||||||
|
export function deleteSegmentation(segmentationId) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/deleteSegmentation/${segmentationId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取分割
|
||||||
|
export function getSegmentList(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/getSegmentList`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 新增修改分割
|
||||||
|
export function addOrUpdateSegment(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/addOrUpdateSegment`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 删除分割
|
||||||
|
export function deleteSegment(segmentId) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/deleteSegment/${segmentId}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取分割绑定关系
|
||||||
|
export function getSegmentBindingList(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/getSegmentBindingList`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 保存分割绑定关系(可用作修改删除)
|
||||||
|
export function saveSegmentBindingAndAnswer(param) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/saveSegmentBindingAndAnswer`,
|
||||||
|
method: 'post',
|
||||||
|
data: param
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取表格问题配置
|
||||||
|
export function getReadingTableQuestionTrialById(params) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingQuestion/getReadingTableQuestionTrialById`,
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取外层问题配置
|
||||||
|
export function getReadingQuestionTrialById(params) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingQuestion/getReadingQuestionTrialById`,
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 修改分割组保存状态
|
||||||
|
export function changeSegmentationSavedStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/changeSegmentationSavedStatus`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 修改分割片段锁定状态
|
||||||
|
export function lockOrUnLockSegment(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/lockOrUnLockSegment`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 图像数据匿名
|
||||||
|
export function studyMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/studyMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 撤销匿名
|
||||||
|
export function studyUndoMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/studyUndoMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 非dicom图像数据匿名
|
||||||
|
export function noneDicomStudyMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/NoneDicomStudy/noneDicomStudyMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 非dicom图像数据撤销匿名
|
||||||
|
export function noneDicomStudyUndoMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/NoneDicomStudy/noneDicomStudyUndoMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取分割组历史版本
|
||||||
|
export function getSegmentationVersionList(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/getSegmentationVersionList`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 恢复分割历史版本
|
||||||
|
export function restoreSegmentationVersion(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/restoreSegmentationVersion`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取标记信息
|
||||||
|
export function getMarkList(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/getMarkList`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function getNoneDicomMarkList(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/getNoneDicomMarkList`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFilterTableQuestion(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingImageTask/getFilterTableQuestion`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function deleteImageCache(params) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/deleteImageCache`,
|
||||||
|
method: 'delete',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function getAnonymizeInfo(params) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/getAnonymizeInfo`,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function updateModality(params) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/updateModality`,
|
||||||
|
method: 'put',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -357,10 +357,11 @@ export function getSubjectList(param) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTrialSiteSelect(trialId) {
|
export function getTrialSiteSelect(trialId, params) {
|
||||||
return request({
|
return request({
|
||||||
url: `/trialMaintenance/getTrialSiteSelect/${trialId}`,
|
url: `/trialMaintenance/getTrialSiteSelect/${trialId}`,
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4431,3 +4432,114 @@ export function updateImageResizePath(data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取PET图像上患者信息
|
||||||
|
export function getPatientInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/getPatientInfo`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//编辑患者基本信息
|
||||||
|
export function editPatientInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/editPatientInfo`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//修正患者基本信息
|
||||||
|
export function amendmentPatientInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Inspection/Study/amendmentPatientInfo`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//修改临床数据后 将签名状态变更为未签名
|
||||||
|
export function updateReadModuleClinicalData(data) {
|
||||||
|
return request({
|
||||||
|
url: `/ReadingClinicalData/updateReadModuleClinicalData`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTrialUnreadVisitList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/DownloadAndUpload/getTrialUnreadVisitList`,
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function getDoctorUserTrialReadingStat(data) {
|
||||||
|
return request({
|
||||||
|
url: `/DoctorWorkload/getDoctorUserTrialReadingStat`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 设置项目链接过期时间
|
||||||
|
export function setTrialLinkExpirationTime(data) {
|
||||||
|
return request({
|
||||||
|
url: `/TrialConfig/setTrialLinkExpirationTime`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取项目链接过期时间
|
||||||
|
export function getTrialLinkExpirationTime(data) {
|
||||||
|
return request({
|
||||||
|
url: `/TrialConfig/getTrialLinkExpirationTime`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取项目链接时间是否过期
|
||||||
|
export function getLinkLinkExpirationTime(data) {
|
||||||
|
return request({
|
||||||
|
url: `/TrialConfig/getLinkLinkExpirationTime`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取项目链接code是否有效
|
||||||
|
export function getLinkVerificationCodeIsEffective(data) {
|
||||||
|
return request({
|
||||||
|
url: `/TrialConfig/getLinkVerificationCodeIsEffective`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 上传通用文件记录
|
||||||
|
export function addOrUpdateCommonUploadRecord(data) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/addOrUpdateCommonUploadRecord`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInspectionById(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Inspection/getInspectionById`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setJsonDetail(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Inspection/setJsonDetail`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<div>Series #{{ dicomInfo.series }}</div>
|
<div>Series #{{ dicomInfo.series }}</div>
|
||||||
<div>Image #{{ dicomInfo.frame }}</div>
|
<div>Image #{{ dicomInfo.frame }}</div>
|
||||||
<div>{{ dicomInfo.modality }}</div>
|
<div>{{ dicomInfo.modality }}</div>
|
||||||
|
<div v-if="isComparison" style="font-size: 30px;color: #428bca;">{{ tip }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="dicomInfo.series" class="info-image">
|
<div v-show="dicomInfo.series" class="info-image">
|
||||||
<!-- <div>
|
<!-- <div>
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
<div v-show="dicomInfo.thick">Slice Thickness {{ dicomInfo.thick }}mm</div>
|
<div v-show="dicomInfo.thick">Slice Thickness {{ dicomInfo.thick }}mm</div>
|
||||||
<div>WW/WC {{ dicomInfo.wwwc }}</div>
|
<div>WW/WC {{ dicomInfo.wwwc }}</div>
|
||||||
<div>Zoom {{ dicomInfo.zoom }}</div>
|
<div>Zoom {{ dicomInfo.zoom }}</div>
|
||||||
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div> -->
|
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div>-->
|
||||||
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
|
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
|
||||||
<div v-show="mousePosition.mo">
|
<div v-show="mousePosition.mo">
|
||||||
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
|
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
|
||||||
@@ -23,24 +24,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||||
HU: {{ mousePosition.mo }}
|
HU: {{ mousePosition.mo }}</div>
|
||||||
</div>
|
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">SUVbw(g/ml): {{ mousePosition.suv.toFixed(3)
|
||||||
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
|
}}</div>
|
||||||
SUVbw(g/ml): {{ mousePosition.suv.toFixed(3) }}
|
<div v-else-if="mousePosition.mo">Density: {{ mousePosition.mo }}</div>
|
||||||
</div>
|
<div>W*H: {{ dicomInfo.size }}</div>
|
||||||
<div v-else-if="mousePosition.mo">
|
|
||||||
Density: {{ mousePosition.mo }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
W*H: {{ dicomInfo.size }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>Zoom: {{ dicomInfo.zoom }}</div>
|
<div>Zoom: {{ dicomInfo.zoom }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info-subject">
|
<div class="info-subject">
|
||||||
<div v-if="series.subjectCode">{{ series.subjectCode }}</div>
|
<div v-if="series.subjectCode && IsReadingTaskViewInOrder !== 0">{{ series.subjectCode }}</div>
|
||||||
<div v-if="series.visitName">{{ series.visitName }}</div>
|
<div v-if="series.visitName && IsReadingTaskViewInOrder !== 0">{{ series.visitName }}</div>
|
||||||
<div>{{ stack.description }}</div>
|
<div>{{ stack.description }}</div>
|
||||||
<!-- <div>{{ dicomInfo.hospital }}</div> -->
|
<!-- <div>{{ dicomInfo.hospital }}</div> -->
|
||||||
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
|
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
|
||||||
@@ -56,24 +51,17 @@
|
|||||||
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
||||||
@mousedown="sliderMousedown($event)" />
|
@mousedown="sliderMousedown($event)" />
|
||||||
</div>
|
</div>
|
||||||
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
|
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">{{ markers.top }}</div>
|
||||||
{{ markers.top }}
|
<div style="position: absolute;top: 50%;right: 15px;color: #f44336;">{{ markers.right }}</div>
|
||||||
</div>
|
|
||||||
<div style="position: absolute;top: 50%;right: 15px;color: #f44336;">
|
|
||||||
{{ markers.right }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">
|
<div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">{{ markers.bottom }}</div>
|
||||||
{{ markers.bottom }}
|
<div style="position: absolute;top: 50%;left: 15px;color: #f44336;">{{ markers.left }}</div>
|
||||||
</div>
|
|
||||||
<div style="position: absolute;top: 50%;left: 15px;color: #f44336;">
|
|
||||||
{{ markers.left }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="info-instance">
|
<div class="info-instance">
|
||||||
|
<svg-icon icon-class="IsMasked" style="font-size:20px;" v-show="dicomInfo.IsMasked" />
|
||||||
<!-- <div v-show="dicomInfo.pixel">
|
<!-- <div v-show="dicomInfo.pixel">
|
||||||
Pixel: {{ dicomInfo.pixel }}mm
|
Pixel: {{ dicomInfo.pixel }}mm
|
||||||
</div> -->
|
</div>-->
|
||||||
<div v-show="dicomInfo.location">Location: {{ dicomInfo.location }}</div>
|
<div v-show="dicomInfo.location">Location: {{ dicomInfo.location }}</div>
|
||||||
<div v-show="dicomInfo.thick">Slice Thickness: {{ dicomInfo.thick }}mm</div>
|
<div v-show="dicomInfo.thick">Slice Thickness: {{ dicomInfo.thick }}mm</div>
|
||||||
<div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div>
|
<div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div>
|
||||||
@@ -92,15 +80,18 @@
|
|||||||
import * as cornerstone from 'cornerstone-core'
|
import * as cornerstone from 'cornerstone-core'
|
||||||
import * as cornerstoneMath from 'cornerstone-math'
|
import * as cornerstoneMath from 'cornerstone-math'
|
||||||
import * as cornerstoneTools from 'cornerstone-tools'
|
import * as cornerstoneTools from 'cornerstone-tools'
|
||||||
|
import metaDataProvider from '@/utils/metaDataProvider'
|
||||||
|
|
||||||
const scroll = cornerstoneTools.import('util/scrollToIndex')
|
const scroll = cornerstoneTools.import('util/scrollToIndex')
|
||||||
import Hammer from 'hammerjs'
|
import Hammer from 'hammerjs'
|
||||||
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
|
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
|
||||||
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'
|
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'
|
||||||
|
|
||||||
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
|
const calculateSUV = cornerstoneTools.import('util/calculateSUV')
|
||||||
// import requestPoolManager from '@/utils/request-pool'
|
// import requestPoolManager from '@/utils/request-pool'
|
||||||
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
|
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
|
||||||
|
import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/Note_RectangleRoiTool'
|
||||||
|
let isMetaDataProviderAdded = false
|
||||||
cornerstoneTools.external.cornerstone = cornerstone
|
cornerstoneTools.external.cornerstone = cornerstone
|
||||||
cornerstoneTools.external.Hammer = Hammer
|
cornerstoneTools.external.Hammer = Hammer
|
||||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
||||||
@@ -110,6 +101,7 @@ cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
|
|||||||
// cornerstoneTools.init({ showSVGCursors: true })
|
// cornerstoneTools.init({ showSVGCursors: true })
|
||||||
cornerstoneTools.init()
|
cornerstoneTools.init()
|
||||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||||
|
console.log(cornerstoneTools, 'cornerstoneTools')
|
||||||
import DicomTags from './DicomTags'
|
import DicomTags from './DicomTags'
|
||||||
export default {
|
export default {
|
||||||
name: 'DicomCanvas',
|
name: 'DicomCanvas',
|
||||||
@@ -117,6 +109,12 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
NSTip() {
|
NSTip() {
|
||||||
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
isComparison: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -130,7 +128,7 @@ export default {
|
|||||||
seriesNumber: '',
|
seriesNumber: '',
|
||||||
imageIds: [],
|
imageIds: [],
|
||||||
currentImageIdIndex: 0,
|
currentImageIdIndex: 0,
|
||||||
firstImageLoading: false
|
firstImageLoading: false,
|
||||||
// preventCache: true
|
// preventCache: true
|
||||||
},
|
},
|
||||||
dicomInfo: {
|
dicomInfo: {
|
||||||
@@ -150,14 +148,15 @@ export default {
|
|||||||
wwwc: '',
|
wwwc: '',
|
||||||
zoom: 0,
|
zoom: 0,
|
||||||
location: '',
|
location: '',
|
||||||
fps: 5
|
fps: 5,
|
||||||
|
IsMasked: false
|
||||||
},
|
},
|
||||||
toolState: {
|
toolState: {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
activeTool: 'none',
|
activeTool: 'none',
|
||||||
dicomInfoVisible: false,
|
dicomInfoVisible: false,
|
||||||
clipPlaying: false,
|
clipPlaying: false,
|
||||||
viewportInvert: false
|
viewportInvert: false,
|
||||||
},
|
},
|
||||||
loadImagePromise: null,
|
loadImagePromise: null,
|
||||||
AnnotationSync: null,
|
AnnotationSync: null,
|
||||||
@@ -168,18 +167,25 @@ export default {
|
|||||||
sliderInfo: {
|
sliderInfo: {
|
||||||
oldB: null,
|
oldB: null,
|
||||||
oldM: null,
|
oldM: null,
|
||||||
isMove: false
|
isMove: false,
|
||||||
},
|
},
|
||||||
mousePosition: { x: '', y: '', mo: '' },
|
mousePosition: { x: '', y: '', mo: '' },
|
||||||
markers: { top: '', right: '', bottom: '', left: '' },
|
markers: { top: '', right: '', bottom: '', left: '' },
|
||||||
orientationMarkers: [],
|
orientationMarkers: [],
|
||||||
originalMarkers: [],
|
originalMarkers: [],
|
||||||
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') }
|
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') },
|
||||||
|
tip: '',
|
||||||
|
IsReadingTaskViewInOrder: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
this.type = this.$router.currentRoute.query.type
|
||||||
|
? this.$router.currentRoute.query.type
|
||||||
|
: ''
|
||||||
|
if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
|
||||||
|
this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
|
||||||
|
}
|
||||||
this.canvas = this.$refs.canvas
|
this.canvas = this.$refs.canvas
|
||||||
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
||||||
this.canvas.addEventListener(
|
this.canvas.addEventListener(
|
||||||
@@ -200,17 +206,32 @@ export default {
|
|||||||
document.addEventListener('mousemove', (e) => {
|
document.addEventListener('mousemove', (e) => {
|
||||||
this.sliderMousemove(e)
|
this.sliderMousemove(e)
|
||||||
})
|
})
|
||||||
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
|
this.canvas.addEventListener(
|
||||||
|
'cornerstonetoolsstackscroll',
|
||||||
|
this.stackScrollCallback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
loadImageStack(dicomSeries) {
|
getInfo() {
|
||||||
|
var image = cornerstone.getImage(this.canvas)
|
||||||
|
return image
|
||||||
|
},
|
||||||
|
loadImageStack(dicomSeries, text = '') {
|
||||||
|
this.tip = text
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
if (!dicomSeries || !Array.isArray(dicomSeries.imageIds) || dicomSeries.imageIds.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.series = dicomSeries
|
this.series = dicomSeries
|
||||||
this.stack.seriesId = dicomSeries.seriesId
|
this.stack.seriesId = dicomSeries.seriesId
|
||||||
this.stack.seriesNumber = dicomSeries.seriesNumber
|
this.stack.seriesNumber = dicomSeries.seriesNumber
|
||||||
this.stack.imageIds = dicomSeries.imageIds
|
this.stack.imageIds = dicomSeries.imageIds
|
||||||
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
|
this.stack.currentImageIdIndex =
|
||||||
|
dicomSeries.imageIdIndex &&
|
||||||
|
dicomSeries.imageIdIndex < dicomSeries.imageIds.length
|
||||||
|
? dicomSeries.imageIdIndex
|
||||||
|
: 0
|
||||||
this.stack.firstImageLoading = true
|
this.stack.firstImageLoading = true
|
||||||
this.stack.description = dicomSeries.description
|
this.stack.description = dicomSeries.description
|
||||||
this.toolState.viewportInvert = false
|
this.toolState.viewportInvert = false
|
||||||
@@ -221,18 +242,27 @@ export default {
|
|||||||
// this.stack.instanceId = instanceId
|
// this.stack.instanceId = instanceId
|
||||||
this.toolState.clipPlaying = false
|
this.toolState.clipPlaying = false
|
||||||
const element = this.$refs.canvas
|
const element = this.$refs.canvas
|
||||||
|
if (!isMetaDataProviderAdded) {
|
||||||
|
// 注册自定义 metaDataProvider:统一 SUV 口径(优先接口,缺失回退 DICOM)
|
||||||
|
cornerstone.metaData.addProvider(metaDataProvider, 100000)
|
||||||
|
isMetaDataProviderAdded = true
|
||||||
|
}
|
||||||
cornerstone.enable(element)
|
cornerstone.enable(element)
|
||||||
cornerstoneTools.stopClip(this.canvas)
|
cornerstoneTools.stopClip(this.canvas)
|
||||||
this.toolState.clipPlaying = false
|
this.toolState.clipPlaying = false
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
cornerstone
|
||||||
.then(image => {
|
.loadAndCacheImage(
|
||||||
|
this.stack.imageIds[this.stack.currentImageIdIndex]
|
||||||
|
)
|
||||||
|
.then((image) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
|
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
|
||||||
this.onFirstImageLoaded(image)
|
this.onFirstImageLoaded(image)
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (error.error && error.error.message) {
|
if (error.error && error.error.message) {
|
||||||
this.$alert(error.error.message)
|
this.$alert(error.error.message)
|
||||||
@@ -255,15 +285,17 @@ export default {
|
|||||||
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
||||||
|
|
||||||
if (apiTool) {
|
if (apiTool) {
|
||||||
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(
|
const toolAlreadyAddedToElement =
|
||||||
element,
|
cornerstoneTools.getToolForElement(element, apiTool)
|
||||||
apiTool
|
|
||||||
)
|
|
||||||
if (!toolAlreadyAddedToElement) {
|
if (!toolAlreadyAddedToElement) {
|
||||||
if (toolName === 'RectangleRoi') {
|
if (toolName === 'RectangleRoi') {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true } })
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
||||||
|
configuration: { showMinMax: true, showStatsText: true },
|
||||||
|
})
|
||||||
} else if (toolName === 'EllipticalRoi') {
|
} else if (toolName === 'EllipticalRoi') {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true } })
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
||||||
|
configuration: { showMinMax: true },
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool)
|
cornerstoneTools.addToolForElement(element, apiTool)
|
||||||
}
|
}
|
||||||
@@ -287,8 +319,28 @@ export default {
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.WwwcRegionTool)) {
|
if (
|
||||||
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool)
|
!cornerstoneTools.getToolForElement(element, Note_RectangleRoiTool)
|
||||||
|
) {
|
||||||
|
cornerstoneTools.addToolForElement(element, Note_RectangleRoiTool, {
|
||||||
|
configuration: {
|
||||||
|
color: '#f00',
|
||||||
|
lineWidth: 2,
|
||||||
|
drawHandles: false,
|
||||||
|
fillColor: 'rgba(0, 0, 0, 1)',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!cornerstoneTools.getToolForElement(
|
||||||
|
element,
|
||||||
|
cornerstoneTools.WwwcRegionTool
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
cornerstoneTools.addToolForElement(
|
||||||
|
element,
|
||||||
|
cornerstoneTools.WwwcRegionTool
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!cornerstoneTools.getToolForElement(
|
!cornerstoneTools.getToolForElement(
|
||||||
@@ -347,20 +399,27 @@ export default {
|
|||||||
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
||||||
// instanceId = instanceId.split('.')[0]
|
// instanceId = instanceId.split('.')[0]
|
||||||
// this.stack.instanceId = instanceId
|
// this.stack.instanceId = instanceId
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height = this.getStackHeightPercent()
|
||||||
this.resetWwwc()
|
this.resetWwwc()
|
||||||
},
|
},
|
||||||
onNewImage(e) {
|
onNewImage(e) {
|
||||||
e.detail.enabledElement.options = {}
|
e.detail.enabledElement.options = {}
|
||||||
var data = e.detail.image.data
|
var data = e.detail.image.data
|
||||||
this.dicomInfo.hospital = data.string('x00080080')
|
this.dicomInfo.hospital = data.string('x00080080')
|
||||||
|
// let instanceInfo = this.series.instanceInfoList.find(item => item.ImageId === e.detail.image.imageId)
|
||||||
|
let instanceInfo = this.series?.instanceInfoList?.find(item => {
|
||||||
|
let s1 = item.ImageId ? item.ImageId.split("?")[0] : ''
|
||||||
|
let s2 = e.detail.image.imageId ? e.detail.image.imageId.split("?")[0] : ''
|
||||||
|
return s1 === s2
|
||||||
|
})
|
||||||
|
this.dicomInfo.IsMasked = instanceInfo ? instanceInfo.IsMasked : false
|
||||||
// this.dicomInfo.pid = data.string('x00100020')
|
// this.dicomInfo.pid = data.string('x00100020')
|
||||||
this.dicomInfo.pid = data.string('x00120040')
|
this.dicomInfo.pid = data.string('x00120040')
|
||||||
this.dicomInfo.name = data.string('x00100010')
|
this.dicomInfo.name = data.string('x00100010')
|
||||||
this.dicomInfo.age = data.string('x00101010')
|
this.dicomInfo.age = data.string('x00101010')
|
||||||
this.dicomInfo.sex = data.string('x00100040')
|
this.dicomInfo.sex = data.string('x00100040')
|
||||||
this.dicomInfo.acc = data.string('x00080050') // 登记号
|
this.dicomInfo.acc = data.string('x00080050') // 登记号
|
||||||
this.dicomInfo.modality = data.string('x00080060')
|
this.dicomInfo.modality = (data.string('x00080060') || '').trim()
|
||||||
this.dicomInfo.time = this.formatDicomDateTime(
|
this.dicomInfo.time = this.formatDicomDateTime(
|
||||||
data.string('x00080020'),
|
data.string('x00080020'),
|
||||||
data.string('x00080030')
|
data.string('x00080030')
|
||||||
@@ -379,21 +438,32 @@ export default {
|
|||||||
if (this.dicomInfo.thick) {
|
if (this.dicomInfo.thick) {
|
||||||
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
||||||
}
|
}
|
||||||
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === e.detail.image.imageId)
|
const newImageIdIndex = this.stack.imageIds.findIndex(
|
||||||
|
(i) => i === e.detail.image.imageId
|
||||||
|
)
|
||||||
if (newImageIdIndex === -1) return
|
if (newImageIdIndex === -1) return
|
||||||
this.stack.currentImageIdIndex = newImageIdIndex
|
this.stack.currentImageIdIndex = newImageIdIndex
|
||||||
this.stack.imageIdIndex = newImageIdIndex
|
this.stack.imageIdIndex = newImageIdIndex
|
||||||
this.series.imageIdIndex = newImageIdIndex
|
this.series.imageIdIndex = newImageIdIndex
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height = this.getStackHeightPercent()
|
||||||
this.resetWwwc()
|
},
|
||||||
|
getStackHeightPercent() {
|
||||||
|
const imageCount = Array.isArray(this.stack.imageIds) ? this.stack.imageIds.length : 0
|
||||||
|
if (imageCount <= 1) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (this.stack.currentImageIdIndex * 100) / (imageCount - 1)
|
||||||
},
|
},
|
||||||
stackScrollCallback(e) {
|
stackScrollCallback(e) {
|
||||||
const { detail } = e
|
const { detail } = e
|
||||||
if (this.isScrollSync) {
|
if (this.isScrollSync) {
|
||||||
this.$emit('scrollSync', { canvasIndex: this.canvasIndex, direction: detail.direction })
|
this.$emit('scrollSync', {
|
||||||
|
canvasIndex: this.canvasIndex,
|
||||||
|
direction: detail.direction,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
this.stack.currentImageIdIndex = e.detail.newImageIdIndex
|
this.stack.currentImageIdIndex = e.detail.newImageIdIndex
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height = this.getStackHeightPercent()
|
||||||
// var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
|
// var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
|
||||||
|
|
||||||
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
|
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
|
||||||
@@ -408,7 +478,9 @@ export default {
|
|||||||
if (date) {
|
if (date) {
|
||||||
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
|
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
|
||||||
}
|
}
|
||||||
if (time) { time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}` }
|
if (time) {
|
||||||
|
time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
|
||||||
|
}
|
||||||
return time ? `${date} ${time}` : `${date} 00:00:00`
|
return time ? `${date} ${time}` : `${date} 00:00:00`
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -453,7 +525,7 @@ export default {
|
|||||||
top: oppositeColumn,
|
top: oppositeColumn,
|
||||||
bottom: column,
|
bottom: column,
|
||||||
left: oppositeRow,
|
left: oppositeRow,
|
||||||
right: row
|
right: row,
|
||||||
}
|
}
|
||||||
if (!markers) {
|
if (!markers) {
|
||||||
return
|
return
|
||||||
@@ -500,13 +572,7 @@ export default {
|
|||||||
if (image.color) {
|
if (image.color) {
|
||||||
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
|
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
|
||||||
} else {
|
} else {
|
||||||
stats.storedPixels = cornerstone.getStoredPixels(
|
stats.storedPixels = cornerstone.getStoredPixels(element, x, y, 1, 1)
|
||||||
element,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
)
|
|
||||||
stats.sp = stats.storedPixels[0]
|
stats.sp = stats.storedPixels[0]
|
||||||
stats.mo = stats.sp * image.slope + image.intercept
|
stats.mo = stats.sp * image.slope + image.intercept
|
||||||
stats.suv = calculateSUV(image, stats.sp)
|
stats.suv = calculateSUV(image, stats.sp)
|
||||||
@@ -533,7 +599,8 @@ export default {
|
|||||||
if (enabledElement.image.color) {
|
if (enabledElement.image.color) {
|
||||||
for (row = 0; row < height; row++) {
|
for (row = 0; row < height; row++) {
|
||||||
for (column = 0; column < width; column++) {
|
for (column = 0; column < width; column++) {
|
||||||
spIndex = ((row + y) * enabledElement.image.columns + (column + x)) * 4
|
spIndex =
|
||||||
|
((row + y) * enabledElement.image.columns + (column + x)) * 4
|
||||||
const red = pixelData[spIndex]
|
const red = pixelData[spIndex]
|
||||||
const green = pixelData[spIndex + 1]
|
const green = pixelData[spIndex + 1]
|
||||||
const blue = pixelData[spIndex + 2]
|
const blue = pixelData[spIndex + 2]
|
||||||
@@ -551,7 +618,8 @@ export default {
|
|||||||
},
|
},
|
||||||
sliderMousedown(e) {
|
sliderMousedown(e) {
|
||||||
var boxHeight = this.$refs['sliderBox'].clientHeight
|
var boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
this.sliderInfo.oldB =
|
||||||
|
(parseInt(e.srcElement.style.top) * boxHeight) / 100
|
||||||
this.sliderInfo.oldM = e.clientY
|
this.sliderInfo.oldM = e.clientY
|
||||||
this.sliderInfo.isMove = true
|
this.sliderInfo.isMove = true
|
||||||
e.stopImmediatePropagation()
|
e.stopImmediatePropagation()
|
||||||
@@ -564,9 +632,14 @@ export default {
|
|||||||
var boxHeight = this.$refs['sliderBox'].clientHeight
|
var boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
if (PX < 0) return
|
if (PX < 0) return
|
||||||
if (PX > boxHeight) return
|
if (PX > boxHeight) return
|
||||||
var height = PX * 100 / boxHeight
|
var height = (PX * 100) / boxHeight
|
||||||
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
||||||
index = index > this.stack.imageIds.length ? this.stack.imageIds.length : index < 0 ? 0 : index
|
index =
|
||||||
|
index > this.stack.imageIds.length
|
||||||
|
? this.stack.imageIds.length
|
||||||
|
: index < 0
|
||||||
|
? 0
|
||||||
|
: index
|
||||||
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
|
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
|
||||||
this.height = height
|
this.height = height
|
||||||
if (this.stack.currentImageIdIndex !== index) {
|
if (this.stack.currentImageIdIndex !== index) {
|
||||||
@@ -578,9 +651,9 @@ export default {
|
|||||||
},
|
},
|
||||||
goViewer(e) {
|
goViewer(e) {
|
||||||
// console.log(this.$refs['sliderBox'].clientHeight)
|
// console.log(this.$refs['sliderBox'].clientHeight)
|
||||||
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
var height = (e.offsetY * 100) / this.$refs['sliderBox'].clientHeight
|
||||||
this.height = height
|
this.height = height
|
||||||
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
||||||
scroll(this.canvas, index)
|
scroll(this.canvas, index)
|
||||||
},
|
},
|
||||||
onClipStopped() {
|
onClipStopped() {
|
||||||
@@ -673,10 +746,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.toolState.clipPlaying = true
|
this.toolState.clipPlaying = true
|
||||||
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
||||||
cornerstoneTools.getToolState(
|
cornerstoneTools.getToolState(this.canvas, 'playClip').data[0].loop = true
|
||||||
this.canvas,
|
|
||||||
'playClip'
|
|
||||||
).data[0].loop = true
|
|
||||||
},
|
},
|
||||||
setFps(fps) {
|
setFps(fps) {
|
||||||
this.dicomInfo.fps = fps
|
this.dicomInfo.fps = fps
|
||||||
@@ -687,6 +757,7 @@ export default {
|
|||||||
var viewport = cornerstone.getViewport(this.canvas)
|
var viewport = cornerstone.getViewport(this.canvas)
|
||||||
// viewport.invert = false
|
// viewport.invert = false
|
||||||
var image = cornerstone.getImage(this.canvas)
|
var image = cornerstone.getImage(this.canvas)
|
||||||
|
if (!viewport || !image) return
|
||||||
viewport.voi.windowWidth = image.windowWidth
|
viewport.voi.windowWidth = image.windowWidth
|
||||||
viewport.voi.windowCenter = image.windowCenter
|
viewport.voi.windowCenter = image.windowCenter
|
||||||
cornerstone.setViewport(this.canvas, viewport)
|
cornerstone.setViewport(this.canvas, viewport)
|
||||||
@@ -712,8 +783,8 @@ export default {
|
|||||||
invert: false,
|
invert: false,
|
||||||
preventZoomOutsideImage: false,
|
preventZoomOutsideImage: false,
|
||||||
minScale: 0.1,
|
minScale: 0.1,
|
||||||
maxScale: 20.0
|
maxScale: 20.0,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
||||||
this.toolState.activeTool = 'zoom'
|
this.toolState.activeTool = 'zoom'
|
||||||
@@ -797,9 +868,120 @@ export default {
|
|||||||
setToolPassive(toolName) {
|
setToolPassive(toolName) {
|
||||||
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
||||||
},
|
},
|
||||||
|
async reloadImage(newImageId = null) {
|
||||||
|
// 1. 获取当前imageId(如果未指定新imageId)
|
||||||
|
let element = this.canvas
|
||||||
|
this.stack.imageIds.splice(this.stack.currentImageIdIndex, 1, newImageId)
|
||||||
|
const currentImageId =
|
||||||
|
newImageId || cornerstone.getImage(element)?.imageId
|
||||||
|
|
||||||
|
if (!currentImageId) {
|
||||||
|
console.error('没有找到可用的imageId')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 清除该影像关联的工具状态(标注数据)
|
||||||
|
this.clearToolStateForImage(element, currentImageId)
|
||||||
|
|
||||||
|
// 3. 从缓存中移除该影像
|
||||||
|
this.removeImageFromCache(currentImageId)
|
||||||
|
|
||||||
|
// 4. 重新加载并渲染
|
||||||
|
await this.loadAndRenderImage(element, currentImageId)
|
||||||
|
},
|
||||||
|
clearToolStateForImage(element, imageId) {
|
||||||
|
// 获取全局状态管理器
|
||||||
|
const globalToolStateManager =
|
||||||
|
cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||||
|
|
||||||
|
if (globalToolStateManager) {
|
||||||
|
// 方式1:清空该影像的全部工具数据
|
||||||
|
globalToolStateManager.clearImageIdToolState(imageId)
|
||||||
|
console.log(`已清除影像 ${imageId} 的所有标注数据`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方式2:如果使用元素级别的状态管理器
|
||||||
|
const elementToolStateManager =
|
||||||
|
cornerstoneTools.getElementToolStateManager(element)
|
||||||
|
if (elementToolStateManager && elementToolStateManager.get(element)) {
|
||||||
|
// 清空该元素上当前显示影像的数据
|
||||||
|
elementToolStateManager.clear(element)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeImageFromCache(imageId) {
|
||||||
|
const imageCache = cornerstone.imageCache
|
||||||
|
|
||||||
|
if (imageCache && imageCache[imageId]) {
|
||||||
|
// 从缓存中移除
|
||||||
|
delete imageCache[imageId]
|
||||||
|
console.log(`已从缓存中移除影像: ${imageId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 也可以使用官方API(如果可用)
|
||||||
|
if (typeof cornerstone.imageCache.removeImage === 'function') {
|
||||||
|
cornerstone.imageCache.removeImageLoadObject(imageId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadAndRenderImage(element, imageId) {
|
||||||
|
try {
|
||||||
|
// 1. 清除当前画布内容(可选)
|
||||||
|
const canvas = element.querySelector('canvas')
|
||||||
|
if (canvas) {
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 重新加载图像(强制从源头重新获取)
|
||||||
|
const image = await cornerstone.loadAndCacheImage(imageId)
|
||||||
|
|
||||||
|
// 3. 获取或创建视口设置
|
||||||
|
let viewport = cornerstone.getViewport(element)
|
||||||
|
if (!viewport) {
|
||||||
|
viewport = cornerstone.getDefaultViewport(element, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 显示图像
|
||||||
|
cornerstone.displayImage(element, image, viewport)
|
||||||
|
|
||||||
|
// 5. 触发重绘
|
||||||
|
cornerstone.updateImage(element)
|
||||||
|
|
||||||
|
console.log(`影像 ${imageId} 重新加载并渲染完成`)
|
||||||
|
|
||||||
|
return image
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载图像失败:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNote_RectangleRoi() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let toolInfo = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
||||||
|
let image = cornerstone.getImage(this.canvas)
|
||||||
|
resolve({ toolInfo, image })
|
||||||
|
})
|
||||||
|
// console.log(
|
||||||
|
// cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
||||||
|
// )
|
||||||
|
// console.log(cornerstone.getImage(this.canvas))
|
||||||
|
// let image = cornerstone.getImage(this.canvas)
|
||||||
|
// // cornerstone.imageCache.removeImageLoadObject(image.imageId)
|
||||||
|
|
||||||
|
// this.reloadImage(this.canvas, image.imageId)
|
||||||
|
},
|
||||||
|
removeNote_RectangleRoi() {
|
||||||
|
const toolState = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi');
|
||||||
|
if (toolState && toolState.data.length > 0) {
|
||||||
|
let arr = toolState.data.map(item => item)
|
||||||
|
arr.forEach(item => {
|
||||||
|
cornerstoneTools.removeToolState(this.canvas, 'Note_RectangleRoi', item);
|
||||||
|
})
|
||||||
|
cornerstone.updateImage(this.canvas);
|
||||||
|
}
|
||||||
|
},
|
||||||
setToolActive(toolName) {
|
setToolActive(toolName) {
|
||||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||||
mouseButtonMask: 1
|
mouseButtonMask: 1,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setAllToolsPassive() {
|
setAllToolsPassive() {
|
||||||
@@ -833,7 +1015,7 @@ export default {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
||||||
synchronizationContext: synchronizer
|
synchronizationContext: synchronizer,
|
||||||
})
|
})
|
||||||
|
|
||||||
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
||||||
@@ -864,7 +1046,7 @@ export default {
|
|||||||
}
|
}
|
||||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||||
mouseButtonMask: 1,
|
mouseButtonMask: 1,
|
||||||
synchronizationContext: synchronizer
|
synchronizationContext: synchronizer,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
disabledViewPortToolSync(synchronizer, toolName) {
|
disabledViewPortToolSync(synchronizer, toolName) {
|
||||||
@@ -1095,7 +1277,7 @@ export default {
|
|||||||
'CobbAngle',
|
'CobbAngle',
|
||||||
'Angle',
|
'Angle',
|
||||||
'Bidirectional',
|
'Bidirectional',
|
||||||
'FreehandRoi'
|
'FreehandRoi',
|
||||||
]
|
]
|
||||||
for (let i = 0; i < toolROITypes.length; i++) {
|
for (let i = 0; i < toolROITypes.length; i++) {
|
||||||
const toolROIType = toolROITypes[i]
|
const toolROIType = toolROITypes[i]
|
||||||
@@ -1115,12 +1297,12 @@ export default {
|
|||||||
removeLabel(item) {
|
removeLabel(item) {
|
||||||
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
||||||
const scope = this
|
const scope = this
|
||||||
Promise.all([promise]).then(res => {
|
Promise.all([promise]).then((res) => {
|
||||||
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
||||||
cornerstone.updateImage(scope.canvas)
|
cornerstone.updateImage(scope.canvas)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ export default {
|
|||||||
TrialConfig: {},
|
TrialConfig: {},
|
||||||
TrialStatusStr: null,
|
TrialStatusStr: null,
|
||||||
trialId: null,
|
trialId: null,
|
||||||
IsAdditionalAssessment: false
|
IsAdditionalAssessment: false,
|
||||||
|
isReload: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -71,17 +72,23 @@ export default {
|
|||||||
if (~url.indexOf('?')) {
|
if (~url.indexOf('?')) {
|
||||||
query = url.split('?')[1]
|
query = url.split('?')[1]
|
||||||
}
|
}
|
||||||
zzSessionStorage.setItem('lastWorkbench', `${v.path}${query ? '?' : ''}${query}`)
|
if (!this.isReload) {
|
||||||
|
zzSessionStorage.setItem('lastWorkbench', `${v.path}${query ? '?' : ''}${query}`)
|
||||||
|
} else {
|
||||||
|
this.isReload = false
|
||||||
|
}
|
||||||
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
||||||
if (this.trialsTab === '/trials/trials-panel') {
|
if (this.trialsTab === '/trials/trials-panel') {
|
||||||
this.$router.replace({ path: `${firstGoIn.path}${query ? '?' : ''}${query}` })
|
var targetPath = firstGoIn.path
|
||||||
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
||||||
this.$router.replace({ path: `${firstGoIn.children[0].path}${query ? '?' : ''}${query}` })
|
targetPath = firstGoIn.children[0].path
|
||||||
}
|
}
|
||||||
|
this.$router.replace({ path: `${targetPath}${query ? '?' : ''}${query}` })
|
||||||
}
|
}
|
||||||
// document.cookie = 'TrialId=' + this.$route.query.trialId + ';path=/'
|
// document.cookie = 'TrialId=' + this.$route.query.trialId + ';path=/'
|
||||||
},
|
},
|
||||||
trialId(v) {
|
trialId(v) {
|
||||||
|
if (!this.$route.query.trialId) return
|
||||||
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(async res => {
|
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(async res => {
|
||||||
var total = res.OtherInfo.NeedSignCount
|
var total = res.OtherInfo.NeedSignCount
|
||||||
var TrialStatusStr = res.OtherInfo.TrialStatusStr
|
var TrialStatusStr = res.OtherInfo.TrialStatusStr
|
||||||
@@ -94,28 +101,34 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.$EventBus.$on("reload", () => {
|
||||||
|
this.isReload = true
|
||||||
|
})
|
||||||
var query = ``
|
var query = ``
|
||||||
var url = window.location.href
|
var url = window.location.href
|
||||||
if (~url.indexOf('?')) {
|
if (~url.indexOf('?')) {
|
||||||
query = url.split('?')[1]
|
query = url.split('?')[1]
|
||||||
}
|
}
|
||||||
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(async res => {
|
if (this.$route.query.trialId) {
|
||||||
var total = res.OtherInfo.NeedSignCount
|
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(async res => {
|
||||||
var TrialStatusStr = res.OtherInfo.TrialStatusStr
|
var total = res.OtherInfo.NeedSignCount
|
||||||
this.IsAdditionalAssessment = res.OtherInfo.IsAdditionalAssessment
|
var TrialStatusStr = res.OtherInfo.TrialStatusStr
|
||||||
this.TrialStatusStr = TrialStatusStr
|
this.IsAdditionalAssessment = res.OtherInfo.IsAdditionalAssessment
|
||||||
await store.dispatch('user/setTotalNeedSignTrialDocCount', total)
|
this.TrialStatusStr = TrialStatusStr
|
||||||
await store.dispatch('user/setTrialStatusStr', TrialStatusStr)
|
await store.dispatch('user/setTotalNeedSignTrialDocCount', total)
|
||||||
this.TrialConfig = res.OtherInfo.TrialConfig
|
await store.dispatch('user/setTrialStatusStr', TrialStatusStr)
|
||||||
})
|
this.TrialConfig = res.OtherInfo.TrialConfig
|
||||||
|
})
|
||||||
|
}
|
||||||
this.selectedTab()
|
this.selectedTab()
|
||||||
this.getTrialList()
|
this.getTrialList()
|
||||||
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
||||||
if (this.trialsTab === '/trials/trials-panel') {
|
if (this.trialsTab === '/trials/trials-panel') {
|
||||||
this.$router.replace({ path: `${firstGoIn.path}${query ? '?' : ''}${query}` })
|
var targetPath = firstGoIn.path
|
||||||
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
||||||
this.$router.replace({ path: `${firstGoIn.children[0].path}${query ? '?' : ''}${query}` })
|
targetPath = firstGoIn.children[0].path
|
||||||
}
|
}
|
||||||
|
this.$router.replace({ path: `${targetPath}${query ? '?' : ''}${query}` })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -130,6 +143,9 @@ export default {
|
|||||||
let chartList = [
|
let chartList = [
|
||||||
'/trials/trials-panel/trial-summary/report-forms'
|
'/trials/trials-panel/trial-summary/report-forms'
|
||||||
]
|
]
|
||||||
|
let dataSyncList = [
|
||||||
|
`/trials/trials-panel/trial-summary/data-sync`
|
||||||
|
]
|
||||||
var qualityList = [
|
var qualityList = [
|
||||||
'/trials/trials-panel/visit/crc-question',
|
'/trials/trials-panel/visit/crc-question',
|
||||||
'/trials/trials-panel/visit/qc-check',
|
'/trials/trials-panel/visit/qc-check',
|
||||||
@@ -145,6 +161,9 @@ export default {
|
|||||||
'/trials/trials-panel/trial-summary/image-inspect',
|
'/trials/trials-panel/trial-summary/image-inspect',
|
||||||
'/trials/trials-panel/trial-summary/push-record',
|
'/trials/trials-panel/trial-summary/push-record',
|
||||||
]
|
]
|
||||||
|
if (this.$store.state.trials.config.TrialDataStoreType !== 1 && ~dataSyncList.indexOf(path)) {
|
||||||
|
isShow = false
|
||||||
|
}
|
||||||
if (!this.$store.state.trials.config.IsExternalViewTrialChart && ~chartList.indexOf(path) && this.hasPermi(['role:cmm', 'role:cpm', 'role:ea', 'role:mc', 'role:smm', 'role:spm'])) {
|
if (!this.$store.state.trials.config.IsExternalViewTrialChart && ~chartList.indexOf(path) && this.hasPermi(['role:cmm', 'role:cpm', 'role:ea', 'role:mc', 'role:smm', 'role:spm'])) {
|
||||||
isShow = false
|
isShow = false
|
||||||
}
|
}
|
||||||
@@ -201,15 +220,19 @@ export default {
|
|||||||
if (~url.indexOf('?')) {
|
if (~url.indexOf('?')) {
|
||||||
query = url.split('?')[1]
|
query = url.split('?')[1]
|
||||||
}
|
}
|
||||||
this.$router.push({ path: `${v.name}${query ? '?' : ''}${query}` })
|
var trialsPanelList = this.trialsRouter.children.find(item => { return item.name === 'TrialsPanel' }).children
|
||||||
var trialsPanelList = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children
|
var currentRoute = trialsPanelList.find(c => { return c.path === v.name })
|
||||||
var isHasChild = trialsPanelList.find(c => { return c.path === v.name }) && trialsPanelList.find(c => { return c.path === v.name }).children
|
|
||||||
if (trialsPanelList.find(c => { return c.path === v.name }) && trialsPanelList.find(c => { return c.path === v.name }).tabHiddn) {
|
if (currentRoute && currentRoute.tabHiddn) {
|
||||||
|
this.$router.push({ path: `${v.name}${query ? '?' : ''}${query}` })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var isHasChild = currentRoute && currentRoute.children
|
||||||
if (isHasChild && isHasChild.length > 0) {
|
if (isHasChild && isHasChild.length > 0) {
|
||||||
this.trialsTabChild = isHasChild[0].path
|
this.trialsTabChild = isHasChild[0].path
|
||||||
this.$router.push({ path: `${this.trialsTabChild}${query ? '?' : ''}${query}` })
|
this.$router.push({ path: `${this.trialsTabChild}${query ? '?' : ''}${query}` })
|
||||||
|
} else {
|
||||||
|
this.$router.push({ path: `${v.name}${query ? '?' : ''}${query}` })
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<el-table-column type="index" width="40" />
|
<el-table-column type="index" width="40" />
|
||||||
<!--受试者-->
|
<!--受试者-->
|
||||||
<el-table-column :label="$t('download:table:subjectCode')" min-width="130" prop="SubjectCode"
|
<el-table-column :label="$t('download:table:subjectCode')" min-width="130" prop="SubjectCode"
|
||||||
show-overflow-tooltip />
|
show-overflow-tooltip v-if="isReadingTaskViewInOrder !== 0" />
|
||||||
<!--访视名称-->
|
<!--访视名称-->
|
||||||
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" sortable v-if="IsImageSegment" />
|
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" sortable v-if="IsImageSegment" />
|
||||||
<!--任务名称-->
|
<!--任务名称-->
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<el-table-column :label="$t('common:action:action')" fixed="right" width="150">
|
<el-table-column :label="$t('common:action:action')" fixed="right" width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!--预览--->
|
<!--预览--->
|
||||||
<el-button circle icon="el-icon-view" :title="$t('download:button:preview')"
|
<el-button circle icon="el-icon-view" :title="$t('download:button:preview')" :disabled="forbid"
|
||||||
@click.stop="preview(scope.row)" />
|
@click.stop="preview(scope.row)" />
|
||||||
<!--下载--->
|
<!--下载--->
|
||||||
<el-button circle icon="el-icon-download" :title="$t('download:button:download')"
|
<el-button circle icon="el-icon-download" :title="$t('download:button:download')"
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :modelList="modelList" :bodyPart="bodyPart"
|
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :modelList="modelList" :bodyPart="bodyPart"
|
||||||
:subjectVisitId="modelSubjectVisitId" :IsDicom="IsDicom" :isDownload="true" :visitTaskId="modelTaskId"
|
:subjectVisitId="modelSubjectVisitId" :IsDicom="IsDicom" :isDownload="true" :visitTaskId="modelTaskId"
|
||||||
:IsImageSegment="IsImageSegment" :Criterion="Criterion" />
|
:IsImageSegment="IsImageSegment" :Criterion="Criterion" :IsReadingTaskViewInOrder="isReadingTaskViewInOrder" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -111,6 +111,10 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
forbid: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
SubjectId: {
|
SubjectId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -132,6 +136,14 @@ export default {
|
|||||||
IsImageSegment: {
|
IsImageSegment: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
},
|
||||||
|
isReadingTaskViewInOrder: {
|
||||||
|
type: Number,
|
||||||
|
default: 2,
|
||||||
|
},
|
||||||
|
isReading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -166,6 +178,7 @@ export default {
|
|||||||
this.getList()
|
this.getList()
|
||||||
this.title = `Download Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
this.title = `Download Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||||
if (this.IsImageSegment) this.title = `Download Images:${this.SubjectCode}`
|
if (this.IsImageSegment) this.title = `Download Images:${this.SubjectCode}`
|
||||||
|
if (this.isReadingTaskViewInOrder === 0) this.title = ''
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
store.dispatch('trials/setUnLock', false)
|
store.dispatch('trials/setUnLock', false)
|
||||||
@@ -433,6 +446,9 @@ export default {
|
|||||||
let params = {
|
let params = {
|
||||||
TrialImageDownloadId: this.downloadId,
|
TrialImageDownloadId: this.downloadId,
|
||||||
}
|
}
|
||||||
|
if (this.isReading) {
|
||||||
|
params.VisitTaskId = this.TaskId
|
||||||
|
}
|
||||||
await downloadImageSuccess(params)
|
await downloadImageSuccess(params)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
@@ -443,6 +459,9 @@ export default {
|
|||||||
if (this.IsImageSegment) {
|
if (this.IsImageSegment) {
|
||||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.VisitName}`
|
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.VisitName}`
|
||||||
}
|
}
|
||||||
|
if (this.isReadingTaskViewInOrder === 0) {
|
||||||
|
this.model_cfg.title = ''
|
||||||
|
}
|
||||||
if (item.IsDicom) {
|
if (item.IsDicom) {
|
||||||
this.modelList = item.DicomStudyList
|
this.modelList = item.DicomStudyList
|
||||||
} else {
|
} else {
|
||||||
@@ -484,11 +503,11 @@ export default {
|
|||||||
let routeData = null
|
let routeData = null
|
||||||
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
||||||
routeData = this.$router.resolve({
|
routeData = this.$router.resolve({
|
||||||
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
|
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
routeData = this.$router.resolve({
|
routeData = this.$router.resolve({
|
||||||
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
|
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.open = window.open(routeData.href, '_blank')
|
this.open = window.open(routeData.href, '_blank')
|
||||||
@@ -501,7 +520,7 @@ export default {
|
|||||||
var token = getToken()
|
var token = getToken()
|
||||||
let trialId = this.$route.query.trialId
|
let trialId = this.$route.query.trialId
|
||||||
const routeData = this.$router.resolve({
|
const routeData = this.$router.resolve({
|
||||||
path: `/showvisitdicoms?page=download&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
|
path: `/showvisitdicoms?page=download&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
this.open = window.open(routeData.href, '_blank')
|
this.open = window.open(routeData.href, '_blank')
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,36 +2,21 @@
|
|||||||
<!--FEEDBACK-->
|
<!--FEEDBACK-->
|
||||||
<div v-if="visible" @click.stop="() => false" class="feedBack-box">
|
<div v-if="visible" @click.stop="() => false" class="feedBack-box">
|
||||||
<div class="feedBack-box-modal"></div>
|
<div class="feedBack-box-modal"></div>
|
||||||
<el-dialog
|
<el-dialog :visible.sync="visible" v-dialogDrag width="800px" :close-on-click-modal="false" @close="cancel"
|
||||||
:visible.sync="visible"
|
:modal="false">
|
||||||
v-dialogDrag
|
|
||||||
width="800px"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
@close="cancel"
|
|
||||||
:modal="false"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</div>
|
</div>
|
||||||
<!-- 项目详情 -->
|
<!-- 项目详情 -->
|
||||||
<div class="trialsBox" v-if="visitTaskId || SubjectVisitId">
|
<div class="trialsBox" v-if="visitTaskId || SubjectVisitId">
|
||||||
<el-form
|
<el-form label-position="right" :model="form" :inline="true" class="trialsForm" v-if="type === 'detail'">
|
||||||
label-position="right"
|
|
||||||
:model="form"
|
|
||||||
:inline="true"
|
|
||||||
class="trialsForm"
|
|
||||||
v-if="type === 'detail'"
|
|
||||||
>
|
|
||||||
<el-form-item :label="$t('feedBack:trials:code')" style="width: 40%">
|
<el-form-item :label="$t('feedBack:trials:code')" style="width: 40%">
|
||||||
<span>{{ form.TrialCode }}</span>
|
<span>{{ form.TrialCode }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('feedBack:trials:name')" style="width: 40%">
|
<el-form-item :label="$t('feedBack:trials:name')" style="width: 40%">
|
||||||
<span>{{ form.ExperimentName }}</span>
|
<span>{{ form.ExperimentName }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:trials:siteCode')" style="width: 40%">
|
||||||
:label="$t('feedBack:trials:siteCode')"
|
|
||||||
style="width: 40%"
|
|
||||||
>
|
|
||||||
<span>{{ form.TrialSiteCode }}</span>
|
<span>{{ form.TrialSiteCode }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('feedBack:trials:visit')" style="width: 40%">
|
<el-form-item :label="$t('feedBack:trials:visit')" style="width: 40%">
|
||||||
@@ -39,47 +24,21 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<el-form
|
<el-form ref="feedBackForm" label-position="right" :model="form" :rules="rules" label-width="100px">
|
||||||
ref="feedBackForm"
|
|
||||||
label-position="right"
|
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="100px"
|
|
||||||
>
|
|
||||||
<!-- 影像异常tip -->
|
<!-- 影像异常tip -->
|
||||||
<p class="tip" v-if="type === 'imgfail'">
|
<p class="tip" v-if="type === 'imgfail'">
|
||||||
<i
|
<i class="el-icon-warning-outline" style="color: #f56c6c; font-size: 24px"></i>
|
||||||
class="el-icon-warning-outline"
|
|
||||||
style="color: #f56c6c; font-size: 24px"
|
|
||||||
></i>
|
|
||||||
<span>{{ $t('feedBack:imgfail:tip') }}</span>
|
<span>{{ $t('feedBack:imgfail:tip') }}</span>
|
||||||
</p>
|
</p>
|
||||||
<!-- 问题反馈 -->
|
<!-- 问题反馈 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:form:feedBack')" prop="QuestionType" v-if="type === 'feedback' && trialId">
|
||||||
:label="$t('feedBack:form:feedBack')"
|
<el-select v-model="form.QuestionType" style="width: 100%" popper-class="feedBack-select-box">
|
||||||
prop="QuestionType"
|
<el-option v-for="item in QuestionTypeOptions" :key="item.id" :label="item.label" :value="item.value">
|
||||||
v-if="type === 'feedback' && trialId"
|
|
||||||
>
|
|
||||||
<el-select
|
|
||||||
v-model="form.QuestionType"
|
|
||||||
style="width: 100%"
|
|
||||||
popper-class="feedBack-select-box"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in QuestionTypeOptions"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 问题反馈 -->
|
<!-- 问题反馈 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:form:feedBack')" prop="QuestionType" v-if="type === 'detail'">
|
||||||
:label="$t('feedBack:form:feedBack')"
|
|
||||||
prop="QuestionType"
|
|
||||||
v-if="type === 'detail'"
|
|
||||||
>
|
|
||||||
<span>{{
|
<span>{{
|
||||||
QuestionTypeOptions.filter(
|
QuestionTypeOptions.filter(
|
||||||
(item) => item.value === form.QuestionType
|
(item) => item.value === form.QuestionType
|
||||||
@@ -87,43 +46,22 @@
|
|||||||
}}</span>
|
}}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 问题描述 -->
|
<!-- 问题描述 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:form:description')" prop="QuestionDescription">
|
||||||
:label="$t('feedBack:form:description')"
|
<el-input v-model="form.QuestionDescription" type="textarea" :rows="4" :maxlength="500"
|
||||||
prop="QuestionDescription"
|
:disabled="type === 'detail'" />
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="form.QuestionDescription"
|
|
||||||
type="textarea"
|
|
||||||
:rows="4"
|
|
||||||
:maxlength="500"
|
|
||||||
:disabled="type === 'detail'"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 截图 -->
|
<!-- 截图 -->
|
||||||
<el-form-item :label="$t('feedBack:form:screenshot')" prop="screenshot">
|
<el-form-item :label="$t('feedBack:form:screenshot')" prop="screenshot">
|
||||||
<uploadImage
|
<uploadImage :path.sync="form.ScreenshotList" :isUpload.sync="loading" :trialId="trialId"
|
||||||
:path.sync="form.ScreenshotList"
|
:disabled="type === 'detail'" ref="uploadImage" />
|
||||||
:isUpload.sync="loading"
|
|
||||||
:trialId="trialId"
|
|
||||||
:disabled="type === 'detail'"
|
|
||||||
ref="uploadImage"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 反馈时间 -->
|
<!-- 反馈时间 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:form:time')" prop="screenshot" v-if="type === 'detail'">
|
||||||
:label="$t('feedBack:form:time')"
|
|
||||||
prop="screenshot"
|
|
||||||
v-if="type === 'detail'"
|
|
||||||
>
|
|
||||||
<span>{{ form.CreateTime }}</span>
|
<span>{{ form.CreateTime }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 状态 -->
|
<!-- 状态 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:form:status')" prop="screenshot" v-if="type === 'detail' && level >= 7">
|
||||||
:label="$t('feedBack:form:status')"
|
<!-- <el-switch
|
||||||
prop="screenshot"
|
|
||||||
v-if="type === 'detail' && level > 7"
|
|
||||||
>
|
|
||||||
<el-switch
|
|
||||||
v-model="form.State"
|
v-model="form.State"
|
||||||
active-color="#13ce66"
|
active-color="#13ce66"
|
||||||
inactive-color="#ff4949"
|
inactive-color="#ff4949"
|
||||||
@@ -134,21 +72,27 @@
|
|||||||
:disabled="level < 8 || !isStateChange"
|
:disabled="level < 8 || !isStateChange"
|
||||||
@change="changeState"
|
@change="changeState"
|
||||||
>
|
>
|
||||||
</el-switch>
|
</el-switch> -->
|
||||||
|
<el-select v-model="form.State" :popper-append-to-body="false" :disabled="level < 8">
|
||||||
|
<el-option v-for="item in $d.FeedBackStatus" :key="item.id" :label="item.label"
|
||||||
|
:value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 无法解决原因 -->
|
||||||
|
<el-form-item :label="$t('feedBack:form:Reason')" prop="Reason"
|
||||||
|
v-if="type === 'detail' && level >= 7 && form.State === 2">
|
||||||
|
<el-input v-model="form.Reason" type="textarea" :rows="4" :maxlength="500" :disabled="level < 8" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" v-if="type !== 'detail' || isImgfail">
|
<!--type !== 'detail'-->
|
||||||
|
<div slot="footer" v-if="level >= 7 || isImgfail">
|
||||||
<!-- 取消 -->
|
<!-- 取消 -->
|
||||||
<el-button size="small" @click.stop="cancel">
|
<el-button size="small" @click.stop="cancel" v-if="type !== 'detail' || level >= 8">
|
||||||
{{ $t('feedBack:button:cancel') }}
|
{{ $t('feedBack:button:cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 保存 -->
|
<!-- 保存 -->
|
||||||
<el-button
|
<el-button type="primary" size="small" @click.stop="save" :loading="loading"
|
||||||
type="primary"
|
v-if="type !== 'detail' || level >= 8">
|
||||||
size="small"
|
|
||||||
@click.stop="save"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
{{ $t('feedBack:button:save') }}
|
{{ $t('feedBack:button:save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -190,6 +134,7 @@ export default {
|
|||||||
SubjectVisitId: null,
|
SubjectVisitId: null,
|
||||||
ScreenshotList: [],
|
ScreenshotList: [],
|
||||||
ScreenshotListStr: null,
|
ScreenshotListStr: null,
|
||||||
|
Reason: null
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
QuestionType: [
|
QuestionType: [
|
||||||
@@ -307,6 +252,7 @@ export default {
|
|||||||
// 修改状态
|
// 修改状态
|
||||||
async changeState() {
|
async changeState() {
|
||||||
if (this.isImgfail) return
|
if (this.isImgfail) return
|
||||||
|
if (this.form.State !== 1 && this.form.State !== 0) return false
|
||||||
try {
|
try {
|
||||||
let data = {
|
let data = {
|
||||||
IdList: [this.Id],
|
IdList: [this.Id],
|
||||||
@@ -381,6 +327,10 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
::v-deep.el-popper {
|
||||||
|
z-index: 4000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.tip {
|
.tip {
|
||||||
width: 86%;
|
width: 86%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
@@ -389,12 +339,14 @@ export default {
|
|||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
// border-radius: 5px;
|
// border-radius: 5px;
|
||||||
// background-color: #eee;
|
// background-color: #eee;
|
||||||
i {
|
i {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.trialsBox {
|
.trialsBox {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@@ -405,11 +357,13 @@ export default {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trialsForm {
|
.trialsForm {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,20 +8,49 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getReportsChartData } from "@/api/reading"
|
import { getReportsChartData } from "@/api/reading"
|
||||||
let echarts = require('echarts/lib/echarts');
|
import * as echarts from 'echarts/core';
|
||||||
|
import { LineChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
// 标签自动布局、全局过渡动画等特性
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
LineChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
// let echarts = require('echarts/lib/echarts');
|
||||||
|
|
||||||
// 按需引入图表
|
// 按需引入图表
|
||||||
// require('echarts/lib/chart/bar');
|
// require('echarts/lib/chart/bar');
|
||||||
require('echarts/lib/chart/line');
|
// require('echarts/lib/chart/line');
|
||||||
// require('echarts/lib/chart/pie');
|
// require('echarts/lib/chart/pie');
|
||||||
// require('echarts/lib/chart/scatter');
|
// require('echarts/lib/chart/scatter');
|
||||||
|
|
||||||
// 按需引入组件
|
// 按需引入组件
|
||||||
require('echarts/lib/component/tooltip');
|
// require('echarts/lib/component/tooltip');
|
||||||
require('echarts/lib/component/title');
|
// require('echarts/lib/component/title');
|
||||||
require('echarts/lib/component/legend');
|
// require('echarts/lib/component/legend');
|
||||||
require('echarts/lib/component/grid');
|
// require('echarts/lib/component/grid');
|
||||||
require('echarts/lib/component/dataZoom');
|
// require('echarts/lib/component/dataZoom');
|
||||||
export default {
|
export default {
|
||||||
name: "readingChart",
|
name: "readingChart",
|
||||||
props: {
|
props: {
|
||||||
@@ -33,7 +62,8 @@ export default {
|
|||||||
zIndex: 9,
|
zIndex: 9,
|
||||||
chart: null,
|
chart: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
key: 'readingChart'
|
key: 'readingChart',
|
||||||
|
isInteger: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -72,12 +102,13 @@ export default {
|
|||||||
let res = await getReportsChartData(params)
|
let res = await getReportsChartData(params)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
|
this.isInteger = res.Result.Type === 'number' && res.Result.ValueType === 0
|
||||||
let LatestScanDateList = res.Result.LatestScanDateList.map(item => item.split(" ")[0])
|
let LatestScanDateList = res.Result.LatestScanDateList.map(item => item.split(" ")[0])
|
||||||
let obj = {
|
let obj = {
|
||||||
title: QuestionName,
|
title: QuestionName,
|
||||||
xAxisData: LatestScanDateList || [],
|
xAxisData: LatestScanDateList || [],
|
||||||
series: [],
|
series: [],
|
||||||
unit: this.$fd("ValueUnit", res.Result.Unit),
|
unit: res.Result.Unit === 0 ? '' : res.Result.Unit === 4 ? res.Result.CustomUnit : this.$fd("ValueUnit", res.Result.Unit),
|
||||||
visitName: res.Result.VisitTaskNameList,
|
visitName: res.Result.VisitTaskNameList,
|
||||||
min: null,
|
min: null,
|
||||||
max: null
|
max: null
|
||||||
@@ -94,43 +125,6 @@ export default {
|
|||||||
type: 'line'
|
type: 'line'
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
// if (Array.isArray(res.Result.LatestScanDateList) && res.Result.LatestScanDateList.length >= 2) {
|
|
||||||
// let hours = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'hours');
|
|
||||||
// let days = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'days');
|
|
||||||
// let months = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'months');
|
|
||||||
// console.log(hours, 'hours')
|
|
||||||
// console.log(days, 'days')
|
|
||||||
// console.log(months, 'months')
|
|
||||||
// if (hours < 24) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (days >= 1 && days <= 7) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'days').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (days > 7 && days < 30) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).endOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (months >= 1 && months <= 3) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(4, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (months > 3 && months <= 6) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (months > 6 && months <= 12) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(13, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// if (months > 12) {
|
|
||||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
|
||||||
// obj.max = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).add(1, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// console.log(obj)
|
|
||||||
this.initChart(obj)
|
this.initChart(obj)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -151,7 +145,13 @@ export default {
|
|||||||
text: obj.title,
|
text: obj.title,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: "#fff"
|
color: "#fff"
|
||||||
}
|
},
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 50,
|
||||||
|
bottom: 30
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
@@ -193,6 +193,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
|
show: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
}
|
}
|
||||||
@@ -200,6 +201,9 @@ export default {
|
|||||||
},
|
},
|
||||||
series: obj.series
|
series: obj.series
|
||||||
};
|
};
|
||||||
|
if (this.isInteger) {
|
||||||
|
option.yAxis.minInterval = 1
|
||||||
|
}
|
||||||
// 4. 使用配置项渲染图表
|
// 4. 使用配置项渲染图表
|
||||||
this.chart.setOption(option);
|
this.chart.setOption(option);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export default {
|
|||||||
display: none !important; /* 隐藏原生 radio 输入,但仍然允许交互 */
|
display: none !important; /* 隐藏原生 radio 输入,但仍然允许交互 */
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled)
|
::v-deep .el-radio:focus:not(.is-focus):not(:active):not(.is-disabled)
|
||||||
.el-radio__inner {
|
.el-radio__inner {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
<!--检查列表-->
|
<!--检查列表-->
|
||||||
<el-table :data="list" style="width: 100%" height="300" :loading="loading">
|
<el-table :data="list" style="width: 100%" height="300" :loading="loading">
|
||||||
<!--受试者-->
|
<!--受试者-->
|
||||||
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" sortable />
|
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" sortable
|
||||||
|
v-if="isReadingTaskViewInOrder !== 0" />
|
||||||
<!--访视名称-->
|
<!--访视名称-->
|
||||||
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" v-if="IsImageSegment" sortable />
|
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" v-if="IsImageSegment" sortable />
|
||||||
<!--任务名称-->
|
<!--任务名称-->
|
||||||
@@ -42,7 +43,8 @@
|
|||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div class="btnBox">
|
<div class="btnBox">
|
||||||
<!--上传--->
|
<!--上传--->
|
||||||
<form id="inputForm" :ref="`uploadForm_${scope.row.Id}`" enctype="multipart/form-data">
|
<form id="inputForm" :ref="`uploadForm_${scope.row.Id}`" enctype="multipart/form-data"
|
||||||
|
v-if="!forbid && (!isReading || isDownloaded)">
|
||||||
<div class="form-group" style="margin-right: 10px">
|
<div class="form-group" style="margin-right: 10px">
|
||||||
<div :id="`directoryInputWrapper_${scope.row.Id}`" class="btn btn-link file-input">
|
<div :id="`directoryInputWrapper_${scope.row.Id}`" class="btn btn-link file-input">
|
||||||
<el-button circle icon="el-icon-upload2" :disabled="btnLoading" :loading="btnLoading"
|
<el-button circle icon="el-icon-upload2" :disabled="btnLoading" :loading="btnLoading"
|
||||||
@@ -59,27 +61,22 @@
|
|||||||
scope.row.UploadStudyList.length <= 0
|
scope.row.UploadStudyList.length <= 0
|
||||||
" @click.stop="handleViewReadingImages(scope.row)" :title="$t('upload:dicom:button:preview')" />
|
" @click.stop="handleViewReadingImages(scope.row)" :title="$t('upload:dicom:button:preview')" />
|
||||||
<!--删除--->
|
<!--删除--->
|
||||||
<el-button circle :disabled="!scope.row.UploadStudyList ||
|
<el-button circle icon="el-icon-delete" :title="$t('upload:dicom:button:delete')"
|
||||||
scope.row.UploadStudyList.length <= 0 ||
|
@click.stop="remove(scope.row)" />
|
||||||
scope.row.ReadingTaskState === 2
|
|
||||||
" icon="el-icon-delete" :title="$t('upload:dicom:button:delete')" @click.stop="remove(scope.row)" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div style="margin: 10px 0" class="top">
|
<div style="margin: 10px 0" class="top">
|
||||||
<span>{{ $t('upload:dicom:uploadTitle') }}</span>
|
<span>{{ $t('upload:dicom:uploadTitle') }}</span>
|
||||||
<div class="btnBox">
|
<div class="btnBox" v-if="!forbid && (!isReading || isDownloaded)">
|
||||||
<span style="margin-right: 10px">
|
<span style="margin-right: 10px">{{ $store.state.trials.uploadTip }}</span>
|
||||||
{{ $store.state.trials.uploadTip }}
|
|
||||||
</span>
|
|
||||||
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
|
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div id="directoryInputWrapper" class="btn btn-link file-input">
|
<div id="directoryInputWrapper" class="btn btn-link file-input">
|
||||||
<el-button type="primary" :disabled="btnLoading" :loading="btnLoading" size="mini">
|
<el-button type="primary" :disabled="btnLoading" :loading="btnLoading" size="mini">{{
|
||||||
{{ $t('upload:dicom:button:batchUpload') }}
|
$t('upload:dicom:button:batchUpload') }}</el-button>
|
||||||
</el-button>
|
<input type="file" name="file" ref="pathClear" :disabled="btnLoading" webkitdirectory multiple title
|
||||||
<input type="file" name="file" ref="pathClear" :disabled="btnLoading" webkitdirectory multiple title=""
|
|
||||||
@change="beginScanFiles($event)" />
|
@change="beginScanFiles($event)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,8 +91,10 @@
|
|||||||
<template slot="header">
|
<template slot="header">
|
||||||
<el-tooltip placement="top">
|
<el-tooltip placement="top">
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
{{ $t('trials:uploadDicomList:table:studyDetail1') }}<br />
|
{{ $t('trials:uploadDicomList:table:studyDetail1') }}
|
||||||
{{ $t('trials:uploadDicomList:table:studyDetail2') }}<br />
|
<br />
|
||||||
|
{{ $t('trials:uploadDicomList:table:studyDetail2') }}
|
||||||
|
<br />
|
||||||
{{ $t('trials:uploadedDicoms:table:studyDate') }}
|
{{ $t('trials:uploadedDicoms:table:studyDate') }}
|
||||||
</div>
|
</div>
|
||||||
<span>{{ $t('trials:uploadDicomList:table:studyInfo') }}</span>
|
<span>{{ $t('trials:uploadDicomList:table:studyInfo') }}</span>
|
||||||
@@ -105,13 +104,15 @@
|
|||||||
<div style="line-height: 15px">
|
<div style="line-height: 15px">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span v-if="scope.row.dicomInfo.accNumber"><span style="font-weight: 500">Acc:</span>
|
<span v-if="scope.row.dicomInfo.accNumber">
|
||||||
{{ scope.row.dicomInfo.accNumber }}</span>
|
<span style="font-weight: 500">Acc:</span>
|
||||||
|
{{ scope.row.dicomInfo.accNumber }}
|
||||||
|
</span>
|
||||||
<span v-else style="color: #f44336">N/A</span>
|
<span v-else style="color: #f44336">N/A</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: inline-block; margin-right: 2px">
|
<div style="display: inline-block; margin-right: 2px">
|
||||||
<span v-if="scope.row.dicomInfo.modality.length > 0">
|
<span v-if="scope.row.dicomInfo.modality.length > 0">{{ scope.row.dicomInfo.modality.join('、')
|
||||||
{{ scope.row.dicomInfo.modality.join('、') }},</span>
|
}},</span>
|
||||||
<span v-else style="color: #f44336">N/A,</span>
|
<span v-else style="color: #f44336">N/A,</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: inline-block; margin-right: 2px">
|
<div style="display: inline-block; margin-right: 2px">
|
||||||
@@ -126,20 +127,15 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div style="display: inline-block; margin-right: 2px">
|
<div style="display: inline-block; margin-right: 2px">
|
||||||
<span v-if="scope.row.dicomInfo.bodyPart">
|
<span v-if="scope.row.dicomInfo.bodyPart">{{ scope.row.dicomInfo.bodyPart }},</span>
|
||||||
{{ scope.row.dicomInfo.bodyPart }},
|
<span v-else style="color: #f44336">N/A,</span>
|
||||||
</span>
|
|
||||||
<span v-else style="color: #f44336">N/A, </span>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: inline-block">
|
<div style="display: inline-block">
|
||||||
<span v-if="scope.row.dicomInfo.description">
|
<span v-if="scope.row.dicomInfo.description">{{ scope.row.dicomInfo.description }}</span>
|
||||||
{{ scope.row.dicomInfo.description }}</span>
|
|
||||||
<span v-else style="color: #f44336">N/A</span>
|
<span v-else style="color: #f44336">N/A</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>{{ scope.row.dicomInfo.studyTime }}</div>
|
||||||
{{ scope.row.dicomInfo.studyTime }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -147,8 +143,10 @@
|
|||||||
<template slot="header">
|
<template slot="header">
|
||||||
<el-tooltip placement="top">
|
<el-tooltip placement="top">
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
{{ $t('trials:uploadDicomList:table:pId') }}<br />
|
{{ $t('trials:uploadDicomList:table:pId') }}
|
||||||
{{ $t('trials:uploadDicomList:table:patientName') }}<br />
|
<br />
|
||||||
|
{{ $t('trials:uploadDicomList:table:patientName') }}
|
||||||
|
<br />
|
||||||
{{ $t('trials:uploadDicomList:table:pInfo') }}
|
{{ $t('trials:uploadDicomList:table:pInfo') }}
|
||||||
</div>
|
</div>
|
||||||
<span>{{ $t('trials:uploadDicomList:table:patientInfo') }}</span>
|
<span>{{ $t('trials:uploadDicomList:table:patientInfo') }}</span>
|
||||||
@@ -157,8 +155,11 @@
|
|||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div style="line-height: 15px">
|
<div style="line-height: 15px">
|
||||||
<div>
|
<div>
|
||||||
<span v-if="scope.row.dicomInfo.patientId"><span style="font-weight: 500">PID: </span>{{
|
<span v-if="scope.row.dicomInfo.patientId">
|
||||||
scope.row.dicomInfo.patientId }}</span>
|
<span style="font-weight: 500">PID:</span>
|
||||||
|
{{
|
||||||
|
scope.row.dicomInfo.patientId }}
|
||||||
|
</span>
|
||||||
<span v-else style="color: #f44336">N/A</span>
|
<span v-else style="color: #f44336">N/A</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -227,8 +228,7 @@
|
|||||||
<span v-if="
|
<span v-if="
|
||||||
!scope.row.dicomInfo.failedFileCount &&
|
!scope.row.dicomInfo.failedFileCount &&
|
||||||
!scope.row.dicomInfo.isInit
|
!scope.row.dicomInfo.isInit
|
||||||
">
|
">{{ $t('trials:uploadDicomList:table:status1') }}</span>
|
||||||
{{ $t('trials:uploadDicomList:table:status1') }}</span>
|
|
||||||
<span style="color: #409eff" v-else-if="
|
<span style="color: #409eff" v-else-if="
|
||||||
!scope.row.dicomInfo.failedFileCount &&
|
!scope.row.dicomInfo.failedFileCount &&
|
||||||
scope.row.dicomInfo.isInit &&
|
scope.row.dicomInfo.isInit &&
|
||||||
@@ -246,9 +246,11 @@
|
|||||||
scope.row.uploadState.record &&
|
scope.row.uploadState.record &&
|
||||||
scope.row.uploadState.record.fileCount === 0
|
scope.row.uploadState.record.fileCount === 0
|
||||||
">{{ $t('trials:uploadDicomList:table:status5') }}</span>
|
">{{ $t('trials:uploadDicomList:table:status5') }}</span>
|
||||||
<span style="color: #f66" v-else>{{
|
<span style="color: #f66" v-else>
|
||||||
$t('trials:uploadDicomList:table:Failed')
|
{{
|
||||||
}}</span>
|
$t('trials:uploadDicomList:table:Failed')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('trials:uploadDicomList:table:record')" min-width="140" show-overflow-tooltip>
|
<el-table-column :label="$t('trials:uploadDicomList:table:record')" min-width="140" show-overflow-tooltip>
|
||||||
@@ -259,42 +261,42 @@
|
|||||||
{{ $t('trials:uploadDicomList:table:Existed') }}:
|
{{ $t('trials:uploadDicomList:table:Existed') }}:
|
||||||
<div v-if="scope.row.uploadState.record.Existed.length">
|
<div v-if="scope.row.uploadState.record.Existed.length">
|
||||||
<div v-for="item of scope.row.uploadState.record.Existed" :key="item"
|
<div v-for="item of scope.row.uploadState.record.Existed" :key="item"
|
||||||
style="font-size: 12px; color: #baa72a">
|
style="font-size: 12px; color: #baa72a">{{ item }}</div>
|
||||||
{{ item }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else> </div>
|
<div v-else> </div>
|
||||||
{{ $t('trials:uploadDicomList:table:Uploaded') }}:
|
{{ $t('trials:uploadDicomList:table:Uploaded') }}:
|
||||||
<div v-if="scope.row.uploadState.record.Uploaded.length">
|
<div v-if="scope.row.uploadState.record.Uploaded.length">
|
||||||
<div v-for="item of scope.row.uploadState.record.Uploaded" :key="item"
|
<div v-for="item of scope.row.uploadState.record.Uploaded" :key="item"
|
||||||
style="font-size: 12px; color: #24b837">
|
style="font-size: 12px; color: #24b837">{{ item }}</div>
|
||||||
{{ item }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else> </div>
|
<div v-else> </div>
|
||||||
<br />
|
<br />
|
||||||
{{ $t('trials:uploadDicomList:table:Failed') }}:
|
{{ $t('trials:uploadDicomList:table:Failed') }}:
|
||||||
<div v-if="scope.row.uploadState.record.Failed.length">
|
<div v-if="scope.row.uploadState.record.Failed.length">
|
||||||
<div v-for="item of scope.row.uploadState.record.Failed" :key="item"
|
<div v-for="item of scope.row.uploadState.record.Failed" :key="item"
|
||||||
style="font-size: 12px; color: #f66">
|
style="font-size: 12px; color: #f66">{{ item }}</div>
|
||||||
{{ item }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else> </div>
|
<div v-else> </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-button size="mini" style="cursor: pointer">
|
<el-button size="mini" style="cursor: pointer">
|
||||||
<span style="font-size: 12px; color: #baa72a">{{
|
<span style="font-size: 12px; color: #baa72a">
|
||||||
scope.row.uploadState.record.Existed.length
|
{{
|
||||||
}}</span>
|
scope.row.uploadState.record.Existed.length
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
/
|
/
|
||||||
<span style="font-size: 12px; color: #24b837">{{
|
<span style="font-size: 12px; color: #24b837">
|
||||||
scope.row.uploadState.record.Uploaded.length
|
{{
|
||||||
}}</span>
|
scope.row.uploadState.record.Uploaded.length
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
/
|
/
|
||||||
<span style="font-size: 12px; color: #f66">{{
|
<span style="font-size: 12px; color: #f66">
|
||||||
scope.row.uploadState.record.Failed.length
|
{{
|
||||||
}}</span>
|
scope.row.uploadState.record.Failed.length
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
@@ -302,7 +304,8 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :IsDicom="true" :bodyPart="bodyPart"
|
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :IsDicom="true" :bodyPart="bodyPart"
|
||||||
:subjectVisitId="openSubjectVisitId" :modelList="modelList" :isUpload="openIsUpload"
|
:subjectVisitId="openSubjectVisitId" :modelList="modelList" :isUpload="openIsUpload"
|
||||||
:visitTaskId="openVisitTaskId" :TrialModality="TrialModality" @getList="getList" />
|
:visitTaskId="openVisitTaskId" :TrialModality="TrialModality" :IsReadingTaskViewInOrder="IsReadingTaskViewInOrder"
|
||||||
|
@getList="getList" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -335,6 +338,7 @@ cornerstoneWADOImageLoader.external.cornerstone = cornerstone
|
|||||||
import { convertBytes } from '@/utils/dicom-character-set'
|
import { convertBytes } from '@/utils/dicom-character-set'
|
||||||
import { parseDicom } from '@/utils/parseDicom.js'
|
import { parseDicom } from '@/utils/parseDicom.js'
|
||||||
import { dcmUpload } from '@/utils/dcmUpload/dcmUpload'
|
import { dcmUpload } from '@/utils/dcmUpload/dcmUpload'
|
||||||
|
import dcmjs from '@/utils/dcmUpload/dcmjs'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
export default {
|
export default {
|
||||||
@@ -354,6 +358,10 @@ export default {
|
|||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
forbid: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
TaskId: {
|
TaskId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -369,6 +377,14 @@ export default {
|
|||||||
IsImageSegment: {
|
IsImageSegment: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
},
|
||||||
|
isReading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
StudyInstanceUID: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -419,6 +435,8 @@ export default {
|
|||||||
openSubjectVisitId: null,
|
openSubjectVisitId: null,
|
||||||
openVisitTaskId: null,
|
openVisitTaskId: null,
|
||||||
TrialModality: [],
|
TrialModality: [],
|
||||||
|
IsReadingTaskViewInOrder: 2,
|
||||||
|
isDownloaded: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -451,15 +469,19 @@ export default {
|
|||||||
}
|
}
|
||||||
if (this.IsImageSegment) {
|
if (this.IsImageSegment) {
|
||||||
params.IsImageSegmentLabel = true
|
params.IsImageSegmentLabel = true
|
||||||
}
|
} else if (
|
||||||
else if (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20) {
|
this.Criterion.CriterionType == 19 ||
|
||||||
|
this.Criterion.CriterionType == 20
|
||||||
|
) {
|
||||||
params.IsImageSegmentLabel = false
|
params.IsImageSegmentLabel = false
|
||||||
}
|
}
|
||||||
this.loading = true
|
this.loading = true
|
||||||
let res = await getSubjectImageUploadList(params)
|
let res = await getSubjectImageUploadList(params)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
|
this.isDownloaded = res.OtherInfo.IsIRImageDownloaded
|
||||||
this.TrialModality = res.OtherInfo.TrialModality.split('|')
|
this.TrialModality = res.OtherInfo.TrialModality.split('|')
|
||||||
|
this.IsReadingTaskViewInOrder = res.OtherInfo.IsReadingTaskViewInOrder || res.OtherInfo.IsReadingTaskViewInOrder === 0 ? res.OtherInfo.IsReadingTaskViewInOrder : 2
|
||||||
this.StudyInstanceUidList = []
|
this.StudyInstanceUidList = []
|
||||||
this.SopInstanceUidList = []
|
this.SopInstanceUidList = []
|
||||||
this.UploadStudyList = []
|
this.UploadStudyList = []
|
||||||
@@ -539,7 +561,9 @@ export default {
|
|||||||
this.openIsUpload = isUpload
|
this.openIsUpload = isUpload
|
||||||
this.openSubjectVisitId = item.SubjectVisitId || item.SourceSubjectVisitId
|
this.openSubjectVisitId = item.SubjectVisitId || item.SourceSubjectVisitId
|
||||||
this.openVisitTaskId = item.VisitTaskId
|
this.openVisitTaskId = item.VisitTaskId
|
||||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${this.IsImageSegment ? item.VisitName : item.TaskBlindName}`
|
this.model_cfg.title = `${item.SubjectCode || ''} > ${this.IsImageSegment ? item.VisitName : item.TaskBlindName
|
||||||
|
}`
|
||||||
|
if (this.isReadingTaskViewInOrder === 0) this.model_cfg.title = ''
|
||||||
this.modelList = item[list]
|
this.modelList = item[list]
|
||||||
this.model_cfg.visible = true
|
this.model_cfg.visible = true
|
||||||
},
|
},
|
||||||
@@ -641,7 +665,10 @@ export default {
|
|||||||
for (let i = 0; i < checkFiles.length; i++) {
|
for (let i = 0; i < checkFiles.length; i++) {
|
||||||
let item = checkFiles[i]
|
let item = checkFiles[i]
|
||||||
var dicom = await parseDicom(item, ['StudyInstanceUid', 'Modality'])
|
var dicom = await parseDicom(item, ['StudyInstanceUid', 'Modality'])
|
||||||
if (!!~this.errStudyUidList.indexOf(dicom.StudyInstanceUid) || (this.IsImageSegment && dicom.Modality !== 'IVUS')) {
|
if (
|
||||||
|
!!~this.errStudyUidList.indexOf(dicom.StudyInstanceUid) ||
|
||||||
|
(this.IsImageSegment && dicom.Modality !== 'IVUS')
|
||||||
|
) {
|
||||||
this.hasOtherStudy = true
|
this.hasOtherStudy = true
|
||||||
checkFiles.splice(i, 1)
|
checkFiles.splice(i, 1)
|
||||||
i--
|
i--
|
||||||
@@ -708,12 +735,13 @@ export default {
|
|||||||
var studyUid = data.string('x0020000d')
|
var studyUid = data.string('x0020000d')
|
||||||
if (!studyUid) return resolve()
|
if (!studyUid) return resolve()
|
||||||
var pixelDataElement = data.elements.x7fe00010
|
var pixelDataElement = data.elements.x7fe00010
|
||||||
if (!pixelDataElement && modality !== 'SR') return resolve()
|
if (!pixelDataElement && modality !== 'SR' && modality !== 'ECG')
|
||||||
|
return resolve()
|
||||||
var studyIndex = 0
|
var studyIndex = 0
|
||||||
while (
|
while (
|
||||||
studyIndex < scope.uploadQueues.length &&
|
studyIndex < scope.uploadQueues.length &&
|
||||||
scope.uploadQueues[studyIndex].dicomInfo.studyUid !== studyUid &&
|
scope.uploadQueues[studyIndex].dicomInfo.studyUid !== studyUid &&
|
||||||
(pixelDataElement || modality === 'SR') &&
|
(pixelDataElement || modality === 'SR' || modality === 'ECG') &&
|
||||||
modality != ''
|
modality != ''
|
||||||
) {
|
) {
|
||||||
++studyIndex
|
++studyIndex
|
||||||
@@ -805,6 +833,39 @@ export default {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
!scope.uploadQueues[studyIndex].dicomInfo.RadionuclideTotalDose
|
||||||
|
) {
|
||||||
|
let dataset = dcmjs.data.DicomMessage.readFile(e.target.result)
|
||||||
|
if (
|
||||||
|
dataset.dict['00540016'] &&
|
||||||
|
dataset.dict['00540016'].Value &&
|
||||||
|
dataset.dict['00540016'].Value[0]
|
||||||
|
) {
|
||||||
|
let RadionuclideTotalDose = dataset.dict['00540016'].Value[0][
|
||||||
|
'00181074'
|
||||||
|
]
|
||||||
|
? dataset.dict['00540016'].Value[0]['00181074'].Value[0]
|
||||||
|
: null
|
||||||
|
let RadionuclideHalfLife = dataset.dict['00540016'].Value[0][
|
||||||
|
'00181075'
|
||||||
|
]
|
||||||
|
? dataset.dict['00540016'].Value[0]['00181075'].Value[0]
|
||||||
|
: null
|
||||||
|
let RadiopharmaceuticalStartTime = dataset.dict['00540016']
|
||||||
|
.Value[0]['00181072']
|
||||||
|
? dataset.dict['00540016'].Value[0]['00181072'].Value[0]
|
||||||
|
: null
|
||||||
|
scope.uploadQueues[studyIndex].dicomInfo.RadionuclideTotalDose =
|
||||||
|
RadionuclideTotalDose
|
||||||
|
scope.uploadQueues[studyIndex].dicomInfo.RadionuclideHalfLife =
|
||||||
|
RadionuclideHalfLife
|
||||||
|
scope.uploadQueues[
|
||||||
|
studyIndex
|
||||||
|
].dicomInfo.RadiopharmaceuticalStartTime =
|
||||||
|
RadiopharmaceuticalStartTime
|
||||||
|
}
|
||||||
|
}
|
||||||
var modality = scope.uploadQueues[studyIndex].dicomInfo.modality
|
var modality = scope.uploadQueues[studyIndex].dicomInfo.modality
|
||||||
var currentModality = data.string('x00080060')
|
var currentModality = data.string('x00080060')
|
||||||
if (!(modality.indexOf(currentModality) > -1)) {
|
if (!(modality.indexOf(currentModality) > -1)) {
|
||||||
@@ -872,8 +933,9 @@ export default {
|
|||||||
)
|
)
|
||||||
seriesItem = {
|
seriesItem = {
|
||||||
seriesUid: seriesUid,
|
seriesUid: seriesUid,
|
||||||
RadiopharmaceuticalInformationSequence: data.string('x00540016') || "",
|
RadiopharmaceuticalInformationSequence:
|
||||||
AcquisitionDate: data.string('x00080022') || "",
|
data.string('x00540016') || '',
|
||||||
|
AcquisitionDate: data.string('x00080022') || '',
|
||||||
|
|
||||||
DicomSeriesDate: data.string('x00080021'),
|
DicomSeriesDate: data.string('x00080021'),
|
||||||
DicomSeriesTime: data.string('x00080031'),
|
DicomSeriesTime: data.string('x00080031'),
|
||||||
@@ -895,7 +957,7 @@ export default {
|
|||||||
var instanceItem = instanceList.find(function (item) {
|
var instanceItem = instanceList.find(function (item) {
|
||||||
return item.instanceUid === instanceUid
|
return item.instanceUid === instanceUid
|
||||||
})
|
})
|
||||||
if (!instanceItem) {
|
if (!false) {
|
||||||
var date = data.string('x00080023')
|
var date = data.string('x00080023')
|
||||||
var time = data.string('x00080033')
|
var time = data.string('x00080033')
|
||||||
var instanceTime = ''
|
var instanceTime = ''
|
||||||
@@ -1024,11 +1086,12 @@ export default {
|
|||||||
async verifyStudy() {
|
async verifyStudy() {
|
||||||
this.btnLoading = true
|
this.btnLoading = true
|
||||||
var studyList = []
|
var studyList = []
|
||||||
|
let scope = this
|
||||||
this.selectArr.forEach((item) => {
|
this.selectArr.forEach((item) => {
|
||||||
item.dicomInfo.uploadFileSize = 0
|
item.dicomInfo.uploadFileSize = 0
|
||||||
if (!item.uploadState.selected) {
|
if (!item.uploadState.selected) {
|
||||||
studyList.push({
|
studyList.push({
|
||||||
studyInstanceUid: item.dicomInfo.studyUid,
|
studyInstanceUid: scope.isReading && scope.StudyInstanceUID ? scope.StudyInstanceUID : item.dicomInfo.studyUid,
|
||||||
studyDate: item.dicomInfo.studyTime,
|
studyDate: item.dicomInfo.studyTime,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1081,16 +1144,20 @@ export default {
|
|||||||
var scope = this
|
var scope = this
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
try {
|
try {
|
||||||
let subjectVisitId = null;
|
let subjectVisitId = null
|
||||||
|
let dicomInfo = {}
|
||||||
if (scope.VisitTaskId) {
|
if (scope.VisitTaskId) {
|
||||||
scope.StudyInstanceUidList.forEach(item => {
|
scope.StudyInstanceUidList.forEach((item) => {
|
||||||
if (item.VisitTaskId === scope.VisitTaskId) {
|
if (item.VisitTaskId === scope.VisitTaskId) {
|
||||||
subjectVisitId = item.SourceSubjectVisitId
|
subjectVisitId = item.SourceSubjectVisitId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
scope.StudyInstanceUidList.forEach(item => {
|
scope.StudyInstanceUidList.forEach((item) => {
|
||||||
if (item.StudyInstanceUid === scope.uploadQueues[index].dicomInfo.studyUid) {
|
if (
|
||||||
|
item.StudyInstanceUid ===
|
||||||
|
scope.uploadQueues[index].dicomInfo.studyUid
|
||||||
|
) {
|
||||||
subjectVisitId = item.SourceSubjectVisitId
|
subjectVisitId = item.SourceSubjectVisitId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1108,7 +1175,7 @@ export default {
|
|||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
scope.uploadQueues[index].dicomInfo.failedFileCount = 0
|
scope.uploadQueues[index].dicomInfo.failedFileCount = 0
|
||||||
scope.$set(scope.uploadQueues[index].dicomInfo, 'isInit', true)
|
scope.$set(scope.uploadQueues[index].dicomInfo, 'isInit', true)
|
||||||
let dicomInfo = scope.uploadQueues[index].dicomInfo
|
dicomInfo = scope.uploadQueues[index].dicomInfo
|
||||||
let seriesNum = scope.uploadQueues[index].seriesList.length
|
let seriesNum = scope.uploadQueues[index].seriesList.length
|
||||||
let fileNum = scope.uploadQueues[index].fileList.length
|
let fileNum = scope.uploadQueues[index].fileList.length
|
||||||
let seriesList = scope.uploadQueues[index].seriesList
|
let seriesList = scope.uploadQueues[index].seriesList
|
||||||
@@ -1119,7 +1186,7 @@ export default {
|
|||||||
let t = setInterval(() => {
|
let t = setInterval(() => {
|
||||||
dicomUploadInProgress({
|
dicomUploadInProgress({
|
||||||
trialId: scope.trialId,
|
trialId: scope.trialId,
|
||||||
studyInstanceUid: dicomInfo.studyUid,
|
studyInstanceUid: scope.isReading && scope.StudyInstanceUID ? scope.StudyInstanceUID : dicomInfo.studyUid,
|
||||||
VisitTaskId: dicomInfo.visitTaskId,
|
VisitTaskId: dicomInfo.visitTaskId,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
console.log(dicomInfo.visitTaskId)
|
console.log(dicomInfo.visitTaskId)
|
||||||
@@ -1140,8 +1207,13 @@ export default {
|
|||||||
failedFileCount: 0,
|
failedFileCount: 0,
|
||||||
RecordPath: null,
|
RecordPath: null,
|
||||||
study: {
|
study: {
|
||||||
|
RadionuclideTotalDose: dicomInfo.RadionuclideTotalDose,
|
||||||
|
RadionuclideHalfLife: dicomInfo.RadionuclideHalfLife,
|
||||||
|
RadiopharmaceuticalStartTime:
|
||||||
|
dicomInfo.RadiopharmaceuticalStartTime,
|
||||||
|
|
||||||
studyId: dicomInfo.studyId,
|
studyId: dicomInfo.studyId,
|
||||||
studyInstanceUid: dicomInfo.studyUid,
|
studyInstanceUid: scope.isReading && scope.StudyInstanceUID ? scope.StudyInstanceUID : dicomInfo.studyUid,
|
||||||
studyTime: dicomInfo.studyTime,
|
studyTime: dicomInfo.studyTime,
|
||||||
description: dicomInfo.description,
|
description: dicomInfo.description,
|
||||||
seriesCount: dicomInfo.seriesNum,
|
seriesCount: dicomInfo.seriesNum,
|
||||||
@@ -1149,8 +1221,8 @@ export default {
|
|||||||
institutionName: dicomInfo.institutionName,
|
institutionName: dicomInfo.institutionName,
|
||||||
patientId: dicomInfo.patientId,
|
patientId: dicomInfo.patientId,
|
||||||
patientName: '',
|
patientName: '',
|
||||||
patientAge: '',
|
patientAge: dicomInfo.patientAge,
|
||||||
patientSex: dicomInfo.patientSex,
|
patientSex: config?.DicomStoreInfo.SubjectSex || dicomInfo.patientSex,
|
||||||
accessionNumber: dicomInfo.accNumber,
|
accessionNumber: dicomInfo.accNumber,
|
||||||
patientBirthDate: '',
|
patientBirthDate: '',
|
||||||
acquisitionTime: dicomInfo.acquisitionTime,
|
acquisitionTime: dicomInfo.acquisitionTime,
|
||||||
@@ -1170,6 +1242,7 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
let arr = []
|
let arr = []
|
||||||
|
let uploadBatchId = scope.$guid()
|
||||||
for (let i = 0; i < seriesList.length; i++) {
|
for (let i = 0; i < seriesList.length; i++) {
|
||||||
let v = seriesList[i]
|
let v = seriesList[i]
|
||||||
let instanceList = []
|
let instanceList = []
|
||||||
@@ -1181,20 +1254,171 @@ export default {
|
|||||||
try {
|
try {
|
||||||
let o = v.instanceList[ii]
|
let o = v.instanceList[ii]
|
||||||
let name = `${v.instanceList[ii].file.webkitRelativePath}_${v.instanceList[ii].instanceUid}`
|
let name = `${v.instanceList[ii].file.webkitRelativePath}_${v.instanceList[ii].instanceUid}`
|
||||||
if (o.isReUpload) {
|
// if (o.isReUpload) {
|
||||||
dicomInfo.failedFileCount++
|
// dicomInfo.failedFileCount++
|
||||||
dicomInfo.uploadFileSize += o.file.size
|
// dicomInfo.uploadFileSize += o.file.size
|
||||||
Record.Existed.push(name)
|
// Record.Existed.push(name)
|
||||||
Record.FileCount++
|
// Record.FileCount++
|
||||||
} else if (o.myPath) {
|
// }
|
||||||
|
// else if (o.myPath) {
|
||||||
|
// instanceList.push({
|
||||||
|
// studyInstanceUid: dicomInfo.studyUid,
|
||||||
|
// seriesInstanceUid: v.seriesUid,
|
||||||
|
// SOPClassUID: o.SOPClassUID,
|
||||||
|
// TransferSytaxUID: o.TransferSytaxUID,
|
||||||
|
// MediaStorageSOPInstanceUID:
|
||||||
|
// o.MediaStorageSOPInstanceUID,
|
||||||
|
// MediaStorageSOPClassUID:
|
||||||
|
// o.MediaStorageSOPClassUID,
|
||||||
|
// sopInstanceUid: o.instanceUid,
|
||||||
|
// instanceNumber: o.instanceNumber,
|
||||||
|
// instanceTime: o.instanceTime,
|
||||||
|
// imageRows: o.imageRows,
|
||||||
|
// imageColumns: o.imageColumns,
|
||||||
|
// sliceLocation: o.sliceLocation,
|
||||||
|
// sliceThickness: o.sliceThickness,
|
||||||
|
// numberOfFrames: o.numberOfFrames,
|
||||||
|
// pixelSpacing: o.pixelSpacing,
|
||||||
|
// imagerPixelSpacing: o.imagerPixelSpacing,
|
||||||
|
// frameOfReferenceUID: o.frameOfReferenceUID,
|
||||||
|
// windowCenter: o.windowCenter,
|
||||||
|
// windowWidth: o.windowWidth,
|
||||||
|
// path: o.myPath,
|
||||||
|
// FileSize: o.FileSize,
|
||||||
|
|
||||||
|
// PhotometricInterpretation:
|
||||||
|
// o.PhotometricInterpretation,
|
||||||
|
// BitsAllocated: o.BitsAllocated,
|
||||||
|
// PixelRepresentation: o.PixelRepresentation,
|
||||||
|
// RescaleIntercept: o.RescaleIntercept,
|
||||||
|
// RescaleSlope: o.RescaleSlope,
|
||||||
|
// ImagePositionPatient: o.ImagePositionPatient,
|
||||||
|
// ImageOrientationPatient:
|
||||||
|
// o.ImageOrientationPatient,
|
||||||
|
// SequenceOfUltrasoundRegions:
|
||||||
|
// o.SequenceOfUltrasoundRegions,
|
||||||
|
// FrameTime: o.FrameTime,
|
||||||
|
// CorrectedImage: o.CorrectedImage,
|
||||||
|
// Units: o.Units,
|
||||||
|
// DecayCorrection: o.DecayCorrection,
|
||||||
|
// EncapsulatedDocument: o.EncapsulatedDocument,
|
||||||
|
// })
|
||||||
|
// Record.Uploaded.push(name)
|
||||||
|
// dicomInfo.failedFileCount++
|
||||||
|
// Record.FileCount++
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
let path = `/${params.trialId}/Image/${params.subjectId
|
||||||
|
}/${params.subjectVisitId}/${dicomInfo.visitTaskId
|
||||||
|
}/${scope.getGuid(
|
||||||
|
dicomInfo.studyUid +
|
||||||
|
v.seriesUid +
|
||||||
|
o.instanceUid +
|
||||||
|
params.trialId
|
||||||
|
)}`
|
||||||
|
if (scope.IsImageSegment) {
|
||||||
|
path = `/${params.trialId}/Image/${params.subjectId
|
||||||
|
}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId
|
||||||
|
}/${scope.getGuid(
|
||||||
|
dicomInfo.studyUid +
|
||||||
|
v.seriesUid +
|
||||||
|
o.instanceUid +
|
||||||
|
params.trialId
|
||||||
|
)}`
|
||||||
|
}
|
||||||
|
if (scope.isClose) return
|
||||||
|
let res = await dcmUpload(
|
||||||
|
{
|
||||||
|
path: path,
|
||||||
|
file: o.file,
|
||||||
|
speed: true,
|
||||||
|
},
|
||||||
|
scope.isReading && scope.StudyInstanceUID ? {
|
||||||
|
AnonymizeFixedList: [
|
||||||
|
{
|
||||||
|
Element: '000D',
|
||||||
|
Group: '0020',
|
||||||
|
ReplaceValue: scope.StudyInstanceUID,
|
||||||
|
Id: 'StudyInstanceUID'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
AnonymizeNotFixedList: [],
|
||||||
|
DicomStoreInfo: {}
|
||||||
|
} : null,
|
||||||
|
(percentage, checkpoint, lastPer) => {
|
||||||
|
dicomInfo.uploadFileSize +=
|
||||||
|
checkpoint.size * (percentage - lastPer)
|
||||||
|
if (
|
||||||
|
dicomInfo.uploadFileSize > dicomInfo.fileSize
|
||||||
|
) {
|
||||||
|
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: o.file.name,
|
||||||
|
fileSize: o.file.size,
|
||||||
|
fileType: 'application/dicom',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 5,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!res || !res.url) {
|
||||||
|
params.failedFileCount++
|
||||||
|
} else {
|
||||||
|
if (ii === 0 && o.modality !== 'SR') {
|
||||||
|
try {
|
||||||
|
let fileId =
|
||||||
|
cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
||||||
|
o.file
|
||||||
|
)
|
||||||
|
let blob = await scope.dicomToPng(
|
||||||
|
fileId,
|
||||||
|
o.imageColumns,
|
||||||
|
o.imageRows
|
||||||
|
)
|
||||||
|
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||||
|
if (scope.IsImageSegment) {
|
||||||
|
thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||||
|
}
|
||||||
|
let OSSclient = scope.OSSclient
|
||||||
|
let seriesRes = await OSSclient.put(
|
||||||
|
thumbnailPath,
|
||||||
|
blob,
|
||||||
|
{
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 6,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (seriesRes && seriesRes.url) {
|
||||||
|
ImageResizePath = scope.$getObjectName(
|
||||||
|
seriesRes.url
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res && res.url) {
|
||||||
instanceList.push({
|
instanceList.push({
|
||||||
studyInstanceUid: dicomInfo.studyUid,
|
studyInstanceUid: scope.isReading && scope.StudyInstanceUID ? scope.StudyInstanceUID : dicomInfo.studyUid,
|
||||||
seriesInstanceUid: v.seriesUid,
|
seriesInstanceUid: v.seriesUid,
|
||||||
|
sopInstanceUid: o.instanceUid,
|
||||||
SOPClassUID: o.SOPClassUID,
|
SOPClassUID: o.SOPClassUID,
|
||||||
TransferSytaxUID: o.TransferSytaxUID,
|
TransferSytaxUID: o.TransferSytaxUID,
|
||||||
MediaStorageSOPInstanceUID: o.MediaStorageSOPInstanceUID,
|
MediaStorageSOPInstanceUID:
|
||||||
MediaStorageSOPClassUID: o.MediaStorageSOPClassUID,
|
o.MediaStorageSOPInstanceUID,
|
||||||
sopInstanceUid: o.instanceUid,
|
MediaStorageSOPClassUID:
|
||||||
|
o.MediaStorageSOPClassUID,
|
||||||
instanceNumber: o.instanceNumber,
|
instanceNumber: o.instanceNumber,
|
||||||
instanceTime: o.instanceTime,
|
instanceTime: o.instanceTime,
|
||||||
imageRows: o.imageRows,
|
imageRows: o.imageRows,
|
||||||
@@ -1207,143 +1431,35 @@ export default {
|
|||||||
frameOfReferenceUID: o.frameOfReferenceUID,
|
frameOfReferenceUID: o.frameOfReferenceUID,
|
||||||
windowCenter: o.windowCenter,
|
windowCenter: o.windowCenter,
|
||||||
windowWidth: o.windowWidth,
|
windowWidth: o.windowWidth,
|
||||||
path: o.myPath,
|
path: scope.$getObjectName(res.url),
|
||||||
FileSize: o.FileSize,
|
FileSize: o.FileSize,
|
||||||
|
|
||||||
PhotometricInterpretation: o.PhotometricInterpretation,
|
PhotometricInterpretation:
|
||||||
|
o.PhotometricInterpretation,
|
||||||
BitsAllocated: o.BitsAllocated,
|
BitsAllocated: o.BitsAllocated,
|
||||||
PixelRepresentation: o.PixelRepresentation,
|
PixelRepresentation: o.PixelRepresentation,
|
||||||
RescaleIntercept: o.RescaleIntercept,
|
RescaleIntercept: o.RescaleIntercept,
|
||||||
RescaleSlope: o.RescaleSlope,
|
RescaleSlope: o.RescaleSlope,
|
||||||
ImagePositionPatient: o.ImagePositionPatient,
|
ImagePositionPatient: o.ImagePositionPatient,
|
||||||
ImageOrientationPatient: o.ImageOrientationPatient,
|
ImageOrientationPatient:
|
||||||
SequenceOfUltrasoundRegions: o.SequenceOfUltrasoundRegions,
|
o.ImageOrientationPatient,
|
||||||
|
SequenceOfUltrasoundRegions:
|
||||||
|
o.SequenceOfUltrasoundRegions,
|
||||||
FrameTime: o.FrameTime,
|
FrameTime: o.FrameTime,
|
||||||
CorrectedImage: o.CorrectedImage,
|
CorrectedImage: o.CorrectedImage,
|
||||||
Units: o.Units,
|
Units: o.Units,
|
||||||
DecayCorrection: o.DecayCorrection,
|
DecayCorrection: o.DecayCorrection,
|
||||||
EncapsulatedDocument: o.EncapsulatedDocument,
|
EncapsulatedDocument: o.EncapsulatedDocument,
|
||||||
})
|
})
|
||||||
|
o.myPath = scope.$getObjectName(res.url)
|
||||||
Record.Uploaded.push(name)
|
Record.Uploaded.push(name)
|
||||||
dicomInfo.failedFileCount++
|
dicomInfo.failedFileCount++
|
||||||
Record.FileCount++
|
Record.FileCount++
|
||||||
} else {
|
} else {
|
||||||
let path = `/${params.trialId}/Image/${params.subjectId
|
Record.Failed.push(name)
|
||||||
}/${params.subjectVisitId}/${dicomInfo.visitTaskId
|
Record.FileCount++
|
||||||
}/${scope.getGuid(
|
|
||||||
dicomInfo.studyUid +
|
|
||||||
v.seriesUid +
|
|
||||||
o.instanceUid +
|
|
||||||
params.trialId
|
|
||||||
)}`
|
|
||||||
if (scope.IsImageSegment) {
|
|
||||||
path = `/${params.trialId}/Image/${params.subjectId
|
|
||||||
}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId
|
|
||||||
}/${scope.getGuid(
|
|
||||||
dicomInfo.studyUid +
|
|
||||||
v.seriesUid +
|
|
||||||
o.instanceUid +
|
|
||||||
params.trialId
|
|
||||||
)}`
|
|
||||||
}
|
|
||||||
if (scope.isClose) return
|
|
||||||
let res = await dcmUpload(
|
|
||||||
{
|
|
||||||
path: path,
|
|
||||||
file: o.file,
|
|
||||||
speed: true,
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
(percentage, checkpoint, lastPer) => {
|
|
||||||
dicomInfo.uploadFileSize +=
|
|
||||||
checkpoint.size * (percentage - lastPer)
|
|
||||||
if (
|
|
||||||
dicomInfo.uploadFileSize > dicomInfo.fileSize
|
|
||||||
) {
|
|
||||||
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (!res || !res.url) {
|
|
||||||
params.failedFileCount++
|
|
||||||
} else {
|
|
||||||
if (ii === 0 && o.modality !== 'SR') {
|
|
||||||
try {
|
|
||||||
let fileId =
|
|
||||||
cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
|
||||||
o.file
|
|
||||||
)
|
|
||||||
let blob = await scope.dicomToPng(
|
|
||||||
fileId,
|
|
||||||
o.imageColumns,
|
|
||||||
o.imageRows
|
|
||||||
)
|
|
||||||
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
|
||||||
if (scope.IsImageSegment) {
|
|
||||||
thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
|
||||||
}
|
|
||||||
let OSSclient = scope.OSSclient
|
|
||||||
let seriesRes = await OSSclient.put(
|
|
||||||
thumbnailPath,
|
|
||||||
blob
|
|
||||||
)
|
|
||||||
if (seriesRes && seriesRes.url) {
|
|
||||||
ImageResizePath = scope.$getObjectName(
|
|
||||||
seriesRes.url
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res && res.url) {
|
|
||||||
instanceList.push({
|
|
||||||
studyInstanceUid: dicomInfo.studyUid,
|
|
||||||
seriesInstanceUid: v.seriesUid,
|
|
||||||
sopInstanceUid: o.instanceUid,
|
|
||||||
SOPClassUID: o.SOPClassUID,
|
|
||||||
TransferSytaxUID: o.TransferSytaxUID,
|
|
||||||
MediaStorageSOPInstanceUID: o.MediaStorageSOPInstanceUID,
|
|
||||||
MediaStorageSOPClassUID: o.MediaStorageSOPClassUID,
|
|
||||||
instanceNumber: o.instanceNumber,
|
|
||||||
instanceTime: o.instanceTime,
|
|
||||||
imageRows: o.imageRows,
|
|
||||||
imageColumns: o.imageColumns,
|
|
||||||
sliceLocation: o.sliceLocation,
|
|
||||||
sliceThickness: o.sliceThickness,
|
|
||||||
numberOfFrames: o.numberOfFrames,
|
|
||||||
pixelSpacing: o.pixelSpacing,
|
|
||||||
imagerPixelSpacing: o.imagerPixelSpacing,
|
|
||||||
frameOfReferenceUID: o.frameOfReferenceUID,
|
|
||||||
windowCenter: o.windowCenter,
|
|
||||||
windowWidth: o.windowWidth,
|
|
||||||
path: scope.$getObjectName(res.url),
|
|
||||||
FileSize: o.FileSize,
|
|
||||||
|
|
||||||
PhotometricInterpretation: o.PhotometricInterpretation,
|
|
||||||
BitsAllocated: o.BitsAllocated,
|
|
||||||
PixelRepresentation: o.PixelRepresentation,
|
|
||||||
RescaleIntercept: o.RescaleIntercept,
|
|
||||||
RescaleSlope: o.RescaleSlope,
|
|
||||||
ImagePositionPatient: o.ImagePositionPatient,
|
|
||||||
ImageOrientationPatient: o.ImageOrientationPatient,
|
|
||||||
SequenceOfUltrasoundRegions: o.SequenceOfUltrasoundRegions,
|
|
||||||
FrameTime: o.FrameTime,
|
|
||||||
CorrectedImage: o.CorrectedImage,
|
|
||||||
Units: o.Units,
|
|
||||||
DecayCorrection: o.DecayCorrection,
|
|
||||||
EncapsulatedDocument: o.EncapsulatedDocument,
|
|
||||||
})
|
|
||||||
o.myPath = scope.$getObjectName(res.url)
|
|
||||||
Record.Uploaded.push(name)
|
|
||||||
dicomInfo.failedFileCount++
|
|
||||||
Record.FileCount++
|
|
||||||
} else {
|
|
||||||
Record.Failed.push(name)
|
|
||||||
Record.FileCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
resolve1()
|
resolve1()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
@@ -1361,7 +1477,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
params.study.seriesList.push({
|
params.study.seriesList.push({
|
||||||
studyInstanceUid: dicomInfo.studyUid,
|
studyInstanceUid: scope.isReading && scope.StudyInstanceUID ? scope.StudyInstanceUID : dicomInfo.studyUid,
|
||||||
seriesInstanceUid: v.seriesUid,
|
seriesInstanceUid: v.seriesUid,
|
||||||
seriesNumber: v.seriesNumber,
|
seriesNumber: v.seriesNumber,
|
||||||
seriesTime: v.seriesTime,
|
seriesTime: v.seriesTime,
|
||||||
@@ -1383,7 +1499,8 @@ export default {
|
|||||||
instanceList: instanceList,
|
instanceList: instanceList,
|
||||||
ImageResizePath: ImageResizePath,
|
ImageResizePath: ImageResizePath,
|
||||||
|
|
||||||
RadiopharmaceuticalInformationSequence: v.RadiopharmaceuticalInformationSequence,
|
RadiopharmaceuticalInformationSequence:
|
||||||
|
v.RadiopharmaceuticalInformationSequence,
|
||||||
AcquisitionDate: v.AcquisitionDate,
|
AcquisitionDate: v.AcquisitionDate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1543,16 @@ export default {
|
|||||||
}
|
}
|
||||||
let OSSclient = scope.OSSclient
|
let OSSclient = scope.OSSclient
|
||||||
try {
|
try {
|
||||||
let seriesRes = await OSSclient.put(thumbnailPath, blob)
|
let seriesRes = await OSSclient.put(thumbnailPath, blob, {
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 6,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId,
|
||||||
|
})
|
||||||
if (seriesRes && seriesRes.url) {
|
if (seriesRes && seriesRes.url) {
|
||||||
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
||||||
}
|
}
|
||||||
@@ -1444,6 +1570,7 @@ export default {
|
|||||||
if (scope.IsImageSegment) {
|
if (scope.IsImageSegment) {
|
||||||
params.IsImageSegmentLabel = true
|
params.IsImageSegmentLabel = true
|
||||||
}
|
}
|
||||||
|
params.UploadBatchId = uploadBatchId
|
||||||
addOrUpdateArchiveTaskStudy(params)
|
addOrUpdateArchiveTaskStudy(params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
||||||
@@ -1538,7 +1665,9 @@ export default {
|
|||||||
var token = getToken()
|
var token = getToken()
|
||||||
let trialId = this.$route.query.trialId
|
let trialId = this.$route.query.trialId
|
||||||
const routeData = this.$router.resolve({
|
const routeData = this.$router.resolve({
|
||||||
path: `/showvisitdicoms?page=upload&trialId=${trialId}&visitTaskId=${this.IsImageSegment ? 'undefined' : row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
|
path: `/showvisitdicoms?page=upload&trialId=${trialId}&visitTaskId=${this.IsImageSegment ? 'undefined' : row.VisitTaskId
|
||||||
|
}&subjectVisitId=${row.SourceSubjectVisitId
|
||||||
|
}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
this.open = window.open(routeData.href, '_blank')
|
this.open = window.open(routeData.href, '_blank')
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:dicom')" name="dicom">
|
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:dicom')" name="dicom">
|
||||||
<dicomFile v-if="activeName === 'dicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
<dicomFile v-if="activeName === 'dicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
||||||
:Criterion="Criterion" :TaskId="VisitTaskId" :isUpload.sync="isUpload"
|
:Criterion="Criterion" :TaskId="VisitTaskId" :isUpload.sync="isUpload"
|
||||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :IsImageSegment="IsImageSegment" />
|
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :IsImageSegment="IsImageSegment" :forbid="forbid"
|
||||||
|
:isReading="isReading" :StudyInstanceUID="StudyInstanceUID" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom">
|
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom">
|
||||||
<nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
<nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
||||||
:Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload"
|
:Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload" :IsImageSegment="IsImageSegment"
|
||||||
:IsImageSegment="IsImageSegment" />
|
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :forbid="forbid" :isReading="isReading" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -29,6 +30,10 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
forbid: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
SubjectId: {
|
SubjectId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -54,6 +59,14 @@ export default {
|
|||||||
IsImageSegment: {
|
IsImageSegment: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
},
|
||||||
|
isReading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
StudyInstanceUID: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -66,6 +79,7 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.title = `Upload Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
this.title = `Upload Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||||
if (this.IsImageSegment) this.title = `Upload Images:${this.SubjectCode}`
|
if (this.IsImageSegment) this.title = `Upload Images:${this.SubjectCode}`
|
||||||
|
if (this.isReadingTaskViewInOrder === 0) this.title = ''
|
||||||
store.dispatch('trials/setUnLock', true)
|
store.dispatch('trials/setUnLock', true)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -82,16 +96,16 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
::v-deep.el-tabs--left .el-tabs__header.is-left {
|
::v-deep .el-tabs--left .el-tabs__header.is-left {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploadDicomAndNonedicom {
|
.uploadDicomAndNonedicom {
|
||||||
::v-deep.el-tabs--border-card>.el-tabs__header .el-tabs__item {
|
::v-deep .el-tabs--border-card>.el-tabs__header .el-tabs__item {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
|
::v-deep .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
|
||||||
color: #428bca;
|
color: #428bca;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-right-color: #dcdfe6;
|
border-right-color: #dcdfe6;
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
|
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
|
||||||
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
||||||
<!--受试者 sortable="custom"-->
|
<!--受试者 sortable="custom"-->
|
||||||
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')" />
|
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')"
|
||||||
|
v-if="isReadingTaskViewInOrder !== 0" />
|
||||||
<!--访视名称-->
|
<!--访视名称-->
|
||||||
<el-table-column prop="VisitName" :label="$t('upload:nonedicom:table:VisitName')" sortable
|
<el-table-column prop="VisitName" :label="$t('upload:nonedicom:table:VisitName')" sortable
|
||||||
v-if="IsImageSegment" />
|
v-if="IsImageSegment" />
|
||||||
@@ -109,12 +110,10 @@
|
|||||||
<el-button circle :disabled="scope.row.UploadedFileCount <= 0" icon="el-icon-view"
|
<el-button circle :disabled="scope.row.UploadedFileCount <= 0" icon="el-icon-view"
|
||||||
:title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" />
|
:title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" />
|
||||||
<!--上传--->
|
<!--上传--->
|
||||||
<el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')"
|
<el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')" v-if="!forbid"
|
||||||
@click.native.prevent="handleUpload(scope.row)" />
|
@click.native.prevent="handleUpload(scope.row)" :disabled="isReading && !isDownloaded" />
|
||||||
<!--删除--->
|
<!--删除--->
|
||||||
<el-button :disabled="scope.row.UploadedFileCount <= 0 ||
|
<el-button circle icon="el-icon-delete" :title="$t('upload:nonedicom:button:delete')"
|
||||||
scope.row.ReadingTaskState === 2
|
|
||||||
" circle icon="el-icon-delete" :title="$t('upload:nonedicom:button:delete')"
|
|
||||||
@click.stop="remove(scope.row)" />
|
@click.stop="remove(scope.row)" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -239,6 +238,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
forbid: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
SubjectCode: {
|
SubjectCode: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -261,6 +264,14 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
isReadingTaskViewInOrder: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
isReading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -282,7 +293,8 @@ export default {
|
|||||||
BodyPart: {},
|
BodyPart: {},
|
||||||
relationInfo: {
|
relationInfo: {
|
||||||
ImageFormatList: []
|
ImageFormatList: []
|
||||||
}
|
},
|
||||||
|
isDownloaded: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -339,6 +351,7 @@ export default {
|
|||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
this.list = res.Result
|
this.list = res.Result
|
||||||
this.relationInfo = res.OtherInfo
|
this.relationInfo = res.OtherInfo
|
||||||
|
this.isDownloaded = res.OtherInfo.IsIRImageDownloaded
|
||||||
this.faccept = []
|
this.faccept = []
|
||||||
this.relationInfo.ImageFormatList.forEach((item) => {
|
this.relationInfo.ImageFormatList.forEach((item) => {
|
||||||
this.faccept.push(`.${item}`)
|
this.faccept.push(`.${item}`)
|
||||||
@@ -471,7 +484,7 @@ export default {
|
|||||||
let trialId = this.$route.query.trialId
|
let trialId = this.$route.query.trialId
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
const routeData = this.$router.resolve({
|
const routeData = this.$router.resolve({
|
||||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&visitTaskId=${row.VisitTaskId}&TokenKey=${token}`,
|
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&visitTaskId=${row.VisitTaskId}&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
this.open = window.open(routeData.href, '_blank')
|
this.open = window.open(routeData.href, '_blank')
|
||||||
},
|
},
|
||||||
@@ -544,8 +557,9 @@ export default {
|
|||||||
})
|
})
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
this.studyMonitorId = res.Result
|
this.studyMonitorId = res.Result
|
||||||
|
let uploadBatchId = this.$guid()
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
funArr.push(this.handleUploadTask(this.selectArr, i))
|
funArr.push(this.handleUploadTask(this.selectArr, i, uploadBatchId))
|
||||||
}
|
}
|
||||||
if (funArr.length > 0) {
|
if (funArr.length > 0) {
|
||||||
let res = await Promise.all(funArr)
|
let res = await Promise.all(funArr)
|
||||||
@@ -556,7 +570,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 并发上传
|
// 并发上传
|
||||||
async handleUploadTask(arr, index) {
|
async handleUploadTask(arr, index, uploadBatchId) {
|
||||||
if (!this.uploadVisible) return
|
if (!this.uploadVisible) return
|
||||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||||
file.status = 1
|
file.status = 1
|
||||||
@@ -572,7 +586,7 @@ export default {
|
|||||||
}
|
}
|
||||||
file.curPath = path
|
file.curPath = path
|
||||||
const fileData = await this.fileToBlob(file.file)
|
const fileData = await this.fileToBlob(file.file)
|
||||||
let res = await this.fileToOss(path, fileData, file)
|
let res = await this.fileToOss(path, fileData, file, uploadBatchId)
|
||||||
if (res) {
|
if (res) {
|
||||||
file.status = 2
|
file.status = 2
|
||||||
this.successFileList.push({
|
this.successFileList.push({
|
||||||
@@ -606,13 +620,13 @@ export default {
|
|||||||
}
|
}
|
||||||
let ind = arr.findIndex((item) => item.status === 0)
|
let ind = arr.findIndex((item) => item.status === 0)
|
||||||
if (ind >= 0) {
|
if (ind >= 0) {
|
||||||
return this.handleUploadTask(arr, ind)
|
return this.handleUploadTask(arr, ind, uploadBatchId)
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// file上传到oss
|
// file上传到oss
|
||||||
async fileToOss(path, file, item) {
|
async fileToOss(path, file, item, uploadBatchId) {
|
||||||
try {
|
try {
|
||||||
let res = await this.OSSclient.multipartUpload(
|
let res = await this.OSSclient.multipartUpload(
|
||||||
{
|
{
|
||||||
@@ -625,6 +639,17 @@ export default {
|
|||||||
if (item.uploadFileSize > file.fileSize) {
|
if (item.uploadFileSize > file.fileSize) {
|
||||||
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: item.name,
|
||||||
|
fileSize: item.size,
|
||||||
|
fileType: item.fileType,
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 7,
|
||||||
|
trialId: this.$route.query.trialId,
|
||||||
|
subjectId: this.currentRow.SubjectId,
|
||||||
|
subjectVisitId: this.currentRow.SourceSubjectVisitId,
|
||||||
|
studyCode: this.SubjectCode
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-table :data="modelList" style="width: 100%" height="300">
|
<el-table :data="modelList" style="width: 100%" height="300">
|
||||||
<!--检查编号-->
|
<!--检查编号-->
|
||||||
<el-table-column prop="StudyCode" :label="$t('trials:uploadImage:table:StudyCode')" />
|
<el-table-column prop="StudyCode" :label="$t('trials:uploadImage:table:StudyCode')"
|
||||||
|
v-if="IsReadingTaskViewInOrder !== 0" />
|
||||||
<!--检查类型-->
|
<!--检查类型-->
|
||||||
<el-table-column prop="ModalityForEdit" :label="$t('trials:uploadImage:table:ModalityForEdit')"
|
<el-table-column prop="ModalityForEdit" :label="$t('trials:uploadImage:table:ModalityForEdit')"
|
||||||
v-if="IsDicom" />
|
v-if="IsDicom" />
|
||||||
@@ -139,6 +140,10 @@ export default {
|
|||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
IsReadingTaskViewInOrder: {
|
||||||
|
type: Number,
|
||||||
|
default: 2,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
'base-model': baseModel,
|
'base-model': baseModel,
|
||||||
@@ -176,18 +181,18 @@ export default {
|
|||||||
var token = getToken()
|
var token = getToken()
|
||||||
let trialId = this.$route.query.trialId
|
let trialId = this.$route.query.trialId
|
||||||
routeData = this.$router.resolve({
|
routeData = this.$router.resolve({
|
||||||
path: `/showvisitdicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&isReading=1&TokenKey=${token}`,
|
path: `/showvisitdicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let trialId = this.$route.query.trialId
|
let trialId = this.$route.query.trialId
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
||||||
routeData = this.$router.resolve({
|
routeData = this.$router.resolve({
|
||||||
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
|
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
routeData = this.$router.resolve({
|
routeData = this.$router.resolve({
|
||||||
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
|
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import resize from './resize'
|
||||||
|
|
||||||
|
const install = function (Vue) {
|
||||||
|
// 绑定v-adaptive指令
|
||||||
|
Vue.directive('resize', resize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (window.Vue) {
|
||||||
|
// window['adaptive'] = adaptive
|
||||||
|
// // eslint-disable-next-line no-undef
|
||||||
|
// Vue.use(install)
|
||||||
|
// }
|
||||||
|
|
||||||
|
resize.install = install
|
||||||
|
|
||||||
|
export default resize
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const map = new WeakMap()
|
||||||
|
const ob = new ResizeObserver(entries => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const handler = map.get(entry.target)
|
||||||
|
if (handler) {
|
||||||
|
const { inlineSize, blockSize } = entry.contentBoxSize[0]
|
||||||
|
handler({ width: inlineSize, height: blockSize })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default {
|
||||||
|
bind(el, binding) {
|
||||||
|
map.set(el, binding.value)
|
||||||
|
ob.observe(el)
|
||||||
|
},
|
||||||
|
unbind(el) {
|
||||||
|
ob.unobserve(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777010831812" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1646" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 896c-230.058667 0-421.461333-165.546667-461.610667-384a468.565333 468.565333 0 0 1 142.506667-258.816L89.6 149.973333A42.666667 42.666667 0 1 1 149.930667 89.6L934.4 874.112a42.666667 42.666667 0 0 1-60.373333 60.330667l-111.061334-111.061334A466.901333 466.901333 0 0 1 512 896zM253.226667 313.6A382.506667 382.506667 0 0 0 137.514667 512a384.213333 384.213333 0 0 0 563.242666 249.088l-86.528-86.528A192 192 0 0 1 349.44 409.770667L253.226667 313.6z m297.770666 297.728l-138.325333-138.325333a106.666667 106.666667 0 0 0 138.282667 138.282666l0.042666 0.042667z m285.312 22.357333l10.24-18.218666A381.226667 381.226667 0 0 0 886.485333 512a384.213333 384.213333 0 0 0-440.661333-292.949333c-2.944 0.512-9.173333 1.877333-18.730667 4.096a42.88 42.88 0 1 1-19.2-83.541334A470.912 470.912 0 0 1 512 128c230.058667 0 421.461333 165.546667 461.610667 384a467.072 467.072 0 0 1-57.685334 153.856 94.933333 94.933333 0 0 1-8.021333 11.178667 44.373333 44.373333 0 0 1-58.794667 9.088 39.552 39.552 0 0 1-12.8-52.437334z m-188.501333-257.493333a192 192 0 0 1 55.850667 147.626667l-203.52-203.477334a192 192 0 0 1 147.626666 55.893334z" fill="#e6e6e6" p-id="1647"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="24px" height="24px" viewBox="0 0 24 24" class="h-6 w-6"><g id="tool-seg-brush" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><rect id="Rectangle" x="0" y="0" width="24" height="24"></rect><path d="M3.24640621,21.8286833 C3.09173375,21.7551472 2.99513748,21.5971513 3.00018895,21.4259625 C3.00524042,21.2547737 3.11098486,21.1027485 3.26972426,21.0384606 C5.3260304,20.2059201 4.66362518,17.8620247 5.27421252,16.6088957 C6.02197747,15.1026514 7.84114758,14.4766383 9.35746132,15.2037675 C13.9485253,17.4422999 8.48346644,24.3211232 3.24640621,21.8286833 Z" id="Path" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M21.5968442,2.302022 C21.1256527,1.8826075 20.4094461,1.90228142 19.9619901,2.34693083 L9.69255027,12.5887345 C11.0536437,13.0051578 12.1843437,13.9616637 12.8206229,15.2349008 L21.7410706,3.93687606 C22.1347378,3.44008272 22.0714081,2.72222021 21.5968442,2.302022 Z" id="Path" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="h-6 w-6" color="#fff">
|
||||||
|
<path
|
||||||
|
d="M10.3945 12.6113C10.043 12.6113 9.78516 12.3945 9.78516 12.0371C9.78516 11.6855 10.043 11.4688 10.3945 11.4688H13.2012C13.5527 11.4688 13.8164 11.6855 13.8164 12.0371C13.8164 12.3945 13.5527 12.6113 13.2012 12.6113H10.3945Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
<path opacity="0.5"
|
||||||
|
d="M18.312 6.84473C21.8473 8.88583 22.9225 13.6424 20.7134 17.4687C18.5042 21.2951 13.8473 22.7422 10.312 20.7011C9.51661 20.2419 8.84737 19.6439 8.31042 18.9512C11.3012 19.3598 14.4827 17.8251 16.1946 14.8598C17.9067 11.8945 17.6457 8.3712 15.7963 5.98538C16.6645 6.10409 17.5167 6.38556 18.312 6.84473Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
<circle cx="13.7852" cy="13.4688" r="8" stroke="currentColor"></circle>
|
||||||
|
<path
|
||||||
|
d="M4.50586 8.22266C4.14844 8.22266 3.92578 7.9707 3.92578 7.60742V5.68555H2.10352C1.74609 5.68555 1.5 5.46875 1.5 5.11719C1.5 4.76562 1.74609 4.54297 2.10352 4.54297H3.92578V2.61523C3.92578 2.25195 4.14844 2 4.50586 2C4.85742 2 5.08008 2.25195 5.08008 2.61523V4.54297H6.89648C7.25391 4.54297 7.50586 4.76562 7.50586 5.11719C7.50586 5.46875 7.25391 5.68555 6.89648 5.68555H5.08008V7.60742C5.08008 7.9707 4.85742 8.22266 4.50586 8.22266Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1751350116150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20392" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M870.4 819.2a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4zM512 179.2a332.8 332.8 0 1 1 0 665.6 332.8 332.8 0 0 1 0-665.6z m0 51.2a281.6 281.6 0 1 0 0 563.2 281.6 281.6 0 0 0 0-563.2zM153.6 102.4a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z" fill="#ADAEB8" p-id="20393"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1597744457882" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10125" width="285.64453125" height="250" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M926.216214 404.588947l1.511115-151.84272H1079.570048c18.035893 0 33.098301-15.062408 33.098301-33.0983a33.390775 33.390775 0 0 0-33.098301-33.098301H927.727329V33.195792a33.390775 33.390775 0 0 0-33.049555-33.049555 33.390775 33.390775 0 0 0-33.0983 33.049555c0 3.022231 0 4.533346 1.511115 7.555577v144.287142H711.24787a33.390775 33.390775 0 0 0-33.098301 33.147046c0 18.035893 15.062408 33.049555 33.098301 33.049555H863.090589v139.802542c0 3.022231-1.46237 4.533346-1.46237 7.506831 0 18.035893 15.013662 33.098301 33.049555 33.098301 15.013662 1.46237 28.564955-10.529062 31.53844-27.053839zM1032.969201 790.995763a29.393631 29.393631 0 0 0-22.520493 10.480316 546.000095 546.000095 0 0 1-117.282049 88.717095 29.101157 29.101157 0 0 0-15.062408 25.591469c0 16.524777 13.551292 30.027324 30.07607 30.027324 4.533346 0 10.529062-1.46237 13.551292-2.973485 1.46237 0 1.46237-1.511115 1.46237-1.511115a523.235874 523.235874 0 0 0 127.811111-97.735041c6.044461-5.995716 10.529062-13.551292 10.529061-22.569238a28.028752 28.028752 0 0 0-28.564954-30.027325zM793.920503 935.282906c-2.973485 0-7.506831 0-10.529062 1.511115-46.600847 15.062408-96.223925 24.080354-145.798258 27.053839-15.062408 1.511115-25.59147 15.062408-25.591469 30.07607 0 16.573523 13.551292 30.07607 30.07607 30.07607 55.618794-4.4846 108.215357-13.502547 159.398295-30.07607a28.95492 28.95492 0 0 0 22.520494-28.564954 30.173561 30.173561 0 0 0-30.07607-30.07607zM535.324796 960.874375c-12.040177-1.511115-24.031609-1.511115-36.071785-3.02223a564.962155 564.962155 0 0 1-49.623078-7.506832c-230.030752-45.089732-389.380302-202.976912-389.380302-380.362355 0-139.851288 99.19741-269.124768 260.106822-339.805969 13.502547-5.995716 27.053839-12.040177 40.556386-16.573523 10.529062-4.4846 22.569239-7.506831 33.0983-10.480317 12.040177-4.533346 21.058123-15.062408 21.058124-28.564954a30.173561 30.173561 0 0 0-30.07607-30.07607 25.396487 25.396487 0 0 0-15.062408 4.4846c-10.529062 3.022231-19.498262 6.044461-28.564955 9.017947l-45.089732 18.035893C114.357309 254.257343 0.097491 406.148808 0.097491 568.471843c0 207.510258 180.407674 387.917932 439.00338 440.563241l54.107679 9.017946c12.040177 1.46237 25.59147 3.022231 37.631646 3.022231h1.46237c16.573523 0 30.07607-13.551292 30.07607-30.07607a30.758509 30.758509 0 0 0-27.05384-30.07607zM1169.798258 569.982958a30.173561 30.173561 0 0 0-30.07607-30.07607 30.173561 30.173561 0 0 0-30.07607 30.07607v1.46237c0 46.649593-10.529062 93.25044-33.049555 136.829057-1.511115 3.022231-1.511115 7.506831-1.511115 12.040177 0 16.573523 13.551292 30.07607 30.07607 30.07607 13.502547 0 24.031609-9.017946 28.564954-21.058124a361.985243 361.985243 0 0 0 36.071786-157.88718v-1.46237z" p-id="10126"></path><path d="M1052.516209 297.835959c-5.995716-4.533346-13.502547-9.017946-22.520493-9.017946a30.173561 30.173561 0 0 0-30.07607 30.07607c0 7.506831 2.973485 15.013662 9.017946 21.009378a375.14657 375.14657 0 0 1 79.699148 118.793164c4.4846 10.529062 15.013662 19.547008 27.053839 19.547008 16.524777 0 30.07607-13.551292 30.07607-30.07607 0-4.4846-1.511115-7.506831-3.02223-12.040177a422.039891 422.039891 0 0 0-90.179464-138.291427zM666.158138 182.065026h4.4846c16.573523 0 30.07607-13.551292 30.07607-30.07607 0-15.013662-12.040177-28.564955-27.053839-28.564954v-1.46237a761.602133 761.602133 0 0 0-154.86495-1.559861h-3.022231a30.173561 30.173561 0 0 0-30.07607 30.07607c0 16.573523 13.551292 30.07607 30.07607 30.07607h3.022231v1.462369c46.600847-5.94697 97.735041-4.4846 147.358119 0z" p-id="10127"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 623 B After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777014169186" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4736" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1024 739.560727V1024H739.560727v-84.898909h199.540364v-199.540364H1024z m-939.101091 0v199.540364h199.540364V1024H0V739.560727h84.898909zM824.878545 199.121455v625.75709H199.121455V199.121455h625.75709z m-85.317818 85.317818H284.439273v455.121454h455.121454V284.439273zM1024 0v284.439273h-84.898909V84.898909h-199.540364V0H1024zM284.439273 0v84.898909H84.898909v199.540364H0V0h284.439273z" fill="#e6e6e6" p-id="4737"></path></svg>
|
||||||
|
After Width: | Height: | Size: 764 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" fill="currentColor" x="2" y="2" width="14" height="14" rx="1"></rect></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 338 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-outline-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" stroke="currentColor" x="1.5" y="1.5" width="15" height="15" rx="1"></rect><rect id="Rectangle" fill="currentColor" x="3.5" y="3.5" width="11" height="11" rx="1"></rect></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 446 B |
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1609205172733" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2919" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M320 640v256H256v-192H64v-64h256z m640 0v64h-192v192h-64v-256h256zM512 384a128 128 0 1 1 0 256 128 128 0 0 1 0-256zM320 128v256H64V320h192V128h64z m448 0v192h192v64h-256V128h64z" p-id="2920"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426164195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5541" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M316 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8zM512 622c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39zM512 482c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39z" p-id="5542"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-40 728H184V184h656v656z" p-id="5543"></path><path d="M648 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8z" p-id="5544"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 581 B After Width: | Height: | Size: 908 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777352764855" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10736" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M587.808 383.392l-102.208 102.208A37.472 37.472 0 0 0 512 549.408a36.288 36.288 0 0 0 26.272-11.104l315.84-315.232a454.976 454.976 0 1 0 43.52 61.888l-54.688 54.752a372.704 372.704 0 1 1-94.816-116.928l-106.56 106.496-53.792 54.144z" p-id="10737"></path></svg>
|
||||||
|
After Width: | Height: | Size: 594 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1775115523115" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5347" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M458.105263 970.105263h-215.578947V264.084211h215.578947V970.105263z m-161.68421-53.894737h107.789473V317.978947h-107.789473V916.210526z" fill="#ffffff" p-id="5348"></path><path d="M296.421053 970.105263h-215.578948V479.663158h215.578948V970.105263z m-161.684211-53.894737h107.789474V533.557895h-107.789474V916.210526zM943.157895 970.105263h-215.578948V479.663158h215.578948V970.105263z m-161.684211-53.894737h107.789474V533.557895h-107.789474V916.210526zM619.789474 970.105263h-215.578948V53.894737h215.578948v916.210526z m-161.684211-53.894737h107.789474V107.789474h-107.789474v808.421052z" fill="#ffffff" p-id="5349"></path><path d="M781.473684 970.105263h-215.578947V264.084211h215.578947V970.105263z m-161.68421-53.894737h107.789473V317.978947h-107.789473V916.210526z" fill="#ffffff" p-id="5350"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1774331916694" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1627" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M198.4 960A134.4 134.4 0 0 1 64 825.6V198.4A134.4 134.4 0 0 1 198.4 64h268.8a44.8 44.8 0 0 1 44.8 44.8 44.8 44.8 0 0 1-44.8 44.8H198.4a44.8 44.8 0 0 0-44.8 44.8v627.2a44.8 44.8 0 0 0 44.8 44.8h627.2a44.8 44.8 0 0 0 44.8-44.8V556.8a44.8 44.8 0 0 1 44.8-44.8 44.8 44.8 0 0 1 44.8 44.8v268.8A134.4 134.4 0 0 1 825.6 960z m281.984-416.384a44.8 44.8 0 0 1 0-63.296L807.232 153.6H646.464a44.8 44.8 0 0 1-44.8-44.8 44.8 44.8 0 0 1 44.8-44.8h267.264a44.8 44.8 0 0 1 28.288 8.896l1.408 1.152 0.64 0.512 1.024 0.96a41.216 41.216 0 0 1 3.136 3.072l0.896 1.088 0.512 0.64 1.152 1.344a44.8 44.8 0 0 1 8.832 28.288V377.28a44.8 44.8 0 0 1-44.8 44.8 44.8 44.8 0 0 1-44.8-44.8V216.512l-326.4 326.4a44.8 44.8 0 0 1-32 13.248A44.8 44.8 0 0 1 480 543.616z" p-id="1628" fill="#2c2c2c"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" stroke="currentColor" x="1.5" y="1.5" width="15" height="15" rx="1"></rect></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 347 B |
@@ -1 +1 @@
|
|||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1597744457882" class="icon" viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10125" width="285.64453125" height="250" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M926.216214 404.588947l1.511115-151.84272H1079.570048c18.035893 0 33.098301-15.062408 33.098301-33.0983a33.390775 33.390775 0 0 0-33.098301-33.098301H927.727329V33.195792a33.390775 33.390775 0 0 0-33.049555-33.049555 33.390775 33.390775 0 0 0-33.0983 33.049555c0 3.022231 0 4.533346 1.511115 7.555577v144.287142H711.24787a33.390775 33.390775 0 0 0-33.098301 33.147046c0 18.035893 15.062408 33.049555 33.098301 33.049555H863.090589v139.802542c0 3.022231-1.46237 4.533346-1.46237 7.506831 0 18.035893 15.013662 33.098301 33.049555 33.098301 15.013662 1.46237 28.564955-10.529062 31.53844-27.053839zM1032.969201 790.995763a29.393631 29.393631 0 0 0-22.520493 10.480316 546.000095 546.000095 0 0 1-117.282049 88.717095 29.101157 29.101157 0 0 0-15.062408 25.591469c0 16.524777 13.551292 30.027324 30.07607 30.027324 4.533346 0 10.529062-1.46237 13.551292-2.973485 1.46237 0 1.46237-1.511115 1.46237-1.511115a523.235874 523.235874 0 0 0 127.811111-97.735041c6.044461-5.995716 10.529062-13.551292 10.529061-22.569238a28.028752 28.028752 0 0 0-28.564954-30.027325zM793.920503 935.282906c-2.973485 0-7.506831 0-10.529062 1.511115-46.600847 15.062408-96.223925 24.080354-145.798258 27.053839-15.062408 1.511115-25.59147 15.062408-25.591469 30.07607 0 16.573523 13.551292 30.07607 30.07607 30.07607 55.618794-4.4846 108.215357-13.502547 159.398295-30.07607a28.95492 28.95492 0 0 0 22.520494-28.564954 30.173561 30.173561 0 0 0-30.07607-30.07607zM535.324796 960.874375c-12.040177-1.511115-24.031609-1.511115-36.071785-3.02223a564.962155 564.962155 0 0 1-49.623078-7.506832c-230.030752-45.089732-389.380302-202.976912-389.380302-380.362355 0-139.851288 99.19741-269.124768 260.106822-339.805969 13.502547-5.995716 27.053839-12.040177 40.556386-16.573523 10.529062-4.4846 22.569239-7.506831 33.0983-10.480317 12.040177-4.533346 21.058123-15.062408 21.058124-28.564954a30.173561 30.173561 0 0 0-30.07607-30.07607 25.396487 25.396487 0 0 0-15.062408 4.4846c-10.529062 3.022231-19.498262 6.044461-28.564955 9.017947l-45.089732 18.035893C114.357309 254.257343 0.097491 406.148808 0.097491 568.471843c0 207.510258 180.407674 387.917932 439.00338 440.563241l54.107679 9.017946c12.040177 1.46237 25.59147 3.022231 37.631646 3.022231h1.46237c16.573523 0 30.07607-13.551292 30.07607-30.07607a30.758509 30.758509 0 0 0-27.05384-30.07607zM1169.798258 569.982958a30.173561 30.173561 0 0 0-30.07607-30.07607 30.173561 30.173561 0 0 0-30.07607 30.07607v1.46237c0 46.649593-10.529062 93.25044-33.049555 136.829057-1.511115 3.022231-1.511115 7.506831-1.511115 12.040177 0 16.573523 13.551292 30.07607 30.07607 30.07607 13.502547 0 24.031609-9.017946 28.564954-21.058124a361.985243 361.985243 0 0 0 36.071786-157.88718v-1.46237z" p-id="10126"></path><path d="M1052.516209 297.835959c-5.995716-4.533346-13.502547-9.017946-22.520493-9.017946a30.173561 30.173561 0 0 0-30.07607 30.07607c0 7.506831 2.973485 15.013662 9.017946 21.009378a375.14657 375.14657 0 0 1 79.699148 118.793164c4.4846 10.529062 15.013662 19.547008 27.053839 19.547008 16.524777 0 30.07607-13.551292 30.07607-30.07607 0-4.4846-1.511115-7.506831-3.02223-12.040177a422.039891 422.039891 0 0 0-90.179464-138.291427zM666.158138 182.065026h4.4846c16.573523 0 30.07607-13.551292 30.07607-30.07607 0-15.013662-12.040177-28.564955-27.053839-28.564954v-1.46237a761.602133 761.602133 0 0 0-154.86495-1.559861h-3.022231a30.173561 30.173561 0 0 0-30.07607 30.07607c0 16.573523 13.551292 30.07607 30.07607 30.07607h3.022231v1.462369c46.600847-5.94697 97.735041-4.4846 147.358119 0z" p-id="10127"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777352032068" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5387" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M924.8 337.8c-22.6-53.4-54.9-101.3-96-142.4s-89-73.4-142.4-96C631.2 76.1 572.5 64.2 512 64.2S392.9 76.1 337.6 99.4c-53.4 22.6-101.3 54.9-142.4 96s-73.4 89-96 142.4C75.9 393.1 64 451.8 64 512.2c0 60.5 11.8 119.1 35.2 174.4 22.6 53.4 54.9 101.3 96 142.4 41.1 41.1 89 73.4 142.4 96 55.3 23.4 113.9 35.2 174.4 35.2s119.1-11.8 174.4-35.2c53.4-22.6 101.3-54.9 142.4-96 41.1-41.1 73.4-89 96-142.4 23.4-55.3 35.2-113.9 35.2-174.4 0-60.4-11.8-119.1-35.2-174.4zM780.3 780.5C708.6 852.2 613.4 891.6 512 891.6c-101.3 0-196.6-39.5-268.3-111.1S132.6 613.6 132.6 512.2c0-101.3 39.5-196.6 111.1-268.3s167-111.1 268.3-111.1c101.3 0 196.6 39.5 268.3 111.1s111.1 166.9 111.1 268.3S852 708.8 780.3 780.5z" p-id="5388"></path><path d="M512 512.2m-106.2 0a106.2 106.2 0 1 0 212.4 0 106.2 106.2 0 1 0-212.4 0Z" p-id="5389"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1779246817161" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5348" width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M473 71a8 8 0 0 1 8-8h64a8 8 0 0 1 8 8v77.161C722.848 166.622 857.812 301.289 876.729 471H952a8 8 0 0 1 8 8v64a8 8 0 0 1-8 8h-75.053C858.871 721.652 723.515 857.305 553 875.839V951a8 8 0 0 1-8 8h-64a8 8 0 0 1-8-8v-75.161C302.818 857.341 167.659 722.182 149.161 552H72a8 8 0 0 1-8-8v-64a8 8 0 0 1 8-8h77.161C167.659 301.818 302.818 166.659 473 148.161V71z m326 441c0-157.953-128.047-286-286-286S227 354.047 227 512s128.047 286 286 286 286-128.047 286-286z m-286 60c33.137 0 60-26.863 60-60s-26.863-60-60-60-60 26.863-60 60 26.863 60 60 60z" fill="#ffffff" p-id="5349"></path></svg>
|
||||||
|
After Width: | Height: | Size: 913 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777432778355" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2607" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M954.026667 913.6128H600.746667a35.908267 35.908267 0 0 1-35.771734-35.771733V116.736a35.703467 35.703467 0 0 1 68.266667-15.018667l353.143467 761.0368a35.566933 35.566933 0 0 1-2.2528 34.269867 35.362133 35.362133 0 0 1-30.173867 16.5888z" fill="#FFFFFF" p-id="2608"></path><path d="M465.373867 913.544533H112.162133a35.6352 35.6352 0 0 1-32.494933-50.722133L432.878933 101.717333a35.6352 35.6352 0 0 1 40.277334-19.8656 35.566933 35.566933 0 0 1 27.989333 34.952534V877.909333a35.771733 35.771733 0 0 1-35.771733 35.6352z" fill="#FFFFFF" fill-opacity=".4" p-id="2609"></path></svg>
|
||||||
|
After Width: | Height: | Size: 916 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426622063" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8288" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M667.69962 294.974152l0 589.688383 316.384787 0L667.69962 294.974152zM632.522446 884.662535 632.522446 572.426231 34.882973 884.662535 632.522446 884.662535zM510.16777 357.862457l-137.677663-31.323403c0 0 97.523127-217.392192 349.512279-98.842169 0 0-196.516746-248.618381-487.190965 67.571978l-137.677663-31.273261 158.803819 250.082732L510.16777 357.862457z" p-id="8289"></path></svg>
|
||||||
|
After Width: | Height: | Size: 719 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426691300" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2490" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M34.884 883.64h316.385V293.95L34.884 883.64z m949.201 0L386.446 571.402v312.236h597.64zM763.03 513.053l158.805-250.083-137.678 31.274c-290.674-316.19-487.191-67.572-487.191-67.572 251.99-118.55 349.512 98.842 349.512 98.842l-137.677 31.323L763.03 513.054z" fill="" p-id="2491"></path></svg>
|
||||||
|
After Width: | Height: | Size: 623 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777432945307" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4263" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M106.496 928.426667V575.2832c0-19.729067 16.042667-35.771733 35.771733-35.771733h761.0368a35.703467 35.703467 0 0 1 15.086934 68.266666L157.354667 960.9216a35.566933 35.566933 0 0 1-34.269867-2.321067 35.362133 35.362133 0 0 1-16.5888-30.173866z" fill="#FFFFFF" p-id="4264"></path><path d="M106.496 439.842133V86.6304a35.6352 35.6352 0 0 1 50.7904-32.494933l761.0368 353.211733a35.6352 35.6352 0 0 1 19.933867 40.209067 35.566933 35.566933 0 0 1-34.952534 27.989333H142.199467a35.771733 35.771733 0 0 1-35.703467-35.703467z" fill="#FFFFFF" fill-opacity=".4" p-id="4265"></path></svg>
|
||||||
|
After Width: | Height: | Size: 916 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1782284218093" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4982" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 51.2a460.8 460.8 0 1 1 0 921.6 460.8 460.8 0 0 1 0-921.6z m0 51.2a409.6 409.6 0 1 0 0 819.2 409.6 409.6 0 0 0 0-819.2z" fill="#ffffff" p-id="4983"></path><path d="M512 358.4c70.4 0 137.1136 5.2736 196.7616 14.6432l27.0336 4.6592C877.1584 403.9168 972.8 454.2464 972.8 512c0 57.7536-95.6416 108.032-237.0048 134.2976l-27.0336 4.608A1275.1872 1275.1872 0 0 1 512 665.6c-70.4 0-137.1136-5.2736-196.7616-14.6432l-27.0336-4.6592C146.8416 620.0832 51.2 569.7536 51.2 512c0-57.7536 95.6416-108.032 237.0048-134.2976l27.0336-4.608c55.0912-8.704 116.1728-13.824 180.5824-14.592L512 358.4z m0 51.2c-31.5904 0-62.3104 1.1776-91.8528 3.328l-29.0816 2.5088-28.2112 3.072c-23.1424 2.7648-45.2096 6.144-66.048 9.984l-24.4224 4.7616-23.0912 5.12-21.76 5.5296C150.3744 464.5376 102.4 490.8544 102.4 512c0 21.1456 47.9744 47.4624 125.1328 68.096l21.76 5.4784 23.0912 5.1712 24.4224 4.7616c20.8384 3.84 42.9056 7.168 66.048 9.984l28.16 3.072 29.1328 2.5088a1261.4656 1261.4656 0 0 0 183.7056 0l29.0816-2.5088 28.2112-3.072c23.1424-2.7648 45.2096-6.144 66.048-9.984l24.4224-4.7616 23.0912-5.12 21.76-5.5296C873.6256 559.4624 921.6 533.1456 921.6 512c0-21.1456-47.9744-47.4624-125.1328-68.096l-21.76-5.4784-23.0912-5.1712-24.4224-4.7616c-20.8384-3.84-42.9056-7.168-66.048-9.984l-28.16-3.072-29.1328-2.5088c-24.576-1.792-50.0736-2.9184-76.1344-3.2256L512 409.6z" fill="#ffffff" p-id="4984"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="24px" height="24px" viewBox="0 0 24 24" class="h-6 w-6"><g id="tool-seg-threshold" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><rect id="Rectangle" x="0" y="0" width="24" height="24"></rect><g id="Group" transform="translate(2.4184, 14.3673)" stroke="currentColor" stroke-width="1.5"><line x1="16.5816327" y1="2.13265306" x2="19.0816327" y2="2.13265306" id="Line-2" stroke-linecap="round"></line><line x1="0.0816326531" y1="2.13265306" x2="12.0816327" y2="2.13265306" id="Line-2" stroke-linecap="round"></line><circle id="Oval" cx="14.2244898" cy="2.09183673" r="2.09183673"></circle></g><g id="Group" transform="translate(11.7092, 7.4592) scale(-1, 1) translate(-11.7092, -7.4592)translate(1.9184, 5.3673)" stroke="currentColor" stroke-width="1.5"><line x1="16" y1="2.13265306" x2="19.0816327" y2="2.13265306" id="Line-2" stroke-linecap="round"></line><line x1="0.0816326531" y1="2.13265306" x2="11" y2="2.13265306" id="Line-2" stroke-linecap="round"></line><circle id="Oval" cx="13.2244898" cy="2.09183673" r="2.09183673"></circle></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -2,11 +2,7 @@
|
|||||||
<div class="navbar navbar-flex-wrapper">
|
<div class="navbar navbar-flex-wrapper">
|
||||||
<div class="leftMenu">
|
<div class="leftMenu">
|
||||||
<div class="navbar-flex-wrapper">
|
<div class="navbar-flex-wrapper">
|
||||||
<hamburger
|
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||||
:is-active="sidebar.opened"
|
|
||||||
class="hamburger-container"
|
|
||||||
@toggleClick="toggleSideBar"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<breadcrumb class="breadcrumb-container" />
|
<breadcrumb class="breadcrumb-container" />
|
||||||
</div>
|
</div>
|
||||||
@@ -51,12 +47,8 @@
|
|||||||
<TopLang></TopLang>
|
<TopLang></TopLang>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<toggleRole
|
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
|
||||||
v-if="toggleRoleVisible"
|
@save="loginByRole" />
|
||||||
:visible.sync="toggleRoleVisible"
|
|
||||||
:loading="toggleRoleLoading"
|
|
||||||
@save="loginByRole"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -192,12 +184,14 @@ export default {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
// position: relative;
|
// position: relative;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||||
|
|
||||||
.hamburger-container {
|
.hamburger-container {
|
||||||
line-height: 46px;
|
line-height: 46px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -219,6 +213,7 @@ export default {
|
|||||||
// float: right;
|
// float: right;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 65px;
|
line-height: 65px;
|
||||||
|
|
||||||
// position: relative;
|
// position: relative;
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -245,6 +240,7 @@ export default {
|
|||||||
.avatar-container {
|
.avatar-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 200px;
|
margin-right: 200px;
|
||||||
|
|
||||||
.user-avatar {
|
.user-avatar {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
@@ -252,16 +248,19 @@ export default {
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-container {
|
.dropdown-container {
|
||||||
// margin-left: 30px;
|
// margin-left: 30px;
|
||||||
// position: absolute;
|
// position: absolute;
|
||||||
// right: 20px;
|
// right: 20px;
|
||||||
// top: 0px;
|
// top: 0px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.el-icon-caret-bottom {
|
.el-icon-caret-bottom {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dropdown-link {
|
.el-dropdown-link {
|
||||||
color: #999c9e;
|
color: #999c9e;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "~@/styles/mixin.scss";
|
@use "@/styles/mixin.scss" as *;
|
||||||
@import "~@/styles/variables.module.scss";
|
@use "@/styles/variables.module.scss" as *;
|
||||||
|
// @import "~@/styles/mixin.scss";
|
||||||
|
// @import "~@/styles/variables.module.scss";
|
||||||
|
|
||||||
.app-wrapper {
|
.app-wrapper {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
||||||
// import { createVersionPolling } from "@/utils/version-polling.esm.js";
|
// import { createVersionPolling } from "@/utils/version-polling.esm.js";
|
||||||
import ElementUI, { MessageBox } from 'element-ui'
|
import ElementUI, { MessageBox } from 'element-ui'
|
||||||
@@ -70,6 +71,9 @@ import FB from '@/components/feedBack/index'
|
|||||||
Vue.use(FB)
|
Vue.use(FB)
|
||||||
import FBT from '@/components/feedBackTable/index'
|
import FBT from '@/components/feedBackTable/index'
|
||||||
Vue.use(FBT)
|
Vue.use(FBT)
|
||||||
|
import resize from '@/directive/resize/index'
|
||||||
|
// 表格自适应指令
|
||||||
|
Vue.use(resize)
|
||||||
import adaptive from '@/directive/adaptive/index'
|
import adaptive from '@/directive/adaptive/index'
|
||||||
// 表格自适应指令
|
// 表格自适应指令
|
||||||
Vue.use(adaptive)
|
Vue.use(adaptive)
|
||||||
@@ -334,8 +338,10 @@ async function VueInit() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
|
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
|
||||||
if (CompanyInfo && CompanyInfo.SystemShortName && text.toUpperCase() !== "CIRCLE") {
|
if (CompanyInfo && CompanyInfo.SystemShortName && (text.toUpperCase() !== "CIRCLE")) {
|
||||||
let test = new RegExp('IRC', 'ig')
|
// 精准匹配独立单词 IRC
|
||||||
|
// let test = new RegExp('IRC', 'ig')
|
||||||
|
let test = new RegExp('\\bIRC\\b', 'ig')
|
||||||
text = text.replace(test, CompanyInfo.SystemShortName)
|
text = text.replace(test, CompanyInfo.SystemShortName)
|
||||||
}
|
}
|
||||||
// return i18n.t(key)
|
// return i18n.t(key)
|
||||||
@@ -446,6 +452,7 @@ async function VueInit() {
|
|||||||
isOpen = false
|
isOpen = false
|
||||||
isLock = null
|
isLock = null
|
||||||
zzSessionStorage.removeItem('isLock')
|
zzSessionStorage.removeItem('isLock')
|
||||||
|
DicomEvent.$emit('isLock', false)
|
||||||
router.push("/login")
|
router.push("/login")
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// _vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
|
// _vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
|
||||||
@@ -457,160 +464,166 @@ async function VueInit() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
} : () => { }, process.env.VUE_APP_LOGOUT_FOR_TIME,
|
} : () => { }, process.env.VUE_APP_LOGOUT_FOR_TIME,
|
||||||
eval(process.env.VUE_APP_LOCK_FOR_PERMISSION) ? () => {
|
eval(process.env.VUE_APP_LOCK_FOR_PERMISSION)
|
||||||
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
|
? () => {
|
||||||
if (_vm.$store.state.trials.unlock || WHITELIST.includes(_vm.$route.path)) {
|
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
|
||||||
count = 0;
|
if (_vm.$store.state.trials.unlock || WHITELIST.includes(_vm.$route.path)) {
|
||||||
localStorage.setItem('count', '0')
|
count = 0;
|
||||||
if (_vm.$route.path === '/login') {
|
localStorage.setItem('count', '0')
|
||||||
zzSessionStorage.removeItem('lastWorkbench')
|
if (_vm.$route.path === '/login') {
|
||||||
zzSessionStorage.removeItem('isLock')
|
zzSessionStorage.removeItem('lastWorkbench')
|
||||||
isLock = null
|
zzSessionStorage.removeItem('isLock')
|
||||||
}
|
DicomEvent.$emit('isLock', false)
|
||||||
return
|
isLock = null
|
||||||
}
|
|
||||||
if (isOpen) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isOpen = true
|
|
||||||
zzSessionStorage.setItem('isLock', 'true')
|
|
||||||
_vm.$msgbox({
|
|
||||||
title: _vm.$t("env:lock:msgBox:title"),
|
|
||||||
confirmButtonText: _vm.$t("env:lock:msgBox:confirmButtonText"),
|
|
||||||
showClose: false,
|
|
||||||
beforeClose: (action, instance, done) => {
|
|
||||||
if (action === 'confirm') {
|
|
||||||
if (!_vm.unlock.my_username) {
|
|
||||||
_vm.$message.warning(_vm.$t("env:lock:msgBox:iupUser"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!_vm.unlock.my_password) {
|
|
||||||
_vm.$message.warning(_vm.$t("env:lock:msgBox:inpPassword"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var my_username = zzSessionStorage.getItem('my_username')
|
|
||||||
var my_password = zzSessionStorage.getItem('my_password')
|
|
||||||
let my_userid = zzSessionStorage.getItem('userId')
|
|
||||||
let my_EMail = zzSessionStorage.getItem('my_EMail') || ''
|
|
||||||
if (md5(_vm.unlock.my_password) === my_password && (my_username === _vm.unlock.my_username || my_EMail.toUpperCase() === _vm.unlock.my_username.toUpperCase())) {
|
|
||||||
resetReadingRestTime().then(() => {
|
|
||||||
})
|
|
||||||
const closeLock = (_vm) => {
|
|
||||||
_vm.$message.success(_vm.$t("env:lock:msgBox:lockSuccess"))
|
|
||||||
_vm.unlock = {
|
|
||||||
my_username: null,
|
|
||||||
my_password: null,
|
|
||||||
view: false
|
|
||||||
}
|
|
||||||
isOpen = false
|
|
||||||
count = 0;
|
|
||||||
isLock = null
|
|
||||||
zzSessionStorage.removeItem('isLock')
|
|
||||||
localStorage.setItem('count', '0')
|
|
||||||
document.querySelector('#my_username').value = null
|
|
||||||
document.querySelector('#my_password').value = null
|
|
||||||
setTimeout(() => {
|
|
||||||
done()
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
// if (eval(process.env.VUE_APP_LOCK_FOR_PERMISSION_MFA)) {
|
|
||||||
// sendMFAEmail({ UserId: my_userid, MfaType: 1 }).then((res) => {
|
|
||||||
// done();
|
|
||||||
// Vue.prototype.$MFA({
|
|
||||||
// status: "lock",
|
|
||||||
// UserId: my_userid,
|
|
||||||
// EMail: res.Result,
|
|
||||||
// username: my_username,
|
|
||||||
// callBack: () => {
|
|
||||||
// closeLock(_vm)
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
closeLock(_vm)
|
|
||||||
// }
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// console.log(111)
|
|
||||||
_vm.$message.error(_vm.$t('env:lock:msgBox:userFail'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
return
|
||||||
message: h('div', {}, [
|
}
|
||||||
h('el-form', {
|
if (isOpen) {
|
||||||
props: { labelWidth: "80px" }
|
return
|
||||||
}, [
|
}
|
||||||
h('el-form-item', {
|
isOpen = true
|
||||||
props: { label: _vm.$t("env:lock:msgBox:form:username") },
|
zzSessionStorage.setItem('isLock', 'true')
|
||||||
}, [
|
DicomEvent.$emit('isLock', true)
|
||||||
h('input', {
|
_vm.$msgbox({
|
||||||
props: {
|
title: _vm.$t("env:lock:msgBox:title"),
|
||||||
value: _vm.unlock.my_username
|
confirmButtonText: _vm.$t("env:lock:msgBox:confirmButtonText"),
|
||||||
},
|
showClose: false,
|
||||||
attrs: {
|
beforeClose: (action, instance, done) => {
|
||||||
id: 'my_username',
|
if (action === 'confirm') {
|
||||||
class: 'el-input__inner',
|
if (!_vm.unlock.my_username) {
|
||||||
autocomplete: 'new-password'
|
_vm.$message.warning(_vm.$t("env:lock:msgBox:iupUser"))
|
||||||
},
|
return
|
||||||
on: {
|
|
||||||
change: (event) => {
|
|
||||||
_vm.unlock.my_username = event.target.value
|
|
||||||
},
|
|
||||||
input: (event) => {
|
|
||||||
_vm.unlock.my_username = event.target.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
h('el-form-item', {
|
|
||||||
props: { label: _vm.$t("env:lock:msgBox:form:Password") },
|
|
||||||
attrs: {
|
|
||||||
style: "position: relative;"
|
|
||||||
}
|
}
|
||||||
}, [
|
if (!_vm.unlock.my_password) {
|
||||||
h('input', {
|
_vm.$message.warning(_vm.$t("env:lock:msgBox:inpPassword"))
|
||||||
props: {
|
return
|
||||||
value: _vm.unlock.my_password
|
}
|
||||||
},
|
var my_username = zzSessionStorage.getItem('my_username')
|
||||||
ref: "unlock_my_password_input",
|
var my_password = zzSessionStorage.getItem('my_password')
|
||||||
attrs: {
|
let my_userid = zzSessionStorage.getItem('userId')
|
||||||
id: 'my_password',
|
let my_EMail = zzSessionStorage.getItem('my_EMail') || ''
|
||||||
class: 'el-input__inner',
|
if (md5(_vm.unlock.my_password) === my_password && (my_username === _vm.unlock.my_username || my_EMail.toUpperCase() === _vm.unlock.my_username.toUpperCase())) {
|
||||||
type: _vm.unlock.view ? 'text' : 'password',
|
resetReadingRestTime().then(() => {
|
||||||
autocomplete: 'new-password',
|
})
|
||||||
style: "padding-right:25px"
|
const closeLock = (_vm) => {
|
||||||
},
|
_vm.$message.success(_vm.$t("env:lock:msgBox:lockSuccess"))
|
||||||
on: {
|
_vm.unlock = {
|
||||||
change: (event) => {
|
my_username: null,
|
||||||
_vm.unlock.my_password = event.target.value
|
my_password: null,
|
||||||
},
|
view: false
|
||||||
input: (event) => {
|
|
||||||
_vm.unlock.my_password = event.target.value
|
|
||||||
}
|
}
|
||||||
|
isOpen = false
|
||||||
|
count = 0;
|
||||||
|
isLock = null
|
||||||
|
zzSessionStorage.removeItem('isLock')
|
||||||
|
DicomEvent.$emit('isLock', false)
|
||||||
|
localStorage.setItem('count', '0')
|
||||||
|
document.querySelector('#my_username').value = null
|
||||||
|
document.querySelector('#my_password').value = null
|
||||||
|
setTimeout(() => {
|
||||||
|
done()
|
||||||
|
}, 500)
|
||||||
}
|
}
|
||||||
}),
|
// if (eval(process.env.VUE_APP_LOCK_FOR_PERMISSION_MFA)) {
|
||||||
h('i', {
|
// sendMFAEmail({ UserId: my_userid, MfaType: 1 }).then((res) => {
|
||||||
attrs: {
|
// done();
|
||||||
id: 'my_password_view',
|
// Vue.prototype.$MFA({
|
||||||
class: "el-icon-view",
|
// status: "lock",
|
||||||
style: "cursor: pointer;position: absolute;top:35%;right:10px"
|
// UserId: my_userid,
|
||||||
},
|
// EMail: res.Result,
|
||||||
on: {
|
// username: my_username,
|
||||||
click: (event) => {
|
// callBack: () => {
|
||||||
_vm.unlock.view = !_vm.unlock.view
|
// closeLock(_vm)
|
||||||
if (_vm.unlock.view) {
|
// },
|
||||||
_vm.$refs['unlock_my_password_input'].type = "text"
|
// })
|
||||||
} else {
|
// })
|
||||||
_vm.$refs['unlock_my_password_input'].type = "password"
|
// } else {
|
||||||
}
|
closeLock(_vm)
|
||||||
|
// }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// console.log(111)
|
||||||
|
_vm.$message.error(_vm.$t('env:lock:msgBox:userFail'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message: h('div', {}, [
|
||||||
|
h('el-form', {
|
||||||
|
props: { labelWidth: "80px" }
|
||||||
|
}, [
|
||||||
|
h('el-form-item', {
|
||||||
|
props: { label: _vm.$t("env:lock:msgBox:form:username") },
|
||||||
|
}, [
|
||||||
|
h('input', {
|
||||||
|
props: {
|
||||||
|
value: _vm.unlock.my_username
|
||||||
},
|
},
|
||||||
|
attrs: {
|
||||||
|
id: 'my_username',
|
||||||
|
class: 'el-input__inner',
|
||||||
|
autocomplete: 'new-password'
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
change: (event) => {
|
||||||
|
_vm.unlock.my_username = event.target.value
|
||||||
|
},
|
||||||
|
input: (event) => {
|
||||||
|
_vm.unlock.my_username = event.target.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
h('el-form-item', {
|
||||||
|
props: { label: _vm.$t("env:lock:msgBox:form:Password") },
|
||||||
|
attrs: {
|
||||||
|
style: "position: relative;"
|
||||||
}
|
}
|
||||||
}),
|
}, [
|
||||||
|
h('input', {
|
||||||
|
props: {
|
||||||
|
value: _vm.unlock.my_password
|
||||||
|
},
|
||||||
|
ref: "unlock_my_password_input",
|
||||||
|
attrs: {
|
||||||
|
id: 'my_password',
|
||||||
|
class: 'el-input__inner',
|
||||||
|
type: _vm.unlock.view ? 'text' : 'password',
|
||||||
|
autocomplete: 'new-password',
|
||||||
|
style: "padding-right:25px"
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
change: (event) => {
|
||||||
|
_vm.unlock.my_password = event.target.value
|
||||||
|
},
|
||||||
|
input: (event) => {
|
||||||
|
_vm.unlock.my_password = event.target.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
h('i', {
|
||||||
|
attrs: {
|
||||||
|
id: 'my_password_view',
|
||||||
|
class: "el-icon-view",
|
||||||
|
style: "cursor: pointer;position: absolute;top:35%;right:10px"
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
click: (event) => {
|
||||||
|
_vm.unlock.view = !_vm.unlock.view
|
||||||
|
if (_vm.unlock.view) {
|
||||||
|
_vm.$refs['unlock_my_password_input'].type = "text"
|
||||||
|
} else {
|
||||||
|
_vm.$refs['unlock_my_password_input'].type = "password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
])
|
})
|
||||||
})
|
} : () => { },
|
||||||
} : () => { }, process.env.VUE_APP_LOCK_FOR_TIME)
|
process.env.VUE_APP_LOCK_FOR_TIME
|
||||||
|
)
|
||||||
}
|
}
|
||||||
VueInit()
|
VueInit()
|
||||||
// createVersionPolling({
|
// createVersionPolling({
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ NProgress.configure({ showSpinner: false })
|
|||||||
|
|
||||||
const whiteList = WHITELIST
|
const whiteList = WHITELIST
|
||||||
store.state.trials.whiteList = whiteList
|
store.state.trials.whiteList = whiteList
|
||||||
router.beforeEach(async(to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
// 设置页面标题
|
// 设置页面标题
|
||||||
// document.title = getPageTitle(to.meta.title) store.state.trials.whiteList.indexOf(to.path) === -1
|
// document.title = getPageTitle(to.meta.title) store.state.trials.whiteList.indexOf(to.path) === -1
|
||||||
@@ -60,7 +60,7 @@ router.beforeEach(async(to, from, next) => {
|
|||||||
Vue.prototype.toPath = to.path
|
Vue.prototype.toPath = to.path
|
||||||
Vue.prototype.$path = []
|
Vue.prototype.$path = []
|
||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
if (to.path === '/login' || to.path === '/recompose' || to.path === '/email-recompose' || to.path === '/error' || to.path === '/ReviewersResearchForm' || to.path === '/ReviewersResearch') {
|
if (to.path === '/login' || to.path === '/recompose' || to.path === '/email-recompose' || to.path === '/link_expired' || to.path === '/error' || to.path === '/ReviewersResearchForm' || to.path === '/ReviewersResearch') {
|
||||||
if (to.path === '/ReviewersResearch') {
|
if (to.path === '/ReviewersResearch') {
|
||||||
await OSSclient()
|
await OSSclient()
|
||||||
await store.dispatch('user/logout')
|
await store.dispatch('user/logout')
|
||||||
@@ -92,8 +92,13 @@ router.beforeEach(async(to, from, next) => {
|
|||||||
await store.dispatch('user/getUserInfo')
|
await store.dispatch('user/getUserInfo')
|
||||||
const accessRoutes = await store.dispatch('permission/generateRoutes')
|
const accessRoutes = await store.dispatch('permission/generateRoutes')
|
||||||
resetRouter()
|
resetRouter()
|
||||||
router.addRoutes(accessRoutes)
|
if (accessRoutes.length > 0) {
|
||||||
next({ ...to, replace: true })
|
router.addRoutes(accessRoutes)
|
||||||
|
next({ ...to, replace: true })
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
// 删除token并进入登录页面以重新登录
|
// 删除token并进入登录页面以重新登录
|
||||||
|
|||||||
@@ -128,6 +128,11 @@ export const constantRoutes = [
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
component: () => import('@/views/none-dicom-show/index')
|
component: () => import('@/views/none-dicom-show/index')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/none_dicoms',
|
||||||
|
hidden: true,
|
||||||
|
component: () => import('@/views/none-dicoms/index')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/noneDicomReading',
|
path: '/noneDicomReading',
|
||||||
name: 'noneDicomReading',
|
name: 'noneDicomReading',
|
||||||
@@ -144,6 +149,11 @@ export const constantRoutes = [
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
component: () => import('@/views/trials/trials-panel/reading/dicoms/none-dicoms')
|
component: () => import('@/views/trials/trials-panel/reading/dicoms/none-dicoms')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/ecrfList',
|
||||||
|
hidden: true,
|
||||||
|
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/TableList')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/readingPage',
|
path: '/readingPage',
|
||||||
name: 'readingPage',
|
name: 'readingPage',
|
||||||
@@ -156,12 +166,6 @@ export const constantRoutes = [
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt')
|
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt')
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/fusion',
|
|
||||||
name: 'fusion',
|
|
||||||
hidden: true,
|
|
||||||
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/demo/index')
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/historyScreenshot',
|
path: '/historyScreenshot',
|
||||||
@@ -284,6 +288,11 @@ export const constantRoutes = [
|
|||||||
component: () => import('@/views/error'),
|
component: () => import('@/views/error'),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/link_expired',
|
||||||
|
component: () => import('@/views/linkExpired'),
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/404',
|
path: '/404',
|
||||||
component: () => import('@/views/404'),
|
component: () => import('@/views/404'),
|
||||||
|
|||||||
@@ -128,7 +128,14 @@ const actions = {
|
|||||||
if (response.IsSuccess) {
|
if (response.IsSuccess) {
|
||||||
var noticeList = []
|
var noticeList = []
|
||||||
response.Result.forEach(el => {
|
response.Result.forEach(el => {
|
||||||
noticeList.push({ Id: el.Id, Content: el.NoticeContent, NoticeTypeEnum: el.NoticeTypeEnum })
|
noticeList.push({
|
||||||
|
Id: el.Id,
|
||||||
|
Content: el.NoticeContent,
|
||||||
|
NoticeTypeEnum: el.NoticeTypeEnum,
|
||||||
|
PublishedTime: el.PublishedTime,
|
||||||
|
FileName: el.FileName,
|
||||||
|
Path: el.Path
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
commit('SET_NOTICE', noticeList)
|
commit('SET_NOTICE', noticeList)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function getQuestions(questions) {
|
|||||||
answerObj.angle = angle
|
answerObj.angle = angle
|
||||||
answerObj.saveTypeEnum = isNaN(parseFloat(angle)) ? 1 : 2
|
answerObj.saveTypeEnum = isNaN(parseFloat(angle)) ? 1 : 2
|
||||||
}
|
}
|
||||||
} else if (criterionType === 21) {
|
} else if (criterionType === 21 || criterionType === 22) {
|
||||||
// MRI-PDFF
|
// MRI-PDFF
|
||||||
let isMeasurable = getQuestionAnswer(item.TableQuestions.Questions, 1105, answerObj)
|
let isMeasurable = getQuestionAnswer(item.TableQuestions.Questions, 1105, answerObj)
|
||||||
answerObj.isMeasurable = isMeasurable
|
answerObj.isMeasurable = isMeasurable
|
||||||
@@ -932,6 +932,12 @@ const actions = {
|
|||||||
data.IsDicom = study.IsDicom
|
data.IsDicom = study.IsDicom
|
||||||
data.PreviewImageCount = 0
|
data.PreviewImageCount = 0
|
||||||
data.IsCriticalSequence = study.IsCriticalSequence
|
data.IsCriticalSequence = study.IsCriticalSequence
|
||||||
|
data.PatientSex = study.PatientSex
|
||||||
|
data.PatientWeight = study.PatientWeight
|
||||||
|
data.RadionuclideHalfLife = study.RadionuclideHalfLife
|
||||||
|
data.RadionuclideTotalDose = study.RadionuclideTotalDose
|
||||||
|
data.RadiopharmaceuticalStartTime = study.RadiopharmaceuticalStartTime
|
||||||
|
data.AcquisitionTime = study.AcquisitionTime
|
||||||
var seriesList = []
|
var seriesList = []
|
||||||
study.SeriesList.forEach((series, seriesIndex) => {
|
study.SeriesList.forEach((series, seriesIndex) => {
|
||||||
const imageIds = []
|
const imageIds = []
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ const actions = {
|
|||||||
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
|
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
|
||||||
const data = response.Result
|
const data = response.Result
|
||||||
commit('SET_ROLES', data.BasicInfo.AccountList)
|
commit('SET_ROLES', data.BasicInfo.AccountList)
|
||||||
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1) {
|
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1 || data.BasicInfo.IsNeedResetPwd) {
|
||||||
try {
|
try {
|
||||||
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
|
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
|
||||||
commit('SET_TOKEN', data.JWTStr)
|
commit('SET_TOKEN', data.JWTStr)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
@import "./variables.module.scss";
|
@use "./variables.module.scss";
|
||||||
@import "./mixin.scss";
|
@use "./mixin.scss";
|
||||||
@import "./transition.scss";
|
@use "./transition.scss";
|
||||||
@import "./element-ui.scss";
|
@use "./element-ui.scss";
|
||||||
@import "./sidebar.scss";
|
@use "./sidebar.scss";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||||
|
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||||
// font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
|
// font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
// font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
// font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
||||||
// "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial,
|
// "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial,
|
||||||
@@ -205,139 +206,143 @@ body .el-table th.gutter {
|
|||||||
.el-descriptions {
|
.el-descriptions {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #303133
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__header {
|
.el-descriptions__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__title {
|
.el-descriptions__title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body {
|
.el-descriptions__body {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
background-color: #fff
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body .el-descriptions__table {
|
.el-descriptions__body .el-descriptions__table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell {
|
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.5
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-left {
|
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-left {
|
||||||
text-align: left
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-center {
|
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-center {
|
||||||
text-align: center
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-right {
|
.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-right {
|
||||||
text-align: right
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions .is-bordered {
|
.el-descriptions .is-bordered {
|
||||||
table-layout: auto
|
table-layout: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions .is-bordered .el-descriptions-item__cell {
|
.el-descriptions .is-bordered .el-descriptions-item__cell {
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
padding: 12px 10px
|
padding: 12px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions :not(.is-bordered) .el-descriptions-item__cell {
|
.el-descriptions :not(.is-bordered) .el-descriptions-item__cell {
|
||||||
padding-bottom: 12px
|
padding-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--medium.is-bordered .el-descriptions-item__cell {
|
.el-descriptions--medium.is-bordered .el-descriptions-item__cell {
|
||||||
padding: 10px
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--medium:not(.is-bordered) .el-descriptions-item__cell {
|
.el-descriptions--medium:not(.is-bordered) .el-descriptions-item__cell {
|
||||||
padding-bottom: 10px
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--small {
|
.el-descriptions--small {
|
||||||
font-size: 12px
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--small.is-bordered .el-descriptions-item__cell {
|
.el-descriptions--small.is-bordered .el-descriptions-item__cell {
|
||||||
padding: 8px 10px
|
padding: 8px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--small:not(.is-bordered) .el-descriptions-item__cell {
|
.el-descriptions--small:not(.is-bordered) .el-descriptions-item__cell {
|
||||||
padding-bottom: 8px
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--mini {
|
.el-descriptions--mini {
|
||||||
font-size: 12px
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--mini.is-bordered .el-descriptions-item__cell {
|
.el-descriptions--mini.is-bordered .el-descriptions-item__cell {
|
||||||
padding: 6px 10px
|
padding: 6px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions--mini:not(.is-bordered) .el-descriptions-item__cell {
|
.el-descriptions--mini:not(.is-bordered) .el-descriptions-item__cell {
|
||||||
padding-bottom: 6px
|
padding-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item {
|
.el-descriptions-item {
|
||||||
vertical-align: top
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__container {
|
.el-descriptions-item__container {
|
||||||
display: flex
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__container .el-descriptions-item__content,
|
.el-descriptions-item__container .el-descriptions-item__content,
|
||||||
.el-descriptions-item__container .el-descriptions-item__label {
|
.el-descriptions-item__container .el-descriptions-item__label {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: baseline
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__container .el-descriptions-item__content {
|
.el-descriptions-item__container .el-descriptions-item__content {
|
||||||
flex: 1
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__label.has-colon:after {
|
.el-descriptions-item__label.has-colon:after {
|
||||||
content: ":";
|
content: ":";
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -.5px
|
top: -0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__label.is-bordered-label {
|
.el-descriptions-item__label.is-bordered-label {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
background: #fafafa
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__label:not(.is-bordered-label) {
|
.el-descriptions-item__label:not(.is-bordered-label) {
|
||||||
margin-right: 10px
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions-item__content {
|
.el-descriptions-item__content {
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
overflow-wrap: break-word
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feedBack-box {
|
.feedBack-box {
|
||||||
.el-dialog__wrapper {
|
.el-dialog__wrapper {
|
||||||
z-index: 3999 !important;
|
z-index: 3999 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-popper {
|
||||||
|
z-index: 4000 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.feedBack-select-box {
|
.feedBack-select-box {
|
||||||
@@ -350,7 +355,7 @@ body .el-table th.gutter {
|
|||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
background: #000;
|
background: #000;
|
||||||
z-index: 3999;
|
z-index: 3999;
|
||||||
}
|
}
|
||||||
@@ -372,3 +377,7 @@ body .el-table th.gutter {
|
|||||||
vertical-align: -0.4em !important;
|
vertical-align: -0.4em !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile_confirm {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ export const anonymization = function (file, config) {
|
|||||||
try {
|
try {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
let AnonymizeFixedList = config.AnonymizeFixedList
|
let AnonymizeFixedList = config.AnonymizeFixedList
|
||||||
|
console.log(AnonymizeFixedList, 'AnonymizeFixedList')
|
||||||
let AnonymizeNotFixedList = config.AnonymizeNotFixedList
|
let AnonymizeNotFixedList = config.AnonymizeNotFixedList
|
||||||
let DicomStoreInfo = config.DicomStoreInfo
|
let DicomStoreInfo = config.DicomStoreInfo
|
||||||
reader.onload = async (event) => {
|
reader.onload = async (event) => {
|
||||||
@@ -15,9 +16,11 @@ export const anonymization = function (file, config) {
|
|||||||
let dataset = dcmjs.data.DicomMessage.readFile(buffer)
|
let dataset = dcmjs.data.DicomMessage.readFile(buffer)
|
||||||
for (var i = 0; i < AnonymizeFixedList.length; i++) {
|
for (var i = 0; i < AnonymizeFixedList.length; i++) {
|
||||||
let AnonymizeFixed = AnonymizeFixedList[i]
|
let AnonymizeFixed = AnonymizeFixedList[i]
|
||||||
if (!dataset.dict.hasOwnProperty(`${AnonymizeFixed.Group + AnonymizeFixed.Element}`)) continue
|
if (!dataset.dict.hasOwnProperty(`${AnonymizeFixed.Group + AnonymizeFixed.Element}`) && !dataset.meta.hasOwnProperty(`${AnonymizeFixed.Group + AnonymizeFixed.Element}`)) continue
|
||||||
if (dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element]) {
|
if (dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element]) {
|
||||||
dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element].Value[0] = AnonymizeFixed.ReplaceValue
|
dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element].Value[0] = AnonymizeFixed.ReplaceValue
|
||||||
|
} else if (dataset.meta[AnonymizeFixed.Group + AnonymizeFixed.Element]) {
|
||||||
|
dataset.meta[AnonymizeFixed.Group + AnonymizeFixed.Element].Value[0] = AnonymizeFixed.ReplaceValue
|
||||||
} else {
|
} else {
|
||||||
dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element] = {
|
dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element] = {
|
||||||
vr: AnonymizeFixed.ValueRepresentation,
|
vr: AnonymizeFixed.ValueRepresentation,
|
||||||
@@ -60,7 +63,7 @@ export const anonymization = function (file, config) {
|
|||||||
let newDicomFile = dataset.write() // fragmentMultiframe 原始数据是否进行分割
|
let newDicomFile = dataset.write() // fragmentMultiframe 原始数据是否进行分割
|
||||||
const bufferArray = new Uint8Array(newDicomFile)
|
const bufferArray = new Uint8Array(newDicomFile)
|
||||||
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
|
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
|
||||||
resolve({ blob, pixelDataElement })
|
resolve({ blob, pixelDataElement, Modality: dataset.dict['00080060'].Value[0] })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(file, 'warning')
|
console.log(file, 'warning')
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { anonymization } from './anonymization'
|
import { anonymization } from './anonymization'
|
||||||
export const dcmUpload = async function (data, config, progressFn) {
|
export const dcmUpload = async function (data, config, progressFn, fileInfo) {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
try {
|
try {
|
||||||
// let blob = await encoder(file, config)
|
// let blob = await encoder(file, config)
|
||||||
@@ -8,10 +8,12 @@ export const dcmUpload = async function (data, config, progressFn) {
|
|||||||
if (config) {
|
if (config) {
|
||||||
blob = await anonymization(data.file, config)
|
blob = await anonymization(data.file, config)
|
||||||
}
|
}
|
||||||
let res = await Vue.prototype.OSSclient.multipartUpload(Object.assign(data, { file: blob.blob }), progressFn)
|
|
||||||
|
let res = await Vue.prototype.OSSclient.multipartUpload(Object.assign(data, { file: blob.blob }), progressFn, fileInfo)
|
||||||
resolve({
|
resolve({
|
||||||
...res,
|
...res,
|
||||||
image: blob.pixelDataElement
|
image: blob.pixelDataElement,
|
||||||
|
Modality: blob.Modality
|
||||||
})
|
})
|
||||||
// let OSSclientA = await OSSclient
|
// let OSSclientA = await OSSclient
|
||||||
// let blob = await encoder(file)
|
// let blob = await encoder(file)
|
||||||
|
|||||||
@@ -8366,7 +8366,7 @@
|
|||||||
|
|
||||||
for (var i = 0; i < valarr.length; i++) {
|
for (var i = 0; i < valarr.length; i++) {
|
||||||
var checkValue = valarr[i],
|
var checkValue = valarr[i],
|
||||||
checklen = lengths[i],
|
checklen = lengths[i] || 0,
|
||||||
isString = false,
|
isString = false,
|
||||||
displaylen = checklen;
|
displaylen = checklen;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,343 @@
|
|||||||
|
import getNumberValues from "./getNumberValues";
|
||||||
|
import isNMReconstructable from "./isNMReconstructable";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a subpart of Image Type dicom tag defined by index
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @param {*} index 0 based index of the subtype
|
||||||
|
*/
|
||||||
|
function getImageTypeSubItemFromDataset(dataSet, index) {
|
||||||
|
const imageType = dataSet.string("x00080008");
|
||||||
|
|
||||||
|
if (imageType) {
|
||||||
|
const subTypes = imageType.split("\\");
|
||||||
|
|
||||||
|
if (subTypes.length > index) {
|
||||||
|
return subTypes[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
// DICOM 标准中针对 Enhanced CT/MR/PET 等“增强型多帧”(Enhanced Multi-frame)影像, 强制要求为每一帧显式记录真实的独立空间坐标 。
|
||||||
|
|
||||||
|
// - 它们的数据通常存放在: Per-frame Functional Groups Sequence (5200,9230) -> 对应的 Frame Item -> Plane Position Sequence (0020,9113) -> ImagePositionPatient (0020,0032) 。
|
||||||
|
function getSharedFunctionalGroupsDataSet(dataSet) {
|
||||||
|
const seq = dataSet?.elements?.x52009229;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return seq.items[0].dataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPerFrameFunctionalGroupsDataSet(dataSet, frameIndex) {
|
||||||
|
const seq = dataSet?.elements?.x52009230;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!Number.isInteger(frameIndex) ||
|
||||||
|
frameIndex < 0 ||
|
||||||
|
frameIndex >= seq.items.length
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return seq.items[frameIndex].dataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOrientationFromPlaneOrientationSequence(dataSet) {
|
||||||
|
const seq = dataSet?.elements?.x00209116;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return getNumberValues(seq.items[0].dataSet, "x00200037", 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPositionFromPlanePositionSequence(dataSet) {
|
||||||
|
const seq = dataSet?.elements?.x00209113;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return getNumberValues(seq.items[0].dataSet, "x00200032", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPixelSpacingFromPixelMeasuresSequence(dataSet) {
|
||||||
|
const seq = dataSet?.elements?.x00289110;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return getNumberValues(seq.items[0].dataSet, "x00280030", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSliceThicknessFromPixelMeasuresSequence(dataSet) {
|
||||||
|
const seq = dataSet?.elements?.x00289110;
|
||||||
|
if (!seq?.items?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!seq.items[0]?.dataSet?.elements?.x00180050) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return seq.items[0].dataSet.floatString("x00180050");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the orientation from NM multiframe dataset, if image type
|
||||||
|
* equal to RECON TOMO or RECON GATED TOMO
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractOrientationFromNMMultiframeDataset(dataSet) {
|
||||||
|
let imageOrientationPatient;
|
||||||
|
const modality = dataSet.string("x00080060");
|
||||||
|
|
||||||
|
if (modality?.includes("NM")) {
|
||||||
|
const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2);
|
||||||
|
|
||||||
|
if (imageSubType && isNMReconstructable(imageSubType)) {
|
||||||
|
if (dataSet.elements.x00540022) {
|
||||||
|
imageOrientationPatient = getNumberValues(
|
||||||
|
dataSet.elements.x00540022.items[0].dataSet,
|
||||||
|
"x00200037",
|
||||||
|
6
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageOrientationPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the position from NM multiframe dataset, if image type
|
||||||
|
* equal to RECON TOMO or RECON GATED TOMO
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractPositionFromNMMultiframeDataset(dataSet) {
|
||||||
|
let imagePositionPatient;
|
||||||
|
const modality = dataSet.string("x00080060");
|
||||||
|
|
||||||
|
if (modality?.includes("NM")) {
|
||||||
|
const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2);
|
||||||
|
|
||||||
|
if (imageSubType && isNMReconstructable(imageSubType)) {
|
||||||
|
if (dataSet.elements.x00540022) {
|
||||||
|
imagePositionPatient = getNumberValues(
|
||||||
|
dataSet.elements.x00540022.items[0].dataSet,
|
||||||
|
"x00200032",
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imagePositionPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMultiFrame(dataSet) {
|
||||||
|
const numberOfFrames =
|
||||||
|
dataSet.string("x00280008") || dataSet.uint16("x00280008");
|
||||||
|
return numberOfFrames !== undefined && Number(numberOfFrames) > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract orientation information from a dataset. It tries to get the orientation
|
||||||
|
* from the Detector Information Sequence (for NM images) if image type equal
|
||||||
|
* to RECON TOMO or RECON GATED TOMO
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractOrientationFromDataset(dataSet) {
|
||||||
|
// let imageOrientationPatient;
|
||||||
|
|
||||||
|
// if (isMultiFrame(dataSet)) {
|
||||||
|
// const perFrameDataSet = getPerFrameFunctionalGroupsDataSet(
|
||||||
|
// dataSet,
|
||||||
|
// frameIndex
|
||||||
|
// );
|
||||||
|
// imageOrientationPatient =
|
||||||
|
// getOrientationFromPlaneOrientationSequence(perFrameDataSet);
|
||||||
|
|
||||||
|
// if (!imageOrientationPatient) {
|
||||||
|
// const sharedDataSet = getSharedFunctionalGroupsDataSet(dataSet);
|
||||||
|
// imageOrientationPatient =
|
||||||
|
// getOrientationFromPlaneOrientationSequence(sharedDataSet);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!imageOrientationPatient) {
|
||||||
|
// imageOrientationPatient = getNumberValues(dataSet, "x00200037", 6);
|
||||||
|
// }
|
||||||
|
let imageOrientationPatient = getNumberValues(dataSet, "x00200037", 6)
|
||||||
|
// Trying to get the orientation from the Plane Orientation Sequence
|
||||||
|
if (!imageOrientationPatient && dataSet.elements.x00209116) {
|
||||||
|
imageOrientationPatient = getNumberValues(
|
||||||
|
dataSet.elements.x00209116.items[0].dataSet,
|
||||||
|
"x00200037",
|
||||||
|
6
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If orientation not valid to this point, trying to get the orientation
|
||||||
|
// from the Detector Information Sequence (for NM images) with image type
|
||||||
|
// equal to RECON TOMO or RECON GATED TOMO
|
||||||
|
|
||||||
|
if (!imageOrientationPatient) {
|
||||||
|
imageOrientationPatient =
|
||||||
|
extractOrientationFromNMMultiframeDataset(dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageOrientationPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract position information from a dataset. It tries to get the position
|
||||||
|
* from the Detector Information Sequence (for NM images) if image type equal
|
||||||
|
* to RECON TOMO or RECON GATED TOMO
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractPositionFromDataset(dataSet) {
|
||||||
|
// let imagePositionPatient;
|
||||||
|
|
||||||
|
// if (isMultiFrame(dataSet)) {
|
||||||
|
// const perFrameDataSet = getPerFrameFunctionalGroupsDataSet(
|
||||||
|
// dataSet,
|
||||||
|
// frameIndex
|
||||||
|
// );
|
||||||
|
// imagePositionPatient =
|
||||||
|
// getPositionFromPlanePositionSequence(perFrameDataSet);
|
||||||
|
|
||||||
|
// if (!imagePositionPatient) {
|
||||||
|
// const sharedDataSet = getSharedFunctionalGroupsDataSet(dataSet);
|
||||||
|
// imagePositionPatient =
|
||||||
|
// getPositionFromPlanePositionSequence(sharedDataSet);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!imagePositionPatient) {
|
||||||
|
// imagePositionPatient = getNumberValues(dataSet, "x00200032", 3);
|
||||||
|
// }
|
||||||
|
let imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
|
||||||
|
// Trying to get the position from the Plane Position Sequence
|
||||||
|
if (!imagePositionPatient && dataSet.elements.x00209113) {
|
||||||
|
imagePositionPatient = getNumberValues(
|
||||||
|
dataSet.elements.x00209113.items[0].dataSet,
|
||||||
|
"x00200032",
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If position not valid to this point, trying to get the position
|
||||||
|
// from the Detector Information Sequence (for NM images)
|
||||||
|
if (!imagePositionPatient) {
|
||||||
|
imagePositionPatient = extractPositionFromNMMultiframeDataset(dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
return imagePositionPatient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the pixelSpacing information. If exists, extracts this information
|
||||||
|
* from Pixel Measures Sequence
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractSpacingFromDataset(dataSet) {
|
||||||
|
// let pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
|
||||||
|
|
||||||
|
// // If pixelSpacing not valid to this point, trying to get the spacing
|
||||||
|
// // from the Pixel Measures Sequence
|
||||||
|
// if (!pixelSpacing && dataSet.elements.x00289110) {
|
||||||
|
// pixelSpacing = getNumberValues(
|
||||||
|
// dataSet.elements.x00289110.items[0].dataSet,
|
||||||
|
// 'x00280030',
|
||||||
|
// 2
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return pixelSpacing;
|
||||||
|
|
||||||
|
let rowPixelSpacing = null;
|
||||||
|
let columnPixelSpacing = null;
|
||||||
|
// let pixelSpacing;
|
||||||
|
|
||||||
|
// if (isMultiFrame(dataSet)) {
|
||||||
|
// const perFrameDataSet = getPerFrameFunctionalGroupsDataSet(
|
||||||
|
// dataSet,
|
||||||
|
// frameIndex
|
||||||
|
// );
|
||||||
|
// const sharedDataSet = getSharedFunctionalGroupsDataSet(dataSet);
|
||||||
|
// pixelSpacing =
|
||||||
|
// getPixelSpacingFromPixelMeasuresSequence(perFrameDataSet) ||
|
||||||
|
// getPixelSpacingFromPixelMeasuresSequence(sharedDataSet);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!pixelSpacing) {
|
||||||
|
// pixelSpacing =
|
||||||
|
// getNumberValues(dataSet, "x00280030", 2) ||
|
||||||
|
// getPixelSpacingFromPixelMeasuresSequence(dataSet);
|
||||||
|
// }
|
||||||
|
let pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
|
||||||
|
const imagePixelSpacing = getNumberValues(dataSet, "x00181164", 2);
|
||||||
|
const estimatedRadiographicMagnificationFactor = getNumberValues(
|
||||||
|
dataSet,
|
||||||
|
"x00181114",
|
||||||
|
2
|
||||||
|
);
|
||||||
|
if (pixelSpacing) {
|
||||||
|
rowPixelSpacing = pixelSpacing[0];
|
||||||
|
columnPixelSpacing = pixelSpacing[1];
|
||||||
|
} else if (imagePixelSpacing && estimatedRadiographicMagnificationFactor) {
|
||||||
|
rowPixelSpacing =
|
||||||
|
imagePixelSpacing[0] / estimatedRadiographicMagnificationFactor[0];
|
||||||
|
columnPixelSpacing =
|
||||||
|
imagePixelSpacing[1] / estimatedRadiographicMagnificationFactor[1];
|
||||||
|
} else if (imagePixelSpacing && !estimatedRadiographicMagnificationFactor) {
|
||||||
|
rowPixelSpacing = imagePixelSpacing[0];
|
||||||
|
columnPixelSpacing = imagePixelSpacing[1];
|
||||||
|
}
|
||||||
|
return rowPixelSpacing !== null
|
||||||
|
? [rowPixelSpacing, columnPixelSpacing]
|
||||||
|
: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the sliceThickness information. If exists, extracts this information
|
||||||
|
* from Pixel Measures Sequence
|
||||||
|
* @param {*} dataSet
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function extractSliceThicknessFromDataset(dataSet) {
|
||||||
|
let sliceThickness;
|
||||||
|
if (dataSet.elements.x00180050) {
|
||||||
|
sliceThickness = dataSet.floatString('x00180050');
|
||||||
|
}
|
||||||
|
else if (dataSet.elements.x00289110 &&
|
||||||
|
dataSet.elements.x00289110.items.length &&
|
||||||
|
dataSet.elements.x00289110.items[0].dataSet.elements.x00180050) {
|
||||||
|
sliceThickness =
|
||||||
|
dataSet.elements.x00289110.items[0].dataSet.floatString('x00180050');
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (sliceThickness === undefined && isMultiFrame(dataSet)) {
|
||||||
|
// const perFrameDataSet = getPerFrameFunctionalGroupsDataSet(
|
||||||
|
// dataSet,
|
||||||
|
// frameIndex
|
||||||
|
// );
|
||||||
|
// const sharedDataSet = getSharedFunctionalGroupsDataSet(dataSet);
|
||||||
|
// sliceThickness =
|
||||||
|
// getSliceThicknessFromPixelMeasuresSequence(perFrameDataSet) ||
|
||||||
|
// getSliceThicknessFromPixelMeasuresSequence(sharedDataSet);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return sliceThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getImageTypeSubItemFromDataset,
|
||||||
|
extractOrientationFromDataset,
|
||||||
|
extractPositionFromDataset,
|
||||||
|
extractSpacingFromDataset,
|
||||||
|
extractSliceThicknessFromDataset,
|
||||||
|
};
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
function getNumberValues(
|
||||||
|
dataSet,
|
||||||
|
tag,
|
||||||
|
minimumLength
|
||||||
|
){
|
||||||
|
const values = [];
|
||||||
|
const valueAsString = dataSet.string(tag);
|
||||||
|
|
||||||
|
if (!valueAsString) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const split = valueAsString.split('\\');
|
||||||
|
|
||||||
|
if (minimumLength && split.length < minimumLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < split.length; i++) {
|
||||||
|
values.push(parseFloat(split[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getNumberValues;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default function isNMReconstructable(imageSubType) {
|
||||||
|
return imageSubType === 'RECON TOMO' || imageSubType === 'RECON GATED TOMO';
|
||||||
|
}
|
||||||
@@ -1,25 +1,123 @@
|
|||||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
import * as cornerstoneWADOImageLoader from "cornerstone-wado-image-loader";
|
||||||
|
import store from "@/store";
|
||||||
|
import { getPTClinicalDataForInstance } from "@/utils/ptClinicalDataCache";
|
||||||
|
import {
|
||||||
|
getImageTypeSubItemFromDataset,
|
||||||
|
extractOrientationFromDataset,
|
||||||
|
extractPositionFromDataset,
|
||||||
|
extractSpacingFromDataset,
|
||||||
|
extractSliceThicknessFromDataset,
|
||||||
|
} from "./extractPositioningFromDataset";
|
||||||
|
|
||||||
|
function toNumber(val) {
|
||||||
|
if (val === undefined || val === null || val === "") return null;
|
||||||
|
const n = typeof val === "number" ? val : parseFloat(val);
|
||||||
|
return Number.isFinite(n) ? n : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeDicomTime(value) {
|
||||||
|
if (value === undefined || value === null || value === "") return null;
|
||||||
|
const num = toNumber(value);
|
||||||
|
if (num != null) {
|
||||||
|
return String(Math.floor(num)).padStart(6, "0");
|
||||||
|
}
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (!trimmed) return null;
|
||||||
|
const plain = trimmed.replace(/:/g, "");
|
||||||
|
const parts = plain.split(".");
|
||||||
|
const main = parts[0];
|
||||||
|
const fractional = parts[1];
|
||||||
|
if (!/^\d+$/.test(main)) {
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
const normalizedMain = main.padStart(6, "0");
|
||||||
|
return fractional ? `${normalizedMain}.${fractional}` : normalizedMain;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPTClinicalOverrideFromImageId(imageId) {
|
||||||
|
try {
|
||||||
|
const qIndex = imageId.indexOf("?");
|
||||||
|
if (qIndex === -1) return null;
|
||||||
|
const params = new URLSearchParams(imageId.slice(qIndex + 1));
|
||||||
|
const visitTaskId = params.get("visitTaskId");
|
||||||
|
const idx = params.get("idx");
|
||||||
|
|
||||||
|
// 场景1:trials/dicoms,imageId 带 visitTaskId + idx,优先使用列表中的最新 study 值
|
||||||
|
if (visitTaskId && idx) {
|
||||||
|
const parts = idx.split("|");
|
||||||
|
const studyIndex = toNumber(parts[0]);
|
||||||
|
if (Number.isInteger(studyIndex) && studyIndex >= 0) {
|
||||||
|
const visitTaskList = store.state.reading.visitTaskList;
|
||||||
|
if (Array.isArray(visitTaskList)) {
|
||||||
|
const visitTaskInfo = visitTaskList.find(
|
||||||
|
(v) => v && String(v.VisitTaskId) === visitTaskId
|
||||||
|
);
|
||||||
|
const study = visitTaskInfo?.StudyList?.[studyIndex];
|
||||||
|
if (
|
||||||
|
study &&
|
||||||
|
!(
|
||||||
|
study.PatientWeight == null &&
|
||||||
|
study.RadionuclideTotalDose == null &&
|
||||||
|
study.RadionuclideHalfLife == null &&
|
||||||
|
study.RadiopharmaceuticalStartTime == null &&
|
||||||
|
study.AcquisitionTime == null &&
|
||||||
|
study.PatientSex == null
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return study;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 场景2:src/components/Dicom,imageId 仅带 instanceId,回退到实例缓存
|
||||||
|
const instanceId = params.get("instanceId");
|
||||||
|
if (instanceId) {
|
||||||
|
const cached = getPTClinicalDataForInstance(instanceId);
|
||||||
|
if (cached) return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
function parseImageId(imageId) {
|
function parseImageId(imageId) {
|
||||||
// build a url by parsing out the url scheme and frame index from the imageId
|
// 兼容 frame 参数不在最后的情况:只移除 frame 参数本身,保留 instanceId/visitTaskId/idx 等其余 query
|
||||||
const firstColonIndex = imageId.indexOf(':');
|
const firstColonIndex = imageId.indexOf(":");
|
||||||
|
const scheme = imageId.substr(0, firstColonIndex);
|
||||||
let url = imageId.substring(firstColonIndex + 1);
|
const urlPart = imageId.substring(firstColonIndex + 1);
|
||||||
const frameIndex = url.indexOf('frame=');
|
let url = urlPart;
|
||||||
|
|
||||||
let frame;
|
let frame;
|
||||||
|
const qIndex = urlPart.indexOf("?");
|
||||||
|
if (qIndex !== -1) {
|
||||||
|
const base = urlPart.slice(0, qIndex);
|
||||||
|
const query = urlPart.slice(qIndex + 1);
|
||||||
|
const parts = query.split("&").filter(Boolean);
|
||||||
|
const preservedParts = [];
|
||||||
|
|
||||||
if (frameIndex !== -1) {
|
parts.forEach((part) => {
|
||||||
const frameStr = url.substr(frameIndex + 6);
|
const eqIndex = part.indexOf("=");
|
||||||
|
const key = eqIndex === -1 ? part : part.slice(0, eqIndex);
|
||||||
|
const value = eqIndex === -1 ? "" : part.slice(eqIndex + 1);
|
||||||
|
|
||||||
frame = parseInt(frameStr, 10);
|
if (key === "frame") {
|
||||||
url = url.substr(0, frameIndex - 1);
|
const n = value !== "" ? parseInt(value, 10) : NaN;
|
||||||
|
if (Number.isFinite(n)) {
|
||||||
|
frame = n;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留原始 query 片段,避免 URLSearchParams 把 | 编码成 %7C 导致 dataSetCache key 对不上
|
||||||
|
preservedParts.push(part);
|
||||||
|
});
|
||||||
|
|
||||||
|
url = preservedParts.length ? `${base}?${preservedParts.join("&")}` : base;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { scheme, url, frame };
|
||||||
scheme: imageId.substr(0, firstColonIndex),
|
|
||||||
url,
|
|
||||||
frame,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
function getNumberValues(dataSet, tag, minimumLength) {
|
function getNumberValues(dataSet, tag, minimumLength) {
|
||||||
const values = [];
|
const values = [];
|
||||||
@@ -28,7 +126,7 @@ function getNumberValues(dataSet, tag, minimumLength) {
|
|||||||
if (!valueAsString) {
|
if (!valueAsString) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const split = valueAsString.split('\\');
|
const split = valueAsString.split("\\");
|
||||||
|
|
||||||
if (minimumLength && split.length < minimumLength) {
|
if (minimumLength && split.length < minimumLength) {
|
||||||
return;
|
return;
|
||||||
@@ -67,28 +165,31 @@ function getLutData(lutDataSet, tag, lutDescriptor) {
|
|||||||
return lut;
|
return lut;
|
||||||
}
|
}
|
||||||
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
|
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
|
||||||
const pixelRepresentation = dataSet.uint16('x00280103');
|
const pixelRepresentation = dataSet.uint16("x00280103");
|
||||||
if (pixelRepresentation === 0) {
|
if (pixelRepresentation === 0) {
|
||||||
imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
|
imagePixelModule.smallestPixelValue = dataSet.uint16("x00280106");
|
||||||
imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
|
imagePixelModule.largestPixelValue = dataSet.uint16("x00280107");
|
||||||
} else {
|
} else {
|
||||||
imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
|
imagePixelModule.smallestPixelValue = dataSet.int16("x00280106");
|
||||||
imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
|
imagePixelModule.largestPixelValue = dataSet.int16("x00280107");
|
||||||
}
|
}
|
||||||
imagePixelModule.largestPixelValue = imagePixelModule.largestPixelValue === 0 ? undefined : imagePixelModule.largestPixelValue;
|
imagePixelModule.largestPixelValue =
|
||||||
|
imagePixelModule.largestPixelValue === 0
|
||||||
|
? undefined
|
||||||
|
: imagePixelModule.largestPixelValue;
|
||||||
}
|
}
|
||||||
function populatePaletteColorLut(dataSet, imagePixelModule) {
|
function populatePaletteColorLut(dataSet, imagePixelModule) {
|
||||||
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
|
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281101'
|
"x00281101"
|
||||||
);
|
);
|
||||||
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
|
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281102'
|
"x00281102"
|
||||||
);
|
);
|
||||||
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
|
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281103'
|
"x00281103"
|
||||||
);
|
);
|
||||||
|
|
||||||
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
|
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
|
||||||
@@ -127,33 +228,196 @@ function populatePaletteColorLut(dataSet, imagePixelModule) {
|
|||||||
|
|
||||||
imagePixelModule.redPaletteColorLookupTableData = getLutData(
|
imagePixelModule.redPaletteColorLookupTableData = getLutData(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281201',
|
"x00281201",
|
||||||
imagePixelModule.redPaletteColorLookupTableDescriptor
|
imagePixelModule.redPaletteColorLookupTableDescriptor
|
||||||
);
|
);
|
||||||
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
|
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281202',
|
"x00281202",
|
||||||
imagePixelModule.greenPaletteColorLookupTableDescriptor
|
imagePixelModule.greenPaletteColorLookupTableDescriptor
|
||||||
);
|
);
|
||||||
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
|
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
|
||||||
dataSet,
|
dataSet,
|
||||||
'x00281203',
|
"x00281203",
|
||||||
imagePixelModule.bluePaletteColorLookupTableDescriptor
|
imagePixelModule.bluePaletteColorLookupTableDescriptor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSpacingBetweenSlices(dataSet) {
|
||||||
|
if (dataSet?.elements?.x00180088) {
|
||||||
|
return dataSet.floatString("x00180088");
|
||||||
|
}
|
||||||
|
const pixelMeasuresSequence = dataSet?.elements?.x00289110;
|
||||||
|
if (
|
||||||
|
pixelMeasuresSequence?.items?.length &&
|
||||||
|
pixelMeasuresSequence.items[0]?.dataSet?.elements?.x00180088
|
||||||
|
) {
|
||||||
|
return pixelMeasuresSequence.items[0].dataSet.floatString("x00180088");
|
||||||
|
}
|
||||||
|
}
|
||||||
function metaDataProvider(type, imageId) {
|
function metaDataProvider(type, imageId) {
|
||||||
const parsedImageId = parseImageId(imageId);
|
const parsedImageId = parseImageId(imageId);
|
||||||
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
|
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(
|
||||||
|
parsedImageId.url
|
||||||
|
);
|
||||||
|
|
||||||
if (!dataSet) {
|
if (!dataSet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (type === 'imagePlaneModule') {
|
const ptOverride = getPTClinicalOverrideFromImageId(imageId);
|
||||||
const imageOrientationPatient = getNumberValues(dataSet, 'x00200037', 6);
|
if (type === "generalSeriesModule") {
|
||||||
const imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
|
const { dicomParser } = cornerstoneWADOImageLoader.external || {};
|
||||||
const pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
|
const overrideTime = normalizeDicomTime(ptOverride?.AcquisitionTime);
|
||||||
const imagePixelSpacing = getNumberValues(dataSet, 'x00181164', 2);
|
const seriesTimeRaw =
|
||||||
const estimatedRadiographicMagnificationFactor = getNumberValues(dataSet, 'x00181114', 2);
|
overrideTime ||
|
||||||
|
dataSet.string("x00080031") ||
|
||||||
|
dataSet.string("x00080032") ||
|
||||||
|
"";
|
||||||
|
const acquisitionTimeRaw =
|
||||||
|
overrideTime ||
|
||||||
|
dataSet.string("x00080032") ||
|
||||||
|
dataSet.string("x00080031") ||
|
||||||
|
"";
|
||||||
|
return {
|
||||||
|
modality: dataSet.string("x00080060"),
|
||||||
|
seriesInstanceUID: dataSet.string("x0020000e"),
|
||||||
|
seriesNumber: dataSet.intString("x00200011"),
|
||||||
|
studyInstanceUID: dataSet.string("x0020000d"),
|
||||||
|
seriesDate: dicomParser.parseDA(dataSet.string("x00080021")),
|
||||||
|
// 2D SUV 计算读取的是 seriesTime,这里同步使用用户录入采集时间
|
||||||
|
// seriesTime: dicomParser.parseTM(String(seriesTimeRaw)),
|
||||||
|
seriesTime: dicomParser.parseTM(dataSet.string('x00080031') || ''),
|
||||||
|
acquisitionDate: dicomParser.parseDA(dataSet.string("x00080022") || ""),
|
||||||
|
acquisitionTime: dicomParser.parseTM(String(acquisitionTimeRaw)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (type === "patientStudyModule") {
|
||||||
|
const weightOverride = ptOverride?.PatientWeight;
|
||||||
|
const weight =
|
||||||
|
weightOverride
|
||||||
|
? toNumber(weightOverride)
|
||||||
|
: dataSet.floatString("x00101030");
|
||||||
|
return {
|
||||||
|
patientAge: dataSet.intString("x00101010"),
|
||||||
|
patientSize: dataSet.floatString("x00101020"),
|
||||||
|
patientWeight: weight,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "petIsotopeModule") {
|
||||||
|
const { dicomParser } = cornerstoneWADOImageLoader.external || {};
|
||||||
|
const radiopharmaceuticalInfo = dataSet.elements.x00540016;
|
||||||
|
|
||||||
|
if (radiopharmaceuticalInfo === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const firstRadiopharmaceuticalInfoDataSet =
|
||||||
|
radiopharmaceuticalInfo.items[0].dataSet;
|
||||||
|
|
||||||
|
const startTimeRaw =
|
||||||
|
firstRadiopharmaceuticalInfoDataSet.string("x00181072") || "";
|
||||||
|
const totalDoseRaw =
|
||||||
|
firstRadiopharmaceuticalInfoDataSet.floatString("x00181074");
|
||||||
|
const halfLifeRaw =
|
||||||
|
firstRadiopharmaceuticalInfoDataSet.floatString("x00181075");
|
||||||
|
let startTimeValue = normalizeDicomTime(
|
||||||
|
ptOverride?.RadiopharmaceuticalStartTime
|
||||||
|
);
|
||||||
|
if (!startTimeValue && startTimeRaw) {
|
||||||
|
startTimeValue = normalizeDicomTime(startTimeRaw) || startTimeRaw;
|
||||||
|
}
|
||||||
|
const radiopharmaceuticalStartTime = dicomParser.parseTM(
|
||||||
|
String(startTimeValue)
|
||||||
|
);
|
||||||
|
const overrideTotalDose =
|
||||||
|
ptOverride?.RadionuclideTotalDose != null &&
|
||||||
|
ptOverride.RadionuclideTotalDose !== ""
|
||||||
|
? toNumber(ptOverride.RadionuclideTotalDose)
|
||||||
|
: null;
|
||||||
|
const overrideHalfLife =
|
||||||
|
ptOverride?.RadionuclideHalfLife != null &&
|
||||||
|
ptOverride.RadionuclideHalfLife !== ""
|
||||||
|
? toNumber(ptOverride.RadionuclideHalfLife)
|
||||||
|
: null;
|
||||||
|
const radionuclideTotalDose =
|
||||||
|
overrideTotalDose != null ? overrideTotalDose : toNumber(totalDoseRaw);
|
||||||
|
const radionuclideHalfLife =
|
||||||
|
overrideHalfLife != null ? overrideHalfLife : toNumber(halfLifeRaw);
|
||||||
|
return {
|
||||||
|
radiopharmaceuticalInfo: {
|
||||||
|
radiopharmaceuticalStartTime,
|
||||||
|
radionuclideTotalDose,
|
||||||
|
radionuclideHalfLife,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (type === "imagePlaneModule") {
|
||||||
|
// const imageOrientationPatient = getNumberValues(dataSet, 'x00200037', 6);
|
||||||
|
// const imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
|
||||||
|
// const pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
|
||||||
|
const imagePixelSpacing = getNumberValues(dataSet, "x00181164", 2);
|
||||||
|
const frameIndex =
|
||||||
|
parsedImageId.frame !== undefined ? parsedImageId.frame - 1 : undefined;
|
||||||
|
const imageOrientationPatient = extractOrientationFromDataset(
|
||||||
|
dataSet,
|
||||||
|
frameIndex
|
||||||
|
);
|
||||||
|
let imagePositionPatient = extractPositionFromDataset(dataSet, frameIndex);
|
||||||
|
const pixelSpacing = extractSpacingFromDataset(dataSet, frameIndex);
|
||||||
|
const sliceThickness = extractSliceThicknessFromDataset(
|
||||||
|
dataSet,
|
||||||
|
frameIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
const modality = dataSet.string("x00080060");
|
||||||
|
if (
|
||||||
|
modality &&
|
||||||
|
modality.includes("NM") &&
|
||||||
|
parsedImageId.frame !== undefined &&
|
||||||
|
parsedImageId.frame > 1
|
||||||
|
) {
|
||||||
|
const spacingBetweenSlices = getSpacingBetweenSlices(dataSet);
|
||||||
|
const step =
|
||||||
|
spacingBetweenSlices !== undefined
|
||||||
|
? spacingBetweenSlices
|
||||||
|
: sliceThickness;
|
||||||
|
if (
|
||||||
|
imageOrientationPatient &&
|
||||||
|
imagePositionPatient &&
|
||||||
|
step !== undefined &&
|
||||||
|
frameIndex !== undefined
|
||||||
|
) {
|
||||||
|
const rowCosines = [
|
||||||
|
parseFloat(imageOrientationPatient[0]),
|
||||||
|
parseFloat(imageOrientationPatient[1]),
|
||||||
|
parseFloat(imageOrientationPatient[2]),
|
||||||
|
];
|
||||||
|
const columnCosines = [
|
||||||
|
parseFloat(imageOrientationPatient[3]),
|
||||||
|
parseFloat(imageOrientationPatient[4]),
|
||||||
|
parseFloat(imageOrientationPatient[5]),
|
||||||
|
];
|
||||||
|
const normal = [
|
||||||
|
rowCosines[1] * columnCosines[2] - rowCosines[2] * columnCosines[1],
|
||||||
|
rowCosines[2] * columnCosines[0] - rowCosines[0] * columnCosines[2],
|
||||||
|
rowCosines[0] * columnCosines[1] - rowCosines[1] * columnCosines[0],
|
||||||
|
];
|
||||||
|
|
||||||
|
const offset = frameIndex * parseFloat(step);
|
||||||
|
|
||||||
|
imagePositionPatient = [
|
||||||
|
parseFloat(imagePositionPatient[0]) + normal[0] * offset,
|
||||||
|
parseFloat(imagePositionPatient[1]) + normal[1] * offset,
|
||||||
|
parseFloat(imagePositionPatient[2]) + normal[2] * offset,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const estimatedRadiographicMagnificationFactor = getNumberValues(
|
||||||
|
dataSet,
|
||||||
|
"x00181114",
|
||||||
|
2
|
||||||
|
);
|
||||||
let columnPixelSpacing = null;
|
let columnPixelSpacing = null;
|
||||||
|
|
||||||
let rowPixelSpacing = null;
|
let rowPixelSpacing = null;
|
||||||
@@ -162,8 +426,10 @@ function metaDataProvider(type, imageId) {
|
|||||||
rowPixelSpacing = pixelSpacing[0];
|
rowPixelSpacing = pixelSpacing[0];
|
||||||
columnPixelSpacing = pixelSpacing[1];
|
columnPixelSpacing = pixelSpacing[1];
|
||||||
} else if (imagePixelSpacing && estimatedRadiographicMagnificationFactor) {
|
} else if (imagePixelSpacing && estimatedRadiographicMagnificationFactor) {
|
||||||
rowPixelSpacing = imagePixelSpacing[0] / estimatedRadiographicMagnificationFactor[0];
|
rowPixelSpacing =
|
||||||
columnPixelSpacing = imagePixelSpacing[1] / estimatedRadiographicMagnificationFactor[1];
|
imagePixelSpacing[0] / estimatedRadiographicMagnificationFactor[0];
|
||||||
|
columnPixelSpacing =
|
||||||
|
imagePixelSpacing[1] / estimatedRadiographicMagnificationFactor[1];
|
||||||
} else if (imagePixelSpacing && !estimatedRadiographicMagnificationFactor) {
|
} else if (imagePixelSpacing && !estimatedRadiographicMagnificationFactor) {
|
||||||
rowPixelSpacing = imagePixelSpacing[0];
|
rowPixelSpacing = imagePixelSpacing[0];
|
||||||
columnPixelSpacing = imagePixelSpacing[1];
|
columnPixelSpacing = imagePixelSpacing[1];
|
||||||
@@ -187,43 +453,48 @@ function metaDataProvider(type, imageId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
frameOfReferenceUID: dataSet.string('x00200052'),
|
frameOfReferenceUID: dataSet.string("x00200052"),
|
||||||
rows: dataSet.uint16('x00280010'),
|
rows: dataSet.uint16("x00280010"),
|
||||||
columns: dataSet.uint16('x00280011'),
|
columns: dataSet.uint16("x00280011"),
|
||||||
imageOrientationPatient,
|
imageOrientationPatient,
|
||||||
rowCosines,
|
rowCosines,
|
||||||
columnCosines,
|
columnCosines,
|
||||||
imagePositionPatient,
|
imagePositionPatient,
|
||||||
sliceThickness: dataSet.floatString('x00180050'),
|
sliceThickness,
|
||||||
sliceLocation: dataSet.floatString('x00201041'),
|
sliceLocation: dataSet.floatString("x00201041"),
|
||||||
pixelSpacing,
|
pixelSpacing,
|
||||||
rowPixelSpacing,
|
rowPixelSpacing,
|
||||||
columnPixelSpacing,
|
columnPixelSpacing,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (type === 'imagePixelModule') {
|
if (type === "imagePixelModule") {
|
||||||
const imagePixelModule = {
|
const imagePixelModule = {
|
||||||
samplesPerPixel: dataSet.uint16('x00280002'),
|
samplesPerPixel: dataSet.uint16("x00280002"),
|
||||||
photometricInterpretation: dataSet.string('x00280004'),
|
photometricInterpretation: dataSet.string("x00280004"),
|
||||||
rows: dataSet.uint16('x00280010'),
|
rows: dataSet.uint16("x00280010"),
|
||||||
columns: dataSet.uint16('x00280011'),
|
columns: dataSet.uint16("x00280011"),
|
||||||
bitsAllocated: dataSet.uint16('x00280100'),
|
bitsAllocated: dataSet.uint16("x00280100"),
|
||||||
bitsStored: dataSet.uint16('x00280101'),
|
bitsStored: dataSet.uint16("x00280101"),
|
||||||
highBit: dataSet.uint16('x00280102'),
|
highBit: dataSet.uint16("x00280102"),
|
||||||
pixelRepresentation: dataSet.uint16('x00280103'),
|
pixelRepresentation: dataSet.uint16("x00280103"),
|
||||||
planarConfiguration: dataSet.uint16('x00280006'),
|
planarConfiguration: dataSet.uint16("x00280006"),
|
||||||
pixelAspectRatio: dataSet.string('x00280034'),
|
pixelAspectRatio: dataSet.string("x00280034"),
|
||||||
};
|
};
|
||||||
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
|
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
|
imagePixelModule.photometricInterpretation === "PALETTE COLOR" &&
|
||||||
dataSet.elements.x00281101
|
dataSet.elements.x00281101
|
||||||
) {
|
) {
|
||||||
populatePaletteColorLut(dataSet, imagePixelModule);
|
populatePaletteColorLut(dataSet, imagePixelModule);
|
||||||
}
|
}
|
||||||
return imagePixelModule;
|
return imagePixelModule;
|
||||||
}
|
}
|
||||||
|
// if (type === "multiframeModule") {
|
||||||
|
// return {
|
||||||
|
// NumberOfFrames: dataSet.uint16("x00280008") || dataSet.string("x00280008")
|
||||||
|
// };
|
||||||
|
// }
|
||||||
// if (type === 'imagePixelModule') {
|
// if (type === 'imagePixelModule') {
|
||||||
// return {
|
// return {
|
||||||
// samplesPerPixel: dataSet.uint16('x00280002'),
|
// samplesPerPixel: dataSet.uint16('x00280002'),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const stream = require('stream')
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss"
|
import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss"
|
||||||
import { exist, AWSclose } from "@/utils/multipartUpload/aws"
|
import { exist, AWSclose } from "@/utils/multipartUpload/aws"
|
||||||
|
import { addOrUpdateFileUploadRecord } from '@/api/file'
|
||||||
const { GetObjectStoreToken } = require('../api/user.js')
|
const { GetObjectStoreToken } = require('../api/user.js')
|
||||||
const {
|
const {
|
||||||
S3Client,
|
S3Client,
|
||||||
@@ -22,7 +23,6 @@ async function ossGenerateSTS() {
|
|||||||
res = await GetObjectStoreToken()
|
res = await GetObjectStoreToken()
|
||||||
localStorage.setItem('stsToken', JSON.stringify(res))
|
localStorage.setItem('stsToken', JSON.stringify(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
// res.Result.ObjectStoreUse = 'AWS';
|
// res.Result.ObjectStoreUse = 'AWS';
|
||||||
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
|
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
|
||||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
|
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
|
||||||
@@ -34,12 +34,13 @@ async function ossGenerateSTS() {
|
|||||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||||
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
||||||
Vue.prototype.OSSclient = {
|
Vue.prototype.OSSclient = {
|
||||||
put: async function (objectName, object) {
|
put: async function (objectName, object, fileInfo = {}) {
|
||||||
|
|
||||||
OSSclient = await RefreshClient(OSSclient)
|
OSSclient = await RefreshClient(OSSclient)
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
let _vm = router.default.app
|
let _vm = router.default.app
|
||||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && _vm._route.path !== '/readingDicoms' && _vm._route.path !== '/showdicom') {
|
||||||
var objectItem = objectName.split('/')
|
var objectItem = objectName.split('/')
|
||||||
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||||
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
||||||
@@ -52,6 +53,20 @@ async function ossGenerateSTS() {
|
|||||||
}
|
}
|
||||||
let res = await OSSclient.put(objectName, object)
|
let res = await OSSclient.put(objectName, object)
|
||||||
if (res && res.url) {
|
if (res && res.url) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
fileInfo.fileType = mimeTypeToExt(fileInfo.fileType)
|
||||||
|
let params = Object.assign({ path: objectName }, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
const fileName = objectName.split('/').pop()
|
||||||
|
const fileType = fileName.includes('.')
|
||||||
|
? fileName.split('.').pop().toLowerCase()
|
||||||
|
: ''
|
||||||
|
let params = { trialId, path: objectName, fileName, fileType }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: objectName,
|
name: objectName,
|
||||||
url: res.url
|
url: res.url
|
||||||
@@ -65,7 +80,7 @@ async function ossGenerateSTS() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
multipartUpload: async (data, progress) => {
|
multipartUpload: async (data, progress, fileInfo = {}) => {
|
||||||
OSSclient = await RefreshClient(OSSclient)
|
OSSclient = await RefreshClient(OSSclient)
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
@@ -82,7 +97,7 @@ async function ossGenerateSTS() {
|
|||||||
OSSclient = new OSS(Vue.prototype.OSSclientConfig);
|
OSSclient = new OSS(Vue.prototype.OSSclientConfig);
|
||||||
}
|
}
|
||||||
let _vm = router.default.app
|
let _vm = router.default.app
|
||||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && _vm._route.path !== '/readingDicoms' && _vm._route.path !== '/showdicom') {
|
||||||
var objectItem = data.path.split('/')
|
var objectItem = data.path.split('/')
|
||||||
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||||
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
||||||
@@ -95,6 +110,21 @@ async function ossGenerateSTS() {
|
|||||||
}
|
}
|
||||||
let res = await customerHttp(OSSclient, data, progress);
|
let res = await customerHttp(OSSclient, data, progress);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
fileInfo.fileType = mimeTypeToExt(fileInfo.fileType)
|
||||||
|
let params = Object.assign({ path: data.path }, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
const fileName = data.path.split('/').pop()
|
||||||
|
const fileType = fileName.includes('.')
|
||||||
|
? fileName.split('.').pop().toLowerCase()
|
||||||
|
: ''
|
||||||
|
let params = { trialId, path: data.path, fileName, fileType }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
name: data.path,
|
name: data.path,
|
||||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name)
|
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name)
|
||||||
@@ -121,7 +151,7 @@ async function ossGenerateSTS() {
|
|||||||
try {
|
try {
|
||||||
var name = objectName.split('/')[objectName.split('/').length - 1]
|
var name = objectName.split('/')[objectName.split('/').length - 1]
|
||||||
let _vm = router.default.app
|
let _vm = router.default.app
|
||||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && _vm._route.path !== '/readingDicoms' && _vm._route.path !== '/showdicom') {
|
||||||
var objectItem = objectName.split('/')
|
var objectItem = objectName.split('/')
|
||||||
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||||
objectName = objectItem.join('/')
|
objectName = objectItem.join('/')
|
||||||
@@ -169,17 +199,17 @@ async function ossGenerateSTS() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
Vue.prototype.OSSclient = {
|
Vue.prototype.OSSclient = {
|
||||||
put: async function (objectName, object) {
|
put: async function (objectName, object, fileInfo = {}) {
|
||||||
let data = {
|
let data = {
|
||||||
file: object,
|
file: object,
|
||||||
path: objectName
|
path: objectName
|
||||||
}
|
}
|
||||||
aws = await RefreshClient(aws);
|
aws = await RefreshClient(aws);
|
||||||
return uploadAWS(aws, data, () => { });
|
return uploadAWS(aws, data, () => { }, fileInfo);
|
||||||
},
|
},
|
||||||
multipartUpload: async (data, progress) => {
|
multipartUpload: async (data, progress, fileInfo = {}) => {
|
||||||
aws = await RefreshClient(aws);
|
aws = await RefreshClient(aws);
|
||||||
return uploadAWS(aws, data, progress);
|
return uploadAWS(aws, data, progress, fileInfo);
|
||||||
},
|
},
|
||||||
close: () => {
|
close: () => {
|
||||||
AWSclose();
|
AWSclose();
|
||||||
@@ -189,13 +219,13 @@ async function ossGenerateSTS() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// AWS上传函数
|
// AWS上传函数
|
||||||
function uploadAWS(aws, data, progress) {
|
function uploadAWS(aws, data, progress, fileInfo) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { file, path } = data;
|
const { file, path } = data;
|
||||||
if (!file || !path) return reject('file and path be required');
|
if (!file || !path) return reject('file and path be required');
|
||||||
let _vm = router.default.app
|
let _vm = router.default.app
|
||||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload' && _vm._route.path !== '/readingDicoms' && _vm._route.path !== '/showdicom') {
|
||||||
var objectItem = data.path.split('/')
|
var objectItem = data.path.split('/')
|
||||||
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
// objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||||
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring(
|
||||||
@@ -211,6 +241,21 @@ function uploadAWS(aws, data, progress) {
|
|||||||
data.path = data.path.replace(`/${bucketName}/`, '');
|
data.path = data.path.replace(`/${bucketName}/`, '');
|
||||||
await exist(aws, bucketName, data, progress, (path, status) => {
|
await exist(aws, bucketName, data, progress, (path, status) => {
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
fileInfo.fileType = mimeTypeToExt(fileInfo.fileType)
|
||||||
|
let params = Object.assign({ path: decodeUtf8(curPath) }, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
const fileName = decodeUtf8(curPath).split('/').pop()
|
||||||
|
const fileType = fileName.includes('.')
|
||||||
|
? fileName.split('.').pop().toLowerCase()
|
||||||
|
: ''
|
||||||
|
let params = { trialId, path: decodeUtf8(curPath), fileName, fileType }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: decodeUtf8(curPath),
|
name: decodeUtf8(curPath),
|
||||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath)
|
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath)
|
||||||
@@ -320,5 +365,37 @@ function isCredentialsExpired(credentials) {
|
|||||||
return expireDate.getTime() - now.getTime() <= 300000;
|
return expireDate.getTime() - now.getTime() <= 300000;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
function mimeTypeToExt(mimeType) {
|
||||||
|
const map = {
|
||||||
|
// 图片
|
||||||
|
'image/jpeg': 'jpg',
|
||||||
|
'image/jpg': 'jpg',
|
||||||
|
'image/png': 'png',
|
||||||
|
'image/gif': 'gif',
|
||||||
|
'image/webp': 'webp',
|
||||||
|
'image/svg+xml': 'svg',
|
||||||
|
'image/bmp': 'bmp',
|
||||||
|
|
||||||
|
// 文档
|
||||||
|
'application/dicom': 'dcm',
|
||||||
|
'application/pdf': 'pdf',
|
||||||
|
'application/msword': 'doc',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
|
||||||
|
'application/vnd.ms-excel': 'xls',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
|
||||||
|
'application/vnd.ms-powerpoint': 'ppt',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
|
||||||
|
'text/plain': 'txt',
|
||||||
|
// 音频/视频
|
||||||
|
'audio/mpeg': 'mp3',
|
||||||
|
'audio/wav': 'wav',
|
||||||
|
'video/mp4': 'mp4',
|
||||||
|
'video/mpeg': 'mpeg',
|
||||||
|
// 压缩包
|
||||||
|
'application/zip': 'zip',
|
||||||
|
'application/x-rar-compressed': 'rar',
|
||||||
|
'application/x-7z-compressed': '7z',
|
||||||
|
};
|
||||||
|
return map[mimeType] || ''; // 找不到返回空字符串
|
||||||
|
}
|
||||||
export const OSSclient = ossGenerateSTS
|
export const OSSclient = ossGenerateSTS
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// PT 临床数据缓存:用于统一 SUV 口径(优先接口,缺失则回退 DICOM 元数据)
|
||||||
|
const instanceIdToClinicalData = new Map()
|
||||||
|
|
||||||
|
function normalizeId(id) {
|
||||||
|
if (id === undefined || id === null) return null
|
||||||
|
const s = String(id).trim()
|
||||||
|
return s ? s : null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setPTClinicalDataForInstance(instanceId, clinicalData) {
|
||||||
|
const key = normalizeId(instanceId)
|
||||||
|
if (!key) return
|
||||||
|
if (!clinicalData || typeof clinicalData !== 'object') return
|
||||||
|
instanceIdToClinicalData.set(key, { ...clinicalData })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPTClinicalDataForInstance(instanceId) {
|
||||||
|
const key = normalizeId(instanceId)
|
||||||
|
if (!key) return null
|
||||||
|
return instanceIdToClinicalData.get(key) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deletePTClinicalDataForInstance(instanceId) {
|
||||||
|
const key = normalizeId(instanceId)
|
||||||
|
if (!key) return
|
||||||
|
instanceIdToClinicalData.delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearPTClinicalDataCache() {
|
||||||
|
instanceIdToClinicalData.clear()
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ async function executeTask() {
|
|||||||
task.callback({ success: true, res: result })
|
task.callback({ success: true, res: result })
|
||||||
|
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
task.callback({ success: true, err: error })
|
task.callback({ success: false, err: error })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// let starLoadTime = performance.now()
|
// let starLoadTime = performance.now()
|
||||||
|
|||||||
@@ -21,6 +21,16 @@ var path
|
|||||||
|
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
async config => {
|
async config => {
|
||||||
|
if (config.url.includes("/Dictionary/getBasicDataSelect")) {
|
||||||
|
let query = router && router.app && router.app._route && router.app._route.query
|
||||||
|
if (query.trialId) {
|
||||||
|
let str = config.url.split("?")
|
||||||
|
config.url = `${str[0]}?TrialId=${query.trialId}`
|
||||||
|
if (str[1]) {
|
||||||
|
config.url += `&${str[1]}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
path = router && router.app && router.app._route && router.app._route.path
|
path = router && router.app && router.app._route && router.app._route.path
|
||||||
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
||||||
// config.baseURL = process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api'
|
// config.baseURL = process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api'
|
||||||
@@ -108,6 +118,9 @@ service.interceptors.response.use(
|
|||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
return Promise.resolve(res)
|
return Promise.resolve(res)
|
||||||
} else if (res.IsSuccess === false) {
|
} else if (res.IsSuccess === false) {
|
||||||
|
if (res.Code === -4) {
|
||||||
|
return Promise.resolve(res)
|
||||||
|
}
|
||||||
if (res.Code !== 5) {
|
if (res.Code !== 5) {
|
||||||
MessageBox.confirm(res.ErrorMessage, {
|
MessageBox.confirm(res.ErrorMessage, {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
|||||||
@@ -52,18 +52,22 @@ function getScreen() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
export async function openWindow(url, name, Skip = false) {
|
export async function openWindow(url, name, Skip = false, noreferrer = false) {
|
||||||
// 判断浏览器是否兼容
|
// 判断浏览器是否兼容
|
||||||
// 高版本的谷歌,edge不支持跨屏,需要降低浏览器版本86.0版
|
// 高版本的谷歌,edge不支持跨屏,需要降低浏览器版本86.0版
|
||||||
|
let fulls = ''
|
||||||
|
if (noreferrer) {
|
||||||
|
fulls = 'noopener,noreferrer'
|
||||||
|
}
|
||||||
if (!window.getScreens && !window.getScreenDetails) {
|
if (!window.getScreens && !window.getScreenDetails) {
|
||||||
console.log('你的浏览器版本不支持多屏展示功能!');
|
console.log('你的浏览器版本不支持多屏展示功能!');
|
||||||
return window.open(url, name);
|
return window.open(url, name, fulls);
|
||||||
}
|
}
|
||||||
let permission = await getPermission()
|
let permission = await getPermission()
|
||||||
if (!permission) {
|
if (!permission) {
|
||||||
// alert('使用多屏功能请先进行授权')
|
// alert('使用多屏功能请先进行授权')
|
||||||
if (Skip) {
|
if (Skip) {
|
||||||
return window.open(url, name);
|
return window.open(url, name, fulls);
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -72,14 +76,13 @@ export async function openWindow(url, name, Skip = false) {
|
|||||||
// 判断是否2个屏幕
|
// 判断是否2个屏幕
|
||||||
if (multiScreen.length < 2) {
|
if (multiScreen.length < 2) {
|
||||||
console.log('请接入多个显示屏!');
|
console.log('请接入多个显示屏!');
|
||||||
return window.open(url, name);
|
return window.open(url, name, fulls);
|
||||||
}
|
}
|
||||||
console.log(screen, 'screen')
|
console.log(screen, 'screen')
|
||||||
// 获取当前屏幕availLeft信息和所有信息比对,取另一个屏幕数据
|
// 获取当前屏幕availLeft信息和所有信息比对,取另一个屏幕数据
|
||||||
let currentAvailLeft = screen.availLeft ? screen.availLeft : '0'
|
let currentAvailLeft = screen.availLeft ? screen.availLeft : '0'
|
||||||
let newCurr = multiScreen.find((t) => t.availLeft != currentAvailLeft)
|
let newCurr = multiScreen.find((t) => t.availLeft != currentAvailLeft)
|
||||||
console.log(newCurr, 'newCurr')
|
console.log(newCurr, 'newCurr')
|
||||||
let fulls = ''
|
|
||||||
for (let key in newCurr) {
|
for (let key in newCurr) {
|
||||||
fulls += `${key}=${(newCurr[key] || newCurr[key] === 0) ? newCurr[key] : 0},`
|
fulls += `${key}=${(newCurr[key] || newCurr[key] === 0) ? newCurr[key] : 0},`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
|
const WHITELIST = ['/', "/curriculumVitae", 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/link_expired', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms', '/ecrfList']
|
||||||
export default WHITELIST
|
export default WHITELIST
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
<div ref="mapbox" class="map-wrapper" />
|
<div ref="mapbox" class="map-wrapper" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import 'modules/echarts/map/js/world.js'
|
import worldMap from 'echarts-map/json/world.json';
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
|
echarts.registerMap('world', worldMap);
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
area: { type: String, default: '' },
|
area: { type: String, default: '' },
|
||||||
@@ -14,7 +15,7 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
area() {
|
area() {
|
||||||
const that = this
|
const that = this
|
||||||
this.$nextTick(function() {
|
this.$nextTick(function () {
|
||||||
that.myChart.resize()
|
that.myChart.resize()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -56,7 +57,7 @@ export default {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
var convertData = function(data) {
|
var convertData = function (data) {
|
||||||
var res = []
|
var res = []
|
||||||
for (var i = 0; i < data.length; i++) {
|
for (var i = 0; i < data.length; i++) {
|
||||||
var dataItem = data[i]
|
var dataItem = data[i]
|
||||||
@@ -76,8 +77,8 @@ export default {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
var series = []
|
var series = [];
|
||||||
;[['Shanghai', BJData]].forEach(function(item, i) {
|
[['Shanghai', BJData]].forEach(function (item, i) {
|
||||||
series.push(
|
series.push(
|
||||||
{
|
{
|
||||||
type: 'lines',
|
type: 'lines',
|
||||||
@@ -125,11 +126,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
symbol: 'circle',
|
symbol: 'circle',
|
||||||
symbolSize: function(val) {
|
symbolSize: function (val) {
|
||||||
return fontSize(0.08) // 圆环大小
|
return fontSize(0.08) // 圆环大小
|
||||||
},
|
},
|
||||||
|
|
||||||
data: item[1].map(function(dataItem) {
|
data: item[1].map(function (dataItem) {
|
||||||
return {
|
return {
|
||||||
name: dataItem[0].name,
|
name: dataItem[0].name,
|
||||||
value: geoCoordMap[dataItem[0].name]
|
value: geoCoordMap[dataItem[0].name]
|
||||||
@@ -161,7 +162,7 @@ export default {
|
|||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
fontSize: fontSize(0.16),
|
fontSize: fontSize(0.16),
|
||||||
formatter: function(params) {
|
formatter: function (params) {
|
||||||
if (typeof params.value === 'undefined') {
|
if (typeof params.value === 'undefined') {
|
||||||
return ''
|
return ''
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="trials_stats" style="width:100%;height:100%;" />
|
<div ref="trials_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getTrialCountRank } from '@/api/dashboard'
|
import { getTrialCountRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 5
|
const Count = 5
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="enroll_stats" style="width:100%;height:100%;" />
|
<div ref="enroll_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getEnrollDataByQuarter } from '@/api/dashboard'
|
import { getEnrollDataByQuarter } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 6
|
const Count = 6
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="reviewers_stats" style="width:100%;height:100%;padding:5px;" />
|
<div ref="reviewers_stats" style="width:100%;height:100%;padding:5px;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReviewersByRank } from '@/api/dashboard'
|
import { getReviewersByRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="monthly_reading_stats" style="width:100%;height:100%;" />
|
<div ref="monthly_reading_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataByMonth } from '@/api/dashboard'
|
import { getReadingDataByMonth } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 6
|
const Count = 6
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="reading_rank" class="reading-rank" />
|
<div ref="reading_rank" class="reading-rank" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataRank } from '@/api/dashboard'
|
import { getReadingDataRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 5
|
const Count = 5
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div ref="reading_stats" style="width:100%;height:100%;padding-top:5px;" />
|
<div ref="reading_stats" style="width:100%;height:100%;padding-top:5px;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataByType } from '@/api/dashboard'
|
import { getReadingDataByType } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
v-for="(instance, idx) in item.instanceInfoList"
|
v-for="(instance, idx) in item.instanceInfoList"
|
||||||
:key="instance.InstanceUid"
|
:key="instance.InstanceUid"
|
||||||
class="frame_content"
|
class="frame_content"
|
||||||
|
:class="{ 'frame_content_active': activeInstanceUid === instance.InstanceUid }"
|
||||||
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
|
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
|
||||||
@click="showMultiFrames(item, index, instance)"
|
@click="showMultiFrames(item, index, instance)"
|
||||||
>
|
>
|
||||||
@@ -136,7 +137,8 @@ export default {
|
|||||||
studyTitle: '',
|
studyTitle: '',
|
||||||
seriesCount: 0,
|
seriesCount: 0,
|
||||||
seriesList: [],
|
seriesList: [],
|
||||||
currentSeriesIndex: -1
|
currentSeriesIndex: -1,
|
||||||
|
activeInstanceUid: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -231,6 +233,7 @@ export default {
|
|||||||
},
|
},
|
||||||
showMultiFrames(series, seriesIndex, instanceInfo) {
|
showMultiFrames(series, seriesIndex, instanceInfo) {
|
||||||
this.currentSeriesIndex = seriesIndex
|
this.currentSeriesIndex = seriesIndex
|
||||||
|
this.activeInstanceUid = instanceInfo.InstanceUid
|
||||||
const imageIds = []
|
const imageIds = []
|
||||||
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||||
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
||||||
@@ -252,6 +255,7 @@ export default {
|
|||||||
showSeriesImage(seriesIndex) {
|
showSeriesImage(seriesIndex) {
|
||||||
// if (seriesIndex === this.currentSeriesIndex) return;
|
// if (seriesIndex === this.currentSeriesIndex) return;
|
||||||
this.currentSeriesIndex = seriesIndex
|
this.currentSeriesIndex = seriesIndex
|
||||||
|
this.activeInstanceUid = null
|
||||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
|
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
|
||||||
},
|
},
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
@@ -429,4 +433,8 @@ export default {
|
|||||||
border-color: #213a54 !important;
|
border-color: #213a54 !important;
|
||||||
background-color: #213a54;
|
background-color: #213a54;
|
||||||
}
|
}
|
||||||
|
.frame_content_active {
|
||||||
|
border-color: #213a54 !important;
|
||||||
|
background-color: #213a54;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
<div class="frame_list">
|
<div class="frame_list">
|
||||||
<div v-for="(instance, idx) in item.instanceInfoList" :key="instance.Id"
|
<div v-for="(instance, idx) in item.instanceInfoList" :key="instance.Id"
|
||||||
class="frame_content"
|
class="frame_content"
|
||||||
|
:class="{ 'frame_content_active': activeInstanceId === instance.Id }"
|
||||||
:style="{ 'margin-bottom': idx < item.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
:style="{ 'margin-bottom': idx < item.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||||
@click="showMultiFrames(item, index, instance)">
|
@click="showMultiFrames(item, index, instance)">
|
||||||
<div>
|
<div>
|
||||||
@@ -72,17 +73,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;"
|
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;"
|
||||||
@click="popperClick(seriesList, item)" />
|
@click.stop="popperClick(seriesList, item)" />
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="item.instanceCount" style="padding: 1px;">
|
<div v-if="item.instanceCount" style="padding: 1px;">
|
||||||
{{ item.modality }}: {{ item.instanceCount }} image
|
{{ item.modality }}: {{ item.instanceCount }} image
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
|
<div v-if="!item.keySeries && item.sliceThickness" style="padding: 1px;">
|
||||||
T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
|
T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!item.keySeries && item.description"
|
<div v-if="!item.keySeries && item.description"
|
||||||
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||||
{{ item.description }}
|
{{ item.description }}
|
||||||
</div>
|
</div>
|
||||||
@@ -123,12 +124,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="viewerContent">
|
<div class="viewerContent">
|
||||||
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" />
|
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" :loading.sync="loading"
|
||||||
|
:modality="modality" :Comparison.sync="isComparison" :SeriesList="seriesList"
|
||||||
|
:currentSeriesIndex="currentSeriesIndex" @loadStudy="loadStudy" />
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="viewerRightSidePanel">
|
<!-- <div class="viewerRightSidePanel">
|
||||||
<dicom-tools />
|
<dicom-tools />
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -178,7 +180,7 @@ export default {
|
|||||||
description: '',
|
description: '',
|
||||||
seriesCount: 0,
|
seriesCount: 0,
|
||||||
seriesList: [],
|
seriesList: [],
|
||||||
currentSeriesIndex: -1,
|
currentSeriesIndex: 0,
|
||||||
arr: [],
|
arr: [],
|
||||||
activeName: 'first',
|
activeName: 'first',
|
||||||
tpList: [],
|
tpList: [],
|
||||||
@@ -202,7 +204,9 @@ export default {
|
|||||||
isFromCRCUpload: false,
|
isFromCRCUpload: false,
|
||||||
isReading: null,
|
isReading: null,
|
||||||
activeSeriesId: null,
|
activeSeriesId: null,
|
||||||
isPacs: false
|
isPacs: false,
|
||||||
|
isComparison: false,
|
||||||
|
activeInstanceId: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
@@ -250,6 +254,11 @@ export default {
|
|||||||
})
|
})
|
||||||
workSpeedclose(true)
|
workSpeedclose(true)
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
currentSeriesIndex() {
|
||||||
|
console.log(this.currentSeriesIndex, 'currentSeriesIndex')
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async updateImageResizePath(data) {
|
async updateImageResizePath(data) {
|
||||||
try {
|
try {
|
||||||
@@ -307,7 +316,7 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async loadStudy() {
|
async loadStudy(seriesId = null) {
|
||||||
let params = {}
|
let params = {}
|
||||||
if (this.isPacs) {
|
if (this.isPacs) {
|
||||||
params.IsPacs = true
|
params.IsPacs = true
|
||||||
@@ -327,7 +336,7 @@ export default {
|
|||||||
isReading = `?IsPacs=true`
|
isReading = `?IsPacs=true`
|
||||||
}
|
}
|
||||||
const url = `/series/list/${this.studyId}${isReading}`
|
const url = `/series/list/${this.studyId}${isReading}`
|
||||||
this.getSeriesList(url)
|
this.getSeriesList(url, seriesId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadPatientStudy() {
|
async loadPatientStudy() {
|
||||||
@@ -350,13 +359,14 @@ export default {
|
|||||||
i.ImageId = imageId
|
i.ImageId = imageId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId ? this.$router.currentRoute.query.subjectVisitId : item.SubjectVisitId
|
||||||
var studyId = this.$router.currentRoute.query.studyId
|
var studyId = this.$router.currentRoute.query.studyId
|
||||||
var trialId = this.$router.currentRoute.query.trialId
|
var trialId = this.$router.currentRoute.query.trialId
|
||||||
seriesList.push({
|
seriesList.push({
|
||||||
trialId,
|
trialId,
|
||||||
subjectVisitId,
|
subjectVisitId,
|
||||||
studyId,
|
studyId,
|
||||||
|
subjectId: item.SubjectId,
|
||||||
imageIds: imageIds,
|
imageIds: imageIds,
|
||||||
instanceInfoList: item.InstanceInfoList,
|
instanceInfoList: item.InstanceInfoList,
|
||||||
seriesId: item.Id,
|
seriesId: item.Id,
|
||||||
@@ -392,7 +402,7 @@ export default {
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getSeriesList(url) {
|
async getSeriesList(url, seriesId = null) {
|
||||||
try {
|
try {
|
||||||
const data = await getSeriesList(url)
|
const data = await getSeriesList(url)
|
||||||
if (data.IsSuccess) {
|
if (data.IsSuccess) {
|
||||||
@@ -412,12 +422,13 @@ export default {
|
|||||||
i.ImageId = imageId
|
i.ImageId = imageId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId ? this.$router.currentRoute.query.subjectVisitId : item.SubjectVisitId
|
||||||
var studyId = this.$router.currentRoute.query.studyId
|
var studyId = this.$router.currentRoute.query.studyId
|
||||||
var trialId = this.$router.currentRoute.query.trialId
|
var trialId = this.$router.currentRoute.query.trialId
|
||||||
seriesList.push({
|
seriesList.push({
|
||||||
trialId,
|
trialId,
|
||||||
subjectVisitId,
|
subjectVisitId,
|
||||||
|
subjectId: item.SubjectId,
|
||||||
studyId,
|
studyId,
|
||||||
imageIds: imageIds,
|
imageIds: imageIds,
|
||||||
instanceInfoList: item.InstanceInfoList,
|
instanceInfoList: item.InstanceInfoList,
|
||||||
@@ -431,12 +442,12 @@ export default {
|
|||||||
isDeleted: item.IsDeleted,
|
isDeleted: item.IsDeleted,
|
||||||
previewImageUrl: item.ImageResizePath ? this.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`,
|
previewImageUrl: item.ImageResizePath ? this.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`,
|
||||||
instanceCount: item.InstanceCount,
|
instanceCount: item.InstanceCount,
|
||||||
prefetchInstanceCount: 0,
|
prefetchInstanceCount: seriesId ? item.InstanceInfoList.length * 100 : 0,
|
||||||
hasLabel: item.HasLabel,
|
hasLabel: item.HasLabel,
|
||||||
keySeries: item.KeySeries,
|
keySeries: item.KeySeries,
|
||||||
tpCode: this.tpCode,
|
tpCode: this.tpCode,
|
||||||
loadStatus: false,
|
loadStatus: false,
|
||||||
imageloadedArr: [],
|
imageloadedArr: seriesId ? imageIds : [],
|
||||||
isExistMutiFrames: item.IsExistMutiFrames,
|
isExistMutiFrames: item.IsExistMutiFrames,
|
||||||
isShowPopper: false,
|
isShowPopper: false,
|
||||||
subjectCode: item.SubjectCode,
|
subjectCode: item.SubjectCode,
|
||||||
@@ -446,8 +457,14 @@ export default {
|
|||||||
this.seriesList = seriesList
|
this.seriesList = seriesList
|
||||||
if (this.seriesList.length > 0) {
|
if (this.seriesList.length > 0) {
|
||||||
this.loadAllImages()
|
this.loadAllImages()
|
||||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[0], this.labels[this.tpCode])
|
let index = 0;
|
||||||
this.firstInstanceId = this.seriesList[0].imageIds[0]
|
if (seriesId) {
|
||||||
|
index = this.seriesList.findIndex(item => item.seriesId === seriesId)
|
||||||
|
this.refreshImage(this.seriesList[index])
|
||||||
|
}
|
||||||
|
this.$refs.dicomViewer.loadImageStack(this.seriesList[index], this.labels[this.tpCode])
|
||||||
|
this.firstInstanceId = this.seriesList[index].imageIds[0]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -527,7 +544,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
showSeriesImage(e, seriesIndex, series) {
|
showSeriesImage(e, seriesIndex, series) {
|
||||||
|
if (this.isComparison) return false
|
||||||
this.activeSeriesId = series.seriesId
|
this.activeSeriesId = series.seriesId
|
||||||
|
this.activeInstanceId = null
|
||||||
workSpeedclose(true)
|
workSpeedclose(true)
|
||||||
// if (seriesIndex === this.currentSeriesIndex) return
|
// if (seriesIndex === this.currentSeriesIndex) return
|
||||||
const element = e.currentTarget
|
const element = e.currentTarget
|
||||||
@@ -576,6 +595,7 @@ export default {
|
|||||||
},
|
},
|
||||||
showMultiFrames(series, seriesIndex, instanceInfo) {
|
showMultiFrames(series, seriesIndex, instanceInfo) {
|
||||||
this.currentSeriesIndex = seriesIndex
|
this.currentSeriesIndex = seriesIndex
|
||||||
|
this.activeInstanceId = instanceInfo.Id
|
||||||
const imageIds = []
|
const imageIds = []
|
||||||
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||||
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
||||||
@@ -587,6 +607,7 @@ export default {
|
|||||||
const seriesInfo = {
|
const seriesInfo = {
|
||||||
trialId: series.trialId,
|
trialId: series.trialId,
|
||||||
subjectVisitId: series.subjectVisitId,
|
subjectVisitId: series.subjectVisitId,
|
||||||
|
instanceInfoList: series.instanceInfoList,
|
||||||
studyId: series.studyId,
|
studyId: series.studyId,
|
||||||
imageIds: imageIds,
|
imageIds: imageIds,
|
||||||
seriesId: series.seriesId,
|
seriesId: series.seriesId,
|
||||||
@@ -920,6 +941,7 @@ export default {
|
|||||||
}
|
}
|
||||||
if (this.visitTaskId === params.visitTaskId) {
|
if (this.visitTaskId === params.visitTaskId) {
|
||||||
const seriesIndex = params.seriesIndex
|
const seriesIndex = params.seriesIndex
|
||||||
|
if (!this.seriesList[seriesIndex]) return false
|
||||||
var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
|
var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
|
||||||
var instanceCount = this.seriesList[seriesIndex].instanceCount
|
var instanceCount = this.seriesList[seriesIndex].instanceCount
|
||||||
if (!this.activeSeriesId) {
|
if (!this.activeSeriesId) {
|
||||||
@@ -965,8 +987,8 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
.imageBox {
|
.viewerContainer .imageBox {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@@ -1184,6 +1206,11 @@ export default {
|
|||||||
background-color: #213a54;
|
background-color: #213a54;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.frame_content_active {
|
||||||
|
border-color: #213a54 !important;
|
||||||
|
background-color: #213a54;
|
||||||
|
}
|
||||||
|
|
||||||
/* .viewerRightSidePanel {
|
/* .viewerRightSidePanel {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -19,25 +19,26 @@
|
|||||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`"
|
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`"
|
||||||
:name="`${study.StudyId}`">
|
:name="`${study.StudyId}`">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
|
<div class="collapse-title-wrapper">
|
||||||
<div class="text-desc">
|
<div class="text-desc" v-if="IsReadingTaskViewInOrder !== 0">
|
||||||
{{ study.StudyCode }}
|
{{ study.StudyCode }}
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-show="study.Description" class="text-desc">
|
<!-- <div v-show="study.Description" class="text-desc">
|
||||||
{{ study.Description }}
|
{{ study.Description }}
|
||||||
</div> -->
|
</div> -->
|
||||||
<el-tooltip v-show="study.Description" class="item" effect="dark" :content="study.Description"
|
<!-- <el-tooltip v-show="study.Description" class="item" effect="dark" :content="study.Description"
|
||||||
placement="bottom">
|
placement="bottom">
|
||||||
<div v-show="study.Description"
|
<div v-if="study.Description"
|
||||||
style="width: 50px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
style="width: 50px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||||
{{ study.Description }}
|
{{ study.Description }}
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip> -->
|
||||||
<div v-show="study.SeriesCount" class="text-desc">
|
<div v-if="study.SeriesCount" class="text-desc collapse-title-extra">
|
||||||
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
<div v-if="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
||||||
{{ study.Description }}
|
{{ study.Description }}
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(series, i) in study.SeriesList" :key="i"
|
<div v-for="(series, i) in study.SeriesList" :key="i"
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
<div class="frame_list">
|
<div class="frame_list">
|
||||||
<div v-for="(instance, idx) in series.instanceInfoList" :key="instance.Id"
|
<div v-for="(instance, idx) in series.instanceInfoList" :key="instance.Id"
|
||||||
class="frame_content"
|
class="frame_content"
|
||||||
|
:class="{ 'frame_content_active': activeInstanceId === instance.Id }"
|
||||||
:style="{ 'margin-bottom': idx < series.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
:style="{ 'margin-bottom': idx < series.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||||
@click="showMultiFrames(index, series, i, instance)">
|
@click="showMultiFrames(index, series, i, instance)">
|
||||||
<!-- <div>
|
<!-- <div>
|
||||||
@@ -97,12 +99,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<i slot="reference" class="el-icon-connection"
|
<i slot="reference" class="el-icon-connection"
|
||||||
style="font-size: 15px;cursor: pointer;"
|
style="font-size: 15px;cursor: pointer;"
|
||||||
@click="popperClick(studyList, series)" />
|
@click.stop="popperClick(studyList, series)" />
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div v-show="series.InstanceCount" style="padding: 1px;">
|
<div v-show="series.instanceCount" style="padding: 1px;">
|
||||||
{{ series.modality }}: {{ series.instanceCount }} image
|
{{ series.modality }}: {{ series.instanceCount }} image
|
||||||
</div>
|
</div>
|
||||||
<div v-show="series.sliceThickness" style="padding: 1px;">
|
<div v-show="series.sliceThickness" style="padding: 1px;">
|
||||||
@@ -153,113 +155,111 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane v-show="!visitTaskId" :label="$t('trials:dicom-show:relatedVisit')" name="relation-study"
|
<el-tab-pane v-show="!visitTaskId" v-if="IsReadingTaskViewInOrder >= 2"
|
||||||
class="pane-relation-wrapper">
|
:label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper">
|
||||||
<div class="viewerSidethumbinner">
|
<div class="viewerSidethumbinner">
|
||||||
|
|
||||||
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
|
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
|
||||||
<template v-for="item in relationStudyListByVisitName">
|
<div v-for="item in relationStudyListByVisitName" :key="`${item.VisitName}`">
|
||||||
<div :key="`${item.VisitName}`">
|
<div v-show="item.VisitName" class="text-desc" style="background-color: #1f1f1f;">
|
||||||
<div v-show="item.VisitName" class="text-desc" style="background-color: #1f1f1f;">
|
{{ item.VisitName }}
|
||||||
{{ item.VisitName }}
|
</div>
|
||||||
</div>
|
<template v-for="(study, studyIndex) in relationStudyList">
|
||||||
<template v-for="(study, studyIndex) in relationStudyList">
|
<el-collapse-item :key="`${study.StudyId}`" :name="`${study.StudyId}`"
|
||||||
<el-collapse-item :key="`${study.StudyId}`" :name="`${study.StudyId}`"
|
v-if="study.VisitName === item.VisitName">
|
||||||
v-if="study.VisitName === item.VisitName">
|
<template slot="title">
|
||||||
<template slot="title">
|
<div class="collapse-title-wrapper">
|
||||||
|
<div class="text-desc" v-if="IsReadingTaskViewInOrder !== 0">
|
||||||
<div class="text-desc">
|
|
||||||
{{ study.StudyCode }}
|
{{ study.StudyCode }}
|
||||||
</div>
|
</div>
|
||||||
<!-- <div v-show="study.Description" class="text-desc">
|
<!-- <div v-show="study.Description" class="text-desc">
|
||||||
{{ study.Description }}
|
{{ study.Description }}
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<div v-show="study.SeriesCount" class="text-desc">
|
<div v-show="study.SeriesCount" class="text-desc collapse-title-extra">
|
||||||
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
|
||||||
{{ study.Description }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
</template>
|
||||||
<div class="viewerSidethumbinner">
|
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
||||||
<div v-for="(seriesItem, index) in study.seriesList" :key="seriesItem.seriesId">
|
{{ study.Description }}
|
||||||
<div class="viewernavigatorwrapper"
|
</div>
|
||||||
style="position: relative;border:1px solid #434343;" series-type="relation"
|
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||||
@click="showRelationSeriesImage($event, seriesItem, studyIndex, index)">
|
<div class="viewerSidethumbinner">
|
||||||
<div class="imageBox" style="width: 72px;height:72px;">
|
<div v-for="(seriesItem, index) in study.seriesList" :key="seriesItem.seriesId">
|
||||||
<img class="image-preview" :src="seriesItem.previewImageUrl"
|
<div class="viewernavigatorwrapper" style="position: relative;border:1px solid #434343;"
|
||||||
crossorigin="anonymous" alt="" style="width: 72px;height:72px;" fit="fill" />
|
series-type="relation"
|
||||||
<i class="el-icon-refresh" :title="$t('tip:refreshImage')"
|
@click="showRelationSeriesImage($event, seriesItem, studyIndex, index)">
|
||||||
@click.stop="refreshImage(item)"></i>
|
<div class="imageBox" style="width: 72px;height:72px;">
|
||||||
</div>
|
<img class="image-preview" :src="seriesItem.previewImageUrl" crossorigin="anonymous"
|
||||||
|
alt="" style="width: 72px;height:72px;" fit="fill" />
|
||||||
<div class="viewernavitextwrapper">
|
<i class="el-icon-refresh" :title="$t('tip:refreshImage')"
|
||||||
<div
|
@click.stop="refreshImage(item)"></i>
|
||||||
style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
</div>
|
||||||
<div v-if="seriesItem.keySeries" style="color:red">
|
|
||||||
Key Images
|
|
||||||
</div>
|
|
||||||
<div v-else>#{{ seriesItem.seriesNumber }}</div>
|
|
||||||
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
|
|
||||||
<el-popover placement="right-start" trigger="click"
|
|
||||||
popper-class="instance_frame_wrapper">
|
|
||||||
<div class="frame_list">
|
|
||||||
<div v-for="(instance, idx) in seriesItem.instanceInfoList"
|
|
||||||
:key="instance.Id" class="frame_content"
|
|
||||||
:style="{ 'margin-bottom': idx < seriesItem.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
|
||||||
@click="showMultiFrames(studyIndex, seriesItem, index, instance)">
|
|
||||||
<div>
|
|
||||||
<div>{{ instance.InstanceNumber }}</div>
|
|
||||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1}
|
|
||||||
frame`
|
|
||||||
}}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="viewernavitextwrapper">
|
||||||
|
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
||||||
|
<div v-if="seriesItem.keySeries" style="color:red">
|
||||||
|
Key Images
|
||||||
|
</div>
|
||||||
|
<div v-else>#{{ seriesItem.seriesNumber }}</div>
|
||||||
|
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
|
||||||
|
<el-popover placement="right-start" trigger="click"
|
||||||
|
popper-class="instance_frame_wrapper">
|
||||||
|
<div class="frame_list">
|
||||||
|
<div v-for="(instance, idx) in seriesItem.instanceInfoList"
|
||||||
|
:key="instance.Id" class="frame_content"
|
||||||
|
:class="{ 'frame_content_active': activeInstanceId === instance.Id }"
|
||||||
|
:style="{ 'margin-bottom': idx < seriesItem.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||||
|
@click="showMultiFrames(studyIndex, seriesItem, index, instance)">
|
||||||
|
<div>
|
||||||
|
<div>{{ instance.InstanceNumber }}</div>
|
||||||
|
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1}
|
||||||
|
frame`
|
||||||
|
}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<i slot="reference" class="el-icon-connection"
|
|
||||||
style="font-size: 15px;cursor: pointer;" />
|
|
||||||
</el-popover>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i slot="reference" class="el-icon-connection"
|
||||||
|
style="font-size: 15px;cursor: pointer;" />
|
||||||
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="seriesItem.instanceCount" style="padding: 1px;">
|
|
||||||
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
|
|
||||||
</div>
|
|
||||||
<div v-show="seriesItem.sliceThickness" style="padding: 1px;">
|
|
||||||
T: {{ seriesItem.sliceThickness }}
|
|
||||||
</div>
|
|
||||||
<el-tooltip v-show="seriesItem.description" class="item" effect="dark"
|
|
||||||
:content="seriesItem.description" placement="bottom">
|
|
||||||
<div v-show="seriesItem.description"
|
|
||||||
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
|
||||||
{{ seriesItem.description }}
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div v-show="seriesItem.instanceCount" style="padding: 1px;">
|
||||||
|
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
|
||||||
|
</div>
|
||||||
|
<div v-show="seriesItem.sliceThickness" style="padding: 1px;">
|
||||||
|
T: {{ seriesItem.sliceThickness }}
|
||||||
|
</div>
|
||||||
|
<el-tooltip v-show="seriesItem.description" class="item" effect="dark"
|
||||||
|
:content="seriesItem.description" placement="bottom">
|
||||||
|
<div v-show="seriesItem.description"
|
||||||
|
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||||
|
{{ seriesItem.description }}
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<!-- <el-image
|
</div>
|
||||||
class="image-preview"
|
<!-- <el-image
|
||||||
style="height:72px;width:72px;"
|
class="image-preview"
|
||||||
:src="seriesItem.previewImageUrl"
|
style="height:72px;width:72px;"
|
||||||
fit="fill"
|
:src="seriesItem.previewImageUrl"
|
||||||
/> -->
|
fit="fill"
|
||||||
<div
|
/> -->
|
||||||
v-if="seriesItem.prefetchInstanceCount > 0 && seriesItem.prefetchInstanceCount < seriesItem.instanceCount * 100">
|
<div
|
||||||
<el-progress
|
v-if="seriesItem.prefetchInstanceCount > 0 && seriesItem.prefetchInstanceCount < seriesItem.instanceCount * 100">
|
||||||
:percentage="parseInt((seriesItem.prefetchInstanceCount / seriesItem.instanceCount).toFixed(2))" />
|
<el-progress
|
||||||
</div>
|
:percentage="parseInt((seriesItem.prefetchInstanceCount / seriesItem.instanceCount).toFixed(2))" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</div>
|
||||||
</template>
|
</el-collapse-item>
|
||||||
|
</template>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -330,7 +330,9 @@ export default {
|
|||||||
isFromCRCUpload: false,
|
isFromCRCUpload: false,
|
||||||
visitTaskId: null,
|
visitTaskId: null,
|
||||||
page: '',
|
page: '',
|
||||||
activeSeriesId: null
|
activeSeriesId: null,
|
||||||
|
activeInstanceId: null,
|
||||||
|
IsReadingTaskViewInOrder: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -349,20 +351,22 @@ export default {
|
|||||||
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
|
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
|
||||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||||
this.page = this.$route.query.page
|
this.page = this.$route.query.page
|
||||||
|
if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
|
||||||
|
this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
|
||||||
|
}
|
||||||
|
console.log(this.IsReadingTaskViewInOrder)
|
||||||
|
this.beforeUnloadHandler = () => {
|
||||||
|
cornerstone.imageCache.purgeCache()
|
||||||
|
requestPoolManager.resetRequestPool()
|
||||||
|
}
|
||||||
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
||||||
this.getStudiesInfo()
|
this.getStudiesInfo()
|
||||||
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
|
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
|
||||||
window.addEventListener('beforeunload', e => {
|
window.addEventListener('beforeunload', this.beforeUnloadHandler)
|
||||||
cornerstone.imageCache.purgeCache()
|
|
||||||
requestPoolManager.resetRequestPool()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
requestPoolManager.stopTaskTimer()
|
requestPoolManager.stopTaskTimer()
|
||||||
window.removeEventListener('beforeunload', e => {
|
window.removeEventListener('beforeunload', this.beforeUnloadHandler)
|
||||||
cornerstone.imageCache.purgeCache()
|
|
||||||
requestPoolManager.resetRequestPool()
|
|
||||||
})
|
|
||||||
workSpeedclose(true)
|
workSpeedclose(true)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -492,14 +496,17 @@ export default {
|
|||||||
data.SeriesList = seriesList
|
data.SeriesList = seriesList
|
||||||
this.studyList.push(data)
|
this.studyList.push(data)
|
||||||
})
|
})
|
||||||
if (this.studyList.length > 0) {
|
const firstStudy = this.studyList.find(study => Array.isArray(study.SeriesList) && study.SeriesList.length > 0)
|
||||||
this.$refs.dicomViewer.loadImageStack(this.studyList[0].SeriesList[0])
|
if (firstStudy) {
|
||||||
const imageId = this.studyList[0].SeriesList[0].imageIds[0]
|
const firstSeries = firstStudy.SeriesList[0]
|
||||||
|
if (!Array.isArray(firstSeries.imageIds) || firstSeries.imageIds.length === 0) return
|
||||||
|
this.$refs.dicomViewer.loadImageStack(firstSeries)
|
||||||
|
const imageId = firstSeries.imageIds[0]
|
||||||
let instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
let instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||||
instanceId = instanceId.split('.')[0]
|
instanceId = instanceId.split('.')[0]
|
||||||
this.firstInstanceId = instanceId
|
this.firstInstanceId = instanceId
|
||||||
this.activeNames = [this.studyList[0].StudyId]
|
this.activeNames = [firstStudy.StudyId]
|
||||||
this.loadImages(this.studyList[0].SeriesList[0], 0)
|
this.loadImages(firstSeries, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -524,6 +531,7 @@ export default {
|
|||||||
},
|
},
|
||||||
showSeriesImage(e, studyIndex, seriesIndex, series) {
|
showSeriesImage(e, studyIndex, seriesIndex, series) {
|
||||||
this.activeSeriesId = series.seriesId
|
this.activeSeriesId = series.seriesId
|
||||||
|
this.activeInstanceId = null
|
||||||
workSpeedclose(true)
|
workSpeedclose(true)
|
||||||
const element = e.currentTarget
|
const element = e.currentTarget
|
||||||
const elements = document.querySelectorAll('[series-type]')
|
const elements = document.querySelectorAll('[series-type]')
|
||||||
@@ -565,6 +573,7 @@ export default {
|
|||||||
},
|
},
|
||||||
showMultiFrames(studyIndex, series, seriesIndex, instanceInfo) {
|
showMultiFrames(studyIndex, series, seriesIndex, instanceInfo) {
|
||||||
this.currentSeriesIndex = seriesIndex
|
this.currentSeriesIndex = seriesIndex
|
||||||
|
this.activeInstanceId = instanceInfo.Id
|
||||||
const imageIds = []
|
const imageIds = []
|
||||||
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||||
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
||||||
@@ -576,6 +585,7 @@ export default {
|
|||||||
const seriesInfo = {
|
const seriesInfo = {
|
||||||
trialId: series.trialId,
|
trialId: series.trialId,
|
||||||
subjectVisitId: series.subjectVisitId,
|
subjectVisitId: series.subjectVisitId,
|
||||||
|
instanceInfoList: series.instanceInfoList,
|
||||||
studyId: series.studyId,
|
studyId: series.studyId,
|
||||||
imageIds: imageIds,
|
imageIds: imageIds,
|
||||||
seriesId: series.seriesId,
|
seriesId: series.seriesId,
|
||||||
@@ -601,7 +611,11 @@ export default {
|
|||||||
}
|
}
|
||||||
if (!isAddToTakPool) {
|
if (!isAddToTakPool) {
|
||||||
var priority = parseInt(new Date().getTime())
|
var priority = parseInt(new Date().getTime())
|
||||||
if (series.isExistMutiFrames) {
|
if (series.isExistMutiFrames && imageIds.length > 1) {
|
||||||
|
imageIds.map(imageId => {
|
||||||
|
this.imageList.push({ imageId, seriesId: series.seriesId, priority })
|
||||||
|
})
|
||||||
|
} else if (series.isExistMutiFrames) {
|
||||||
series.instanceInfoList.map(image => {
|
series.instanceInfoList.map(image => {
|
||||||
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, priority })
|
this.imageList.push({ imageId: image.ImageId, seriesId: series.seriesId, priority })
|
||||||
})
|
})
|
||||||
@@ -883,6 +897,7 @@ export default {
|
|||||||
},
|
},
|
||||||
showRelationSeriesImage(e, series, studyIndex, index) {
|
showRelationSeriesImage(e, series, studyIndex, index) {
|
||||||
this.activeSeriesId = series.seriesId
|
this.activeSeriesId = series.seriesId
|
||||||
|
this.activeInstanceId = null
|
||||||
workSpeedclose(true)
|
workSpeedclose(true)
|
||||||
this.currentRelationIndex = index
|
this.currentRelationIndex = index
|
||||||
const element = e.currentTarget
|
const element = e.currentTarget
|
||||||
@@ -940,7 +955,7 @@ export default {
|
|||||||
if (this.imageList.length > 0) {
|
if (this.imageList.length > 0) {
|
||||||
requestPoolManager.startTaskTimer()
|
requestPoolManager.startTaskTimer()
|
||||||
this.imageList.map(image => {
|
this.imageList.map(image => {
|
||||||
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
|
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).catch(() => { })
|
||||||
})
|
})
|
||||||
requestPoolManager.sortTaskPool()
|
requestPoolManager.sortTaskPool()
|
||||||
this.imageList = []
|
this.imageList = []
|
||||||
@@ -1012,7 +1027,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.imageBox {
|
.viewerContainer .imageBox {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@@ -1102,6 +1117,7 @@ export default {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
color: #D0D0D0;
|
color: #D0D0D0;
|
||||||
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1110,6 +1126,8 @@ export default {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-x: hidden;
|
||||||
border: 1px solid #3e3f3a;
|
border: 1px solid #3e3f3a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,14 +1156,20 @@ export default {
|
|||||||
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
|
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 220px;
|
width: 220px;
|
||||||
/* height: 84px; */
|
min-height: 85px;
|
||||||
padding: 1px 2px 1px 2px;
|
padding: 1px 2px 1px 2px;
|
||||||
margin: 2px 0 1px 1px;
|
margin: 2px 0 1px 1px;
|
||||||
|
align-items: flex-start;
|
||||||
/* border-radius: 2px;
|
/* border-radius: 2px;
|
||||||
border: 1px solid #404040; */
|
border: 1px solid #404040; */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper .imageBox {
|
||||||
|
align-self: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.viewerContainer .viewernavigatorwrapper .el-progress__text {
|
.viewerContainer .viewernavigatorwrapper .el-progress__text {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -1168,9 +1192,19 @@ export default {
|
|||||||
/* width: 120px;
|
/* width: 120px;
|
||||||
height: 80px; */
|
height: 80px; */
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
padding: 3px 1px 3px 4px;
|
padding: 3px 1px 3px 4px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper>div {
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||||
@@ -1200,12 +1234,24 @@ export default {
|
|||||||
|
|
||||||
.viewerContainer .el-collapse {
|
.viewerContainer .el-collapse {
|
||||||
border: none;
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewerContainer .el-collapse-item {
|
.viewerContainer .el-collapse-item {
|
||||||
background-color: #585453 !important;
|
background-color: #585453 !important;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewerContainer .el-collapse-item__wrap {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewerContainer .el-collapse-item__content {
|
.viewerContainer .el-collapse-item__content {
|
||||||
@@ -1218,9 +1264,42 @@ export default {
|
|||||||
background-color: #585453 !important;
|
background-color: #585453 !important;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
border-bottom-color: #5a5a5a;
|
border-bottom-color: #5a5a5a;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
height: 40px;
|
height: auto;
|
||||||
|
min-height: 30px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewerContainer .collapse-title-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 6px;
|
||||||
|
row-gap: 2px;
|
||||||
|
line-height: 16px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewerContainer .collapse-title-wrapper .text-desc {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewerContainer .collapse-title-wrapper .collapse-title-extra {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instance_frame_wrapper {
|
.instance_frame_wrapper {
|
||||||
@@ -1264,6 +1343,11 @@ export default {
|
|||||||
background-color: #213a54;
|
background-color: #213a54;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.frame_content_active {
|
||||||
|
border-color: #213a54 !important;
|
||||||
|
background-color: #213a54;
|
||||||
|
}
|
||||||
|
|
||||||
/* .viewerRightSidePanel {
|
/* .viewerRightSidePanel {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('dictionary:signature:form:DocLanguageType')" prop="DocLanguageType">
|
||||||
|
<el-select v-model="form.DocLanguageType" style="width: 100%">
|
||||||
|
<el-option v-for="item of $d.DocLanguageType" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
|
<el-form-item :label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
|
||||||
prop="NeedConfirmedUserTypeIdList">
|
prop="NeedConfirmedUserTypeIdList">
|
||||||
<el-select v-model="form.NeedConfirmedUserTypeIdList" style="width: 100%" multiple>
|
<el-select v-model="form.NeedConfirmedUserTypeIdList" style="width: 100%" multiple>
|
||||||
@@ -83,6 +88,7 @@ export default {
|
|||||||
DocUserSignType: 0,
|
DocUserSignType: 0,
|
||||||
CurrentStaffTrainDays: 1,
|
CurrentStaffTrainDays: 1,
|
||||||
NewStaffTrainDays: 14,
|
NewStaffTrainDays: 14,
|
||||||
|
DocLanguageType: null
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
FileTypeId: [
|
FileTypeId: [
|
||||||
@@ -92,6 +98,13 @@ export default {
|
|||||||
trigger: ['blur'],
|
trigger: ['blur'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
DocLanguageType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: this.$t('common:ruleMessage:select'),
|
||||||
|
trigger: ['blur'],
|
||||||
|
},
|
||||||
|
],
|
||||||
SignViewMinimumMinutes: [
|
SignViewMinimumMinutes: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -143,6 +156,9 @@ export default {
|
|||||||
this.form.DocUserSignType = this.data.DocUserSignType
|
this.form.DocUserSignType = this.data.DocUserSignType
|
||||||
this.form.CurrentStaffTrainDays = this.data.CurrentStaffTrainDays
|
this.form.CurrentStaffTrainDays = this.data.CurrentStaffTrainDays
|
||||||
this.form.NewStaffTrainDays = this.data.NewStaffTrainDays
|
this.form.NewStaffTrainDays = this.data.NewStaffTrainDays
|
||||||
|
this.form.DocLanguageType = this.data.DocLanguageType
|
||||||
|
} else {
|
||||||
|
this.form.DocLanguageType = this.$i18n.locale !== 'zh' ? 1 : 0
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
<el-form-item :label="$t('dictionary:signature:search:Name')">
|
<el-form-item :label="$t('dictionary:signature:search:Name')">
|
||||||
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('dictionary:signature:search:DocLanguageType')">
|
||||||
|
<el-select v-model="searchData.DocLanguageType" style="width: 150px" clearable>
|
||||||
|
<el-option v-for="item of $d.DocLanguageType" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:table:NeedConfirmedUserTypes')">
|
<el-form-item :label="$t('dictionary:signature:table:NeedConfirmedUserTypes')">
|
||||||
<el-select v-model="searchData.UserTypeId" style="width: 150px" clearable>
|
<el-select v-model="searchData.UserTypeId" style="width: 150px" clearable>
|
||||||
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName"
|
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName"
|
||||||
@@ -90,6 +95,12 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="DocLanguageType" :label="$t('dictionary:signature:table:DocLanguageType')"
|
||||||
|
show-overflow-tooltip sortable="custom" min-width="120px">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ $fd('DocLanguageType', scope.row.DocLanguageType) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="SignViewMinimumMinutes" :label="$t('dictionary:signature:table:SignViewMinimumMinutes')"
|
<el-table-column prop="SignViewMinimumMinutes" :label="$t('dictionary:signature:table:SignViewMinimumMinutes')"
|
||||||
show-overflow-tooltip sortable="custom" min-width="200px" />
|
show-overflow-tooltip sortable="custom" min-width="200px" />
|
||||||
<el-table-column prop="CurrentStaffTrainDays" :label="$t('dictionary:signature:table:CurrentStaffTrainDays')"
|
<el-table-column prop="CurrentStaffTrainDays" :label="$t('dictionary:signature:table:CurrentStaffTrainDays')"
|
||||||
@@ -161,7 +172,7 @@
|
|||||||
<!-- 新增/编辑 -->
|
<!-- 新增/编辑 -->
|
||||||
<el-dialog v-if="editVisible" :visible.sync="editVisible" :close-on-click-modal="false" :title="title"
|
<el-dialog v-if="editVisible" :visible.sync="editVisible" :close-on-click-modal="false" :title="title"
|
||||||
width="600px" custom-class="base-dialog-wrapper">
|
width="600px" custom-class="base-dialog-wrapper">
|
||||||
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
<TemplateForm :data="currentRow" @closeDialog="closeDialog" v-if="editVisible" @getList="getList" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!--附件列表-->
|
<!--附件列表-->
|
||||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||||
@@ -200,6 +211,7 @@ const searchDataDefault = () => {
|
|||||||
IsDeleted: null,
|
IsDeleted: null,
|
||||||
DocUserSignType: null,
|
DocUserSignType: null,
|
||||||
UserTypeId: null,
|
UserTypeId: null,
|
||||||
|
DocLanguageType: null,
|
||||||
Name: '',
|
Name: '',
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
PageSize: 20,
|
PageSize: 20,
|
||||||
|
|||||||
@@ -26,11 +26,19 @@
|
|||||||
<el-table v-if="refreshTable" v-adaptive="{ bottomOffset: 45 }" v-loading="loading" height="100" :data="menuList"
|
<el-table v-if="refreshTable" v-adaptive="{ bottomOffset: 45 }" v-loading="loading" height="100" :data="menuList"
|
||||||
:default-expand-all="isExpandAll" row-key="Id" :tree-props="{ children: 'Children', hasChildren: 'hasChildren' }">
|
:default-expand-all="isExpandAll" row-key="Id" :tree-props="{ children: 'Children', hasChildren: 'hasChildren' }">
|
||||||
<!-- 模块 -->
|
<!-- 模块 -->
|
||||||
<el-table-column prop="ModuleTypeValueCN" :label="$t('audit:label:moduleType')" show-overflow-tooltip align="left" min-width="230px" />
|
<el-table-column v-if="language === 'en'" prop="ModuleTypeValue" :label="$t('audit:label:moduleType')" show-overflow-tooltip align="left" min-width="230px">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-else prop="ModuleTypeValueCN" :label="$t('audit:label:moduleType')" show-overflow-tooltip align="left" min-width="230px">
|
||||||
|
</el-table-column>
|
||||||
<!-- 操作名称 -->
|
<!-- 操作名称 -->
|
||||||
<el-table-column prop="Description" :label="$t('audit:label:desc')" :show-overflow-tooltip="true" min-width="200px">
|
<el-table-column v-if="language === 'en'" prop="Description" :label="$t('audit:label:desc')" :show-overflow-tooltip="true" min-width="200px">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.DescriptionCN }}({{ scope.row.Description }})</span>
|
<span>{{ scope.row.Description }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-else prop="DescriptionCN" :label="$t('audit:label:desc')" :show-overflow-tooltip="true" min-width="200px">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.DescriptionCN }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 其他 -->
|
<!-- 其他 -->
|
||||||
@@ -61,17 +69,20 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 标识 -->
|
<!-- 标识 -->
|
||||||
<el-table-column prop="Identification" :label="$t('audit:label:identification')" :show-overflow-tooltip="true" min-width="200px" />
|
<el-table-column prop="Identification" :label="$t('audit:label:identification')" :show-overflow-tooltip="true" min-width="120px" />
|
||||||
<!-- 操作类型 -->
|
<!-- 操作类型 -->
|
||||||
<el-table-column prop="OptTypeValueCN" :label="$t('audit:label:optType')" show-overflow-tooltip width="100px" />
|
<el-table-column v-if="language === 'en'" prop="OptTypeValue" :label="$t('audit:label:optType')" show-overflow-tooltip min-width="110px" />
|
||||||
|
<el-table-column v-else prop="OptTypeValueCN" :label="$t('audit:label:optType')" show-overflow-tooltip min-width="110px" />
|
||||||
<!-- 对象类型 -->
|
<!-- 对象类型 -->
|
||||||
<el-table-column prop="ObjectTypeValueCN" :label="$t('audit:label:objectType')" show-overflow-tooltip min-width="100px" />
|
<el-table-column v-if="language === 'en'" prop="ObjectTypeValue" :label="$t('audit:label:objectType')" show-overflow-tooltip width="100px" />
|
||||||
|
<el-table-column v-else prop="ObjectTypeValueCN" :label="$t('audit:label:objectType')" show-overflow-tooltip min-width="100px" />
|
||||||
<!-- 数据类型 -->
|
<!-- 数据类型 -->
|
||||||
<el-table-column prop="ChildrenTypeValueCN" :label="$t('audit:label:dataType')" show-overflow-tooltip min-width="100px" />
|
<el-table-column v-if="language === 'en'" prop="ChildrenTypeValue" :label="$t('audit:label:dataType')" show-overflow-tooltip min-width="100px" />
|
||||||
|
<el-table-column v-else prop="ChildrenTypeValueCN" :label="$t('audit:label:dataType')" show-overflow-tooltip min-width="100px" />
|
||||||
<!-- 显示顺序 -->
|
<!-- 显示顺序 -->
|
||||||
<el-table-column prop="Sort" :label="$t('audit:label:sort')" min-width="80" show-overflow-tooltip />
|
<el-table-column prop="Sort" :label="$t('audit:label:sort')" min-width="100" show-overflow-tooltip />
|
||||||
<!-- 启用 -->
|
<!-- 启用 -->
|
||||||
<el-table-column :label="$t('audit:label:isEnable')" align="center" prop="CreateTime" min-width="80">
|
<el-table-column :label="$t('audit:label:isEnable')" align="center" prop="CreateTime" min-width="90">
|
||||||
<!-- 启用/禁用 -->
|
<!-- 启用/禁用 -->
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- <el-tag v-if="scope.row.IsEnable" size="success">启用</el-tag>
|
<!-- <el-tag v-if="scope.row.IsEnable" size="success">启用</el-tag>
|
||||||
@@ -81,7 +92,7 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('common:action:action')" align="center" fixed="right" min-width="340" class-name="small-padding fixed-width">
|
<el-table-column :label="$t('common:action:action')" align="center" fixed="right" width="290" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 上移 -->
|
<!-- 上移 -->
|
||||||
<el-button
|
<el-button
|
||||||
@@ -659,7 +670,7 @@ import Treeselect from '@riophae/vue-treeselect'
|
|||||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||||
import Sortable from 'sortablejs'
|
import Sortable from 'sortablejs'
|
||||||
import BaseModel from "@/components/BaseModel";
|
import BaseModel from "@/components/BaseModel";
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
name: 'CheckConfig',
|
name: 'CheckConfig',
|
||||||
dicts: ['OptType', 'ObjectType', 'ModuleType', 'ChildrenType'],
|
dicts: ['OptType', 'ObjectType', 'ModuleType', 'ChildrenType'],
|
||||||
@@ -715,6 +726,9 @@ export default {
|
|||||||
this.getList();
|
this.getList();
|
||||||
this.getDictionaryCodeList();
|
this.getDictionaryCodeList();
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['language'])
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
querySearch(queryString, cb) {
|
querySearch(queryString, cb) {
|
||||||
var DictionaryCodeList = this.DictionaryCodeList;
|
var DictionaryCodeList = this.DictionaryCodeList;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<box-content>
|
<box-content>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
<el-form :inline="true" class="base-search-form">
|
<el-form :inline="true" class="base-search-form" @submit.native.prevent="">
|
||||||
<!-- CRO Name -->
|
<!-- CRO Name -->
|
||||||
<el-form-item :label="$t('institutions:cros:label:croName')">
|
<el-form-item :label="$t('institutions:cros:label:croName')">
|
||||||
<el-input v-model="searchData.CROName" style="width: 100px" />
|
<el-input v-model="searchData.CROName" style="width: 100px" />
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form ref="siteForm" v-loading="loading" :model="form" :rules="rules" class="demo-ruleForm" size="small"
|
||||||
ref="siteForm"
|
label-width="150px">
|
||||||
v-loading="loading"
|
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
class="demo-ruleForm"
|
|
||||||
size="small"
|
|
||||||
label-width="150px"
|
|
||||||
>
|
|
||||||
<div class="base-dialog-body">
|
<div class="base-dialog-body">
|
||||||
<!-- Site Code -->
|
<!-- Site Code -->
|
||||||
<el-form-item :label="$t('institutions:sites:label:siteCode')" v-if="form.Id" prop="SiteCode">
|
<el-form-item :label="$t('institutions:sites:label:siteCode')" v-if="form.Id" prop="SiteCode">
|
||||||
@@ -15,17 +8,11 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 中心名称 -->
|
<!-- 中心名称 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('institutions:sites:label:siteName')" prop="SiteName">
|
||||||
:label="$t('institutions:sites:label:siteName')"
|
|
||||||
prop="SiteName"
|
|
||||||
>
|
|
||||||
<el-input v-model="form.SiteName" />
|
<el-input v-model="form.SiteName" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 中心名称(CN) -->
|
<!-- 中心名称(CN) -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('institutions:sites:label:siteNameCN')" prop="SiteNameCN">
|
||||||
:label="$t('institutions:sites:label:siteNameCN')"
|
|
||||||
prop="SiteNameCN"
|
|
||||||
>
|
|
||||||
<el-input v-model="form.SiteNameCN" />
|
<el-input v-model="form.SiteNameCN" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- Alias Name -->
|
<!-- Alias Name -->
|
||||||
@@ -38,7 +25,9 @@
|
|||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<!-- Country -->
|
<!-- Country -->
|
||||||
<el-form-item :label="$t('institutions:sites:label:country')" prop="Country">
|
<el-form-item :label="$t('institutions:sites:label:country')" prop="Country">
|
||||||
<el-input v-model="form.Country" />
|
<el-select v-model="form.Country" style="width: 100%">
|
||||||
|
<el-option v-for="item of $d.SiteCountry" :key="item.id" :label="item.label" :value="item.label" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- City -->
|
<!-- City -->
|
||||||
<el-form-item :label="$t('institutions:sites:label:city')" prop="City">
|
<el-form-item :label="$t('institutions:sites:label:city')" prop="City">
|
||||||
@@ -50,17 +39,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- Affiliated Hospital -->
|
<!-- Affiliated Hospital -->
|
||||||
<el-form-item :label="$t('institutions:sites:label:affiliatedHospital')">
|
<el-form-item :label="$t('institutions:sites:label:affiliatedHospital')">
|
||||||
<el-select
|
<el-select v-model="form.HospitalId" clearable style="width: 100%">
|
||||||
v-model="form.HospitalId"
|
<el-option v-for="item in hospitalList" :key="item.Id" :label="item.HospitalName" :value="item.Id" />
|
||||||
clearable
|
|
||||||
style="width: 100%"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in hospitalList"
|
|
||||||
:key="item.Id"
|
|
||||||
:label="item.HospitalName"
|
|
||||||
:value="item.Id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- Director Name -->
|
<!-- Director Name -->
|
||||||
@@ -82,20 +62,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button
|
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancel">{{
|
||||||
:disabled="btnLoading"
|
$t('common:button:cancel') }}</el-button>
|
||||||
size="small"
|
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">{{ $t('common:button:save')
|
||||||
type="primary"
|
}}</el-button>
|
||||||
@click="handleCancel"
|
|
||||||
>{{ $t('common:button:cancel') }}</el-button
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
:loading="btnLoading"
|
|
||||||
@click="handleSave"
|
|
||||||
>{{ $t('common:button:save') }}</el-button
|
|
||||||
>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<box-content>
|
<box-content>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
<el-form :inline="true" class="base-search-form">
|
<el-form :inline="true" class="base-search-form" @submit.native.prevent="">
|
||||||
<!-- Sponsor Name -->
|
<!-- Sponsor Name -->
|
||||||
<el-form-item :label="$t('institutions:sponsors:label:sponsorName')">
|
<el-form-item :label="$t('institutions:sponsors:label:sponsorName')">
|
||||||
<el-input v-model="searchData.SponsorName" style="width: 100px" />
|
<el-input v-model="searchData.SponsorName" style="width: 100px" />
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export default {
|
|||||||
// console.log(type, No);
|
// console.log(type, No);
|
||||||
if (type !== "Chrome" && type !== "Edge") {
|
if (type !== "Chrome" && type !== "Edge") {
|
||||||
this.tip = this.$t("browser:tip:changeBorwser");
|
this.tip = this.$t("browser:tip:changeBorwser");
|
||||||
this.getSystemInfo()
|
// this.getSystemInfo()
|
||||||
return (this.visible = true);
|
return (this.visible = true);
|
||||||
}
|
}
|
||||||
let res = await this.getInfo();
|
let res = await this.getInfo();
|
||||||
@@ -53,10 +53,10 @@ export default {
|
|||||||
this.tip += "、";
|
this.tip += "、";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.getSystemInfo()
|
// this.getSystemInfo()
|
||||||
return (this.visible = true);
|
return (this.visible = true);
|
||||||
}
|
}
|
||||||
this.getSystemInfo()
|
// this.getSystemInfo()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<el-input v-model="password.UserType" disabled />
|
<el-input v-model="password.UserType" disabled />
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<!-- 用户名 -->
|
<!-- 用户名 -->
|
||||||
<el-form-item :label="$t('recompose:form:userName')" prop="NewUserName">
|
<el-form-item class="my_new_pwd" :label="$t('recompose:form:userName')" prop="NewUserName">
|
||||||
<el-input v-model="password.NewUserName" :disabled="isUpdate" />
|
<el-input v-model="password.NewUserName" :disabled="isUpdate" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 新密码 -->
|
<!-- 新密码 -->
|
||||||
@@ -77,7 +77,7 @@ export default {
|
|||||||
callback(
|
callback(
|
||||||
lang === 'zh'
|
lang === 'zh'
|
||||||
? new Error(
|
? new Error(
|
||||||
'1)新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
|
'新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
|
||||||
)
|
)
|
||||||
: new Error(
|
: new Error(
|
||||||
'For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
|
'For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
|
||||||
|
|||||||
@@ -4,122 +4,57 @@
|
|||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<!--项目编号/实验名称-->
|
<!--项目编号/实验名称-->
|
||||||
<el-form-item :label="$t('feedBack:search:trials')" v-if="level > 8">
|
<el-form-item :label="$t('feedBack:search:trials')" v-if="level > 8">
|
||||||
<el-input
|
<el-input v-model="searchData.TrialKeyInfo" clearable style="width: 150px"></el-input>
|
||||||
v-model="searchData.TrialKeyInfo"
|
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--中心-->
|
<!--中心-->
|
||||||
<el-form-item :label="$t('feedBack:search:site')" v-if="level > 7">
|
<el-form-item :label="$t('feedBack:search:site')" v-if="level > 7">
|
||||||
<el-input
|
<el-input v-model="searchData.TrialSiteCode" clearable style="width: 150px"></el-input>
|
||||||
v-model="searchData.TrialSiteCode"
|
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--受试者访视-->
|
<!--受试者访视-->
|
||||||
<el-form-item
|
<el-form-item :label="$t('feedBack:search:subjectVisit')" v-if="level > 7">
|
||||||
:label="$t('feedBack:search:subjectVisit')"
|
<el-input v-model="searchData.SubejctAndVisitKeyInfo" clearable style="width: 150px"></el-input>
|
||||||
v-if="level > 7"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="searchData.SubejctAndVisitKeyInfo"
|
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--角色-->
|
<!--角色-->
|
||||||
<el-form-item :label="$t('feedBack:search:role')" v-if="level > 7">
|
<el-form-item :label="$t('feedBack:search:role')" v-if="level > 7">
|
||||||
<el-select
|
<el-select v-model="searchData.UserTypeEnum" clearable style="width: 150px"
|
||||||
v-model="searchData.UserTypeEnum"
|
popper-class="feedBack-select-box">
|
||||||
clearable
|
<el-option v-for="item of UserTypeOptins" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
style="width: 150px"
|
|
||||||
popper-class="feedBack-select-box"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item of UserTypeOptins"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--反馈人-->
|
<!--反馈人-->
|
||||||
<el-form-item :label="$t('feedBack:search:user')" v-if="level > 7">
|
<el-form-item :label="$t('feedBack:search:user')" v-if="level > 7">
|
||||||
<el-input
|
<el-input v-model="searchData.FeedBackUserKeyInfo" clearable style="width: 150px"></el-input>
|
||||||
v-model="searchData.FeedBackUserKeyInfo"
|
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--问题类型-->
|
<!--问题类型-->
|
||||||
<el-form-item :label="$t('feedBack:search:questionType')">
|
<el-form-item :label="$t('feedBack:search:questionType')">
|
||||||
<el-select
|
<el-select v-model="searchData.QuestionType" clearable style="width: 150px"
|
||||||
v-model="searchData.QuestionType"
|
popper-class="feedBack-select-box">
|
||||||
clearable
|
<el-option v-for="item of QuestionTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
style="width: 150px"
|
|
||||||
popper-class="feedBack-select-box"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item of QuestionTypeOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--问题描述-->
|
<!--问题描述-->
|
||||||
<el-form-item :label="$t('feedBack:search:description')">
|
<el-form-item :label="$t('feedBack:search:description')">
|
||||||
<el-input
|
<el-input v-model="searchData.QuestionDescription" clearable style="width: 150px"></el-input>
|
||||||
v-model="searchData.QuestionDescription"
|
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--状态-->
|
<!--状态-->
|
||||||
<el-form-item :label="$t('feedBack:search:status')" v-if="level > 7">
|
<el-form-item :label="$t('feedBack:search:status')" v-if="level > 7">
|
||||||
<el-select
|
<el-select v-model="searchData.State" clearable style="width: 150px" popper-class="feedBack-select-box">
|
||||||
v-model="searchData.State"
|
<el-option v-for="item of $d.FeedBackStatus" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
clearable
|
|
||||||
style="width: 150px"
|
|
||||||
popper-class="feedBack-select-box"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d.FeedBackStatus"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--反馈日期-->
|
<!--反馈日期-->
|
||||||
<el-form-item :label="$t('feedBack:search:time')">
|
<el-form-item :label="$t('feedBack:search:time')">
|
||||||
<el-date-picker
|
<el-date-picker v-model="datetimerange" type="datetimerange" :default-time="['00:00:00', '23:59:59']"
|
||||||
v-model="datetimerange"
|
:start-placeholder="$t('feedBack:search:beginTime')" :end-placeholder="$t('feedBack:search:endTime')"
|
||||||
type="datetimerange"
|
value-format="yyyy-MM-dd HH:mm:ss" @change="handleDatetimeChange" style="width: 250px"
|
||||||
:default-time="['00:00:00', '23:59:59']"
|
popper-class="feedBack-select-box" />
|
||||||
:start-placeholder="$t('feedBack:search:beginTime')"
|
|
||||||
:end-placeholder="$t('feedBack:search:endTime')"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
@change="handleDatetimeChange"
|
|
||||||
style="width: 250px"
|
|
||||||
popper-class="feedBack-select-box"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button
|
<el-button type="primary" icon="el-icon-search" @click="getList">
|
||||||
type="primary"
|
|
||||||
icon="el-icon-search"
|
|
||||||
@click="getList"
|
|
||||||
>
|
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 重置 -->
|
<!-- 重置 -->
|
||||||
<el-button
|
<el-button icon="el-icon-refresh-left" @click="handleReset">
|
||||||
icon="el-icon-refresh-left"
|
|
||||||
@click="handleReset"
|
|
||||||
>
|
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- <el-button
|
<!-- <el-button
|
||||||
@@ -131,97 +66,32 @@
|
|||||||
{{ $t("common:button:export") }}
|
{{ $t("common:button:export") }}
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-button
|
<el-button type="primary" @click="resolve" style="float: right" v-if="level > 7"
|
||||||
type="primary"
|
:disabled="tableSelectData.length <= 0">
|
||||||
@click="resolve"
|
|
||||||
style="float: right"
|
|
||||||
v-if="level > 7"
|
|
||||||
:disabled="tableSelectData.length <= 0"
|
|
||||||
>
|
|
||||||
{{ $t('feedBack:button:resolve') }}
|
{{ $t('feedBack:button:resolve') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-table
|
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
|
||||||
v-loading="loading"
|
@selection-change="handleSelectChange" @sort-change="handleSortByColumn"
|
||||||
v-adaptive="{ bottomOffset: 45 }"
|
:default-sort="{ prop: 'CreateTime', order: 'descending' }">
|
||||||
height="100"
|
<el-table-column type="selection" align="center" width="45" v-if="level > 7" :selectable="handleSelectTable" />
|
||||||
:data="list"
|
|
||||||
class="table"
|
|
||||||
@selection-change="handleSelectChange"
|
|
||||||
@sort-change="handleSortByColumn"
|
|
||||||
:default-sort="{ prop: 'CreateTime', order: 'descending' }"
|
|
||||||
>
|
|
||||||
<el-table-column
|
|
||||||
type="selection"
|
|
||||||
align="center"
|
|
||||||
width="45"
|
|
||||||
v-if="level > 7"
|
|
||||||
:selectable="handleSelectTable"
|
|
||||||
/>
|
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column type="index" width="50" />
|
||||||
<el-table-column
|
<el-table-column :label="$t('feedBack:form:trialCode')" prop="TrialCode" min-width="100" show-overflow-tooltip
|
||||||
:label="$t('feedBack:form:trialCode')"
|
sortable="custom" v-if="level > 8" />
|
||||||
prop="TrialCode"
|
<el-table-column :label="$t('feedBack:form:study')" prop="ExperimentName" min-width="140" show-overflow-tooltip
|
||||||
min-width="100"
|
sortable="custom" v-if="level > 8" />
|
||||||
show-overflow-tooltip
|
<el-table-column :label="$t('feedBack:form:siteCode')" prop="TrialSiteCode" min-width="100"
|
||||||
sortable="custom"
|
show-overflow-tooltip sortable="custom" v-if="level > 7" />
|
||||||
v-if="level > 8"
|
<el-table-column :label="$t('feedBack:form:SubjectCode')" prop="SubjectCode" min-width="120"
|
||||||
/>
|
show-overflow-tooltip sortable="custom" v-if="level > 7" />
|
||||||
<el-table-column
|
<el-table-column :label="$t('feedBack:form:subjectVisit')" prop="SubjectVisitName" min-width="120"
|
||||||
:label="$t('feedBack:form:study')"
|
show-overflow-tooltip sortable="custom" v-if="level > 7" />
|
||||||
prop="ExperimentName"
|
<el-table-column :label="$t('feedBack:form:role')" prop="FeedBackUserName" min-width="100" show-overflow-tooltip
|
||||||
min-width="140"
|
sortable="custom" v-if="level > 7" />
|
||||||
show-overflow-tooltip
|
<el-table-column :label="$t('feedBack:form:user')" prop="FeedBackFullName" min-width="140" show-overflow-tooltip
|
||||||
sortable="custom"
|
sortable="custom" v-if="level > 7" />
|
||||||
v-if="level > 8"
|
<el-table-column :label="$t('feedBack:form:questionType')" prop="QuestionType" min-width="180"
|
||||||
/>
|
show-overflow-tooltip sortable="custom">
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:siteCode')"
|
|
||||||
prop="TrialSiteCode"
|
|
||||||
min-width="100"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:SubjectCode')"
|
|
||||||
prop="SubjectCode"
|
|
||||||
min-width="120"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:subjectVisit')"
|
|
||||||
prop="SubjectVisitName"
|
|
||||||
min-width="120"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:role')"
|
|
||||||
prop="FeedBackUserName"
|
|
||||||
min-width="100"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:user')"
|
|
||||||
prop="FeedBackFullName"
|
|
||||||
min-width="140"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:questionType')"
|
|
||||||
prop="QuestionType"
|
|
||||||
min-width="180"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{
|
<span>{{
|
||||||
QuestionTypeOptions.filter(
|
QuestionTypeOptions.filter(
|
||||||
@@ -230,49 +100,22 @@
|
|||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column :label="$t('feedBack:form:description')" prop="QuestionDescription" min-width="200"
|
||||||
:label="$t('feedBack:form:description')"
|
show-overflow-tooltip sortable="custom" />
|
||||||
prop="QuestionDescription"
|
<el-table-column :label="$t('feedBack:form:time')" prop="CreateTime" min-width="180" show-overflow-tooltip
|
||||||
min-width="200"
|
sortable="custom" />
|
||||||
show-overflow-tooltip
|
<el-table-column :label="$t('feedBack:form:status')" prop="State" min-width="120" show-overflow-tooltip
|
||||||
sortable="custom"
|
sortable="custom" v-if="level > 7">
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:time')"
|
|
||||||
prop="CreateTime"
|
|
||||||
min-width="180"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('feedBack:form:status')"
|
|
||||||
prop="State"
|
|
||||||
min-width="120"
|
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="['danger', 'success'][scope.row.State]">{{
|
<el-tag :type="['danger', 'success', 'danger'][scope.row.State]">{{
|
||||||
$fd('FeedBackStatus', scope.row.State)
|
$fd('FeedBackStatus', scope.row.State)
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column :label="$t('feedBack:form:uploadTime')" prop="UpdateTime" min-width="180" show-overflow-tooltip
|
||||||
:label="$t('feedBack:form:uploadTime')"
|
sortable="custom" v-if="level > 7" />
|
||||||
prop="UpdateTime"
|
<el-table-column :label="$t('common:action:action')" fixed="right" prop="UserTypeShortName" width="100"
|
||||||
min-width="180"
|
show-overflow-tooltip>
|
||||||
show-overflow-tooltip
|
|
||||||
sortable="custom"
|
|
||||||
v-if="level > 7"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
:label="$t('common:action:action')"
|
|
||||||
fixed="right"
|
|
||||||
prop="UserTypeShortName"
|
|
||||||
width="100"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" @click="getDetail(scope.row)">
|
<el-button type="text" @click="getDetail(scope.row)">
|
||||||
{{ $t('common:button:view') }}
|
{{ $t('common:button:view') }}
|
||||||
@@ -281,12 +124,8 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div class="pagination" style="text-align: right; margin-top: 5px">
|
<div class="pagination" style="text-align: right; margin-top: 5px">
|
||||||
<pagination
|
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||||
:total="total"
|
@pagination="getList" />
|
||||||
:page.sync="searchData.PageIndex"
|
|
||||||
:limit.sync="searchData.PageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -434,7 +273,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 导出
|
// 导出
|
||||||
report() {},
|
report() { },
|
||||||
// 表格选择
|
// 表格选择
|
||||||
handleSelectChange(selection) {
|
handleSelectChange(selection) {
|
||||||
// console.log(selection, "handleSelectChange");
|
// console.log(selection, "handleSelectChange");
|
||||||
@@ -472,31 +311,37 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 0;
|
width: 0;
|
||||||
flex-grow: 4;
|
flex-grow: 4;
|
||||||
|
|
||||||
// border-right: 1px solid #ccc;
|
// border-right: 1px solid #ccc;
|
||||||
.filter-container {
|
.filter-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table {
|
.data-table {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 5px 0px;
|
padding: 5px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
width: 0;
|
width: 0;
|
||||||
flex-grow: 6;
|
flex-grow: 6;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-right: 1px solid #ccc;
|
border-right: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-row {
|
.selected-row {
|
||||||
background-color: cadetblue;
|
background-color: cadetblue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,276 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wscn-http404-container">
|
||||||
|
<div class="wscn-http404" style="display: flex;align-items: center;flex-wrap: wrap;justify-content: center;">
|
||||||
|
<div class="pic-404">
|
||||||
|
<!-- <img class="pic-404__parent" src="@/assets/login-bg.png" alt="404"> -->
|
||||||
|
<svg-icon icon-class="login-bg" style="width: 100%; height: 100%" />
|
||||||
|
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||||
|
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||||
|
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||||
|
</div>
|
||||||
|
<div class="bullshit">
|
||||||
|
<div class="bullshit__oops" style="color: #428bca">{{ $t('trials:researchForm:title:IsExpired') }}!</div>
|
||||||
|
<!-- <div class="bullshit__headline">{{ $t('trials:researchForm:title:IsExpired') }}</div> -->
|
||||||
|
<!-- <div class="bullshit__return-home" style="background: #428bca" @click="$router.push({ path: '/login' })">{{
|
||||||
|
$t('common:title:goHome') }}</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
...mapGetters([
|
||||||
|
'asyncRoutes',
|
||||||
|
'routes',
|
||||||
|
'language'
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
let lang = this.$route.query.lang
|
||||||
|
if (!lang) {
|
||||||
|
const language = navigator.language
|
||||||
|
lang = 'en'
|
||||||
|
if (language.includes("zh")) {
|
||||||
|
lang = 'zh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$i18n.locale = lang
|
||||||
|
this.setLanguage(lang)
|
||||||
|
this.$updateDictionary()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wscn-http404-container {
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
position: absolute;
|
||||||
|
top: 40%;
|
||||||
|
left: 50%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wscn-http404 {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.pic-404 {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
height: 300px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
&__parent {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__child {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
width: 80px;
|
||||||
|
top: 17px;
|
||||||
|
left: 220px;
|
||||||
|
opacity: 0;
|
||||||
|
animation-name: cloudLeft;
|
||||||
|
animation-duration: 2s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mid {
|
||||||
|
width: 46px;
|
||||||
|
top: 10px;
|
||||||
|
left: 420px;
|
||||||
|
opacity: 0;
|
||||||
|
animation-name: cloudMid;
|
||||||
|
animation-duration: 2s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-delay: 1.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
width: 62px;
|
||||||
|
top: 100px;
|
||||||
|
left: 500px;
|
||||||
|
opacity: 0;
|
||||||
|
animation-name: cloudRight;
|
||||||
|
animation-duration: 2s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cloudLeft {
|
||||||
|
0% {
|
||||||
|
top: 17px;
|
||||||
|
left: 220px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
top: 33px;
|
||||||
|
left: 188px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
top: 81px;
|
||||||
|
left: 92px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 97px;
|
||||||
|
left: 60px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cloudMid {
|
||||||
|
0% {
|
||||||
|
top: 10px;
|
||||||
|
left: 420px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
top: 40px;
|
||||||
|
left: 360px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
70% {
|
||||||
|
top: 130px;
|
||||||
|
left: 180px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 160px;
|
||||||
|
left: 120px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cloudRight {
|
||||||
|
0% {
|
||||||
|
top: 100px;
|
||||||
|
left: 500px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
top: 120px;
|
||||||
|
left: 460px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
top: 180px;
|
||||||
|
left: 340px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
top: 200px;
|
||||||
|
left: 300px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bullshit {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
width: 300px;
|
||||||
|
padding: 30px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__oops {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 40px;
|
||||||
|
color: #1482f0;
|
||||||
|
opacity: 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
animation-name: slideUp;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__headline {
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 24px;
|
||||||
|
color: #222;
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
animation-name: slideUp;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 21px;
|
||||||
|
color: grey;
|
||||||
|
opacity: 0;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
animation-name: slideUp;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-delay: 0.2s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__return-home {
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
width: 110px;
|
||||||
|
height: 36px;
|
||||||
|
background: #1482f0;
|
||||||
|
border-radius: 100px;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
opacity: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 36px;
|
||||||
|
cursor: pointer;
|
||||||
|
animation-name: slideUp;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-delay: 0.3s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideUp {
|
||||||
|
0% {
|
||||||
|
transform: translateY(60px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -152,7 +152,12 @@
|
|||||||
<!-- {{ $t('login:title:system_title_about') }} -->
|
<!-- {{ $t('login:title:system_title_about') }} -->
|
||||||
<svg-icon icon-class="login-logo" style="width: 250px; height: 71px" />
|
<svg-icon icon-class="login-logo" style="width: 250px; height: 71px" />
|
||||||
</p>
|
</p>
|
||||||
<p style="margin-bottom: 0px" v-else>{{ $t('login:title:system') }}</p>
|
<div style="margin-bottom: 0px" v-else>
|
||||||
|
<!-- {{ $t('login:title:system_title_about') }} -->
|
||||||
|
<img src="@/assets/system.png" alt=""
|
||||||
|
:style="{ width: isEN ? '180px' : '200px', height: isEN ? '60px' : '65px' }" />
|
||||||
|
<p style="margin-bottom: 0px">{{ $t('login:title:system') }}</p>
|
||||||
|
</div>
|
||||||
<p style="margin-bottom: 20px; margin-top: 0">
|
<p style="margin-bottom: 20px; margin-top: 0">
|
||||||
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
|
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
|
||||||
</p>
|
</p>
|
||||||
@@ -167,12 +172,12 @@
|
|||||||
Copyright © {{ new Date().getFullYear() }} Shanghai Extensive Imaging
|
Copyright © {{ new Date().getFullYear() }} Shanghai Extensive Imaging
|
||||||
Inc.
|
Inc.
|
||||||
</p>
|
</p>
|
||||||
<div style="margin-bottom: 20px" v-if="NODE_ENV === 'usa'">
|
<!-- <div style="margin-bottom: 20px" v-if="NODE_ENV === 'usa'">
|
||||||
<img style="width: 180px" src="@/assets/zzlogo-usa.png" alt="" />
|
<img style="width: 180px" src="@/assets/zzlogo-usa.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-bottom: 20px" v-else>
|
<div style="margin-bottom: 20px" v-else>
|
||||||
<img style="width: 180px" src="@/assets/zzlogo2.png" alt="" />
|
<img style="width: 180px" src="@/assets/zzlogo2.png" alt="" />
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button type="primary" size="mini" @click="aboutVisible = false">
|
<el-button type="primary" size="mini" @click="aboutVisible = false">
|
||||||
@@ -369,6 +374,15 @@ export default {
|
|||||||
})
|
})
|
||||||
}, 500)
|
}, 500)
|
||||||
return
|
return
|
||||||
|
} else if (res.BasicInfo.IsNeedResetPwd) {
|
||||||
|
// 当前用户管理员重置密码,请先修改密码之后再次登录
|
||||||
|
this.$message.success(this.$t('login:message:login5'))
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$router.push({
|
||||||
|
path: `/user-recompose?UserId=${res.BasicInfo.IdentityUserId}&Email=${res.BasicInfo.EMail}&UserName=${res.BasicInfo.UserName}&lang=${this.$i18n.locale}&access_token=${res.JWTStr}&isUpdate=1`,
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
return
|
||||||
} else if (res.BasicInfo.NeedChangePassWord) {
|
} else if (res.BasicInfo.NeedChangePassWord) {
|
||||||
// 请先修改密码后再登录!
|
// 请先修改密码后再登录!
|
||||||
this.$alert(
|
this.$alert(
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ export default {
|
|||||||
isAudit: false,
|
isAudit: false,
|
||||||
|
|
||||||
activeNames: [],
|
activeNames: [],
|
||||||
Asc: false
|
Asc: false,
|
||||||
|
IsReadingTaskViewInOrder: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
@@ -165,6 +166,9 @@ export default {
|
|||||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||||
changeURLStatic('TokenKey', '')
|
changeURLStatic('TokenKey', '')
|
||||||
}
|
}
|
||||||
|
if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
|
||||||
|
this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
|
||||||
|
}
|
||||||
this.subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
this.subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
||||||
this.studyId = this.$router.currentRoute.query.studyId
|
this.studyId = this.$router.currentRoute.query.studyId
|
||||||
this.getNoneDicomList()
|
this.getNoneDicomList()
|
||||||
|
|||||||
@@ -0,0 +1,516 @@
|
|||||||
|
<template>
|
||||||
|
<div v-loading="loading" class="none-dicom-study-wrapper">
|
||||||
|
<div class="study-info">
|
||||||
|
<div style="cursor: pointer;" @click.stop="sortFile">
|
||||||
|
<i :class="['el-icon-caret-top', asc === false ? '' : 'icon_check']"
|
||||||
|
style="display: block;margin-bottom: -5px;"></i>
|
||||||
|
<i :class="['el-icon-caret-bottom', asc === true ? '' : 'icon_check']"
|
||||||
|
style="display: block; margin-top: -5px;"></i>
|
||||||
|
</div>
|
||||||
|
<div>{{ $t('trials:none-dicom-show:fileList') }} </div>
|
||||||
|
</div>
|
||||||
|
<div class="ps" ref="studyBox_ps">
|
||||||
|
<el-collapse v-model="activeNames">
|
||||||
|
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.Id}`" :name="`${study.Id}`">
|
||||||
|
<template slot="title">
|
||||||
|
<div class="dicom-desc">
|
||||||
|
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||||
|
<span :title="study.CodeView">{{ study.CodeView }}</span>
|
||||||
|
<span v-if="otherInfo && otherInfo.IsShowStudyName" :title="study.StudyName" style="margin-left: 5px;">
|
||||||
|
{{ study.StudyName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||||
|
<span :title="study.BodyPart">{{ getBodyPart(study.BodyPart, study.BodyPartForEditOther) }}</span>
|
||||||
|
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="file-list-container">
|
||||||
|
<div v-for="(k, i) in study.NoneDicomStudyFileList" :key="i" style="position:relative;margin-top:1px;"
|
||||||
|
@click="selectFile(study, index, i, k)" :ref="`noneDicomRef_${index}_${i}`">
|
||||||
|
<div :class="{ 'file-active': index === activeStudyIndex && i === activeFileIndex }" class="file-wrapper">
|
||||||
|
<div class="file-main">
|
||||||
|
<div class="file-image">
|
||||||
|
<el-image
|
||||||
|
v-if="k.FileType === 'image/jpeg' || k.FileType === 'image/jpg' || k.FileType === 'image/bmp' || k.FileType === 'image/png'"
|
||||||
|
style="width: 100%;height: 100%;"
|
||||||
|
:src="`${OSSclientConfig.basePath}${k.Path}?x-oss-process=image/resize,w_50,h_50/format,png`"
|
||||||
|
fit="contain" crossorigin="anonymous" />
|
||||||
|
<el-image v-else-if="k.FileType === 'application/pdf'" style="width: 100%;height: 100%;" :src="pdf"
|
||||||
|
fit="contain" crossorigin="anonymous" />
|
||||||
|
<el-image v-else-if="
|
||||||
|
!!~k.FileType.indexOf('mp4')
|
||||||
|
" style="width: 100%; height: 100%" :src="mp4" fit="contain" crossorigin="anonymous" />
|
||||||
|
<el-image v-else-if="
|
||||||
|
!!~k.FileType.indexOf('zip')
|
||||||
|
" style="width: 100%; height: 100%" :src="zipImg" fit="contain" crossorigin="anonymous" />
|
||||||
|
</div>
|
||||||
|
<div class="file-text" :title="k.FileName">
|
||||||
|
{{ k.FileName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="isQcCheck" class="switchBox">
|
||||||
|
<div class="item">
|
||||||
|
<span>{{ $t('trials:audit:table:isReading') }}</span>
|
||||||
|
<el-switch v-model="k.IsReading" :disabled="k.IsDeleted || isAudit"
|
||||||
|
:active-text="$fd('YesOrNo', true)" :inactive-text="$fd('YesOrNo', false)"
|
||||||
|
@change="changeReadingStatus($event, study, k)" />
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span>{{ $t('trials:audit:table:isDelete') }}</span>
|
||||||
|
<el-switch v-model="k.IsDeleted" :disabled="isAudit" :active-text="$fd('YesOrNo', true)"
|
||||||
|
:inactive-text="$fd('YesOrNo', false)" @change="changeDeleteStatus($event, study, k)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getNoneDicomStudyList, setNodicomStudyState } from '@/api/trials'
|
||||||
|
import FileNameSorter from "@/utils/customSort"
|
||||||
|
import pdf from '@/assets/pdf.png'
|
||||||
|
import mp4 from '@/assets/mp4.png'
|
||||||
|
import zipImg from '@/assets/zip.jpg'
|
||||||
|
export default {
|
||||||
|
name: 'StudyList',
|
||||||
|
props: {
|
||||||
|
visitTaskInfo: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isComparison: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
activeNames: [],
|
||||||
|
activeStudyId: '',
|
||||||
|
activeFileId: '',
|
||||||
|
activeStudyIndex: -1,
|
||||||
|
activeFileIndex: -1,
|
||||||
|
studyList: [],
|
||||||
|
pdf,
|
||||||
|
mp4,
|
||||||
|
zipImg,
|
||||||
|
BodyPart: {},
|
||||||
|
subjectVisitId: '',
|
||||||
|
studyId: '',
|
||||||
|
otherInfo: null,
|
||||||
|
criterionType: null,
|
||||||
|
isQcCheck: false,
|
||||||
|
isAudit: false,
|
||||||
|
asc: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.subjectVisitId = this.$route.query.subjectVisitId
|
||||||
|
this.studyId = this.$route.query.studyId
|
||||||
|
this.isQcCheck = !!this.$route.query.isQcCheck
|
||||||
|
this.getNoneDicoms()
|
||||||
|
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.activeStudy(this.studyList[0].Id)
|
||||||
|
// })
|
||||||
|
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
scrollActiveFileIntoView() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const refKey = `noneDicomRef_${this.activeStudyIndex}_${this.activeFileIndex}`
|
||||||
|
const targetRef = this.$refs[refKey]
|
||||||
|
const element = Array.isArray(targetRef) ? targetRef[0] : targetRef
|
||||||
|
if (!element) return
|
||||||
|
this.scrollElementToVisible(element)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
scrollElementToVisible(element, options = {}) {
|
||||||
|
const container = this.$refs['studyBox_ps']
|
||||||
|
if (!container || !element) return
|
||||||
|
const elementTop = element.offsetTop
|
||||||
|
const elementBottom = elementTop + element.offsetHeight
|
||||||
|
const visibleTop = container.scrollTop
|
||||||
|
const visibleBottom = visibleTop + container.clientHeight
|
||||||
|
if (elementTop >= visibleTop && elementBottom <= visibleBottom) return
|
||||||
|
const offset = options.offset != null
|
||||||
|
? options.offset
|
||||||
|
: Math.max((container.clientHeight - element.offsetHeight) / 2, 0)
|
||||||
|
const targetPosition = Math.max(elementTop - offset, 0)
|
||||||
|
container.scrollTo({
|
||||||
|
top: targetPosition,
|
||||||
|
behavior: options.behavior || 'smooth'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async getNoneDicoms() {
|
||||||
|
const loading = this.$loading({ fullscreen: true })
|
||||||
|
try {
|
||||||
|
let res = await getNoneDicomStudyList(
|
||||||
|
this.subjectVisitId,
|
||||||
|
this.studyId,
|
||||||
|
false,
|
||||||
|
this.$route.query.visitTaskId,
|
||||||
|
!!this.$route.query.isReading,
|
||||||
|
this.$route.query.isImageSegmentLabel,
|
||||||
|
)
|
||||||
|
this.studyList = res.Result
|
||||||
|
this.studyList.forEach(study => {
|
||||||
|
if (study.NoneDicomStudyFileList && study.NoneDicomStudyFileList.length > 0) {
|
||||||
|
study.NoneDicomStudyFileList.forEach(file => {
|
||||||
|
if (file.Path.includes('.MaskNoneDicom_')) {
|
||||||
|
file.IsBeMark = true
|
||||||
|
} else {
|
||||||
|
file.IsBeMark = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.otherInfo = res.OtherInfo
|
||||||
|
this.isAudit = res.OtherInfo.AuditState * 1 > 6
|
||||||
|
const studyIndex = this.studyList.findIndex((item) => {
|
||||||
|
return item.NoneDicomStudyFileList.length > 0
|
||||||
|
})
|
||||||
|
if (studyIndex > -1) {
|
||||||
|
this.selectFile(this.studyList[studyIndex], studyIndex, 0)
|
||||||
|
let studyId = this.studyList[studyIndex].Id
|
||||||
|
this.activeNames = [studyId]
|
||||||
|
}
|
||||||
|
if (this.criterionType === 19 || this.criterionType === 20) {
|
||||||
|
this.sortFile()
|
||||||
|
}
|
||||||
|
loading.close()
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
loading.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
selected() {
|
||||||
|
|
||||||
|
},
|
||||||
|
sortFile() {
|
||||||
|
this.asc = !this.asc
|
||||||
|
this.studyList.forEach(study => {
|
||||||
|
if (study.NoneDicomStudyFileList.length > 0) {
|
||||||
|
study.NoneDicomStudyFileList = FileNameSorter.sortFileNames(study.NoneDicomStudyFileList, {
|
||||||
|
direction: this.asc ? 'asc' : 'desc',
|
||||||
|
key: 'FileName'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.activeStudyIndex = this.studyList.findIndex(item => item.Id === this.activeStudyId)
|
||||||
|
if (this.activeStudyIndex === -1) return
|
||||||
|
this.activeFileIndex = this.studyList[this.activeStudyIndex].NoneDicomStudyFileList.findIndex(item => item.Id === this.activeFileId)
|
||||||
|
},
|
||||||
|
changeReadingStatus(callback, row, file) {
|
||||||
|
let statusStr = ''
|
||||||
|
if (callback) {
|
||||||
|
statusStr = this.$t('trials:audit:label:setSeriesReading')
|
||||||
|
file.IsReading = false
|
||||||
|
} else {
|
||||||
|
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
|
||||||
|
file.IsReading = true
|
||||||
|
}
|
||||||
|
let message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
|
||||||
|
message = message.replace('yyy', this.$fd('YesOrNo', !file.IsReading))
|
||||||
|
this.$confirm(message, {
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const state = file.IsReading ? 1 : 2
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
SubjectVisitId: row.SubjectVisitId,
|
||||||
|
NoneDicomStudyId: row.Id,
|
||||||
|
State: state,
|
||||||
|
NoneDicomStudyFileId: file.Id,
|
||||||
|
}
|
||||||
|
return setNodicomStudyState(params)
|
||||||
|
.then((res) => {
|
||||||
|
this.loading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
file.IsReading = !file.IsReading
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => { })
|
||||||
|
},
|
||||||
|
changeDeleteStatus(callback, row, file) {
|
||||||
|
let statusStr = ''
|
||||||
|
if (callback) {
|
||||||
|
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
|
||||||
|
file.IsDeleted = false
|
||||||
|
} else {
|
||||||
|
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
|
||||||
|
file.IsDeleted = true
|
||||||
|
}
|
||||||
|
let message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
|
||||||
|
message = message.replace('yyy', this.$fd('YesOrNo', !file.IsDeleted))
|
||||||
|
this.$confirm(message, {
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
const state = file.IsDeleted ? 5 : 4
|
||||||
|
this.loading = true
|
||||||
|
const params = {
|
||||||
|
SubjectVisitId: row.SubjectVisitId,
|
||||||
|
NoneDicomStudyId: row.Id,
|
||||||
|
State: state,
|
||||||
|
NoneDicomStudyFileId: file.Id,
|
||||||
|
}
|
||||||
|
return setNodicomStudyState(params)
|
||||||
|
.then((res) => {
|
||||||
|
this.loading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
file.IsDeleted = !file.IsDeleted
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => { })
|
||||||
|
},
|
||||||
|
getBodyPart(bodyPart, other) {
|
||||||
|
if (!bodyPart && !other) return ''
|
||||||
|
var separator = ','
|
||||||
|
if (bodyPart.indexOf('|') > -1) {
|
||||||
|
separator = '|'
|
||||||
|
} else if (bodyPart.indexOf(',') > -1) {
|
||||||
|
separator = ','
|
||||||
|
} else if (bodyPart.indexOf(',') > -1) {
|
||||||
|
separator = ','
|
||||||
|
}
|
||||||
|
var arr = bodyPart.split(separator)
|
||||||
|
var newArr = arr.map((i) => {
|
||||||
|
return this.$fd('Bodypart', i.trim(), 'Code', this.BodyPart, 'Name')
|
||||||
|
})
|
||||||
|
if (other) {
|
||||||
|
newArr.push(other)
|
||||||
|
}
|
||||||
|
newArr = newArr.filter(Boolean)
|
||||||
|
return newArr.join(' | ')
|
||||||
|
},
|
||||||
|
// 切换文件
|
||||||
|
selectFile(study, studyIndex, fileIndex, isReset = false) {
|
||||||
|
if (this.isComparison) return false
|
||||||
|
this.activeStudyIndex = studyIndex
|
||||||
|
this.activeFileIndex = fileIndex
|
||||||
|
this.activeStudyId = study.Id
|
||||||
|
const fileList = study.NoneDicomStudyFileList
|
||||||
|
this.activeFileId = fileList[fileIndex].Id
|
||||||
|
this.$emit('selectFile', { fileInfo: fileList[fileIndex], fileList, visitTaskInfo: this.visitTaskInfo, studyId: study.Id, isReset })
|
||||||
|
this.scrollActiveFileIntoView()
|
||||||
|
},
|
||||||
|
activeImage(obj) {
|
||||||
|
if (!obj || this.studyList.length === 0) return
|
||||||
|
const study = this.studyList.find(i => i.Id === obj.studyId)
|
||||||
|
const studyIndex = this.studyList.findIndex(i => i.Id === obj.studyId)
|
||||||
|
if (studyIndex === -1) return
|
||||||
|
this.activeStudy(`${obj.studyId}`)
|
||||||
|
this.activeStudyIndex = studyIndex
|
||||||
|
this.activeStudyId = obj.studyId
|
||||||
|
const fileList = this.studyList[studyIndex].NoneDicomStudyFileList || []
|
||||||
|
const fileIndex = fileList.findIndex(f => f.Path === obj.path)
|
||||||
|
if (fileIndex === -1) return
|
||||||
|
this.activeFileIndex = fileIndex
|
||||||
|
this.activeFileId = fileList[fileIndex].Id
|
||||||
|
this.selectFile(study, studyIndex, fileIndex)
|
||||||
|
this.scrollActiveFileIntoView()
|
||||||
|
},
|
||||||
|
replaceImage(obj) {
|
||||||
|
if (!obj || this.studyList.length === 0) return
|
||||||
|
const study = this.studyList.find(i => i.Id === obj.studyId)
|
||||||
|
const studyIndex = this.studyList.findIndex(i => i.Id === obj.studyId)
|
||||||
|
if (studyIndex === -1) return
|
||||||
|
this.activeStudy(`${obj.studyId}`)
|
||||||
|
this.activeStudyIndex = studyIndex
|
||||||
|
this.activeStudyId = obj.studyId
|
||||||
|
const fileList = this.studyList[studyIndex].NoneDicomStudyFileList || []
|
||||||
|
const fileIndex = fileList.findIndex(f => f.Path === obj.path)
|
||||||
|
const file = fileList.find(f => f.Path === obj.path)
|
||||||
|
if (fileIndex === -1) return
|
||||||
|
this.activeFileIndex = fileIndex
|
||||||
|
this.activeFileId = fileList[fileIndex].Id
|
||||||
|
file.Path = obj.file.Path
|
||||||
|
file.FullFilePath = obj.file.Path
|
||||||
|
file.IsBeMark = obj.IsBeMark
|
||||||
|
this.selectFile(study, studyIndex, fileIndex, true)
|
||||||
|
},
|
||||||
|
activeStudy(id) {
|
||||||
|
const studyId = `${id}`
|
||||||
|
if (this.activeNames.indexOf(studyId) > -1) return
|
||||||
|
this.activeNames.push(studyId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.none-dicom-study-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.study-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ddd;
|
||||||
|
background-color: #4c4c4c;
|
||||||
|
line-height: 40px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.icon_check {
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
.dicom-desc {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: left;
|
||||||
|
color: #d0d0d0;
|
||||||
|
padding: 2px 8px 2px 2px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ps {
|
||||||
|
flex: 1;
|
||||||
|
overflow-anchor: none;
|
||||||
|
touch-action: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-active {
|
||||||
|
// background: #16477b;
|
||||||
|
background-color: #183553 !important;
|
||||||
|
border: 1px solid #23527b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-progress__text {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
::v-deep .el-switch__label {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.file-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
|
||||||
|
// color: #ddd;
|
||||||
|
// white-space: nowrap;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
.file-main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-progress__text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-progress-bar {
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-image {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-text {
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 5px;
|
||||||
|
color: #ddd;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchBox {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 6px;
|
||||||
|
color: #ddd;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-collapse {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.el-collapse-item {
|
||||||
|
background-color: #000 !important;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-collapse-item__content {
|
||||||
|
padding-bottom: 0px;
|
||||||
|
background-color: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-collapse-item__header {
|
||||||
|
background-color: #353535 !important;
|
||||||
|
color: #ddd;
|
||||||
|
border-bottom-color: #5a5a5a;
|
||||||
|
padding-left: 5px;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
::v-deep .el-progress-bar__inner {
|
||||||
|
transition: width 0s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<div class="read-page-container">
|
||||||
|
<!-- 检查列表 -->
|
||||||
|
<div class="left-panel">
|
||||||
|
<div class="study-info">
|
||||||
|
<study-list ref="studyList" :isComparison="isComparison" @selectFile="selectFile" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图像 -->
|
||||||
|
<div class="middle-panel">
|
||||||
|
|
||||||
|
<file-viewer ref="fileViewer" :isComparison.sync="isComparison" @toggleImage="toggleImage"
|
||||||
|
@selectFile="selectFile" @replaceImage="replaceImage" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import store from '@/store'
|
||||||
|
import { changeURLStatic } from '@/utils/history.js'
|
||||||
|
import StudyList from './components/study-list'
|
||||||
|
import FileViewer from './components/file-viewer'
|
||||||
|
export default {
|
||||||
|
name: 'NoneDicoms',
|
||||||
|
components: {
|
||||||
|
StudyList,
|
||||||
|
FileViewer
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isComparison: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
if (this.$route.query.TokenKey) {
|
||||||
|
store.dispatch('user/setToken', this.$route.query.TokenKey)
|
||||||
|
changeURLStatic('TokenKey', '')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleImage(obj) {
|
||||||
|
this.$refs['studyList'].activeImage(obj)
|
||||||
|
},
|
||||||
|
selectFile(obj) {
|
||||||
|
if (obj.fileInfo && obj.fileList && obj.studyId) {
|
||||||
|
this.$refs['fileViewer'].setActiveCanvasImages(obj)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
replaceImage(obj) {
|
||||||
|
this.$refs['studyList'].replaceImage(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.read-page-container {
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
background-color: #444;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
display: flex;
|
||||||
|
width: 230px;
|
||||||
|
border: 1px solid #727272;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 3px;
|
||||||
|
height: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.study-info {
|
||||||
|
width: 100%;
|
||||||
|
border-left: 1px solid #727272;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle-panel {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #727272;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .right-panel {
|
||||||
|
// width: 400px;
|
||||||
|
// border: 1px solid #727272;
|
||||||
|
// padding: 0 10px;
|
||||||
|
// overflow-y: auto;
|
||||||
|
|
||||||
|
// .text-info {
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// justify-content: space-between;
|
||||||
|
// color: #ddd;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
::v-deep .dialog-container {
|
||||||
|
margin-top: 50px !important;
|
||||||
|
width: 75%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-dialog__body {
|
||||||
|
padding: 20px 20px 0 20px;
|
||||||
|
height: calc(100% - 70px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-dialog-container {
|
||||||
|
::v-deep .is-fullscreen .el-dialog__body {
|
||||||
|
height: calc(100% - 70px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -25,19 +25,10 @@
|
|||||||
<div class="login_content">
|
<div class="login_content">
|
||||||
<div class="form-label-width">
|
<div class="form-label-width">
|
||||||
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
||||||
<el-select
|
<el-select v-model="form.TrialSiteId" filterable style="width:100%;"
|
||||||
v-model="form.TrialSiteId"
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" @change="handleSiteChange">
|
||||||
filterable
|
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
|
||||||
style="width:100%;"
|
:value="item.TrialSiteId" />
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
|
|
||||||
@change="handleSiteChange"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="(item,index) of siteOptions"
|
|
||||||
:key="index"
|
|
||||||
:label="item.TrialSiteAliasName"
|
|
||||||
:value="item.TrialSiteId"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 中心编号 -->
|
<!-- 中心编号 -->
|
||||||
@@ -49,74 +40,149 @@
|
|||||||
<el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
<el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系电话 -->
|
<!-- 联系电话 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('trials:researchForm:form:contactorPhone')" prop="Phone">
|
||||||
:label="$t('trials:researchForm:form:contactorPhone')"
|
|
||||||
prop="Phone"
|
|
||||||
>
|
|
||||||
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系邮箱 -->
|
<!-- 联系邮箱 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')">
|
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="Email">
|
||||||
<el-input v-model="form.Email" disabled />
|
<el-input v-model="form.Email" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('trials:researchForm:form:CommonUploadRecordId')
|
||||||
|
" v-if="IsSupportUploadFile" class="file">
|
||||||
|
<el-input v-model="form.SiteSurveyFile.FileName" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }"
|
||||||
|
style="margin-right: 5px;" disabled />
|
||||||
|
<div class="upload" v-if="!(!(state === 0 && userTypeEnumInt === 0) || isHistory)">
|
||||||
|
<input accept=".pdf,.docx,.doc" type="file" name="uploadFolder" class="select-file" title=""
|
||||||
|
@change="beginScanFiles($event)" />
|
||||||
|
<div class="btn-select">
|
||||||
|
{{ $t('dictionary:template:basicData:button:selectFile') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <el-button type="primary" @click="viewManualFile"
|
||||||
|
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
|
||||||
|
$t('trials:researchForm:form:preview') }}</el-button> -->
|
||||||
|
<el-button type="primary" @click="downLoad"
|
||||||
|
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
|
||||||
|
$t('trials:researchForm:form:download') }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
<!-- 平均刻盘周期(天) -->
|
<!-- 平均刻盘周期(天) -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')" :label="$t('trials:researchForm:form:engravingCycle')">
|
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')"
|
||||||
<el-input-number v-model="form.AverageEngravingCycle" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0" style="width:100%;" />
|
:label="$t('trials:researchForm:form:engravingCycle')">
|
||||||
|
<el-input-number v-model="form.AverageEngravingCycle"
|
||||||
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0"
|
||||||
|
style="width:100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- MRI-PDFF 是否为本中心该适应症的常规诊疗检查项目? -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('IsRoutineMRIPDEE')"
|
||||||
|
:label="$t('trials:researchForm:form:IsRoutineMRIPDEE')" prop="IsRoutineMRIPDEE">
|
||||||
|
<el-radio-group v-model="form.IsRoutineMRIPDEE"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)">
|
||||||
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsRoutineMRIPDEE${item.value}`" :label="item.value">{{
|
||||||
|
item.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- MRI-PDFF 检查的检测周期(含单次检查时长、预约等待时长等) -->
|
||||||
|
<el-form-item
|
||||||
|
v-if="!notShowFieldList.includes('MRIPDFFScanTime') || !notShowFieldList.includes('MRIPDFFLeadTime') || !notShowFieldList.includes('MRIPDFFOther')"
|
||||||
|
:label="$t('trials:researchForm:form:IsMRIPDFF')">
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 单次检查时长(分钟) -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFScanTime')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFScanTime')">
|
||||||
|
<el-input-number v-model="form.MRIPDFFScanTime"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 平均预约等待时长(天) -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFLeadTime')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFLeadTime')">
|
||||||
|
<el-input-number v-model="form.MRIPDFFLeadTime"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" controls-position="right" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 特殊情况备注-->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFOther')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFOther')">
|
||||||
|
<el-input v-model="form.MRIPDFFOther" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 如已选择研究者评估,项目是否会授权影像科老师参与本试验?如不单独授权,是否可在试验中保持 1-2 名固定技师操作?-->
|
||||||
|
<el-form-item
|
||||||
|
v-if="!notShowFieldList.includes('IsAuthorizeRadiologistsParticipate') || !notShowFieldList.includes('AssignFixedTechnologists')"
|
||||||
|
:label="$t('trials:researchForm:form:IsAuthorize')" prop="IsAuthorize">
|
||||||
|
<el-radio-group v-model="form.IsAuthorize" :disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)"
|
||||||
|
@input="handleIsAuthorizeInput">
|
||||||
|
<el-radio label="IsAuthorizeRadiologistsParticipate">{{
|
||||||
|
$t('trials:researchForm:form:IsAuthorizeRadiologistsParticipate') }}</el-radio>
|
||||||
|
<el-radio label="AssignFixedTechnologists">{{
|
||||||
|
$t('trials:researchForm:form:AssignFixedTechnologists') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质(如:“技师证”,对应设备的“大型设备上岗证”) -->
|
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质(如:“技师证”,对应设备的“大型设备上岗证”) -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')" :label="$t('trials:researchForm:form:isQualified')">
|
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')"
|
||||||
<el-radio-group v-model="form.IsConfirmImagingTechnologist" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
:label="$t('trials:researchForm:form:isQualified')" prop="IsConfirmImagingTechnologist">
|
||||||
<el-radio
|
<el-radio-group v-model="form.IsConfirmImagingTechnologist"
|
||||||
v-for="item of $d.YesOrNo"
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
||||||
:key="`IsConfirmImagingTechnologist${item.value}`"
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsConfirmImagingTechnologist${item.value}`"
|
||||||
:label="item.value"
|
:label="item.value">{{ item.label }}</el-radio>
|
||||||
>{{ item.label }}</el-radio>
|
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 原因 -->
|
<!-- 原因 -->
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
|
v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
|
||||||
:label="$t('trials:researchForm:form:notQualifiedReason')"
|
:label="$t('trials:researchForm:form:notQualifiedReason')" prop="NotConfirmReson">
|
||||||
>
|
<el-input v-model="form.NotConfirmReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
<el-input
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
||||||
v-model="form.NotConfirmReson"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 研究单位疗效评估人员类型 -->
|
<!-- 研究单位疗效评估人员类型 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')" :label="$t('trials:researchForm:form:staffType')">
|
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')"
|
||||||
<el-radio-group v-model="form.EfficacyEvaluatorType" :disabled="!(state === 0 && userTypeEnumInt === 0)|| isHistory">
|
:label="$t('trials:researchForm:form:staffType')">
|
||||||
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`" :label="item.value">{{ item.label }}</el-radio>
|
<el-radio-group v-model="form.EfficacyEvaluatorType"
|
||||||
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
||||||
|
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`"
|
||||||
|
:label="item.value">{{ item.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
|
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')">
|
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')" prop="IsFollowStudyParameters">
|
||||||
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
|
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
|
||||||
<el-radio-group v-model="form.IsFollowStudyParameters" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
<el-radio-group v-model="form.IsFollowStudyParameters"
|
||||||
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{ item.label }}</el-radio>
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
||||||
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{
|
||||||
|
item.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
|
<el-button type="primary" size="small" style="margin-left: 5px;" @click="viewManual">
|
||||||
|
{{ $t('trials:researchForm:button:viewManual') }}
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
|
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
|
||||||
<el-form-item
|
<el-form-item v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
|
||||||
v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
|
prop="NotFollowReson">
|
||||||
>
|
|
||||||
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
|
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
|
||||||
<el-input
|
<el-input v-model="form.NotFollowReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
v-model="form.NotFollowReson"
|
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
||||||
type="textarea"
|
</el-form-item>
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
<!-- 是否严格按照影像手册参数完成刻盘 -->
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
|
<el-form-item v-if="!notShowFieldList.includes('ISStrictManualBurnFlag')" prop="ISStrictManualBurnFlag">
|
||||||
/>
|
<span slot="label" v-html="$t('trials:researchForm:form:ISStrictManualBurnFlag')" />
|
||||||
|
<el-radio-group v-model="form.ISStrictManualBurnFlag"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" style="margin-right: 10px;">
|
||||||
|
<el-radio v-for="item of $d.YesOrNo" :key="`ISStrictManualBurnFlag${item.value}`" :label="item.value">{{
|
||||||
|
item.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 不能严格按照影像手册参数完成刻盘原因 -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('NotStrictManualBurnFlagReason') && !form.ISStrictManualBurnFlag"
|
||||||
|
prop="NotStrictManualBurnFlagReason">
|
||||||
|
<span slot="label" v-html="$t('trials:researchForm:form:NotStrictManualBurnFlagReason')" />
|
||||||
|
<el-input v-model="form.NotStrictManualBurnFlagReason" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getTrialSiteSelect } from '@/api/trials'
|
import { getTrialSiteSelect, getTrialDocumentList, addOrUpdateCommonUploadRecord } from '@/api/trials'
|
||||||
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
|
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
|
||||||
export default {
|
export default {
|
||||||
name: 'ResearchBasicInfo',
|
name: 'ResearchBasicInfo',
|
||||||
@@ -124,7 +190,15 @@ export default {
|
|||||||
isHistory: {
|
isHistory: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
},
|
||||||
|
IsOnlyUploadFile: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
IsSupportUploadFile: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
var checkPhone = (rule, value, callback) => {
|
var checkPhone = (rule, value, callback) => {
|
||||||
@@ -156,16 +230,51 @@ export default {
|
|||||||
Phone: '', // 联系人电话
|
Phone: '', // 联系人电话
|
||||||
Email: '', // 联系人邮箱
|
Email: '', // 联系人邮箱
|
||||||
AverageEngravingCycle: '',
|
AverageEngravingCycle: '',
|
||||||
|
IsRoutineMRIPDEE: '',
|
||||||
|
MRIPDFFScanTime: '',
|
||||||
|
MRIPDFFLeadTime: '',
|
||||||
|
MRIPDFFOther: '',
|
||||||
|
IsAuthorize: '',
|
||||||
|
IsAuthorizeRadiologistsParticipate: '',
|
||||||
|
AssignFixedTechnologists: '',
|
||||||
|
ISStrictManualBurnFlag: '',
|
||||||
|
NotStrictManualBurnFlagReason: '',
|
||||||
IsConfirmImagingTechnologist: '',
|
IsConfirmImagingTechnologist: '',
|
||||||
NotConfirmReson: '',
|
NotConfirmReson: '',
|
||||||
EfficacyEvaluatorType: '',
|
EfficacyEvaluatorType: '',
|
||||||
IsFollowStudyParameters: '',
|
IsFollowStudyParameters: '',
|
||||||
NotFollowReson: ''
|
NotFollowReson: '',
|
||||||
|
CommonUploadRecordId: null,
|
||||||
|
SiteSurveyFile: []
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
TrialSiteId: [
|
TrialSiteId: [
|
||||||
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
],
|
],
|
||||||
|
IsRoutineMRIPDEE: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsAuthorize: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
ISStrictManualBurnFlag: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsFollowStudyParameters: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsConfirmImagingTechnologist: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotConfirmReson: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotFollowReson: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotStrictManualBurnFlagReason: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
UserName: [
|
UserName: [
|
||||||
{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: 'blur' },
|
{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: 'blur' },
|
||||||
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: ['blur', 'change'] }
|
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: ['blur', 'change'] }
|
||||||
@@ -186,14 +295,173 @@ export default {
|
|||||||
state: null,
|
state: null,
|
||||||
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
||||||
isShow: false,
|
isShow: false,
|
||||||
notShowFieldList: []
|
notShowFieldList: [],
|
||||||
|
perview_visible: false,
|
||||||
|
ExternalList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async beginScanFiles(e) {
|
||||||
|
try {
|
||||||
|
let file = e.target.files[0]
|
||||||
|
let name = file.name
|
||||||
|
if (!this.checkFileSuffix(name)) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:checkFileSuffix"))
|
||||||
|
this.loading = true
|
||||||
|
file = await this.fileToBlob(file)
|
||||||
|
let scope = this
|
||||||
|
var index = name.lastIndexOf('.')
|
||||||
|
var type = name.substring(index + 1, name.length)
|
||||||
|
let res = await this.OSSclient.put(
|
||||||
|
`/${this.$route.query.trialId}/InspectionUpload/SiteSurvey/${this.form.TrialSiteId}/${scope.getGuid(Date.now() + '_' + name.split('.')[0])}.${type}`,
|
||||||
|
file
|
||||||
|
)
|
||||||
|
let data = {
|
||||||
|
Path: this.$getObjectName(res.url),
|
||||||
|
FileName: name,
|
||||||
|
FileSize: file.size,
|
||||||
|
FileType: type
|
||||||
|
|
||||||
|
}
|
||||||
|
res = await addOrUpdateCommonUploadRecord(data)
|
||||||
|
this.loading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.form.CommonUploadRecordId = res.Result
|
||||||
|
data.Id = res.Result
|
||||||
|
this.form.SiteSurveyFile = data
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkFileSuffix(fileName) {
|
||||||
|
var index = fileName.lastIndexOf('.')
|
||||||
|
var suffix = fileName.substring(index + 1, fileName.length)
|
||||||
|
if ('.pdf'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.docx'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.doc'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleIsAuthorizeInput(label) {
|
||||||
|
this.form.IsAuthorizeRadiologistsParticipate = false
|
||||||
|
this.form.AssignFixedTechnologists = false
|
||||||
|
this.form[label] = true
|
||||||
|
},
|
||||||
|
async viewManualFile() {
|
||||||
|
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
|
||||||
|
this.$preview({
|
||||||
|
path: this.form.SiteSurveyFile.Path,
|
||||||
|
type: this.form.SiteSurveyFile.FileType,
|
||||||
|
title: this.form.SiteSurveyFile.Path.FileName,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async downLoad() {
|
||||||
|
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
|
||||||
|
let link = document.createElement('a')
|
||||||
|
link.href = this.OSSclientConfig.basePath + this.form.SiteSurveyFile.Path;
|
||||||
|
link.target = '_blank'
|
||||||
|
link.download = this.form.SiteSurveyFile.FileName
|
||||||
|
link.style.display = 'none'
|
||||||
|
document.body.append(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
link = null
|
||||||
|
},
|
||||||
|
async viewManual() {
|
||||||
|
try {
|
||||||
|
let data = {
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 20,
|
||||||
|
TrialId: this.$route.query.trialId,
|
||||||
|
IsPublish: true,
|
||||||
|
FileTypeCode: 4,
|
||||||
|
IsDeleted: false
|
||||||
|
}
|
||||||
|
let res = await getTrialDocumentList(data)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
const { CurrentPageData } = res.Result
|
||||||
|
if (CurrentPageData.length <= 0) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:noImageManual"))
|
||||||
|
this.ExternalList = []
|
||||||
|
CurrentPageData.forEach(item => {
|
||||||
|
let obj = {
|
||||||
|
FilePath: item.Path,
|
||||||
|
FileFormat: 'pdf',
|
||||||
|
Name: item.Name
|
||||||
|
}
|
||||||
|
this.ExternalList.push(obj)
|
||||||
|
});
|
||||||
|
// this.perview_visible = true
|
||||||
|
this.ExternalList.forEach(item => {
|
||||||
|
let link = document.createElement('a')
|
||||||
|
link.href = this.OSSclientConfig.basePath + item.FilePath;
|
||||||
|
link.target = '_blank'
|
||||||
|
link.download = item.Name
|
||||||
|
link.style.display = 'none'
|
||||||
|
document.body.append(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
link = null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
// 保存基本信息
|
// 保存基本信息
|
||||||
handleSave(isAutoCommit) {
|
handleSave(isAutoCommit, isCheck = false) {
|
||||||
return new Promise(async(resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
|
isCheck = false
|
||||||
try {
|
try {
|
||||||
|
if (this.IsOnlyUploadFile && !isCheck) {
|
||||||
|
if (!this.form.UserName) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notUserName"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
if (!this.form.Phone) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notPhone"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
if (!this.form.CommonUploadRecordId) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notCommonUploadRecordId"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
this.btnLoading = true
|
||||||
|
const param = {
|
||||||
|
id: this.form.Id,
|
||||||
|
trialId: this.$route.query.trialId,
|
||||||
|
trialSiteId: this.form.TrialSiteId,
|
||||||
|
userName: this.form.UserName,
|
||||||
|
phone: this.form.Phone,
|
||||||
|
email: this.form.Email,
|
||||||
|
averageEngravingCycle: this.form.AverageEngravingCycle,
|
||||||
|
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
|
||||||
|
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
|
||||||
|
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
|
||||||
|
MRIPDFFOther: this.form.MRIPDFFOther,
|
||||||
|
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
|
||||||
|
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
|
||||||
|
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
|
||||||
|
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
|
||||||
|
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
||||||
|
notConfirmReson: this.form.NotConfirmReson,
|
||||||
|
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
||||||
|
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
||||||
|
notFollowReson: this.form.NotFollowReson,
|
||||||
|
CommonUploadRecordId: this.form.CommonUploadRecordId
|
||||||
|
}
|
||||||
|
addOrUpdateTrialSiteSurvey(param).then(res => {
|
||||||
|
this.btnLoading = false
|
||||||
|
if (res.IsSuccess && !isAutoCommit) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
resolve(true)
|
||||||
|
}).catch(() => {
|
||||||
|
this.btnLoading = false
|
||||||
|
reject(false)
|
||||||
|
})
|
||||||
|
return resolve(true)
|
||||||
|
}
|
||||||
const valid = await this.$refs['researchBSForm'].validate()
|
const valid = await this.$refs['researchBSForm'].validate()
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
@@ -205,11 +473,20 @@ export default {
|
|||||||
phone: this.form.Phone,
|
phone: this.form.Phone,
|
||||||
email: this.form.Email,
|
email: this.form.Email,
|
||||||
averageEngravingCycle: this.form.AverageEngravingCycle,
|
averageEngravingCycle: this.form.AverageEngravingCycle,
|
||||||
|
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
|
||||||
|
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
|
||||||
|
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
|
||||||
|
MRIPDFFOther: this.form.MRIPDFFOther,
|
||||||
|
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
|
||||||
|
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
|
||||||
|
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
|
||||||
|
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
|
||||||
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
||||||
notConfirmReson: this.form.NotConfirmReson,
|
notConfirmReson: this.form.NotConfirmReson,
|
||||||
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
||||||
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
||||||
notFollowReson: this.form.NotFollowReson
|
notFollowReson: this.form.NotFollowReson,
|
||||||
|
CommonUploadRecordId: this.form.CommonUploadRecordId
|
||||||
}
|
}
|
||||||
const res = await addOrUpdateTrialSiteSurvey(param)
|
const res = await addOrUpdateTrialSiteSurvey(param)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -232,7 +509,7 @@ export default {
|
|||||||
// 初始化
|
// 初始化
|
||||||
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
|
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
|
||||||
// 获取项目下的site
|
// 获取项目下的site
|
||||||
const { Result } = await getTrialSiteSelect(this.$route.query.trialId)
|
const { Result } = await getTrialSiteSelect(this.$route.query.trialId, { IgnoreDisable: true })
|
||||||
this.siteOptions = Result
|
this.siteOptions = Result
|
||||||
this.form.Id = trialSiteSurvey.Id
|
this.form.Id = trialSiteSurvey.Id
|
||||||
this.form.Sponsor = trialInfo.Sponsor // 申办方
|
this.form.Sponsor = trialInfo.Sponsor // 申办方
|
||||||
@@ -246,7 +523,20 @@ export default {
|
|||||||
this.form.UserName = trialSiteSurvey.UserName // 联系人
|
this.form.UserName = trialSiteSurvey.UserName // 联系人
|
||||||
this.form.Phone = trialSiteSurvey.Phone // 联系人电话
|
this.form.Phone = trialSiteSurvey.Phone // 联系人电话
|
||||||
this.form.Email = trialSiteSurvey.Email // 联系人邮箱
|
this.form.Email = trialSiteSurvey.Email // 联系人邮箱
|
||||||
|
this.form.CommonUploadRecordId = trialSiteSurvey.CommonUploadRecordId
|
||||||
|
this.form.SiteSurveyFile = trialSiteSurvey.SiteSurveyFile || {}
|
||||||
|
this.form.fileStr = this.form.SiteSurveyFile.FileName
|
||||||
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
|
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
|
||||||
|
this.form.IsRoutineMRIPDEE = trialSiteSurvey.IsRoutineMRIPDEE
|
||||||
|
this.form.MRIPDFFScanTime = trialSiteSurvey.MRIPDFFScanTime
|
||||||
|
this.form.MRIPDFFLeadTime = trialSiteSurvey.MRIPDFFLeadTime
|
||||||
|
this.form.MRIPDFFOther = trialSiteSurvey.MRIPDFFOther
|
||||||
|
this.form.IsAuthorizeRadiologistsParticipate = trialSiteSurvey.IsAuthorizeRadiologistsParticipate
|
||||||
|
this.form.AssignFixedTechnologists = trialSiteSurvey.AssignFixedTechnologists
|
||||||
|
if (this.form.IsAuthorizeRadiologistsParticipate) this.form.IsAuthorize = 'IsAuthorizeRadiologistsParticipate'
|
||||||
|
if (this.form.AssignFixedTechnologists) this.form.IsAuthorize = 'AssignFixedTechnologists'
|
||||||
|
this.form.ISStrictManualBurnFlag = trialSiteSurvey.ISStrictManualBurnFlag
|
||||||
|
this.form.NotStrictManualBurnFlagReason = trialSiteSurvey.NotStrictManualBurnFlagReason
|
||||||
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
|
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
|
||||||
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
|
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
|
||||||
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
|
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
|
||||||
@@ -267,51 +557,109 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.research_bs_content{
|
.research_bs_content {
|
||||||
|
|
||||||
.basic_content{
|
.basic_content {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
}
|
}
|
||||||
.login_content{
|
|
||||||
|
.login_content {
|
||||||
padding: 5px 20px;
|
padding: 5px 20px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
::v-deep.el-form-item {
|
|
||||||
|
::v-deep .el-form-item {
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.code_content{
|
|
||||||
display:flex;
|
.code_content {
|
||||||
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
.el-input{
|
|
||||||
|
.el-input {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.form-label-width{
|
|
||||||
::v-deep.el-form-item__label{
|
.form-label-width {
|
||||||
|
::v-deep .el-form-item__label {
|
||||||
width: 140px;
|
width: 140px;
|
||||||
}
|
}
|
||||||
::v-deep.el-form-item__content{
|
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
margin-left: 140px;
|
margin-left: 140px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.submit_content{
|
|
||||||
|
.submit_content {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep.el-form-item {
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
border-bottom: 1px solid #f5f7fa;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
.el-form-item__content{
|
|
||||||
|
.el-form-item__content {
|
||||||
color: #82848a;
|
color: #82848a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upload {
|
||||||
|
display: inline-block;
|
||||||
|
height: 36px;
|
||||||
|
width: 90px;
|
||||||
|
padding: 0 10px;
|
||||||
|
line-height: 23px;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
background: #428bca;
|
||||||
|
border-color: #428bca;
|
||||||
|
color: #fff;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
.select-file {
|
||||||
|
height: 36px;
|
||||||
|
width: 90px;
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
opacity: 0;
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-select {
|
||||||
|
//给显示在页面上的按钮写样式
|
||||||
|
// width: 70px;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 10px;
|
||||||
|
pointer-events: none; //pointer-events:none用来控制该标签的点击穿透事件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file {
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,59 +1,107 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div v-loading="loading" class="equipment_form_content">
|
||||||
v-loading="loading"
|
<el-form ref="equipmentForm" :model="form" :rules="rules" label-position="left">
|
||||||
class="equipment_form_content"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="equipmentForm"
|
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
label-position="left"
|
|
||||||
>
|
|
||||||
<!-- 扫描设备 -->
|
<!-- 扫描设备 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeId">
|
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeEnum"
|
||||||
<el-select
|
v-if="EquipmentControlFieldList.includes('EquipmentTypeEnum')">
|
||||||
v-model="form.EquipmentTypeId"
|
<div style="display: flex;align-items: center;">
|
||||||
style="width:100%"
|
<el-select v-model="form.EquipmentTypeEnum" style="width:100%" @change="form.OtherEquipmentType = null">
|
||||||
>
|
<el-option v-for="item of $d.SiteSurvey_ScanEquipmentType" :key="item.id" :label="item.label"
|
||||||
<el-option
|
:value="item.value" />
|
||||||
v-for="item of $d.SiteSurvey_ScanEquipmentType"
|
</el-select>
|
||||||
:key="item.id"
|
<el-input placeholder="" v-model="form.OtherEquipmentType" style="margin-left: 10px;"
|
||||||
:label="item.label"
|
v-if="form.EquipmentTypeEnum == '-1'" clearable>
|
||||||
:value="item.id"
|
</el-input>
|
||||||
/>
|
</div>
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描参数 -->
|
<!-- 扫描参数 -->
|
||||||
<el-form-item v-if="isShowParameters" :label="$t('trials:equiptResearch:form:param')">
|
<el-form-item :label="$t('trials:equiptResearch:form:param')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('Parameters')" prop="Parameters">
|
||||||
<el-input v-model="form.Parameters" />
|
<el-input v-model="form.Parameters" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描仪器制造商名称 -->
|
<!-- 扫描仪器制造商名称 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')">
|
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')"
|
||||||
<el-input v-model="form.ManufacturerName" />
|
v-if="EquipmentControlFieldList.includes('ManufacturerType')" prop="ManufacturerType">
|
||||||
|
<div style="display: flex;align-items: center;">
|
||||||
|
<el-select v-model="form.ManufacturerType" style="width:100%" @change="form.ManufacturerName = null">
|
||||||
|
<el-option v-for="item of $d.ManufacturerType" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
<el-input placeholder="" v-model="form.ManufacturerName" style="margin-left: 10px;"
|
||||||
|
v-if="form.ManufacturerType == '-1'" clearable>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描仪型号 -->
|
<!-- 扫描仪型号 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:model')">
|
<el-form-item :label="$t('trials:equiptResearch:form:model')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('ScannerType')" prop="ScannerType">
|
||||||
<el-input v-model="form.ScannerType" />
|
<el-input v-model="form.ScannerType" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- 磁场强度 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:MagneticFieldStrengthType')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('MagneticFieldStrengthType')" prop="MagneticFieldStrengthType">
|
||||||
|
<el-select v-model="form.MagneticFieldStrengthType" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.MagneticFieldStrengthType" :key="item.id" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 体部线圈通道数 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:BodyCoilChannelCount')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('BodyCoilChannelCount')" prop="BodyCoilChannelCount">
|
||||||
|
<el-select v-model="form.BodyCoilChannelCount" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.BodyCoilChannelCount" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否具备专用的PDFF脂肪定量序列(CSE-MRI序列) -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:HasDedicatedPdfFatQuantificationSequence')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('HasDedicatedPdfFatQuantificationSequence')"
|
||||||
|
prop="HasDedicatedPdfFatQuantificationSequence">
|
||||||
|
<el-select v-model="form.HasDedicatedPdfFatQuantificationSequence" style="width:100%"
|
||||||
|
@change="form.PdfFatQuantificationSequenceType = null, form.OtherSequenceSpecification = null">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- PDFF脂肪定量序列 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:PdfFatQuantificationSequenceType')"
|
||||||
|
prop="PdfFatQuantificationSequenceType"
|
||||||
|
v-if="form.HasDedicatedPdfFatQuantificationSequence && EquipmentControlFieldList.includes('PdfFatQuantificationSequenceType')">
|
||||||
|
<div style="display: flex;align-items: center;">
|
||||||
|
<el-select v-model="form.PdfFatQuantificationSequenceType" style="width:100%"
|
||||||
|
@change="form.OtherSequenceSpecification = null">
|
||||||
|
<el-option v-for="item of $d.PdfFatQuantificationSequenceType" :key="item.id" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
<el-input placeholder="" v-model="form.OtherSequenceSpecification" style="margin-left: 10px;"
|
||||||
|
v-if="form.PdfFatQuantificationSequenceType == '-1'" clearable>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否包含 T2/R2 校正(用于铁沉积校正) -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:HasT2R2Correction')" prop="HasT2R2Correction"
|
||||||
|
v-if="EquipmentControlFieldList.includes('HasT2R2Correction')">
|
||||||
|
<el-select v-model="form.HasT2R2Correction" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否可完整导出 PDFF 参数图及全部原始 DICOM 数据 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:CanFullyExportPdfParameterMapsAndRawDicom')"
|
||||||
|
prop="CanFullyExportPdfParameterMapsAndRawDicom"
|
||||||
|
v-if="EquipmentControlFieldList.includes('CanFullyExportPdfParameterMapsAndRawDicom')">
|
||||||
|
<el-select v-model="form.CanFullyExportPdfParameterMapsAndRawDicom" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:remark')">
|
<el-form-item :label="$t('trials:equiptResearch:form:remark')" prop="Note"
|
||||||
|
v-if="EquipmentControlFieldList.includes('Note')">
|
||||||
<el-input v-model="form.Note" />
|
<el-input v-model="form.Note" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div style="text-align: center;padding:20px 0px;">
|
<div style="text-align: center;padding:20px 0px;">
|
||||||
<!-- 取消 -->
|
<!-- 取消 -->
|
||||||
<el-button
|
<el-button size="large" type="primary" @click="handleCancel">
|
||||||
size="large"
|
|
||||||
type="primary"
|
|
||||||
@click="handleCancel"
|
|
||||||
>
|
|
||||||
{{ $t("common:button:cancel") }}
|
{{ $t("common:button:cancel") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 保存 -->
|
<!-- 保存 -->
|
||||||
<el-button
|
<el-button size="large" type="primary" @click="handleSave">
|
||||||
size="large"
|
|
||||||
type="primary"
|
|
||||||
@click="handleSave"
|
|
||||||
>
|
|
||||||
{{ $t("common:button:save") }}
|
{{ $t("common:button:save") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,29 +124,96 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
isShowParameters: {
|
EquipmentControlFieldList: {
|
||||||
type: Boolean,
|
type: Array,
|
||||||
default: false
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
Id: '',
|
Id: '',
|
||||||
EquipmentTypeId: '',
|
EquipmentTypeEnum: null,
|
||||||
Parameters: '',
|
OtherEquipmentType: null,
|
||||||
ManufacturerName: '',
|
Parameters: null,
|
||||||
ScannerType: '',
|
Note: null,
|
||||||
Note: '',
|
ManufacturerType: null,
|
||||||
|
ManufacturerName: null,
|
||||||
|
ScannerType: null,
|
||||||
|
MagneticFieldStrengthType: null,
|
||||||
|
BodyCoilChannelCount: null,
|
||||||
|
HasDedicatedPdfFatQuantificationSequence: null,
|
||||||
|
PdfFatQuantificationSequenceType: null,
|
||||||
|
OtherSequenceSpecification: null,
|
||||||
|
HasT2R2Correction: null,
|
||||||
|
CanFullyExportPdfParameterMapsAndRawDicom: null,
|
||||||
TrialSiteSurveyId: ''
|
TrialSiteSurveyId: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
EquipmentTypeId: [
|
EquipmentTypeEnum: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.EquipmentTypeEnum === -1 && !this.form.OtherEquipmentType) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Parameters: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
// Note: [
|
||||||
|
// { required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
// ],
|
||||||
|
ManufacturerType: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.ManufacturerType === -1 && !this.form.ManufacturerName) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
ScannerType: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
MagneticFieldStrengthType: [
|
||||||
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
]
|
],
|
||||||
|
BodyCoilChannelCount: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
HasDedicatedPdfFatQuantificationSequence: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
PdfFatQuantificationSequenceType: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.PdfFatQuantificationSequenceType === -1 && !this.form.OtherSequenceSpecification) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
HasT2R2Correction: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
CanFullyExportPdfParameterMapsAndRawDicom: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
},
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
dictionaryList: {}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -154,13 +269,15 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.equipment_form_content{
|
.equipment_form_content {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
::v-deep.el-form-item {
|
|
||||||
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding: 5px 0 20px 0;
|
padding: 5px 0 20px 0;
|
||||||
border-bottom: 1px solid #f5f7fa;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
.el-form-item__content{
|
|
||||||
|
.el-form-item__content {
|
||||||
color: #82848a;
|
color: #82848a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,18 +13,22 @@
|
|||||||
<i class="el-icon-receiving" />
|
<i class="el-icon-receiving" />
|
||||||
</div>
|
</div>
|
||||||
<div class="p_info">
|
<div class="p_info">
|
||||||
<div
|
<div class="p_info_basic" :style="{
|
||||||
class="p_info_basic"
|
maxWidth: w + 'px', 'white-space': 'nowrap',
|
||||||
:style="{maxWidth:w+'px','white-space': 'nowrap',
|
overflow: 'hidden',
|
||||||
overflow: 'hidden',
|
'text-overflow': 'ellipsis'
|
||||||
'text-overflow': 'ellipsis'}"
|
}">
|
||||||
>
|
<div class="p_text" v-if="EquipmentControlFieldList.includes('EquipmentTypeEnum')">
|
||||||
<div class="p_text">{{ item.EquipmentType }}</div>
|
{{ item.OtherEquipmentType ? item.OtherEquipmentType :
|
||||||
<div v-if="isShowParameters" class="p_text" style="margin-left:10px">{{ item.Parameters }}</div>
|
$fd('SiteSurvey_ScanEquipmentType', item.EquipmentTypeEnum) }}</div>
|
||||||
<div class="p_text" style="margin-left:10px">{{ item.ManufacturerName }}</div>
|
<div v-if="EquipmentControlFieldList.includes('Parameters')" class="p_text" style="margin-left:10px">{{
|
||||||
|
item.Parameters }}</div>
|
||||||
|
<div class="p_text" style="margin-left:10px" v-if="EquipmentControlFieldList.includes('ManufacturerType')">{{
|
||||||
|
item.ManufacturerName ? item.ManufacturerName : $fd('ManufacturerType',
|
||||||
|
item.ManufacturerType) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p_text">{{ item.ScannerType }}</div>
|
<div class="p_text" v-if="EquipmentControlFieldList.includes('ScannerType')">{{ item.ScannerType }}</div>
|
||||||
<div class="p_text">{{ item.Note }}</div>
|
<div class="p_text" v-if="EquipmentControlFieldList.includes('Note')">{{ item.Note }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="state === 0 && userTypeEnumInt === 0 && !isHistory" class="p_func">
|
<div v-if="state === 0 && userTypeEnumInt === 0 && !isHistory" class="p_func">
|
||||||
<el-button type="text" @click="handleEdit(item)">
|
<el-button type="text" @click="handleEdit(item)">
|
||||||
@@ -36,19 +40,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 添加/编辑设备信息 -->
|
<!-- 添加/编辑设备信息 -->
|
||||||
<el-drawer
|
<el-drawer :title="title" :visible.sync="formVisible" direction="btt" size="70%">
|
||||||
:title="title"
|
<EquipmentForm v-if="formVisible" :equipment-info="equipmentInfo"
|
||||||
:visible.sync="formVisible"
|
:EquipmentControlFieldList="EquipmentControlFieldList" @getList="getList" @close="close" />
|
||||||
direction="btt"
|
|
||||||
size="70%"
|
|
||||||
>
|
|
||||||
<EquipmentForm
|
|
||||||
v-if="formVisible"
|
|
||||||
:equipment-info="equipmentInfo"
|
|
||||||
:is-show-parameters="isShowParameters"
|
|
||||||
@getList="getList"
|
|
||||||
@close="close"
|
|
||||||
/>
|
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -81,7 +75,7 @@ export default {
|
|||||||
state: null,
|
state: null,
|
||||||
trialSiteSurveyId: '',
|
trialSiteSurveyId: '',
|
||||||
trialId: '',
|
trialId: '',
|
||||||
isShowParameters: false
|
EquipmentControlFieldList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -142,8 +136,11 @@ export default {
|
|||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initList(TrialSiteEquipmentSurveyList, trialSiteSurvey, isShowParameters) {
|
initList(TrialSiteEquipmentSurveyList, trialSiteSurvey, EquipmentControlFieldList) {
|
||||||
this.isShowParameters = isShowParameters
|
this.EquipmentControlFieldList = []
|
||||||
|
EquipmentControlFieldList.forEach(item => {
|
||||||
|
this.EquipmentControlFieldList.push(item.FiledName)
|
||||||
|
})
|
||||||
this.list = TrialSiteEquipmentSurveyList
|
this.list = TrialSiteEquipmentSurveyList
|
||||||
this.state = trialSiteSurvey.State
|
this.state = trialSiteSurvey.State
|
||||||
this.$forceUpdate()
|
this.$forceUpdate()
|
||||||
@@ -157,63 +154,70 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.equipments_content{
|
.equipments_content {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
.title{
|
|
||||||
|
.title {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.equipment_info{
|
|
||||||
|
.equipment_info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-top: 1px solid #f5f7fa;
|
border-top: 1px solid #f5f7fa;
|
||||||
.p_icon{
|
|
||||||
|
.p_icon {
|
||||||
width: 70px;
|
width: 70px;
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.p_info{
|
|
||||||
|
.p_info {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex:1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
// border-right: 1px solid #f5f7fa;
|
// border-right: 1px solid #f5f7fa;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p_info:after {
|
.p_info:after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
.p_info_basic{
|
|
||||||
|
.p_info_basic {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
.p_text{
|
|
||||||
|
.p_text {
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
color: #82848a;
|
color: #82848a;
|
||||||
}
|
}
|
||||||
.p_func{
|
|
||||||
|
.p_func {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.participants_form_content{
|
.participants_form_content{
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
::v-deep.el-form-item {
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding: 5px 0 20px 0;
|
padding: 5px 0 20px 0;
|
||||||
border-bottom: 1px solid #f5f7fa;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ export default {
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.participants_form_content{
|
.participants_form_content{
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
::v-deep.el-form-item {
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding: 5px 0 20px 0;
|
padding: 5px 0 20px 0;
|
||||||
border-bottom: 1px solid #f5f7fa;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
|
|||||||
@@ -4,30 +4,22 @@
|
|||||||
<div class="d_content">
|
<div class="d_content">
|
||||||
|
|
||||||
<!-- 项目基本信息 -->
|
<!-- 项目基本信息 -->
|
||||||
<BasicInfo ref="basicInfo" />
|
<BasicInfo ref="basicInfo" :IsOnlyUploadFile="IsOnlyUploadFile" :IsSupportUploadFile="IsSupportUploadFile" />
|
||||||
<!-- 历史人员 -->
|
<!-- 历史人员 -->
|
||||||
<HistoricalParticipants ref="historicalParticipant" class="mt5" />
|
<HistoricalParticipants ref="historicalParticipant" class="mt5" />
|
||||||
<!-- 新增人员 -->
|
<!-- 新增人员 -->
|
||||||
<Participants ref="participants" class="mt5" />
|
<Participants ref="participants" class="mt5" />
|
||||||
<!-- 设备调研 -->
|
<!-- 设备调研 -->
|
||||||
<Equipments ref="equipments" class="mt5" />
|
<Equipments ref="equipments" class="mt5" v-if="!siteSurveyNoteInfo.IsCloseEquipmentSurvey" />
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
<Notes ref="notes" class="mt5" />
|
<Notes ref="notes" class="mt5" />
|
||||||
</div>
|
</div>
|
||||||
<div class="d_footer">
|
<div class="d_footer">
|
||||||
<div class="d_func_row">
|
<div class="d_func_row">
|
||||||
<div
|
<div v-if="state === 0 && userTypeEnumInt === 0" class="d_func" @click="handleSave">
|
||||||
v-if="state === 0 && userTypeEnumInt === 0"
|
|
||||||
class="d_func"
|
|
||||||
@click="handleSave"
|
|
||||||
>
|
|
||||||
{{ $t('common:button:save') }}
|
{{ $t('common:button:save') }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="(state === 0 && userTypeEnumInt === 0)" class="d_func" @click="handleSubmit('submit')">
|
||||||
v-if="(state === 0 && userTypeEnumInt === 0)"
|
|
||||||
class="d_func"
|
|
||||||
@click="handleSubmit('submit')"
|
|
||||||
>
|
|
||||||
{{ $t('trials:researchForm:button:submit') }}
|
{{ $t('trials:researchForm:button:submit') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,7 +50,9 @@ export default {
|
|||||||
userTypeEnumInt: 0,
|
userTypeEnumInt: 0,
|
||||||
rejectVisible: false,
|
rejectVisible: false,
|
||||||
rejectForm: { reason: '' },
|
rejectForm: { reason: '' },
|
||||||
siteSurveyNoteInfo: null
|
siteSurveyNoteInfo: {},
|
||||||
|
IsSupportUploadFile: false,
|
||||||
|
IsOnlyUploadFile: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -78,6 +72,9 @@ export default {
|
|||||||
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
|
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
|
||||||
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
|
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
|
||||||
}
|
}
|
||||||
|
this.IsSupportUploadFile = res.Result.SiteSurveyFiledConfig.IsSupportUploadFile
|
||||||
|
this.IsOnlyUploadFile = res.Result.SiteSurveyFiledConfig.IsOnlyUploadFile
|
||||||
|
this.siteSurveyNoteInfo.IsCloseEquipmentSurvey = res.Result.SiteSurveyFiledConfig.IsCloseEquipmentSurvey
|
||||||
this.state = res.Result.TrialSiteSurvey.State
|
this.state = res.Result.TrialSiteSurvey.State
|
||||||
this.$refs['basicInfo'].initForm(res.Result.TrialInfo, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig ? res.Result.SiteSurveyFiledConfig.NotShowFieldList : null)
|
this.$refs['basicInfo'].initForm(res.Result.TrialInfo, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig ? res.Result.SiteSurveyFiledConfig.NotShowFieldList : null)
|
||||||
var historicalArr = []
|
var historicalArr = []
|
||||||
@@ -92,7 +89,7 @@ export default {
|
|||||||
|
|
||||||
this.$refs['historicalParticipant'].initList(historicalArr, res.Result.TrialSiteSurvey)
|
this.$refs['historicalParticipant'].initList(historicalArr, res.Result.TrialSiteSurvey)
|
||||||
this.$refs['participants'].initList(newArr, res.Result.TrialSiteSurvey)
|
this.$refs['participants'].initList(newArr, res.Result.TrialSiteSurvey)
|
||||||
this.$refs['equipments'].initList(res.Result.TrialSiteEquipmentSurveyList, res.Result.TrialSiteSurvey, !(res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0))
|
this.$refs['equipments'].initList(res.Result.TrialSiteEquipmentSurveyList, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig.EquipmentControlFieldList)
|
||||||
this.$refs['notes'].initPage(this.siteSurveyNoteInfo)
|
this.$refs['notes'].initPage(this.siteSurveyNoteInfo)
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -129,7 +126,8 @@ export default {
|
|||||||
this.userTypeEnumInt === 0 ? this.$t('trials:researchForm:message:submitWarning') : this.$t('trials:researchForm:message:submitWarning2'),
|
this.userTypeEnumInt === 0 ? this.$t('trials:researchForm:message:submitWarning') : this.$t('trials:researchForm:message:submitWarning2'),
|
||||||
{
|
{
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
distinguishCancelAndClose: true
|
distinguishCancelAndClose: true,
|
||||||
|
customClass: "mobile_confirm"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (confirm !== 'confirm') return
|
if (confirm !== 'confirm') return
|
||||||
@@ -160,9 +158,10 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.research_detal_wrapper{
|
.research_detal_wrapper {
|
||||||
background-color:#f5f7fa;
|
background-color: #f5f7fa;
|
||||||
.d_title{
|
|
||||||
|
.d_title {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
line-height: 80px;
|
line-height: 80px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
@@ -173,10 +172,11 @@ export default {
|
|||||||
top: 0;
|
top: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .d_content{
|
// .d_content{
|
||||||
|
|
||||||
// }
|
// }
|
||||||
.d_footer{
|
.d_footer {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
@@ -185,12 +185,14 @@ export default {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
// padding: 20px;
|
// padding: 20px;
|
||||||
}
|
}
|
||||||
.d_func_row{
|
|
||||||
|
.d_func_row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.d_func{
|
|
||||||
|
.d_func {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -207,15 +209,16 @@ export default {
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover{
|
|
||||||
|
&:hover {
|
||||||
background: #68a2d5;
|
background: #68a2d5;
|
||||||
border-color: #68a2d5;
|
border-color: #68a2d5;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.mt5{
|
|
||||||
|
.mt5 {
|
||||||
margin-top: 5px
|
margin-top: 5px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,131 +1,88 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="research_login_m_content">
|
<div class="research_login_m_content">
|
||||||
<div class="title">{{ $t('trials:researchForm:title:question') }}</div>
|
<div v-if="IsExpired"></div>
|
||||||
<el-form
|
<div v-else-if="verify" class="LinkVerificationCode_content">
|
||||||
ref="loginForm"
|
<el-form ref="codeForm" v-loading="loading" label-position="top" label-width="120px" :model="codeForm"
|
||||||
v-loading="loading"
|
:rules="code_rules">
|
||||||
label-position="left"
|
<div class="basic_content">
|
||||||
label-width="120px"
|
<!-- 项目编号 -->
|
||||||
:model="form"
|
<el-form-item :label="$t('trials:researchForm:message:LinkVerificationCode')" prop="LinkVerificationCode">
|
||||||
:rules="rules"
|
<el-input v-model="codeForm.LinkVerificationCode" autocomplete="new-password" />
|
||||||
>
|
</el-form-item>
|
||||||
<div class="basic_content">
|
</div>
|
||||||
<!-- 项目编号 -->
|
</el-form>
|
||||||
<el-form-item
|
<div class="submit_content">
|
||||||
:label="$t('trials:researchForm:form:trialId')"
|
<el-button size="large" type="primary" @click="getLinkVerificationCodeIsEffective">
|
||||||
>
|
{{ $t('common:button:submit') }}
|
||||||
<span>{{ form.TrialCode }}</span>
|
</el-button>
|
||||||
</el-form-item>
|
|
||||||
<!-- 试验方案号 -->
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:researchForm:form:researchNo')"
|
|
||||||
>
|
|
||||||
<span>{{ form.ResearchProgramNo }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 试验名称 -->
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:researchForm:form:researchName')"
|
|
||||||
>
|
|
||||||
<span>{{ form.ExperimentName }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 适应症类型 -->
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:researchForm:form:decleareType')"
|
|
||||||
>
|
|
||||||
<span>{{ form.IndicationType }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="login_content">
|
</div>
|
||||||
<el-form-item
|
<template v-else>
|
||||||
:label="$t('trials:researchForm:form:siteName')"
|
<div class="title">{{ $t('trials:researchForm:title:question') }}</div>
|
||||||
prop="TrialSiteId"
|
<el-form ref="loginForm" v-loading="loading" label-position="left" label-width="120px" :model="form"
|
||||||
>
|
:rules="rules">
|
||||||
<el-select
|
<div class="basic_content">
|
||||||
v-model="form.TrialSiteId"
|
<!-- 项目编号 -->
|
||||||
filterable
|
<el-form-item :label="$t('trials:researchForm:form:trialId')">
|
||||||
style="width:100%;"
|
<span>{{ form.TrialCode }}</span>
|
||||||
@change="handleSiteChange"
|
</el-form-item>
|
||||||
>
|
<!-- 试验方案号 -->
|
||||||
<el-option
|
<el-form-item :label="$t('trials:researchForm:form:researchNo')">
|
||||||
v-for="(item,index) of siteOptions"
|
<span>{{ form.ResearchProgramNo }}</span>
|
||||||
:key="index"
|
</el-form-item>
|
||||||
:label="item.TrialSiteAliasName"
|
<!-- 试验名称 -->
|
||||||
:value="item.TrialSiteId"
|
<el-form-item :label="$t('trials:researchForm:form:researchName')">
|
||||||
/>
|
<span>{{ form.ExperimentName }}</span>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
<!-- 适应症类型 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('trials:researchForm:form:decleareType')">
|
||||||
v-if="form.TrialSiteId && isHaveSiteSurveyRecord"
|
<span>{{ form.IndicationType }}</span>
|
||||||
label=""
|
</el-form-item>
|
||||||
style="text-align:right;"
|
</div>
|
||||||
>
|
<div class="login_content">
|
||||||
<!-- 更新调研表 -->
|
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
||||||
<el-link
|
<el-select v-model="form.TrialSiteId" filterable style="width:100%;" @change="handleSiteChange">
|
||||||
v-if="!form.IsUpdate"
|
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
|
||||||
type="primary"
|
:value="item.TrialSiteId" />
|
||||||
@click="form.IsUpdate = true"
|
</el-select>
|
||||||
>
|
</el-form-item>
|
||||||
{{ $t('trials:researchForm:button:updateQsForm') }}
|
<el-form-item v-if="form.TrialSiteId && isHaveSiteSurveyRecord" label="" style="text-align:right;">
|
||||||
</el-link>
|
<!-- 更新调研表 -->
|
||||||
<!-- 取消更新调研表 -->
|
<el-link v-if="!form.IsUpdate" type="primary" @click="form.IsUpdate = true">
|
||||||
<el-link
|
{{ $t('trials:researchForm:button:updateQsForm') }}
|
||||||
v-else
|
</el-link>
|
||||||
type="primary"
|
<!-- 取消更新调研表 -->
|
||||||
@click="form.IsUpdate = false;form.ReplaceUserEmailOrPhone=''"
|
<el-link v-else type="primary" @click="form.IsUpdate = false; form.ReplaceUserEmailOrPhone = ''">
|
||||||
>
|
{{ $t('trials:researchForm:button:cancelUpdateQsForm') }}
|
||||||
{{ $t('trials:researchForm:button:cancelUpdateQsForm') }}
|
</el-link>
|
||||||
</el-link>
|
</el-form-item>
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!-- 原调研表填写人邮箱 -->
|
<!-- 原调研表填写人邮箱 -->
|
||||||
<el-form-item
|
<el-form-item v-if="form.IsUpdate" :label="$t('trials:researchForm:form:originalEmail')"
|
||||||
v-if="form.IsUpdate"
|
prop="ReplaceUserEmailOrPhone">
|
||||||
:label="$t('trials:researchForm:form:originalEmail')"
|
<el-input v-model="form.ReplaceUserEmailOrPhone" autocomplete="new-password" />
|
||||||
prop="ReplaceUserEmailOrPhone"
|
</el-form-item>
|
||||||
>
|
<!-- 联系邮箱 -->
|
||||||
<el-input
|
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="EmailOrPhone">
|
||||||
v-model="form.ReplaceUserEmailOrPhone"
|
<el-input v-model="form.EmailOrPhone" autocomplete="new-password" />
|
||||||
autocomplete="new-password"
|
</el-form-item>
|
||||||
/>
|
<el-form-item :label="$t('trials:researchForm:form:verifyCode')">
|
||||||
</el-form-item>
|
<div class="code_content">
|
||||||
<!-- 联系邮箱 -->
|
<el-input v-model="form.VerificationCode" autocomplete="new-password" />
|
||||||
<el-form-item
|
<el-button type="primary" :disabled="sendDisabled || !form.EmailOrPhone || count > 0"
|
||||||
:label="$t('trials:researchForm:form:contactorEmail')"
|
@click="handleSendCode">
|
||||||
prop="EmailOrPhone"
|
{{ this.$t('trials:researchForm:button:send') }} {{ sendTitle ? `${sendTitle}` : null }}
|
||||||
>
|
</el-button>
|
||||||
<el-input
|
</div>
|
||||||
v-model="form.EmailOrPhone"
|
</el-form-item>
|
||||||
autocomplete="new-password"
|
<div class="submit_content">
|
||||||
/>
|
<el-button size="large" type="primary" @click="onSubmit">
|
||||||
</el-form-item>
|
{{ $t('common:button:submit') }}
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:researchForm:form:verifyCode')"
|
|
||||||
>
|
|
||||||
<div class="code_content">
|
|
||||||
<el-input
|
|
||||||
v-model="form.VerificationCode"
|
|
||||||
autocomplete="new-password"
|
|
||||||
/>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
:disabled="sendDisabled || !form.EmailOrPhone || count > 0"
|
|
||||||
@click="handleSendCode"
|
|
||||||
>
|
|
||||||
{{ this.$t('trials:researchForm:button:send') }} {{ sendTitle ? `${sendTitle}` : null }}
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
|
||||||
<div class="submit_content">
|
|
||||||
<el-button
|
|
||||||
size="large"
|
|
||||||
type="primary"
|
|
||||||
@click="onSubmit"
|
|
||||||
>
|
|
||||||
{{ $t('common:button:submit') }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</el-form>
|
||||||
</el-form>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -133,6 +90,10 @@ import { sendVerifyCode, verifySendCode, getTrialSurveyInitInfo } from '@/api/re
|
|||||||
import { getUserMenuTree, getUserPermissions } from '@/api/user'
|
import { getUserMenuTree, getUserPermissions } from '@/api/user'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { mapGetters, mapMutations } from 'vuex'
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
import {
|
||||||
|
getLinkLinkExpirationTime,
|
||||||
|
getLinkVerificationCodeIsEffective
|
||||||
|
} from '@/api/trials'
|
||||||
export default {
|
export default {
|
||||||
name: 'ResearchMobileLogin',
|
name: 'ResearchMobileLogin',
|
||||||
data() {
|
data() {
|
||||||
@@ -185,6 +146,16 @@ export default {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
trialId: '',
|
trialId: '',
|
||||||
|
IsExpired: true,
|
||||||
|
verify: true,
|
||||||
|
codeForm: {
|
||||||
|
LinkVerificationCode: null,
|
||||||
|
},
|
||||||
|
code_rules: {
|
||||||
|
LinkVerificationCode: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: ['blur'] }
|
||||||
|
],
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
Sponsor: null, // 申办方
|
Sponsor: null, // 申办方
|
||||||
ResearchProgramNo: null, // 方案号
|
ResearchProgramNo: null, // 方案号
|
||||||
@@ -239,16 +210,119 @@ export default {
|
|||||||
])
|
])
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$i18n.locale = this.$route.query.lang
|
let lang = this.$route.query.lang
|
||||||
this.setLanguage(this.$route.query.lang)
|
if (!lang) {
|
||||||
this.$updateDictionary()
|
const language = navigator.language
|
||||||
if (this.$route.query.trialId) {
|
lang = 'en'
|
||||||
this.trialId = this.$route.query.trialId
|
if (language.includes("zh")) {
|
||||||
this.initPage()
|
lang = 'zh'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.$i18n.locale = lang
|
||||||
|
this.setLanguage(lang)
|
||||||
|
this.$updateDictionary()
|
||||||
|
this.getLinkTimeIsExpired()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
||||||
|
async getLinkTimeIsExpired() {
|
||||||
|
try {
|
||||||
|
let data = {
|
||||||
|
TrialId: this.$route.query.trialId,
|
||||||
|
}
|
||||||
|
let res = await getLinkLinkExpirationTime(data)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
if (res.Result.IsExpired) {
|
||||||
|
return this.$router.replace('/link_expired')
|
||||||
|
// return this.$confirm(this.$t("trials:researchForm:confirm:linkIsExpired"), '', {
|
||||||
|
// type: 'warning'
|
||||||
|
// })
|
||||||
|
// return this.IsExpired = true
|
||||||
|
}
|
||||||
|
// this.customPrompt()
|
||||||
|
this.IsExpired = false
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getLinkVerificationCodeIsEffective() {
|
||||||
|
try {
|
||||||
|
let validate = await this.$refs.codeForm.validate()
|
||||||
|
if (!validate) return false
|
||||||
|
let data = {
|
||||||
|
TrialId: this.$route.query.trialId,
|
||||||
|
LinkVerificationCode: this.codeForm.LinkVerificationCode
|
||||||
|
}
|
||||||
|
let res = await getLinkVerificationCodeIsEffective(data)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
if (!res.Result.IsEffective) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.verify = false
|
||||||
|
if (this.$route.query.trialId) {
|
||||||
|
this.trialId = this.$route.query.trialId
|
||||||
|
this.initPage()
|
||||||
|
}
|
||||||
|
if (this.$route.query.isUpload) {
|
||||||
|
this.isUpload = true
|
||||||
|
this.form.IsUpdate = true
|
||||||
|
let { email, oldEMail, trialSiteId } = this.$route.query
|
||||||
|
if (trialSiteId) this.form.TrialSiteId = trialSiteId
|
||||||
|
if (oldEMail) this.form.ReplaceUserEmailOrPhone = oldEMail
|
||||||
|
if (email && email !== 'null') {
|
||||||
|
this.form.EmailOrPhone = email
|
||||||
|
} else {
|
||||||
|
this.form.EmailOrPhone = oldEMail
|
||||||
|
}
|
||||||
|
if ((email && email !== 'null') || (oldEMail && oldEMail !== 'null')) {
|
||||||
|
this.isNeedUpload = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (err) {
|
||||||
|
return false
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async customPrompt(name) {
|
||||||
|
try {
|
||||||
|
const that = this
|
||||||
|
// 请输入标记名称
|
||||||
|
let message = this.$t('trials:researchForm:message:LinkVerificationCode')
|
||||||
|
const { value } = await this.$prompt(message, '', {
|
||||||
|
showClose: false,
|
||||||
|
cancelButtonText: this.$t('common:button:cancel'),
|
||||||
|
confirmButtonText: this.$t('trials:researchForm:button:saveLinkCode'),
|
||||||
|
showCancelButton: false,
|
||||||
|
closeOnClickModal: false,
|
||||||
|
closeOnPressEscape: false,
|
||||||
|
inputValue: name,
|
||||||
|
beforeClose: async (action, instance, done) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
const value = instance.inputValue
|
||||||
|
if (!value) {
|
||||||
|
that.$message.error(this.$t('trials:researchForm:error:noValue'))
|
||||||
|
} else {
|
||||||
|
let flag = await this.getLinkVerificationCodeIsEffective(value)
|
||||||
|
if (!flag) {
|
||||||
|
that.$message.error(this.$t('trials:researchForm:confirm:isEffective'))
|
||||||
|
} else {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.getLinkVerificationCodeIsEffective(value)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
// 初始化页面
|
// 初始化页面
|
||||||
async initPage() {
|
async initPage() {
|
||||||
try {
|
try {
|
||||||
@@ -292,8 +366,18 @@ export default {
|
|||||||
|
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
zzSessionStorage.clear()
|
zzSessionStorage.clear()
|
||||||
this.$i18n.locale = this.$route.query.lang
|
// this.$i18n.locale = this.$route.query.lang
|
||||||
this.setLanguage(this.$route.query.lang)
|
// this.setLanguage(this.$route.query.lang)
|
||||||
|
let lang = this.$route.query.lang
|
||||||
|
if (!lang) {
|
||||||
|
const language = navigator.language
|
||||||
|
lang = 'en'
|
||||||
|
if (language.includes("zh")) {
|
||||||
|
lang = 'zh'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$i18n.locale = lang
|
||||||
|
this.setLanguage(lang)
|
||||||
store.dispatch('user/setToken', res.Result.Token)
|
store.dispatch('user/setToken', res.Result.Token)
|
||||||
zzSessionStorage.setItem('TokenKey', res.Result.Token)
|
zzSessionStorage.setItem('TokenKey', res.Result.Token)
|
||||||
var permissions = await getUserPermissions()
|
var permissions = await getUserPermissions()
|
||||||
@@ -363,9 +447,10 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.research_login_m_content{
|
.research_login_m_content {
|
||||||
background-color:#f5f7fa;
|
background-color: #f5f7fa;
|
||||||
.title{
|
|
||||||
|
.title {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
line-height: 80px;
|
line-height: 80px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
@@ -373,40 +458,55 @@ export default {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.basic_content{
|
|
||||||
|
.basic_content {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.login_content{
|
|
||||||
|
.login_content {
|
||||||
padding: 5px 20px;
|
padding: 5px 20px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
::v-deep.el-form-item {
|
|
||||||
|
::v-deep .el-form-item {
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.code_content{
|
|
||||||
display:flex;
|
.code_content {
|
||||||
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
.el-input{
|
|
||||||
|
.el-input {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.submit_content{
|
|
||||||
|
.submit_content {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep.el-form-item {
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
border-bottom: 1px solid #f5f7fa;
|
border-bottom: 1px solid #f5f7fa;
|
||||||
.el-form-item__content{
|
|
||||||
|
.el-form-item__content {
|
||||||
color: #82848a;
|
color: #82848a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.LinkVerificationCode_content {
|
||||||
|
position: fixed;
|
||||||
|
top: 40%;
|
||||||
|
bottom: 40%;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form v-if="isShow" ref="researchBSForm" size="small" :model="form" :rules="rules" style="width:80%"
|
<el-form v-if="isShow" ref="researchBSForm" size="small" :model="form" :rules="rules" style="width:80%"
|
||||||
label-position="left">
|
label-position="left" v-loading="loading">
|
||||||
<!-- 项目编号 -->
|
<!-- 项目编号 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:trialId')">
|
<el-form-item :label="$t('trials:researchForm:form:trialId')">
|
||||||
<el-input v-model="form.TrialCode" disabled />
|
<el-input v-model="form.TrialCode" disabled />
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<!-- 中心名称 -->
|
<!-- 中心名称 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
||||||
<el-select v-model="form.TrialSiteId" filterable style="width:100%;"
|
<el-select v-model="form.TrialSiteId" filterable style="width:100%;"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" @change="handleSiteChange">
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" @change="handleSiteChange">
|
||||||
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
|
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
|
||||||
:value="item.TrialSiteId" />
|
:value="item.TrialSiteId" />
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -31,53 +31,117 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系人 -->
|
<!-- 联系人 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:contactor')" prop="UserName">
|
<el-form-item :label="$t('trials:researchForm:form:contactor')" prop="UserName">
|
||||||
<el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
<el-input v-model="form.UserName" :disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系电话 -->
|
<!-- 联系电话 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:contactorPhone')" prop="Phone">
|
<el-form-item :label="$t('trials:researchForm:form:contactorPhone')" prop="Phone">
|
||||||
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
<el-input v-model="form.Phone" :disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系邮箱 -->
|
<!-- 联系邮箱 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="Email">
|
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="Email">
|
||||||
<el-input v-model="form.Email" disabled />
|
<el-input v-model="form.Email" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('trials:researchForm:form:CommonUploadRecordId')
|
||||||
|
" v-if="IsSupportUploadFile" class="file">
|
||||||
|
<el-input v-model="form.SiteSurveyFile.FileName" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }"
|
||||||
|
style="width: 30%;margin-right: 5px;" disabled />
|
||||||
|
<div class="upload" v-if="!(!(state === 0 && userTypeEnumInt === 0) || isHistory)">
|
||||||
|
<input accept=".pdf,.docx,.doc" type="file" name="uploadFolder" class="select-file" title=""
|
||||||
|
@change="beginScanFiles($event)" />
|
||||||
|
<div class="btn-select">
|
||||||
|
{{ $t('dictionary:template:basicData:button:selectFile') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" @click="viewManualFile"
|
||||||
|
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
|
||||||
|
$t('trials:researchForm:form:preview') }}</el-button>
|
||||||
|
<el-button type="primary" @click="downLoad"
|
||||||
|
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
|
||||||
|
$t('trials:researchForm:form:download') }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
<!-- <el-divider /> -->
|
<!-- <el-divider /> -->
|
||||||
<!-- 平均刻盘周期(天) -->
|
<!-- 平均刻盘周期(天) -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')"
|
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')"
|
||||||
:label="$t('trials:researchForm:form:engravingCycle')">
|
:label="$t('trials:researchForm:form:engravingCycle')">
|
||||||
<el-input-number v-model="form.AverageEngravingCycle"
|
<el-input-number v-model="form.AverageEngravingCycle"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0" />
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" controls-position="right"
|
||||||
|
:min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- MRI-PDFF 是否为本中心该适应症的常规诊疗检查项目? -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('IsRoutineMRIPDEE')"
|
||||||
|
:label="$t('trials:researchForm:form:IsRoutineMRIPDEE')" prop="IsRoutineMRIPDEE">
|
||||||
|
<el-radio-group v-model="form.IsRoutineMRIPDEE"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM">
|
||||||
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsRoutineMRIPDEE${item.value}`" :label="item.value">{{
|
||||||
|
item.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- MRI-PDFF 检查的检测周期(含单次检查时长、预约等待时长等) -->
|
||||||
|
<el-form-item
|
||||||
|
v-if="!notShowFieldList.includes('MRIPDFFScanTime') || !notShowFieldList.includes('MRIPDFFLeadTime') || !notShowFieldList.includes('MRIPDFFOther')"
|
||||||
|
:label="$t('trials:researchForm:form:IsMRIPDFF')">
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 单次检查时长(分钟) -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFScanTime')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFScanTime')">
|
||||||
|
<el-input-number v-model="form.MRIPDFFScanTime"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" controls-position="right"
|
||||||
|
:min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 平均预约等待时长(天) -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFLeadTime')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFLeadTime')">
|
||||||
|
<el-input-number v-model="form.MRIPDFFLeadTime"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" controls-position="right"
|
||||||
|
:min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 特殊情况备注-->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFOther')"
|
||||||
|
:label="$t('trials:researchForm:form:MRIPDFFOther')">
|
||||||
|
<el-input v-model="form.MRIPDFFOther" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 如已选择研究者评估,项目是否会授权影像科老师参与本试验?如不单独授权,是否可在试验中保持 1-2 名固定技师操作?-->
|
||||||
|
<el-form-item
|
||||||
|
v-if="!notShowFieldList.includes('IsAuthorizeRadiologistsParticipate') || !notShowFieldList.includes('AssignFixedTechnologists')"
|
||||||
|
:label="$t('trials:researchForm:form:IsAuthorize')" prop="IsAuthorize">
|
||||||
|
<el-radio-group v-model="form.IsAuthorize"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" @input="handleIsAuthorizeInput">
|
||||||
|
<el-radio label="IsAuthorizeRadiologistsParticipate">{{
|
||||||
|
$t('trials:researchForm:form:IsAuthorizeRadiologistsParticipate') }}</el-radio>
|
||||||
|
<el-radio label="AssignFixedTechnologists">{{
|
||||||
|
$t('trials:researchForm:form:AssignFixedTechnologists') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质(如:“技师证”,对应设备的“大型设备上岗证”) -->
|
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质(如:“技师证”,对应设备的“大型设备上岗证”) -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')"
|
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')"
|
||||||
:label="$t('trials:researchForm:form:isQualified')">
|
:label="$t('trials:researchForm:form:isQualified')" prop="IsConfirmImagingTechnologist">
|
||||||
<el-radio-group v-model="form.IsConfirmImagingTechnologist"
|
<el-radio-group v-model="form.IsConfirmImagingTechnologist"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM">
|
||||||
<el-radio v-for="item of $d.YesOrNo" :key="`IsConfirmImagingTechnologist${item.value}`" :label="item.value">{{
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsConfirmImagingTechnologist${item.value}`" :label="item.value">{{
|
||||||
item.label }}</el-radio>
|
item.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 原因 -->
|
<!-- 原因 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
|
<el-form-item v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
|
||||||
:label="$t('trials:researchForm:form:notQualifiedReason')">
|
:label="$t('trials:researchForm:form:notQualifiedReason')" prop="NotConfirmReson">
|
||||||
<el-input v-model="form.NotConfirmReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
<el-input v-model="form.NotConfirmReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 研究单位疗效评估人员类型 -->
|
<!-- 研究单位疗效评估人员类型 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')"
|
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')"
|
||||||
:label="$t('trials:researchForm:form:staffType')">
|
:label="$t('trials:researchForm:form:staffType')">
|
||||||
<el-radio-group v-model="form.EfficacyEvaluatorType"
|
<el-radio-group v-model="form.EfficacyEvaluatorType"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM">
|
||||||
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`"
|
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`"
|
||||||
:label="item.value">{{ item.label }}</el-radio>
|
:label="item.value">{{ item.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
|
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')">
|
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')" prop="IsFollowStudyParameters">
|
||||||
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
|
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
|
||||||
<el-radio-group v-model="form.IsFollowStudyParameters"
|
<el-radio-group v-model="form.IsFollowStudyParameters"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" style="margin-right: 10px;">
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" style="margin-right: 10px;">
|
||||||
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{
|
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{
|
||||||
item.label }}</el-radio>
|
item.label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
@@ -86,10 +150,27 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
|
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
|
||||||
<el-form-item v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters">
|
<el-form-item v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
|
||||||
|
prop="NotFollowReson">
|
||||||
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
|
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
|
||||||
<el-input v-model="form.NotFollowReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
<el-input v-model="form.NotFollowReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否严格按照影像手册参数完成刻盘 -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('ISStrictManualBurnFlag')" prop="ISStrictManualBurnFlag">
|
||||||
|
<span slot="label" v-html="$t('trials:researchForm:form:ISStrictManualBurnFlag')" />
|
||||||
|
<el-radio-group v-model="form.ISStrictManualBurnFlag"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" style="margin-right: 10px;">
|
||||||
|
<el-radio v-for="item of $d.YesOrNo" :key="`ISStrictManualBurnFlag${item.value}`" :label="item.value">{{
|
||||||
|
item.label }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 不能严格按照影像手册参数完成刻盘原因 -->
|
||||||
|
<el-form-item v-if="!notShowFieldList.includes('NotStrictManualBurnFlagReason') && !form.ISStrictManualBurnFlag"
|
||||||
|
prop="NotStrictManualBurnFlagReason">
|
||||||
|
<span slot="label" v-html="$t('trials:researchForm:form:NotStrictManualBurnFlagReason')" />
|
||||||
|
<el-input v-model="form.NotStrictManualBurnFlagReason" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory) && !isPM" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<!-- 保存 -->
|
<!-- 保存 -->
|
||||||
@@ -103,9 +184,10 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getTrialSiteSelect, getTrialDocumentList } from '@/api/trials'
|
import { getTrialSiteSelect, getTrialDocumentList, addOrUpdateCommonUploadRecord } from '@/api/trials'
|
||||||
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
|
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
|
||||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
||||||
|
import { downLoadFile } from '@/utils/stream.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'QuestionForm',
|
name: 'QuestionForm',
|
||||||
components: { attachmentPreview },
|
components: { attachmentPreview },
|
||||||
@@ -113,7 +195,19 @@ export default {
|
|||||||
isHistory: {
|
isHistory: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
},
|
||||||
|
IsOnlyUploadFile: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
IsSupportUploadFile: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isPM: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
var checkPhone = (rule, value, callback) => {
|
var checkPhone = (rule, value, callback) => {
|
||||||
@@ -138,6 +232,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
loading: false,
|
||||||
form: {
|
form: {
|
||||||
Id: '',
|
Id: '',
|
||||||
Sponsor: '', // 申办方
|
Sponsor: '', // 申办方
|
||||||
@@ -152,16 +247,51 @@ export default {
|
|||||||
Phone: '', // 联系人电话
|
Phone: '', // 联系人电话
|
||||||
Email: '', // 联系人邮箱
|
Email: '', // 联系人邮箱
|
||||||
AverageEngravingCycle: '',
|
AverageEngravingCycle: '',
|
||||||
|
IsRoutineMRIPDEE: '',
|
||||||
|
MRIPDFFScanTime: '',
|
||||||
|
MRIPDFFLeadTime: '',
|
||||||
|
MRIPDFFOther: '',
|
||||||
|
IsAuthorize: '',
|
||||||
|
IsAuthorizeRadiologistsParticipate: '',
|
||||||
|
AssignFixedTechnologists: '',
|
||||||
|
ISStrictManualBurnFlag: '',
|
||||||
|
NotStrictManualBurnFlagReason: '',
|
||||||
IsConfirmImagingTechnologist: '',
|
IsConfirmImagingTechnologist: '',
|
||||||
NotConfirmReson: '',
|
NotConfirmReson: '',
|
||||||
EfficacyEvaluatorType: '',
|
EfficacyEvaluatorType: '',
|
||||||
IsFollowStudyParameters: '',
|
IsFollowStudyParameters: '',
|
||||||
NotFollowReson: ''
|
NotFollowReson: '',
|
||||||
|
CommonUploadRecordId: null,
|
||||||
|
SiteSurveyFile: []
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
TrialSiteId: [
|
TrialSiteId: [
|
||||||
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
],
|
],
|
||||||
|
IsRoutineMRIPDEE: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsAuthorize: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
ISStrictManualBurnFlag: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsFollowStudyParameters: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
IsConfirmImagingTechnologist: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotConfirmReson: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotFollowReson: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
|
NotStrictManualBurnFlagReason: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
UserName: [
|
UserName: [
|
||||||
{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: 'blur' },
|
{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: 'blur' },
|
||||||
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: ['blur', 'change'] }
|
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: ['blur', 'change'] }
|
||||||
@@ -188,6 +318,68 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async beginScanFiles(e) {
|
||||||
|
try {
|
||||||
|
let file = e.target.files[0]
|
||||||
|
let name = file.name
|
||||||
|
if (!this.checkFileSuffix(name)) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:checkFileSuffix"))
|
||||||
|
this.loading = true
|
||||||
|
file = await this.fileToBlob(file)
|
||||||
|
let scope = this
|
||||||
|
var index = name.lastIndexOf('.')
|
||||||
|
var type = name.substring(index + 1, name.length)
|
||||||
|
let res = await this.OSSclient.put(
|
||||||
|
`/${this.$route.query.trialId}/InspectionUpload/SiteSurvey/${this.form.TrialSiteId}/${scope.getGuid(Date.now() + '_' + name.split('.')[0])}.${type}`,
|
||||||
|
file
|
||||||
|
)
|
||||||
|
let data = {
|
||||||
|
Path: this.$getObjectName(res.url),
|
||||||
|
FileName: name,
|
||||||
|
FileSize: file.size,
|
||||||
|
FileType: type
|
||||||
|
|
||||||
|
}
|
||||||
|
res = await addOrUpdateCommonUploadRecord(data)
|
||||||
|
this.loading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.form.CommonUploadRecordId = res.Result
|
||||||
|
data.Id = res.Result
|
||||||
|
this.form.SiteSurveyFile = data
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
checkFileSuffix(fileName) {
|
||||||
|
var index = fileName.lastIndexOf('.')
|
||||||
|
var suffix = fileName.substring(index + 1, fileName.length)
|
||||||
|
if ('.pdf'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.docx'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.doc'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleIsAuthorizeInput(label) {
|
||||||
|
this.form.IsAuthorizeRadiologistsParticipate = false
|
||||||
|
this.form.AssignFixedTechnologists = false
|
||||||
|
this.form[label] = true
|
||||||
|
},
|
||||||
|
async viewManualFile() {
|
||||||
|
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
|
||||||
|
this.$preview({
|
||||||
|
path: this.form.SiteSurveyFile.Path,
|
||||||
|
type: this.form.SiteSurveyFile.FileType,
|
||||||
|
title: this.form.SiteSurveyFile.Path.FileName,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async downLoad() {
|
||||||
|
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
|
||||||
|
return await downLoadFile(
|
||||||
|
this.OSSclientConfig.basePath + this.form.SiteSurveyFile.Path,
|
||||||
|
this.form.SiteSurveyFile.FileName
|
||||||
|
)
|
||||||
|
},
|
||||||
async viewManual() {
|
async viewManual() {
|
||||||
try {
|
try {
|
||||||
let data = {
|
let data = {
|
||||||
@@ -218,8 +410,58 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 保存基本信息
|
// 保存基本信息
|
||||||
handleSave(isAutoCommit) {
|
handleSave(isAutoCommit, isCheck = false) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
isCheck = false
|
||||||
|
if (this.IsOnlyUploadFile && !isCheck) {
|
||||||
|
if (!this.form.UserName) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notUserName"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
if (!this.form.Phone) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notPhone"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
if (!this.form.CommonUploadRecordId) {
|
||||||
|
this.$message.warning(this.$t("trials:researchForm:message:notCommonUploadRecordId"))
|
||||||
|
return resolve(false)
|
||||||
|
}
|
||||||
|
this.btnLoading = true
|
||||||
|
const param = {
|
||||||
|
id: this.form.Id,
|
||||||
|
trialId: this.$route.query.trialId,
|
||||||
|
trialSiteId: this.form.TrialSiteId,
|
||||||
|
userName: this.form.UserName,
|
||||||
|
phone: this.form.Phone,
|
||||||
|
email: this.form.Email,
|
||||||
|
averageEngravingCycle: this.form.AverageEngravingCycle,
|
||||||
|
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
|
||||||
|
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
|
||||||
|
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
|
||||||
|
MRIPDFFOther: this.form.MRIPDFFOther,
|
||||||
|
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
|
||||||
|
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
|
||||||
|
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
|
||||||
|
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
|
||||||
|
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
||||||
|
notConfirmReson: this.form.NotConfirmReson,
|
||||||
|
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
||||||
|
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
||||||
|
notFollowReson: this.form.NotFollowReson,
|
||||||
|
CommonUploadRecordId: this.form.CommonUploadRecordId
|
||||||
|
}
|
||||||
|
addOrUpdateTrialSiteSurvey(param).then(res => {
|
||||||
|
this.btnLoading = false
|
||||||
|
if (res.IsSuccess && !isAutoCommit) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
resolve(true)
|
||||||
|
}).catch(() => {
|
||||||
|
this.btnLoading = false
|
||||||
|
reject(false)
|
||||||
|
})
|
||||||
|
return resolve(true)
|
||||||
|
}
|
||||||
this.$refs['researchBSForm'].validate(valid => {
|
this.$refs['researchBSForm'].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.btnLoading = true
|
this.btnLoading = true
|
||||||
@@ -231,11 +473,20 @@ export default {
|
|||||||
phone: this.form.Phone,
|
phone: this.form.Phone,
|
||||||
email: this.form.Email,
|
email: this.form.Email,
|
||||||
averageEngravingCycle: this.form.AverageEngravingCycle,
|
averageEngravingCycle: this.form.AverageEngravingCycle,
|
||||||
|
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
|
||||||
|
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
|
||||||
|
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
|
||||||
|
MRIPDFFOther: this.form.MRIPDFFOther,
|
||||||
|
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
|
||||||
|
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
|
||||||
|
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
|
||||||
|
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
|
||||||
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
|
||||||
notConfirmReson: this.form.NotConfirmReson,
|
notConfirmReson: this.form.NotConfirmReson,
|
||||||
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
|
||||||
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
isFollowStudyParameters: this.form.IsFollowStudyParameters,
|
||||||
notFollowReson: this.form.NotFollowReson
|
notFollowReson: this.form.NotFollowReson,
|
||||||
|
CommonUploadRecordId: this.form.CommonUploadRecordId
|
||||||
}
|
}
|
||||||
addOrUpdateTrialSiteSurvey(param).then(res => {
|
addOrUpdateTrialSiteSurvey(param).then(res => {
|
||||||
this.btnLoading = false
|
this.btnLoading = false
|
||||||
@@ -260,7 +511,7 @@ export default {
|
|||||||
// 初始化
|
// 初始化
|
||||||
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
|
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
|
||||||
// 获取项目下的site
|
// 获取项目下的site
|
||||||
const { Result } = await getTrialSiteSelect(this.$route.query.trialId)
|
const { Result } = await getTrialSiteSelect(this.$route.query.trialId, { IgnoreDisable: true })
|
||||||
this.siteOptions = Result
|
this.siteOptions = Result
|
||||||
this.form.Id = trialSiteSurvey.Id
|
this.form.Id = trialSiteSurvey.Id
|
||||||
this.form.Sponsor = trialInfo.Sponsor // 申办方
|
this.form.Sponsor = trialInfo.Sponsor // 申办方
|
||||||
@@ -274,7 +525,20 @@ export default {
|
|||||||
this.form.UserName = trialSiteSurvey.UserName // 联系人
|
this.form.UserName = trialSiteSurvey.UserName // 联系人
|
||||||
this.form.Phone = trialSiteSurvey.Phone // 联系人电话
|
this.form.Phone = trialSiteSurvey.Phone // 联系人电话
|
||||||
this.form.Email = trialSiteSurvey.Email // 联系人邮箱
|
this.form.Email = trialSiteSurvey.Email // 联系人邮箱
|
||||||
|
this.form.CommonUploadRecordId = trialSiteSurvey.CommonUploadRecordId
|
||||||
|
this.form.SiteSurveyFile = trialSiteSurvey.SiteSurveyFile || {}
|
||||||
|
this.form.fileStr = this.form.SiteSurveyFile.FileName
|
||||||
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
|
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
|
||||||
|
this.form.IsRoutineMRIPDEE = trialSiteSurvey.IsRoutineMRIPDEE
|
||||||
|
this.form.MRIPDFFScanTime = trialSiteSurvey.MRIPDFFScanTime
|
||||||
|
this.form.MRIPDFFLeadTime = trialSiteSurvey.MRIPDFFLeadTime
|
||||||
|
this.form.MRIPDFFOther = trialSiteSurvey.MRIPDFFOther
|
||||||
|
this.form.IsAuthorizeRadiologistsParticipate = trialSiteSurvey.IsAuthorizeRadiologistsParticipate
|
||||||
|
this.form.AssignFixedTechnologists = trialSiteSurvey.AssignFixedTechnologists
|
||||||
|
if (this.form.IsAuthorizeRadiologistsParticipate) this.form.IsAuthorize = 'IsAuthorizeRadiologistsParticipate'
|
||||||
|
if (this.form.AssignFixedTechnologists) this.form.IsAuthorize = 'AssignFixedTechnologists'
|
||||||
|
this.form.ISStrictManualBurnFlag = trialSiteSurvey.ISStrictManualBurnFlag
|
||||||
|
this.form.NotStrictManualBurnFlagReason = trialSiteSurvey.NotStrictManualBurnFlagReason
|
||||||
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
|
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
|
||||||
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
|
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
|
||||||
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
|
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
|
||||||
@@ -294,3 +558,54 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.upload {
|
||||||
|
display: inline-block;
|
||||||
|
height: 30px;
|
||||||
|
width: 90px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
line-height: 23px;
|
||||||
|
position: relative;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
background: #428bca;
|
||||||
|
border-color: #428bca;
|
||||||
|
color: #fff;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
.select-file {
|
||||||
|
height: 30px;
|
||||||
|
width: 90px;
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
opacity: 0;
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-select {
|
||||||
|
//给显示在页面上的按钮写样式
|
||||||
|
width: 90px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none; //pointer-events:none用来控制该标签的点击穿透事件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file {
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,40 +1,98 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form ref="equipmentForm" :model="form" :rules="rules" label-width="150px">
|
<el-form ref="equipmentForm" :model="form" :rules="rules" label-width="380px">
|
||||||
<div class="base-dialog-body">
|
<div class="base-dialog-body">
|
||||||
<!-- 扫描设备 -->
|
<!-- 扫描设备 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeId">
|
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeEnum"
|
||||||
<el-select
|
v-if="EquipmentControlFieldList.includes('EquipmentTypeEnum')">
|
||||||
v-model="form.EquipmentTypeId"
|
<div style="display: flex;align-items: center;">
|
||||||
style="width:100%"
|
<el-select v-model="form.EquipmentTypeEnum" style="width:100%" @change="form.OtherEquipmentType = null">
|
||||||
>
|
<el-option v-for="item of $d.SiteSurvey_ScanEquipmentType" :key="item.id" :label="item.label"
|
||||||
<!-- <el-option
|
:value="item.value" />
|
||||||
v-for="item of dictionaryList.SiteSurvey_ScanEquipmentType"
|
</el-select>
|
||||||
:key="item.Id"
|
<el-input placeholder="" v-model="form.OtherEquipmentType" style="margin-left: 10px;"
|
||||||
:label="item.Value"
|
v-if="form.EquipmentTypeEnum == '-1'" clearable>
|
||||||
:value="item.Id"
|
</el-input>
|
||||||
/> -->
|
</div>
|
||||||
<el-option
|
|
||||||
v-for="item of $d.SiteSurvey_ScanEquipmentType"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描参数 -->
|
<!-- 扫描参数 -->
|
||||||
<el-form-item v-if="isShowParameters" :label="$t('trials:equiptResearch:form:param')">
|
<el-form-item :label="$t('trials:equiptResearch:form:param')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('Parameters')" prop="Parameters">
|
||||||
<el-input v-model="form.Parameters" />
|
<el-input v-model="form.Parameters" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描仪器制造商名称 -->
|
<!-- 扫描仪器制造商名称 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')">
|
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')"
|
||||||
<el-input v-model="form.ManufacturerName" />
|
v-if="EquipmentControlFieldList.includes('ManufacturerType')" prop="ManufacturerType">
|
||||||
|
<div style="display: flex;align-items: center;">
|
||||||
|
<el-select v-model="form.ManufacturerType" style="width:100%" @change="form.ManufacturerName = null">
|
||||||
|
<el-option v-for="item of $d.ManufacturerType" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
<el-input placeholder="" v-model="form.ManufacturerName" style="margin-left: 10px;"
|
||||||
|
v-if="form.ManufacturerType == '-1'" clearable>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 扫描仪型号 -->
|
<!-- 扫描仪型号 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:model')">
|
<el-form-item :label="$t('trials:equiptResearch:form:model')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('ScannerType')" prop="ScannerType">
|
||||||
<el-input v-model="form.ScannerType" />
|
<el-input v-model="form.ScannerType" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- 磁场强度 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:MagneticFieldStrengthType')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('MagneticFieldStrengthType')" prop="MagneticFieldStrengthType">
|
||||||
|
<el-select v-model="form.MagneticFieldStrengthType" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.MagneticFieldStrengthType" :key="item.id" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 体部线圈通道数 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:BodyCoilChannelCount')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('BodyCoilChannelCount')" prop="BodyCoilChannelCount">
|
||||||
|
<el-select v-model="form.BodyCoilChannelCount" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.BodyCoilChannelCount" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否具备专用的PDFF脂肪定量序列(CSE-MRI序列) -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:HasDedicatedPdfFatQuantificationSequence')"
|
||||||
|
v-if="EquipmentControlFieldList.includes('HasDedicatedPdfFatQuantificationSequence')"
|
||||||
|
prop="HasDedicatedPdfFatQuantificationSequence">
|
||||||
|
<el-select v-model="form.HasDedicatedPdfFatQuantificationSequence" style="width:100%"
|
||||||
|
@change="form.PdfFatQuantificationSequenceType = null, form.OtherSequenceSpecification = null">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- PDFF脂肪定量序列 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:PdfFatQuantificationSequenceType')"
|
||||||
|
prop="PdfFatQuantificationSequenceType"
|
||||||
|
v-if="form.HasDedicatedPdfFatQuantificationSequence && EquipmentControlFieldList.includes('PdfFatQuantificationSequenceType')">
|
||||||
|
<div style="display: flex;align-items: center;">
|
||||||
|
<el-select v-model="form.PdfFatQuantificationSequenceType" style="width:100%"
|
||||||
|
@change="form.OtherSequenceSpecification = null">
|
||||||
|
<el-option v-for="item of $d.PdfFatQuantificationSequenceType" :key="item.id" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
<el-input placeholder="" v-model="form.OtherSequenceSpecification" style="margin-left: 10px;"
|
||||||
|
v-if="form.PdfFatQuantificationSequenceType == '-1'" clearable>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否包含 T2/R2 校正(用于铁沉积校正) -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:HasT2R2Correction')" prop="HasT2R2Correction"
|
||||||
|
v-if="EquipmentControlFieldList.includes('HasT2R2Correction')">
|
||||||
|
<el-select v-model="form.HasT2R2Correction" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否可完整导出 PDFF 参数图及全部原始 DICOM 数据 -->
|
||||||
|
<el-form-item :label="$t('trials:equiptResearch:form:CanFullyExportPdfParameterMapsAndRawDicom')"
|
||||||
|
prop="CanFullyExportPdfParameterMapsAndRawDicom"
|
||||||
|
v-if="EquipmentControlFieldList.includes('CanFullyExportPdfParameterMapsAndRawDicom')">
|
||||||
|
<el-select v-model="form.CanFullyExportPdfParameterMapsAndRawDicom" style="width:100%">
|
||||||
|
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
<el-form-item :label="$t('trials:equiptResearch:form:remark')">
|
<el-form-item :label="$t('trials:equiptResearch:form:remark')" prop="Note"
|
||||||
|
v-if="EquipmentControlFieldList.includes('Note')">
|
||||||
<el-input v-model="form.Note" />
|
<el-input v-model="form.Note" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,26 +127,98 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
isShowParameters: {
|
EquipmentControlFieldList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isPM: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
Id: '',
|
Id: '',
|
||||||
EquipmentTypeId: '',
|
EquipmentTypeEnum: null,
|
||||||
Parameters: '',
|
OtherEquipmentType: null,
|
||||||
ManufacturerName: '',
|
Parameters: null,
|
||||||
ScannerType: '',
|
Note: null,
|
||||||
Note: '',
|
ManufacturerType: null,
|
||||||
|
ManufacturerName: null,
|
||||||
|
ScannerType: null,
|
||||||
|
MagneticFieldStrengthType: null,
|
||||||
|
BodyCoilChannelCount: null,
|
||||||
|
HasDedicatedPdfFatQuantificationSequence: null,
|
||||||
|
PdfFatQuantificationSequenceType: null,
|
||||||
|
OtherSequenceSpecification: null,
|
||||||
|
HasT2R2Correction: null,
|
||||||
|
CanFullyExportPdfParameterMapsAndRawDicom: null,
|
||||||
TrialSiteSurveyId: ''
|
TrialSiteSurveyId: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
EquipmentTypeId: [
|
EquipmentTypeEnum: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.EquipmentTypeEnum === -1 && !this.form.OtherEquipmentType) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Parameters: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
// Note: [
|
||||||
|
// { required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
// ],
|
||||||
|
ManufacturerType: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.ManufacturerType === -1 && !this.form.ManufacturerName) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
ScannerType: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
MagneticFieldStrengthType: [
|
||||||
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
]
|
],
|
||||||
|
BodyCoilChannelCount: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
HasDedicatedPdfFatQuantificationSequence: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
PdfFatQuantificationSequenceType: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (this.form.PdfFatQuantificationSequenceType === -1 && !this.form.OtherSequenceSpecification) {
|
||||||
|
callback(this.$t('common:ruleMessage:specify'));
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||||
|
},
|
||||||
|
],
|
||||||
|
HasT2R2Correction: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
|
CanFullyExportPdfParameterMapsAndRawDicom: [
|
||||||
|
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
|
||||||
|
],
|
||||||
},
|
},
|
||||||
btnLoading: false,
|
btnLoading: false,
|
||||||
dictionaryList: {}
|
dictionaryList: {}
|
||||||
|
|||||||