Compare commits
616 Commits
f7ad010b2a
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3d011951b | ||
| 7dc76d7b59 | |||
| b2dec2667a | |||
|
|
879d31b51d | ||
|
|
473a5f7f06 | ||
| 2eec988c56 | |||
| 8820048d55 | |||
| 6af7720470 | |||
|
|
5f134945ab | ||
| bc12cc1b08 | |||
| 17b8ea7192 | |||
|
|
2bfdd686c7 | ||
|
|
066cfaba46 | ||
| e8850e85fc | |||
| d083a3123a | |||
| 96c1927f8d | |||
| bdac9d0709 | |||
| 8faba1ea21 | |||
| dd9b77f6bb | |||
| d45955f6de | |||
| f905915f34 | |||
|
|
52951d7296 | ||
| 3c47979913 | |||
| 9aad809322 | |||
| b7850e5b8a | |||
|
|
effcdfbbe6 | ||
| 4277a369d2 | |||
| cf3f971741 | |||
| 75737cf95c | |||
| 4b544dc214 | |||
| 597e621b69 | |||
| 725ac4b76a | |||
| 8e8b35faa4 | |||
| 664ee0312c | |||
| cceaf7fb07 | |||
| d5d638b60b | |||
| 8de5ae3a4f | |||
| 8f20c48baa | |||
|
|
547cccbeb7 | ||
| 86e665bcae | |||
|
|
d1aa91f727 | ||
| bc021924e4 | |||
| 6179a89b6c | |||
| 7c12028f63 | |||
| befb4739ee | |||
| fe07cee58c | |||
|
|
066c457d90 | ||
| 39b608dfd0 | |||
| 6b600b44ca | |||
|
|
b26ad75299 | ||
| b69f312611 | |||
| c65db9abc3 | |||
| 1b4ad5e710 | |||
| e46e2be830 | |||
| f515b90c43 | |||
| 6aff10e240 | |||
|
|
5d02da03b4 | ||
| d99188bfb9 | |||
| c3776c642b | |||
| 46a99ecd55 | |||
| 81744b9b9e | |||
| 469b325f0e | |||
| 8a3fe5461e | |||
| b65841c0cc | |||
| 8ef334ba1b | |||
|
|
2492daa0ad | ||
| 8af06f6916 | |||
| 7008fb007f | |||
| dc039fcced | |||
|
|
fcb1d771f4 | ||
| 30ca81090a | |||
| e722841e60 | |||
| b4ab67aed9 | |||
| 6a8f82bb2e | |||
| 09761c8ce8 | |||
|
|
5e3affcf3a | ||
|
|
455f7938be | ||
|
|
9525b1d927 | ||
| 8810c678c9 | |||
| cd3155e63c | |||
| 45fdca65a7 | |||
| 491db8bc03 | |||
| c735bc3a78 | |||
| e2db4bd3a5 | |||
| fc0f5a11be | |||
| c5528ce1b7 | |||
| 9116ea4a84 | |||
| ce8b0b16b1 | |||
| 259c62b6b4 | |||
| 208b8fc41d | |||
| c611c0ce6f | |||
| 25c266babb | |||
| 04ad139eae | |||
|
|
6add091a7b | ||
|
|
a05b3a8d3c | ||
| 35bc735ecc | |||
|
|
fcd2d03424 | ||
| 87c7981ad9 | |||
| 9edf8936ba | |||
|
|
753bd8bb4b | ||
| 3e09b4cc10 | |||
| 55970622f1 | |||
| 98164c65a2 | |||
|
|
d63a34f4e6 | ||
| 20ab9f890f | |||
| 038213a26c | |||
| ff41aa9c04 | |||
| f60e070984 | |||
| 3f7169844c | |||
|
|
8b993d5ddd | ||
|
|
9cfa9a3417 | ||
|
|
b200f80d88 | ||
|
|
e57baaead6 | ||
|
|
2576f62f88 | ||
|
|
cd24fe007f | ||
|
|
3898880665 | ||
| 562e618aaa | |||
| ec4d57ea69 | |||
|
|
7a5b26607e | ||
|
|
50ceb98e83 | ||
|
|
2065395bd2 | ||
|
|
517dc41f01 | ||
|
|
6f8e677045 | ||
|
|
1747291f41 | ||
|
|
cff1e0145b | ||
|
|
3ab7ea1898 | ||
|
|
c5d75f053b | ||
|
|
730476e927 | ||
| d8a4487b2b | |||
| c93a5f69d8 | |||
|
|
b826afb17c | ||
|
|
2a5a157c57 | ||
|
|
ca9b145d3e | ||
|
|
7676f03c96 | ||
|
|
b5b91d8971 | ||
|
|
f1bddf3fbe | ||
| b1c966f69f | |||
| dba6350493 | |||
|
|
6fb5b5993a | ||
|
|
4c2b015210 | ||
|
|
9f9f193287 | ||
|
|
d34a314f02 | ||
| 8d45cfe9db | |||
| f9d897c081 | |||
| d2616ac2f9 | |||
| d2a6780c23 | |||
| fc32b83980 | |||
|
|
b936654a11 | ||
| 2a525f95b9 | |||
| 585b9bd720 | |||
|
|
faf73a5ac4 | ||
| 89bf85fd97 | |||
| f3d56bff45 | |||
|
|
cd6c015d8f | ||
|
|
dfdab41c00 | ||
|
|
f69de5e78f | ||
|
|
74892ea80f | ||
|
|
4bf74a1ff0 | ||
| 3a53837e50 | |||
|
|
2c2bb1adb0 | ||
|
|
a434dfdfff | ||
| 4c14d802c4 | |||
| a7602057e2 | |||
| 97af9d5eee | |||
|
|
3cabb5f803 | ||
|
|
a55884a710 | ||
| dfac362c37 | |||
|
|
897afd4da2 | ||
| 3d31b3482a | |||
| 3acf8ad50a | |||
|
|
fa06a52d71 | ||
| d1b290881f | |||
| 5781e39c20 | |||
| 9ed43c9413 | |||
| 270004afee | |||
|
|
96941cb4e0 | ||
| 6c15f0d4d5 | |||
|
|
063be326eb | ||
| 5534a71c7d | |||
| 669d669422 | |||
| 98fe9f3301 | |||
| 6f7d723c6b | |||
| 0a08088ada | |||
|
|
48309fcaa4 | ||
|
|
28160e082c | ||
|
|
29ecfd90f2 | ||
| f690b78b18 | |||
| 6f71c678bd | |||
| 1c781c1224 | |||
|
|
638f853af6 | ||
|
|
96a8f75aa1 | ||
| 15a6445e26 | |||
| 0e4b0ad6fd | |||
|
|
7da461a9cb | ||
| b0040bcd48 | |||
| fa5394cc35 | |||
| 81cc8b08a0 | |||
| 0cecf3bcad | |||
|
|
b8d7e3cdf1 | ||
|
|
df2a4c1694 | ||
|
|
a6a4e0ed58 | ||
|
|
ba31371b6f | ||
| 9bd5caaa1b | |||
| 164e4a4b75 | |||
| 4f0cc1a0c4 | |||
|
|
6dedb92b54 | ||
|
|
0f0dc70c7e | ||
|
|
acfce391dc | ||
|
|
b0f2eabf6b | ||
|
|
c5db404290 | ||
|
|
c4c3073be0 | ||
| 41494ebf7c | |||
|
|
4de4d9099e | ||
| 497af01f9b | |||
| ffc1f29b80 | |||
| 86bca03b04 | |||
| 11c2758289 | |||
| 802f845231 | |||
|
|
ea5215a1b0 | ||
| a9fb093d9c | |||
|
|
f4bf064f08 | ||
|
|
4dd824d296 | ||
| 3ab6c2d424 | |||
| 12b2bf255c | |||
|
|
c878dc19d7 | ||
|
|
c1efd84332 | ||
| 1616f66fc4 | |||
|
|
2df1ed645f | ||
|
|
4f7fc1c09a | ||
| bd873f81d2 | |||
| 1975fda73c | |||
| ffce6f81c3 | |||
| ca043de624 | |||
| 054b51c63d | |||
| 5cf2dd165c | |||
| 27b094744c | |||
|
|
55e3533600 | ||
|
|
1522183432 | ||
| 6382741b71 | |||
| 16c854d55f | |||
| 73617e1b0f | |||
| abd5bd9f2f | |||
|
|
9000d66c0c | ||
|
|
61be9ff552 | ||
|
|
9408cf6c2d | ||
|
|
66c70a2b4a | ||
| f6d9321f95 | |||
| ccff9a7246 | |||
| 2884f610f5 | |||
|
|
035738f990 | ||
|
|
d0c6f57f6b | ||
|
|
58c1e02415 | ||
|
|
1e459b8883 | ||
|
|
0d57e984a6 | ||
| 4450e3cc50 | |||
|
|
902ee0587e | ||
| 49550fcc2e | |||
|
|
1dd7ee3428 | ||
|
|
8dff5d466a | ||
|
|
19ada4ace9 | ||
| c92ff38133 | |||
| 1c07108e58 | |||
|
|
34dd969cb4 | ||
| a0b546266d | |||
|
|
fc9ce6241e | ||
|
|
5187ff1ae3 | ||
|
|
73b1d01044 | ||
|
|
b88ad89146 | ||
|
|
de8039c513 | ||
| 3464153d93 | |||
| 6b868e378f | |||
| f6403fa059 | |||
|
|
bc92b9aa62 | ||
|
|
46145ff636 | ||
|
|
3ad32fac9f | ||
| d1223aec07 | |||
| 649f7bcf5b | |||
| a3dce8de60 | |||
| f81dd54f0c | |||
| 803e4d0bb5 | |||
| deebcde41f | |||
| 095c43bbf3 | |||
| aa3beb848b | |||
|
|
ae96bbd0bb | ||
|
|
1a2c444269 | ||
|
|
9cba8fea12 | ||
|
|
f11b7380a4 | ||
| da17b2b89c | |||
| 9e4a010a8d | |||
| 7e76083c37 | |||
| de105adbdc | |||
| f3eeee7405 | |||
| 97f04d0b15 | |||
| 5667e04d12 | |||
| 59157fda56 | |||
| 2fe6d45ad4 | |||
| 982ee316f7 | |||
| 64c7db68e8 | |||
| cb6b6ced67 | |||
|
|
8fcfb481c9 | ||
|
|
be0514bc08 | ||
|
|
2b3add4808 | ||
| b33cb6f9a1 | |||
| 072e71b025 | |||
| 47394de43c | |||
| f0f1dde6b6 | |||
| 1ab1165697 | |||
| a8f1b1fdfa | |||
| 3b94d19199 | |||
| db1139a14f | |||
|
|
bea74aeac2 | ||
|
|
634a1f45f9 | ||
| 8f1ad3307c | |||
| d8080fa22d | |||
|
|
e8783d9f8f | ||
| d8c4348341 | |||
|
|
8e61490005 | ||
| f5f4e3c48e | |||
| 0f013715b8 | |||
| fb9722d328 | |||
| 6f9192d30d | |||
| f2b5b90f34 | |||
| a2cbd5e583 | |||
| d3df46858b | |||
| 47a7a945bc | |||
| 0a56c0dcf0 | |||
| 15d32134e2 | |||
| eff98ea5eb | |||
| a47306825a | |||
|
|
9b35fec931 | ||
| e20e2b637f | |||
| ebd2e8aa75 | |||
| cb268fe26d | |||
| 23bd49d940 | |||
| 32adb984e2 | |||
| c1d453600b | |||
| 02eab2d932 | |||
| d5c8b7a1ad | |||
|
|
4053064a22 | ||
|
|
089e28f913 | ||
| cf9ab03b17 | |||
| d332650bfa | |||
| 840983ac94 | |||
|
|
86673d7be3 | ||
|
|
3753a916f5 | ||
|
|
0556f77870 | ||
|
|
b185c156ca | ||
|
|
a48308dcbf | ||
| e37f6a70f9 | |||
|
|
28629ccd35 | ||
|
|
fbd7f0be78 | ||
|
|
763f05da84 | ||
|
|
8c74d45332 | ||
| 8d62c0461b | |||
| 58936c957d | |||
| 062c4a92b8 | |||
| fb9f85e967 | |||
| 38ef377cbd | |||
| 240d5dc3f7 | |||
| 82702f16e0 | |||
| 0b4b63dfbe | |||
| b4422a0dca | |||
| d8627df2dd | |||
| 09ca077559 | |||
| 3091fc7337 | |||
| b0850257c8 | |||
| fa2884b320 | |||
| 941054734f | |||
| 8d69dc3c00 | |||
| 2157806ba5 | |||
| 2236cbea36 | |||
| 2128e717e7 | |||
| 1311e87e13 | |||
| ddf1553846 | |||
| 5d82800976 | |||
| 0c35044231 | |||
| 61f4020487 | |||
| aeb6b95970 | |||
| b5ce854eb6 | |||
| 4d4828ea71 | |||
| 10e738edd9 | |||
| 88a4e58130 | |||
| 76c324b0df | |||
| a65e8dd2cc | |||
| 1ac9b5ae0b | |||
| 8f77fe8bc9 | |||
| b567747901 | |||
| ed7004ae85 | |||
| d1670b79a0 | |||
| 54cde91aac | |||
| 7974bdc51c | |||
| 91cb465962 | |||
| 1b2c248fa2 | |||
| 1c16d6ba0f | |||
| 49b8a975a8 | |||
| d17a502da1 | |||
| 430adc2112 | |||
| 5f5c47f528 | |||
| 92d74c47ce | |||
| 5d8e7b667f | |||
| 58449fc2f9 | |||
| 4c541f43b9 | |||
| 9a037ae446 | |||
| bb0eb60eae | |||
| cf5dbc6133 | |||
| 5f6fa50000 | |||
| 08b2e76d47 | |||
| 5ffeab8999 | |||
| fc6640b846 | |||
| 8e11dde7c0 | |||
| e8f24ee290 | |||
| a1e07a204b | |||
| a080b4294c | |||
| 0827ce2908 | |||
| 5f600209b8 | |||
| 79ea4ed4f7 | |||
| cbd3e7f981 | |||
| 3c497417dc | |||
| 088861f66e | |||
| 8914c8b143 | |||
| 8c607c8749 | |||
| 3115e38cc4 | |||
| ae6c486114 | |||
| a41ffa4cfc | |||
| b1f74161f8 | |||
| 3bab56a19b | |||
| abc0674531 | |||
| 85fcb7c2e2 | |||
| fc6a7437a3 | |||
| 999a0992e7 | |||
| 55b3dfc077 | |||
|
|
32d1673667 | ||
| 17c7cc70ed | |||
| 44be570ffa | |||
| c6f4996ba7 | |||
| 6c20b15339 | |||
| c297072b36 | |||
| 4c6886be6a | |||
| 8beb7f3d3d | |||
| 91968530b4 | |||
| 0833f82fb4 | |||
| cce71f324b | |||
| ee6efafde4 | |||
| 2051807ecf | |||
| 0a4de15599 | |||
| 25b3c26ec2 | |||
| 91d673de77 | |||
| 0bfa7183f9 | |||
| 79d451931d | |||
| ae5f1c795b | |||
| c1074fc4fb | |||
| e832b6d38e | |||
| 5043466e84 | |||
| fcaeedb543 | |||
| 8cf434a46f | |||
| bfbc061b0b | |||
| f92cd830e9 | |||
| a7a1a18445 | |||
| d1331cd4e1 | |||
| 37d08b8545 | |||
| e69f499ac0 | |||
| 3baf7161f1 | |||
| 85188651ca | |||
| d6fbfb1427 | |||
| 966847499a | |||
| 1e91171001 | |||
| 51f495f81e | |||
| 1e6a5972b9 | |||
| 515f03a5cd | |||
| b27542ba6d | |||
| 4790855079 | |||
| 72cf9c6f2d | |||
| 19ecb65183 | |||
| d85a8684a6 | |||
| 574a9267bf | |||
| 27a7396c78 | |||
| 633cf2c17f | |||
| 3188ca5752 | |||
| c79e4c2623 | |||
| f3c451d0a1 | |||
| a077bd57d4 | |||
| cf16c497bd | |||
| fd1ab239a9 | |||
| caf65e3113 | |||
| c18c21ff4c | |||
| ab6849c9eb | |||
| 6b555f2563 | |||
| 7645405c5b | |||
| 5bfadb9174 | |||
| e1b9d36153 | |||
| fdb8d6c934 | |||
| 22a1ac57b2 | |||
| 4d243815a6 | |||
| 882e8c9199 | |||
| a0c87f6335 | |||
| 538dde55f7 | |||
| f33e3c6f15 | |||
| 0794782505 | |||
| d37fa46b5f | |||
| 8fcc229ad8 | |||
| 39aa710fd3 | |||
| 49f95b40ea | |||
| eb2d7302b7 | |||
| eb26f9db34 | |||
| bd6f3ca587 | |||
| a58e02f2cb | |||
| 8c8ef13021 | |||
| d9a0a98f52 | |||
| 8c84b6eb46 | |||
| 3d797cc0e0 | |||
| df7281a2d4 | |||
| f83d7ae520 | |||
| d9c8525b94 | |||
| bcc5cbb2fb | |||
| 67a8351d70 | |||
| 391506e423 | |||
| b1117b4157 | |||
| b0eb9861b9 | |||
| b863c14f2b | |||
| 18f6a845e6 | |||
| e1385cb3e6 | |||
| c8ca56c3f5 | |||
| b149f7d687 | |||
| 19702c25e5 | |||
|
|
eaa681c9ff | ||
| 205c58782b | |||
| 00e1c62de0 | |||
| 46c9787216 | |||
| e0a768de2e | |||
| fc7f931728 | |||
|
|
3ccb970a09 | ||
|
|
8a9a622aeb | ||
|
|
29e7f0937b | ||
| 029d534b3c | |||
|
|
213723b220 | ||
|
|
c636e77fd0 | ||
|
|
7407562ec5 | ||
|
|
b3c27ec789 | ||
|
|
601ae40666 | ||
| 3dda5ce72d | |||
|
|
99d4c28b95 | ||
|
|
0e70de6de7 | ||
| 72eb1088df | |||
| a853c16854 | |||
| 73a349f98a | |||
| 5fb7a3f488 | |||
| a8eb7d5697 | |||
| eb3b142ce4 | |||
| 9f6a39ba30 | |||
| f7f2f98bbe | |||
| 79e68ee14e | |||
| bc8987c463 | |||
| 3f7174fcd1 | |||
| 080008f447 | |||
| 5c3d935615 | |||
| a0845127c6 | |||
| ba65ab303b | |||
|
|
6fbdddf0ee | ||
| 173cbc7f87 | |||
|
|
2e341a123e | ||
|
|
8beff2ee14 | ||
| 1b939ba5b7 | |||
| 577daabe1c | |||
| 327e88e6d4 | |||
|
|
548fabcffe | ||
| 263e21e157 | |||
| d7955aa628 | |||
|
|
d197f7555f | ||
| a0e52da437 | |||
|
|
88d79729fe | ||
| 6dc6480e64 | |||
| 98c263a72b | |||
| 50a2ef9e00 | |||
| 065f7052c6 | |||
| e23d42404d | |||
| 4120d4e001 | |||
| 1bd2089047 | |||
| 6d9ff7dc10 | |||
| ae7ca984f8 | |||
| 69b7a4d865 | |||
| 864bf55025 | |||
| 249ef5f87e | |||
|
|
df3fb6c66c | ||
|
|
10ec9f4c1b | ||
| 0b98763c05 | |||
|
|
3d3b21a775 | ||
|
|
4ba4f80946 | ||
|
|
ed7cb2dab5 | ||
| 50ef9e6743 | |||
| 250d7dde34 | |||
| 69f3e066db | |||
|
|
afb0c3933c | ||
|
|
45ac07e57c | ||
|
|
262ea97824 | ||
|
|
dcfa13f239 | ||
|
|
27c3c850d6 | ||
| 122a15a73d | |||
| 61749aee4d | |||
| 97a29a31c5 | |||
| c3734f921c | |||
| c561586cfa | |||
|
|
60593233bc | ||
| 992b03f9c2 | |||
| 36628342dc | |||
|
|
3783e4a872 | ||
| 584f79294b | |||
| a5884ec069 | |||
| cc2f7db754 | |||
| fcccfc1959 | |||
| c5ec91e7d3 | |||
| 6b67e25d94 | |||
| 6da3b63012 | |||
|
|
ea0f0e2294 | ||
|
|
980f0aeb9c | ||
|
|
17b40118ce | ||
|
|
d10a78e5e8 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -57,4 +57,9 @@
|
||||
# 忽略设计书
|
||||
PostgreSQL/openHis_DB设计书.xlsx
|
||||
|
||||
public.sql
|
||||
public.sql
|
||||
发版记录/2025-11-12/~$发版日志.docx
|
||||
发版记录/2025-11-12/~$S-管理系统-调价管理.docx
|
||||
发版记录/2025-11-12/发版日志.docx
|
||||
.gitignore
|
||||
openhis-server-new/openhis-application/src/main/resources/application-dev.yml
|
||||
|
||||
29
.qwen/agents/full-stack-developer.md
Normal file
29
.qwen/agents/full-stack-developer.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: full-stack-developer
|
||||
description: Use this agent when you need comprehensive full-stack development assistance including frontend, backend, database design, API integration, deployment planning, and architectural decisions. This agent excels at analyzing complex technical requirements, designing scalable solutions, implementing clean code across multiple technologies, and providing expert guidance on best practices for modern web applications.
|
||||
color: Blue
|
||||
---
|
||||
|
||||
You are an elite full-stack software engineer with extensive experience across all layers of modern web application development. You possess deep expertise in frontend technologies (React, Vue, Angular, HTML/CSS, JavaScript/TypeScript), backend systems (Node.js, Python, Java, .NET, Ruby), databases (SQL and NoSQL), cloud platforms (AWS, Azure, GCP), and DevOps practices.
|
||||
|
||||
Your primary responsibilities include:
|
||||
- Analyzing complex technical requirements and proposing optimal architectural solutions
|
||||
- Writing clean, efficient, maintainable code across frontend and backend systems
|
||||
- Designing robust APIs and data models
|
||||
- Optimizing performance and ensuring security best practices
|
||||
- Providing guidance on scalability, testing, and deployment strategies
|
||||
- Troubleshooting complex issues spanning multiple technology stacks
|
||||
|
||||
When working on projects, you will:
|
||||
1. First understand the complete scope and requirements before proposing solutions
|
||||
2. Consider scalability, maintainability, and security implications of your designs
|
||||
3. Follow industry best practices for code organization, documentation, and testing
|
||||
4. Suggest appropriate technologies based on project requirements and constraints
|
||||
5. Provide implementation details with proper error handling and edge case considerations
|
||||
6. Recommend optimization strategies for performance and resource utilization
|
||||
|
||||
For frontend development, focus on responsive design, accessibility, state management, and user experience. For backend work, emphasize proper architecture patterns, database design, authentication/authorization, and API design principles. When addressing databases, consider normalization, indexing, query optimization, and data consistency.
|
||||
|
||||
Always prioritize clean code principles, proper separation of concerns, and modular design. When uncertain about requirements, ask clarifying questions to ensure your solution meets the actual needs. Provide code examples that demonstrate best practices and include comments where necessary for understanding.
|
||||
|
||||
In your responses, balance technical depth with practical applicability. Consider trade-offs between different approaches and explain your recommendations. When reviewing existing code, identify potential improvements related to performance, security, maintainability, and adherence to best practices.
|
||||
32
.qwen/agents/his-architect-developer.md
Normal file
32
.qwen/agents/his-architect-developer.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: his-architect-developer
|
||||
description: Use this agent when designing, developing, reviewing, or troubleshooting Hospital Information System (HIS) applications. This agent specializes in full-stack development for healthcare systems including database design, backend APIs, frontend interfaces, security compliance, and integration with medical devices or third-party systems.
|
||||
color: Blue
|
||||
---
|
||||
|
||||
You are an elite Healthcare Information System (HIS) Development Architect and Full-Stack Engineer with extensive experience in designing and implementing comprehensive hospital management solutions. You possess deep expertise in healthcare software architecture, regulatory compliance (HIPAA, FDA, etc.), medical data standards (HL7, FHIR), and secure system integration.
|
||||
|
||||
Your responsibilities include:
|
||||
- Designing scalable, secure, and compliant HIS architectures
|
||||
- Developing robust backend services and APIs
|
||||
- Creating intuitive frontend interfaces for healthcare professionals
|
||||
- Ensuring patient data security and privacy compliance
|
||||
- Integrating with medical devices and external healthcare systems
|
||||
- Optimizing system performance for high-availability environments
|
||||
- Troubleshooting complex technical issues in healthcare IT infrastructure
|
||||
|
||||
When working on HIS projects, you will:
|
||||
1. Prioritize patient safety and data security above all other considerations
|
||||
2. Follow healthcare industry standards and regulations (HIPAA, HITECH, FDA guidelines)
|
||||
3. Implement proper audit trails and logging for all patient-related operations
|
||||
4. Design fail-safe mechanisms and disaster recovery procedures
|
||||
5. Ensure accessibility compliance for users with varying technical expertise
|
||||
6. Plan for high availability and minimal downtime in critical systems
|
||||
|
||||
For database design, focus on normalized schemas that support medical record integrity, implement proper indexing for fast queries, and ensure backup/recovery procedures meet healthcare requirements. When developing APIs, follow RESTful principles while incorporating OAuth 2.0 or similar authentication methods suitable for healthcare environments.
|
||||
|
||||
For frontend development, prioritize usability for healthcare workers who may be operating under stress, ensuring clear workflows and minimizing cognitive load. Implement responsive designs that work across various devices commonly used in healthcare settings.
|
||||
|
||||
Always consider scalability requirements for growing healthcare institutions and plan for future expansion. When troubleshooting, approach problems systematically considering the potential impact on patient care.
|
||||
|
||||
In your responses, provide detailed explanations of your architectural decisions, code implementations, and recommendations. Include relevant healthcare industry best practices and explain how your solutions address specific regulatory requirements.
|
||||
33
.qwen/agents/his-developer-architect.md
Normal file
33
.qwen/agents/his-developer-architect.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: his-developer-architect
|
||||
description: Use this agent when developing or architecting Hospital Information System (HIS) solutions using Vue3, Spring Boot, and MyBatis technologies. This agent specializes in healthcare system development, understanding medical workflows, patient management systems, and hospital operational processes. Ideal for designing secure, scalable, and compliant healthcare applications.
|
||||
color: Blue
|
||||
---
|
||||
|
||||
You are an elite Healthcare Information System (HIS) developer and architect with deep expertise in Vue3, Spring Boot, and MyBatis technologies. You specialize in building robust, secure, and scalable hospital management systems that handle critical healthcare operations including patient records, medical workflows, billing, pharmacy management, and administrative processes.
|
||||
|
||||
Your responsibilities include:
|
||||
- Designing and implementing full-stack HIS solutions using Vue3 for modern, responsive frontends and Spring Boot with MyBatis for secure, efficient backends
|
||||
- Ensuring compliance with healthcare industry standards such as HIPAA, HL7, FHIR, and local health data protection regulations
|
||||
- Creating secure authentication and authorization systems for healthcare staff with role-based access controls
|
||||
- Optimizing database designs for handling large volumes of sensitive patient data efficiently
|
||||
- Implementing audit trails and logging systems required for healthcare environments
|
||||
- Building integration capabilities between different hospital systems and external healthcare providers
|
||||
|
||||
Technical Guidelines:
|
||||
- Follow Vue3 best practices using Composition API, TypeScript, and state management with Pinia
|
||||
- Implement Spring Boot microservices architecture with proper security configurations (Spring Security)
|
||||
- Use MyBatis effectively with proper transaction management and connection pooling
|
||||
- Apply healthcare-specific design patterns and architectural principles
|
||||
- Prioritize data integrity, security, and system reliability over performance optimizations when there's a conflict
|
||||
- Implement comprehensive error handling and logging for healthcare regulatory compliance
|
||||
|
||||
When designing solutions, consider:
|
||||
- Patient privacy and data security requirements
|
||||
- High availability and disaster recovery needs for critical healthcare systems
|
||||
- Scalability to handle varying loads during peak times
|
||||
- Integration with existing hospital infrastructure and legacy systems
|
||||
- User experience for healthcare professionals who need quick, reliable access to information
|
||||
- Regulatory compliance and audit requirements specific to healthcare systems
|
||||
|
||||
You will provide detailed technical recommendations, code implementations, architectural diagrams, and best practices tailored specifically to healthcare information systems. Always prioritize patient safety and data security in your solutions.
|
||||
6
.qwen/settings.json
Normal file
6
.qwen/settings.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"tools": {
|
||||
"approvalMode": "yolo"
|
||||
},
|
||||
"$version": 2
|
||||
}
|
||||
188
AGENTS.md
Normal file
188
AGENTS.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# OpenHIS - AI Agent Development Guide
|
||||
|
||||
## 项目概览
|
||||
OpenHIS 是一个医院管理系统,采用 Java 17 + Spring Boot 后端和 Vue 3 + Vite 前端架构。
|
||||
|
||||
## 构建和运行命令
|
||||
|
||||
### 后端(Java/Spring Boot)
|
||||
```bash
|
||||
# 构建整个项目
|
||||
cd openhis-server-new
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 运行后端(开发模式)
|
||||
cd openhis-server-new/openhis-application
|
||||
mvn spring-boot:run
|
||||
|
||||
# 运行特定模块
|
||||
cd openhis-server-new/[module-name]
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
### 前端(Vue 3 + Vite)
|
||||
```bash
|
||||
# 安装依赖
|
||||
cd openhis-ui-vue3
|
||||
npm install
|
||||
|
||||
# 开发服务器
|
||||
npm run dev
|
||||
|
||||
# 生产构建
|
||||
npm run build:prod
|
||||
|
||||
# 测试环境构建
|
||||
npm run build:test
|
||||
|
||||
# 预览构建结果
|
||||
npm run preview
|
||||
```
|
||||
|
||||
### 测试
|
||||
项目当前没有配置正式的测试框架。如需添加测试:
|
||||
- 后端:考虑使用 JUnit 5 + Mockito
|
||||
- 前端:考虑使用 Vitest + Vue Test Utils
|
||||
|
||||
## 代码风格规范
|
||||
|
||||
### Java 后端规范
|
||||
- **Java 版本**: 17
|
||||
- **框架**: Spring Boot 2.5.15
|
||||
- **ORM**: MyBatis Plus 3.5.5
|
||||
- **数据库**: PostgreSQL
|
||||
- **包结构**:
|
||||
- `com.openhis` - 业务逻辑
|
||||
- `com.core` - 核心框架
|
||||
- **命名约定**:
|
||||
- 类名:PascalCase(如 `UserController`)
|
||||
- 方法名:camelCase(如 `getUserList`)
|
||||
- 常量:SCREAMING_SNAKE_CASE
|
||||
- 配置文件:kebab-case
|
||||
- **注解使用**:
|
||||
- 使用 `@Slf4j` 替代手动声明 logger
|
||||
- 使用 `@Data` 在实体类中
|
||||
- 使用 `@Service/@Controller/@Repository` 等 Spring 注解
|
||||
- **异常处理**:
|
||||
- 使用统一的异常处理机制
|
||||
- 自定义业务异常继承 `RuntimeException`
|
||||
|
||||
### Vue 前端规范
|
||||
- **框架**: Vue 3 + Composition API
|
||||
- **UI 库**: Element Plus
|
||||
- **状态管理**: Pinia
|
||||
- **路由**: Vue Router 4
|
||||
- **构建工具**: Vite 5
|
||||
- **组件命名**: PascalCase
|
||||
- **文件命名**: kebab-case
|
||||
- **变量命名**: camelCase
|
||||
- **常量命名**: SCREAMING_SNAKE_CASE
|
||||
- **函数命名**:
|
||||
- 事件处理:`handle` 前缀
|
||||
- 数据获取:`get`/`load` 前缀
|
||||
- 提交操作:`submit` 前缀
|
||||
|
||||
### 导入顺序
|
||||
#### Java
|
||||
1. `java.*`
|
||||
2. `javax.*`
|
||||
3. 第三方库
|
||||
4. `com.core.*`
|
||||
5. `com.openhis.*`
|
||||
6. `*.*`(其他包)
|
||||
|
||||
#### JavaScript/Vue
|
||||
1. `vue` 相关
|
||||
2. 第三方库
|
||||
3. `@/` 别名导入
|
||||
4. 相对路径导入
|
||||
|
||||
### 代码格式
|
||||
#### Java
|
||||
- 缩进:4个空格
|
||||
- 行长度:120字符
|
||||
- 左大括号不换行
|
||||
|
||||
#### Vue/JavaScript
|
||||
- 缩进:2个空格
|
||||
- 字符串:优先使用单引号
|
||||
- 行长度:100字符
|
||||
|
||||
## 关键配置文件
|
||||
|
||||
### 后端配置
|
||||
- 主配置:`openhis-server-new/openhis-application/src/main/resources/application.yml`
|
||||
- 环境配置:`application-{profile}.yml`
|
||||
- Maven 父 POM:`openhis-server-new/pom.xml`
|
||||
|
||||
### 前端配置
|
||||
- Vite 配置:`openhis-ui-vue3/vite.config.js`
|
||||
- 环境变量:`.env.*` 文件
|
||||
- 路由配置:`openhis-ui-vue3/src/router/index.js`
|
||||
|
||||
## 开发约定
|
||||
|
||||
### API 设计
|
||||
- RESTful API 风格
|
||||
- 统一响应格式
|
||||
- 使用 Swagger 文档
|
||||
- 错误码统一管理
|
||||
|
||||
### 数据库
|
||||
- 表名:snake_case
|
||||
- 字段名:snake_case
|
||||
- 主键:使用 `id`
|
||||
- 软删除:使用 `valid_flag` 字段
|
||||
|
||||
### 前端组件
|
||||
- 单一职责原则
|
||||
- Props 使用 camelCase
|
||||
- Events 使用 kebab-case
|
||||
- 使用 Composition API
|
||||
- 组件文档使用 JSDoc
|
||||
|
||||
### 状态管理
|
||||
- 模块化设计
|
||||
- 异步操作使用 actions
|
||||
- 避免在组件中直接修改状态
|
||||
|
||||
## 环境变量
|
||||
|
||||
### 前端
|
||||
- `VITE_APP_BASE_API`: API 基础路径
|
||||
- `VITE_APP_ENV`: 环境标识
|
||||
|
||||
### 后端
|
||||
- `spring.profiles.active`: 激活的配置文件
|
||||
- `core.name`: 应用名称
|
||||
- `core.version`: 应用版本
|
||||
|
||||
## 安全规范
|
||||
- 所有 API 接口需要权限验证
|
||||
- 敏感信息使用环境变量
|
||||
- SQL 注入防护
|
||||
- XSS 攻击防护
|
||||
|
||||
## 性能优化
|
||||
- 后端使用连接池(Druid)
|
||||
- 前端使用路由懒加载
|
||||
- 图片使用 WebP 格式
|
||||
- 大列表使用虚拟滚动
|
||||
|
||||
## 常用工具类
|
||||
- 后端:`com.core.common.utils.*`
|
||||
- 前端:`@/utils/*`
|
||||
|
||||
## 注意事项
|
||||
1. 修改数据库结构需要同步 SQL 脚本
|
||||
2. 新增功能需要添加权限配置
|
||||
3. 前端路由需要在权限系统中注册
|
||||
4. 接口变更需要更新 Swagger 文档
|
||||
5. 遵循现有代码风格,避免不必要的变化
|
||||
|
||||
## 故障排除
|
||||
- 后端端口:18080
|
||||
- 前端端口:81
|
||||
- API 前缀:`/openhis`
|
||||
- Swagger UI:`/openhis/swagger-ui/index.html`
|
||||
- Druid 监控:`/openhis/druid/login.html`
|
||||
674
LICENSE
674
LICENSE
@@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright 2022-2025 湖北天天数链技术有限公司
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
OpenHis Copyright (C) 2022-2025 湖北天天数链技术有限公司
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
68
README.md
68
README.md
@@ -1,68 +0,0 @@
|
||||
# 平台介绍
|
||||
|
||||
## 🏠【关于我们】
|
||||
|
||||

|
||||
|
||||
天天开源致⼒于打造中国应⽤管理 软件开源⽣态,⾯向医疗、企业、教育三⼤⾏业信息化需求,提供优质的开源软件产品与解决⽅案。平台现已发布OpenHIS、OpenCOM、OpenEDU系列开源产品,并持续招募⽣态合作伙伴,期待共同构建开源创新的⾏业协作模式,加速⾏业的数字化进程。
|
||||
|
||||
天天开源的前⾝是新致开源,最早于2022年6⽉发布开源医疗软件平台OpenHIS.org.cn,于2023年6⽉发布开源企业软件平台OpenCOM.com.cn。2025年7⽉,新致开源品牌更新为天天开源,我们始终秉持开源、专业、协作的理念,致⼒于为医疗、教育、中⼩企业等⾏业提供优质的开源解决⽅案。
|
||||
|
||||
了解我们a:https://open.tntlinking.com/about?site=gitee
|
||||
|
||||
## 💾【部署包下载】
|
||||
|
||||
请访问官网产品中心下载部署包:https://open.tntlinking.com/resource/productCenter?site=gitee
|
||||
|
||||
## 📚【支持文档】
|
||||
|
||||
技术支持资源:https://open.tntlinking.com/resource/technicalSupport?site=gitee
|
||||
(含演示环境、操作手册、部署手册、开发手册、常见问题等)
|
||||
|
||||
产品介绍:https://open.tntlinking.com/resource/industryKnowledge?site=gitee
|
||||
|
||||
操作教程:https://open.tntlinking.com/resource/operationTutorial?site=gitee
|
||||
|
||||
沙龙回顾:https://open.tntlinking.com/resource/openSourceSalon#23?site=gitee
|
||||
|
||||
## 🤝【合作方式】
|
||||
|
||||
产品服务价格:https://open.tntlinking.com/cost?site=gitee
|
||||
|
||||
加入生态伙伴:https://open.tntlinking.com/ecology/becomePartner?site=gitee
|
||||
|
||||
## 🤗【技术社区】
|
||||
|
||||
请访问官网扫码加入技术社区交流:https://open.tntlinking.com/ecology/joinCommunity?site=gitee
|
||||
|
||||
请关注公众号【天天开源软件】以便获得最新产品更新信息。
|
||||
|
||||
|
||||
|
||||
# 项目介绍
|
||||
|
||||
OpenHIS医院系统(信创版)集十大核心模块于一体,涵盖目录管理、基础数据配置、个性化设置、门诊/住院全流程管理、药房药库智能管控、精细化耗材管理、财务核算体系、医保合规对接及多维报表分析等功能模块,共计372项标准化功能。
|
||||
|
||||
系统深度适配民营及公立一二级医院业务场景,支持单体医院、集团化运营及区域医疗协同等多种部署模式,并通过国家信创认证体系,确保全栈技术自主可控。如有项目需求,可联系官方平台合作。
|
||||
|
||||
|
||||
|
||||
## 运行环境
|
||||
|
||||
jdk17 (必须)
|
||||
node.js-v16.15 (推荐)
|
||||
PostgreSQL-v16.2 (必须)
|
||||
redis (常用稳定版本即可)
|
||||
|
||||
## 开发提示
|
||||
|
||||
需要修改数据库和redis的连接信息,详见:
|
||||
application.yml
|
||||
application-druid.yml
|
||||
|
||||
## 目录解释
|
||||
|
||||
前端: openhis-ui-vue3
|
||||
后端: openhis-server
|
||||
启动类: OpenHisApplication
|
||||
|
||||
332
md/前端UI规范文档.md
Normal file
332
md/前端UI规范文档.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# OpenHIS UI 风格规范文档
|
||||
|
||||
## 1. 整体布局
|
||||
|
||||
### 1.1 容器结构
|
||||
```
|
||||
<div class="app-container [page-name]-container">
|
||||
<div class="components-container">
|
||||
<!-- 查询表单 -->
|
||||
<el-form class="query-form">...</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row class="button-group">...</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table border>...</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">...</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 1.2 样式说明
|
||||
- `app-container`: 最外层容器,全屏背景
|
||||
- `components-container`: 白色卡片容器,带阴影
|
||||
- `query-form`: 查询表单,底部无间距
|
||||
- `button-group`: 按钮组,间距 8px
|
||||
- `pagination-container`: 分页容器,顶部间距 16px
|
||||
|
||||
## 2. 统一样式规范
|
||||
|
||||
### 2.1 颜色规范
|
||||
```scss
|
||||
// 主色调
|
||||
--color-primary: #409EFF;
|
||||
--color-success: #67C23A;
|
||||
--color-warning: #E6A23C;
|
||||
--color-danger: #F56C6C;
|
||||
--color-info: #909399;
|
||||
|
||||
// 文字颜色
|
||||
--text-regular: #606266; // 常规文字
|
||||
--text-secondary: #909399; // 次要文字
|
||||
--text-placeholder: #A8ABB2; // 占位符
|
||||
```
|
||||
|
||||
### 2.2 间距规范
|
||||
```scss
|
||||
// 容器内边距
|
||||
$spacing-xs: 4px;
|
||||
$spacing-sm: 8px;
|
||||
$spacing-md: 16px;
|
||||
$spacing-lg: 20px;
|
||||
$spacing-xl: 24px;
|
||||
|
||||
// 表单项间距
|
||||
$form-item-margin-bottom: 18px;
|
||||
```
|
||||
|
||||
### 2.3 圆角规范
|
||||
```scss
|
||||
$border-radius-sm: 4px; // 小圆角 - 按钮、输入框
|
||||
$border-radius-md: 8px; // 中圆角 - 卡片、对话框
|
||||
$border-radius-lg: 12px; // 大圆角 - 特殊组件
|
||||
```
|
||||
|
||||
### 2.4 阴影规范
|
||||
```scss
|
||||
// 卡片阴影
|
||||
$box-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
|
||||
// 表格阴影
|
||||
$box-shadow-table: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
|
||||
// 浮动元素阴影
|
||||
$box-shadow-float: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||
```
|
||||
|
||||
### 2.5 字体规范
|
||||
```scss
|
||||
$font-size-base: 14px; // 基础字号
|
||||
$font-size-sm: 12px; // 小字号
|
||||
$font-size-lg: 16px; // 大字号
|
||||
$font-size-xl: 18px; // 特大字号
|
||||
|
||||
$font-weight-regular: 400; // 常规
|
||||
$font-weight-medium: 500; // 中等
|
||||
$font-weight-bold: 600; // 加粗
|
||||
```
|
||||
|
||||
## 3. 组件规范
|
||||
|
||||
### 3.1 表单组件
|
||||
|
||||
#### 输入框
|
||||
```vue
|
||||
<el-input
|
||||
v-model="value"
|
||||
placeholder="请输入xxx"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
```
|
||||
|
||||
#### 下拉框
|
||||
```vue
|
||||
<el-select
|
||||
v-model="value"
|
||||
placeholder="请选择xxx"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dictList"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
```
|
||||
|
||||
#### 按钮规范
|
||||
```vue
|
||||
<!-- 主按钮 -->
|
||||
<el-button type="primary" icon="IconName">按钮文字</el-button>
|
||||
|
||||
<!-- 次要按钮 -->
|
||||
<el-button type="success">按钮文字</el-button>
|
||||
<el-button type="warning">按钮文字</el-button>
|
||||
<el-button type="danger">按钮文字</el-button>
|
||||
|
||||
<!-- 次要按钮(plain) -->
|
||||
<el-button type="primary" plain icon="IconName">按钮文字</el-button>
|
||||
|
||||
<!-- 链接按钮(table内) -->
|
||||
<el-button link type="primary" class="action-button">文字</el-button>
|
||||
```
|
||||
|
||||
### 3.2 表格组件
|
||||
|
||||
```vue
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableData"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
>
|
||||
<!-- 复选列 -->
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
|
||||
<!-- 序号列 -->
|
||||
<el-table-column label="序号" align="center" prop="id" width="80" />
|
||||
|
||||
<!-- 普通列 -->
|
||||
<el-table-column
|
||||
label="列名"
|
||||
align="center"
|
||||
prop="fieldName"
|
||||
min-width="200"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
|
||||
<!-- 带标签列 -->
|
||||
<el-table-column label="状态" align="center" prop="status" width="90">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="dictType" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column label="操作" align="center" min-width="280">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleEdit(scope.row)" class="action-button">编辑</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)" class="action-button">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
```
|
||||
|
||||
### 3.3 对话框组件
|
||||
|
||||
```vue
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogVisible"
|
||||
width="800px"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form :model="form" :rules="rules" label-width="80px">
|
||||
<!-- 表单内容 -->
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
||||
<el-button @click="handleCancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
```
|
||||
|
||||
## 4. 响应式设计
|
||||
|
||||
### 4.1 断点规范
|
||||
```scss
|
||||
$screen-xs: 480px;
|
||||
$screen-sm: 768px;
|
||||
$screen-md: 992px;
|
||||
$screen-lg: 1200px;
|
||||
```
|
||||
|
||||
### 4.2 响应式规范
|
||||
```vue
|
||||
<!-- 栅格系统 -->
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="6" :xs="12" :sm="8">...</el-col>
|
||||
<el-col :span="18" :xs="12" :sm="16">...</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 移动端表单 -->
|
||||
<el-form :label-width="isMobile ? '80px' : '120px'">
|
||||
```
|
||||
|
||||
## 5. 交互规范
|
||||
|
||||
### 5.1 加载状态
|
||||
```vue
|
||||
<!-- 表格加载 -->
|
||||
<el-table v-loading="loading" :data="tableData">
|
||||
|
||||
<!-- 按钮加载 -->
|
||||
<el-button :loading="saving">保存</el-button>
|
||||
|
||||
<!-- 全屏加载 -->
|
||||
<el-button type="primary" :loading="true">提交</el-button>
|
||||
```
|
||||
|
||||
### 5.2 空状态
|
||||
```vue
|
||||
<el-empty
|
||||
description="暂无数据"
|
||||
:image="emptyImage"
|
||||
/>
|
||||
```
|
||||
|
||||
### 5.3 确认对话框
|
||||
```vue
|
||||
<el-dialog title="确认提示" v-model="confirmVisible">
|
||||
<p>{{ confirmMessage }}</p>
|
||||
<template #footer>
|
||||
<el-button @click="confirmVisible = false">取 消</el-button>
|
||||
<el-button type="danger" @click="handleConfirm">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
```
|
||||
|
||||
## 6. 命名规范
|
||||
|
||||
### 6.1 CSS 类名
|
||||
- 使用 kebab-case(短横线命名)
|
||||
- 遵循 BEM 命名规范
|
||||
- 示例:`notice-container`, `button-group`, `action-button`
|
||||
|
||||
### 6.2 变量命名
|
||||
- Vue:使用 camelCase
|
||||
- 事件处理:以 `handle` 开头
|
||||
- 数据获取:以 `get`/`load` 开头
|
||||
- 示例:`handleQuery`, `loadData`, `handleSubmit`
|
||||
|
||||
### 6.3 组件命名
|
||||
- 使用 PascalCase
|
||||
- 多个单词时使用驼峰命名
|
||||
- 示例:`NoticePanel`, `TableHeader`, `SearchForm`
|
||||
|
||||
## 7. 国际化规范
|
||||
|
||||
```vue
|
||||
<!-- 使用字典标签 -->
|
||||
<dict-tag :options="dictType" :value="row.status" />
|
||||
|
||||
<!-- 使用占位符 -->
|
||||
<el-input :placeholder="$t('common.placeholder')"/>
|
||||
```
|
||||
|
||||
## 8. 性能优化
|
||||
|
||||
### 8.1 图片优化
|
||||
- 使用 WebP 格式
|
||||
- 图片懒加载
|
||||
- 响应式图片
|
||||
|
||||
### 8.2 列表优化
|
||||
- 虚拟滚动(大列表)
|
||||
- 分页加载
|
||||
- 骨架屏
|
||||
|
||||
### 8.3 缓存策略
|
||||
- 使用 Vuex/Pinia 缓存用户数据
|
||||
- 本地存储持久化配置
|
||||
- 请求去重
|
||||
|
||||
## 9. 无障碍规范
|
||||
|
||||
### 9.1 语义化标签
|
||||
```vue
|
||||
<nav> <!-- 导航 -->
|
||||
<main> <!-- 主内容 -->
|
||||
<header> <!-- 头部 -->
|
||||
<footer> <!-- 底部 -->
|
||||
```
|
||||
|
||||
### 9.2 ARIA 属性
|
||||
```vue
|
||||
<el-button aria-label="提交按钮">提交</el-button>
|
||||
<el-input aria-label="搜索框" />
|
||||
```
|
||||
|
||||
### 9.3 键盘导航
|
||||
- 支持键盘操作
|
||||
- Tab 键焦点管理
|
||||
- 快捷键支持
|
||||
|
||||
---
|
||||
|
||||
**注意事项:**
|
||||
1. 所有新增页面必须遵循此规范
|
||||
2. 修改现有页面时尽量统一样式
|
||||
3. 保持与系统整体风格一致
|
||||
4. 优先使用已有的组件和样式
|
||||
5. 遵循响应式设计原则
|
||||
273
md/需求/100-门诊手术中临时医嘱生成界面PRD_2026-1-23.md
Normal file
273
md/需求/100-门诊手术中临时医嘱生成界面PRD_2026-1-23.md
Normal file
@@ -0,0 +1,273 @@
|
||||
## 门诊手术中临时医嘱生成界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:门诊手术中临时医嘱生成界面
|
||||
**页面目标**:帮助麻醉医师在手术过程中快速生成临时医嘱,完成药品计费引用、医嘱预览和电子签名确认的全流程操作
|
||||
**适用场景**:门诊手术过程中需要追加药品医嘱时使用
|
||||
**页面类型**:表单页+数据展示页
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 患者手术信息展示
|
||||
2. 已引用计费药品列表展示与汇总
|
||||
3. 临时医嘱预览与编辑功能
|
||||
4. 医师电子签名确认流程
|
||||
5. 数据刷新与退出操作
|
||||
**用户价值**:简化手术中医嘱生成流程,确保医嘱准确性,实现无纸化操作,提高手术室工作效率
|
||||
原型图地址:https://static.pm-ai.cn/prototype/20260122/e1d7f10b85e9efea543bf47bd6831600/index.html
|
||||
**流程图:**
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["Start"]) --> Enter["进入门诊手术中临时医嘱生成界面"]
|
||||
Enter --> ShowBase["展示患者基本信息"]
|
||||
ShowBase --> ShowQuoted["显示已引用计费药品列表"]
|
||||
ShowQuoted --> ShowPreview["显示医嘱预览表格"]
|
||||
ShowPreview --> UserOp{用户操作}
|
||||
|
||||
UserOp -- "引用计费" --> GetLatest{"获取最新计费药品数据\n获取成功?"}
|
||||
GetLatest -- "否" --> ErrTip1["显示错误提示"]
|
||||
GetLatest -- "是" --> UpdateTable["更新药品表格和汇总"]
|
||||
|
||||
UserOp -- "编辑" --> PopEdit["弹出医嘱编辑表单"]
|
||||
PopEdit --> EditVal{"验证通过?"}
|
||||
EditVal -- "否" --> ErrTip2["返回错误提示"]
|
||||
EditVal -- "是" --> SaveClick{"点击保存?"}
|
||||
SaveClick -- "是" --> GenTemp["生成临时药品医嘱"]
|
||||
SaveClick -- "否" --> UserOp
|
||||
|
||||
GenTemp --> UpdatePreview["更新医嘱预览表格"]
|
||||
UpdatePreview --> UpdateRecord["更新手术记录"]
|
||||
UpdateRecord --> ShowResult["显示生成结果"]
|
||||
|
||||
UserOp -- "一键签名并生成医嘱" --> PopPwd["弹出账户密码输入框"]
|
||||
PopPwd --> PopConfirm{"弹出确认对话框"}
|
||||
PopConfirm -- "否" --> UserOp
|
||||
PopConfirm -- "是" --> GenTemp
|
||||
|
||||
UserOp -- "刷新" --> Reload["重新加载界面数据"]
|
||||
Reload --> ShowQuoted
|
||||
|
||||
UserOp -- "退出" --> ExitConfirm{"确认退出?"}
|
||||
ExitConfirm -- "否" --> UserOp
|
||||
ExitConfirm -- "是" --> ReturnUp["返回上级页面"]
|
||||
|
||||
ErrTip1 --> UserOp
|
||||
ErrTip2 --> PopEdit
|
||||
ShowResult --> UserOp
|
||||
ReturnUp --> End([结束])
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
|
||||
**要区域划分**:
|
||||
|
||||
1. 顶部信息区(15%):患者基本信息+操作按钮区
|
||||
2. 计费药品展示区(35%):已引用计费药品表格+金额汇总
|
||||
3. 医嘱预览区(35%):待生成医嘱的预览表格
|
||||
4. 签名确认区(15%):医师签名信息+操作按钮
|
||||
**布局特点**:上下分块布局,采用卡片式设计,主要区域间有明确分隔线
|
||||
**响应式要求**:768px以下时患者信息改为纵向排列,操作按钮换行显示
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部信息区
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:高度180px(包含20px内边距)
|
||||
**区域功能**:展示患者基本信息+提供主要操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **标题栏**:
|
||||
- 元素类型:标题文本
|
||||
- 显示内容:“门诊术中临时医嘱”
|
||||
- 样式特征:白色文字,1.5rem字号,居中显示,渐变蓝色背景
|
||||
- **患者信息卡**:
|
||||
- 元素类型:信息展示区块
|
||||
- 显示内容:患者姓名、就诊卡号、手术单号、科室、医师、角色
|
||||
- 患者:样例值-张三
|
||||
- 就诊卡号:样例值-202507010122
|
||||
- 手术单号:样例值- S202507010135
|
||||
- 科室: 样例值-手术室(OR101)-取值于手术安排的手术间号字段
|
||||
- 医师:样例值-李麻(3015)
|
||||
- 角色:样例值-麻醉医师
|
||||
- 样式特征:半透明白色背景,圆角8px,内部flex布局
|
||||
- **操作按钮组**:
|
||||
- **[刷新按钮]**:
|
||||
- 元素类型:主要操作按钮
|
||||
- 显示内容:↻ 刷新
|
||||
- 交互行为:点击后重新加载当前界面的数据
|
||||
- 样式特征:蓝色渐变背景,悬停有上浮效果
|
||||
- **[引用计费按钮]**:
|
||||
- 元素类型:次要操作按钮
|
||||
- 显示内容:引用计费
|
||||
- 交互行为:点击后拉取当前患者最新计费药品的数据
|
||||
|
||||
#### 2. 计费药品展示区
|
||||
|
||||
**区域位置**:顶部信息区下方
|
||||
**区域尺寸**:高度约420px(包含标题和表格)
|
||||
**区域功能**:展示待生成医嘱的计费药品清单
|
||||
**包含元素**:
|
||||
|
||||
- **表格标题**:
|
||||
- 显示内容:“一、已引用计费药品(待生成医嘱)”
|
||||
- 样式特征:1.2rem字号,底部边框线
|
||||
- **药品数据表格**:
|
||||
|
||||
**取值于门诊术中计费界面生成的药品计费数据(adm_charge_item(费用项管理)、med_medication_request(药品请求管理)等),具体与系统实际业务数据为主。**
|
||||
|
||||
**(参考)关联字段:adm_charge_item. encounter_id = med_medication_request. encounter_id and –就诊ID**
|
||||
|
||||
**adm_charge_item. service_table = 'med_medication_request' and --记录药品数据**
|
||||
|
||||
**adm_charge_item. bus_no = med_medication_request. bus_no -- adm_charge_item. bus_no的值之前多加了‘CI’**
|
||||
|
||||
- 展示方式:斑马纹表格
|
||||
- 数据字段:
|
||||
- 序号:数字 - 自动生成
|
||||
- 药品名称:文本 - 如"罗哌卡因注射液"
|
||||
- 规格:文本 - 如"10ml"
|
||||
- 数量:数字 - 可编辑
|
||||
- 批号:文本 - 如"L240715"
|
||||
- 单价:数字 - 如"38"
|
||||
- 小计:数字 - 自动计算
|
||||
- 医保:标签 - “甲/乙/自费”
|
||||
- 样式特征:表头浅灰色背景,医保类型有颜色区分(蓝色=医保,绿色=自费)
|
||||
- **金额汇总栏**:
|
||||
- 显示内容:
|
||||
- 医保内金额(蓝色强调)
|
||||
- 自费金额(绿色强调)
|
||||
- 总计金额(红色强调)
|
||||
- 位置:表格底部右对齐
|
||||
|
||||
#### 3. 医嘱预览区
|
||||
|
||||
**区域位置**:计费药品展示区下方
|
||||
**区域尺寸**:高度约420px(包含标题和表格)
|
||||
**区域功能**:展示即将生成的药品医嘱
|
||||
**包含元素**:
|
||||
|
||||
\*生成门诊药品医嘱表相关的数据,满足**计费药品明细 ↔ 药品医嘱** 一一对应的要求。
|
||||
|
||||
可以对照参考:需结合门诊医生站开立药品医嘱时生成的药品医嘱表
|
||||
|
||||
- **表格标题**:
|
||||
- 显示内容:“二、临时医嘱预览(已生成)”
|
||||
- **医嘱表格**:
|
||||
- 展示方式:斑马纹表格
|
||||
- 数据字段:
|
||||
- 序号:数字
|
||||
- 医嘱名称:文本(取已引用计费药品的药品名称)
|
||||
- 剂量:数字(自动计算=规格×数量)
|
||||
- 单位:文本(根据药品类型自动判断)
|
||||
- 用法:下拉选择(不可编辑)
|
||||
- 频次:固定"临时"
|
||||
- 执行时间:自动生成当前时间
|
||||
- 操作:编辑/删除按钮
|
||||
- 操作功能:
|
||||
- 编辑:弹出表单修改剂量、用法等字段
|
||||
- 删除:二次确认后移除该条医嘱
|
||||
|
||||
#### 4. 签名确认区
|
||||
|
||||
**区域位置**:页面底部
|
||||
**区域尺寸**:高度约180px
|
||||
**区域功能**:完成医嘱确认和电子签名
|
||||
**包含元素**:
|
||||
|
||||
- **签名信息卡**:
|
||||
- 显示内容:医师姓名工号、签名状态、签名时间
|
||||
- 样式特征:浅灰色背景,圆角边框
|
||||
- **[一键签名按钮]**:
|
||||
- 元素类型:主要操作按钮
|
||||
- 显示内容:“一键签名并生成医嘱”
|
||||
- 交互行为:点击后弹出账户密码输入框
|
||||
- 样式特征:绿色背景,悬停效果
|
||||
- **[取消按钮]**:
|
||||
- 元素类型:次要操作按钮
|
||||
- 显示内容:“取消”
|
||||
- 交互行为:返回上级页面
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 引用计费功能
|
||||
|
||||
**功能描述**:从术中计费药品获取患者当前最新的计费药品数据
|
||||
**触发条件**:点击"引用计费"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 点击按钮获取患者当前最新的计费药品数据
|
||||
2. 成功返回后更新药品表格数据
|
||||
3. 自动计算并更新费用汇总
|
||||
|
||||
**反馈机制**:成功提示弹窗"已成功引用最新计费药品信息!"
|
||||
**异常处理**:请求失败时显示错误提示“获取计费数据失败,请重试”,保留原数据
|
||||
|
||||
#### 2. 医嘱生成功能
|
||||
|
||||
**功能描述**:将计费药品转为正式医嘱
|
||||
**触发条件**:点击"一键签名并生成医嘱"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 自动生成药品医嘱预览(带默认用法和剂量)
|
||||
2. 弹出账户密码输入框
|
||||
3. 验证通过后生成临时药品医嘱数据
|
||||
4. 成功返回后显示生成结果
|
||||
**数据转换规则**:
|
||||
- 剂量 = 规格数值 × 数量(如"10ml"×2 → 20ml)
|
||||
- 单位:根据药品名称自动判断(默认获取当前药品在《药品目录》维护剂量单位的值)
|
||||
- 用法:根据药品名称自动判断(默认获取当前药品在《药品目录》维护用法的值,如果未维护默认空)
|
||||
- 医嘱名称:取值药品名称
|
||||
- 频次:默认ST
|
||||
- 执行时间:默认当前系统时间
|
||||
|
||||
#### 3. 医嘱编辑功能
|
||||
|
||||
**功能描述**:修改已生成的医嘱明细
|
||||
**触发条件**:点击"编辑"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出编辑表单(带当前值医嘱值)
|
||||
2. 修改后点击保存更新表格
|
||||
3. 自动重新计算相关字段得值
|
||||
**字段限制**:
|
||||
- 剂量:必须为数字
|
||||
- 用法:限定下拉选项,取值于字典管理:用药途径(用法)的值
|
||||
- 频次:固定为"ST"不可编辑
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
**关键数据字段**:
|
||||
|
||||
| **字段名** | **说明** | **数据类型** | **示例值** | **是否必填** | **备注** |
|
||||
|---------------|----------|--------------|--------------------|--------------|------------------|
|
||||
| patientId | 患者ID | string | “202507010122” | 是 | 就诊卡号 |
|
||||
| surgeryNo | 手术单号 | string | “S202507010135” | 是 | |
|
||||
| medicineName | 药品名称 | string | “罗哌卡因注射液” | 是 | |
|
||||
| spec | 规格 | string | “10ml” | 是 | 需包含数值和单位 |
|
||||
| batchNo | 批号 | string | “L240715” | 是 | |
|
||||
| insuranceType | 医保类型 | string | “乙” | 是 | 甲/乙/自费 |
|
||||
| usage | 用法 | string | “静脉推注” | 是 | |
|
||||
| execTime | 执行时间 | datetime | “2025-07-01 08:41” | 是 | 精确到分钟 |
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:\#4a90e2(按钮/标题)
|
||||
- **辅助色**:\#5cb85c(成功操作)、\#e74c3c(警告)
|
||||
- **字体规范**:标题1.5rem/正文0.95rem,行高1.6
|
||||
- **间距系统**:区块padding20px,元素间距15px
|
||||
- **表格样式**:斑马纹,行高56px,单元格padding15px 20px
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- **浏览器兼容**:Chrome/Firefox/Edge最新版
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 医嘱生成后需同步更新手术记录
|
||||
2. 所有金额显示保留两位小数
|
||||
505
md/需求/102-门诊医生站传染病报告卡登记-2026-1-28.md
Normal file
505
md/需求/102-门诊医生站传染病报告卡登记-2026-1-28.md
Normal file
@@ -0,0 +1,505 @@
|
||||
## 门诊医生站传染性报卡登记PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:门诊医生站传染性报卡登记
|
||||
**页面目标**:帮助医生完成法定传染病病例的电子报告卡填写与提交
|
||||
**适用场景**:医生确诊或疑似发现法定传染病病例时,进行报卡登记
|
||||
**页面类型**:表单页(复杂表单)
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 患者基本信息录入(含身份验证)
|
||||
2. 传染病分类选择与疾病诊断信息登记
|
||||
3. 病例分类与流行病学信息记录
|
||||
4. 数据校验与表单提交
|
||||
5. 地址四级联动选择(省-市-区县-街道)
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 规范传染病报告流程,确保数据完整准确
|
||||
- 减少手工填写错误,提高上报效率
|
||||
- 自动关联患者基本信息,减少重复录入
|
||||
- 内置校验规则防止漏报错报
|
||||
|
||||
**原型图地址**:https://static.pm-ai.cn/prototype/20260128/6041dcc237645108aa9e917e8d57705f/index.html
|
||||
**流程图**:
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A(["开始报卡"]) --> B["填写患者基本信息"]
|
||||
B --> C{"身份证格式错误"}
|
||||
C -- 是 --> D["提示请输入有效身份证号码"]
|
||||
C -- 否 --> E{"患者年龄≤14岁"}
|
||||
E -- 是 --> F["显示家长姓名输入框"]
|
||||
E -- 否 --> G["隐藏家长姓名输入框"]
|
||||
F --> H["填写现住地址"]
|
||||
G --> H
|
||||
H --> I{"地址加载失败"}
|
||||
I -- 是 --> J["显示手动输入选项"]
|
||||
I -- 否 --> K["选择疾病分类"]
|
||||
J --> K
|
||||
K --> L{"选择特定疾病"}
|
||||
L -- 是 --> M["显示疾病分型选择"]
|
||||
L -- 否 --> N["跳过分型选择"]
|
||||
M --> O["填写发病/诊断日期"]
|
||||
N --> O
|
||||
O --> P{"日期逻辑错误"}
|
||||
P -- 是 --> Q["提示发病日期不能晚于诊断日期"]
|
||||
P -- 否 --> R["填写报告信息"]
|
||||
Q --> R
|
||||
R --> S["表单校验"]
|
||||
S --> T{"校验失败"}
|
||||
T -- 是 --> U["显示错误提示"]
|
||||
T -- 否 --> V["保存报卡"]
|
||||
U --> S
|
||||
V --> W{"点击重置按钮"}
|
||||
W -- 是 --> X["保留关键信息重置其他字段"]
|
||||
X --> S
|
||||
V --> Y{"点击关闭按钮"}
|
||||
Y -- 是 --> Z{"确认关闭"}
|
||||
Z -- 是 --> AA(["结束流程"])
|
||||
Z -- 否 --> V
|
||||
```
|
||||
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. **顶部标题区**(5%):展示表单标题和卡片编号
|
||||
2. **患者信息区**(30%):患者基本信息、联系方式、现住地址等
|
||||
3. **疾病信息区**(50%):疾病分类选择、发病/诊断日期、疾病分型等
|
||||
4. **报告信息区**(10%):报告单位、医生、填卡日期等
|
||||
|
||||
**操作按钮区**(5%):保存、重置、关闭按钮
|
||||
**布局特点**:上下布局,采用响应式网格,表单分组清晰,必填项高亮标识
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 标题区
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:高度60px
|
||||
**区域功能**:展示表单标题和唯一编号标识
|
||||
**包含元素**:
|
||||
|
||||
- 表单标题
|
||||
|
||||
- - 元素类型:标题文本
|
||||
- 默认内容:“中华人民共和国传染病报告卡”
|
||||
- 样式要求:20px字号,深蓝色(#2c3e50),居中加粗
|
||||
|
||||
- 卡片编号
|
||||
|
||||
- - 元素类型:输入框
|
||||
- 默认值:空
|
||||
- 提示文字:“单位自编,与网络直报一致”
|
||||
- 交互行为:支持手动输入12位编号
|
||||
- 样式要求:12px灰色文字,带下划线分隔线
|
||||
|
||||
#### 2. 患者基本信息区
|
||||
|
||||
**区域位置**:标题区下方
|
||||
**区域功能**:采集患者核心身份信息、联系方式、居住地等
|
||||
**包含元素**:
|
||||
|
||||
- 患者姓名输入框
|
||||
|
||||
- - 元素类型:文本输入框,自动引入当前就诊患者信息的姓名
|
||||
- 校验规则:必填项,支持中文姓名2-10字
|
||||
|
||||
- 家长姓名输入框
|
||||
|
||||
- - 元素类型:文本输入框
|
||||
- 条件显示:当系统计算年龄≤14岁时自动显示必填标识
|
||||
|
||||
- 身份证号输入框
|
||||
|
||||
- - 元素类型:文本输入框,自动引入当前就诊患者信息的身份证号
|
||||
- 校验规则:必填项,自动校验18位身份证格式
|
||||
|
||||
- 性别选择
|
||||
|
||||
- - 元素类型:单选按钮组
|
||||
- 选项:男/女/未知,自动匹配当前就诊患者信息的性别
|
||||
- 默认值:必填项
|
||||
|
||||
- 出生日期输入
|
||||
|
||||
- - 元素类型:复合输入区域
|
||||
- 包含:年(4位)/月(2位)/日(2位)三个输入框,自动匹配当前就诊患者信息的出生年月
|
||||
- 联动逻辑:自动计算实足年龄并填充到年龄输入框
|
||||
|
||||
- 工作单位输入框
|
||||
|
||||
- - 元素类型:文本输入框,自动引入当前就诊患者信息的工作单位
|
||||
- 特殊场景:学生自动关联学校信息
|
||||
|
||||
- 联系电话
|
||||
|
||||
- - 元素类型:电话输入框,自动引入当前就诊患者信息的联系方式
|
||||
- 校验规则:必填,11位手机号或带区号固话
|
||||
|
||||
- 紧急联系人电话
|
||||
|
||||
- - 元素类型:电话输入框
|
||||
- 校验规则:必填,11位手机号或带区号固话
|
||||
|
||||
- 病人属于
|
||||
|
||||
- - 复选框类型:通过现地址自动判断
|
||||
- 校验规则:必填
|
||||
|
||||
- 职业
|
||||
|
||||
- - 下拉选项类型:取值于字典管理的字典名称为“职业”维护的数据
|
||||
- 校验规则:必填
|
||||
|
||||
|
||||
|
||||
#### 3. 现住地址选择区
|
||||
|
||||
**区域功能**:四级联动地址选择(省-市-区县-街道)
|
||||
**交互逻辑**:
|
||||
|
||||
1. 省份选择后动态加载对应城市
|
||||
2. 城市选择后动态加载区县
|
||||
3. 区县选择后动态加载街道
|
||||
4. 村(居)和门牌号为手动输入
|
||||
**数据要求**:
|
||||
|
||||
- 初始默认值:省-市-区县-街道(自动引入当前就诊患者信息的现住址)
|
||||
- 异常处理:当上级未选择时禁用下级选择
|
||||
|
||||
**字典取值跟新增患者的现住址保持一致(患者管理-)患者列表)**
|
||||

|
||||
|
||||
|
||||
#### 4. 疾病信息区
|
||||
|
||||
**区域功能**:选择传染病类型及相关临床信息
|
||||
**包含元素**:
|
||||
|
||||
- **疾病分类选择**:
|
||||
|
||||
- - 布局方式:网格布局(3列)
|
||||
- 分类:甲类/乙类/丙类传染病
|
||||
- 交互行为:多选但同类别互斥
|
||||
- 特殊处理:选择炭疽/肺结核/病毒性肝炎/疟疾/梅毒/血吸虫病等疾病时激活分型选择
|
||||
|
||||
- **疾病复选框互斥逻辑:**
|
||||
|
||||
- - 选择炭疽病时显示分型选项(肺炭疽/皮肤炭疽/胃肠炭疽/未分型)
|
||||
- 选择肺结核时显示分型选项(涂阳/仅培阳/菌阴/未痰检)
|
||||
- 选择病毒性肝炎时显示分型选项(甲/乙/丙/戊型)
|
||||
- 选择疟疾时显示分型选项(间日疟/恶性疟/三日疟/卵形疟/未分型)
|
||||
- 选择梅毒时显示分型选项(Ⅰ期/Ⅱ期/Ⅲ期/胎传/隐性)
|
||||
- 选择血吸虫病时显示分型选项(急性/慢性/晚期/未分型)
|
||||
|
||||
- **分型选择**:
|
||||
|
||||
- - 元素类型:动态下拉框
|
||||
- 数据源:根据疾病类型动态加载
|
||||
- 示例:肺结核→涂阳/仅培阳/菌阴/未痰检
|
||||
|
||||
- **其他法定管理以及重点监测传染病输入框:**
|
||||
|
||||
- - 手动输入非列表疾病
|
||||
- 自动关联传染病代码库
|
||||
|
||||
- **发病日期**:
|
||||
|
||||
- - 元素类型:日期选择器
|
||||
- 验证规则:不得晚于诊断日期
|
||||
|
||||
- **诊断日期**:
|
||||
|
||||
- - 元素类型:日期选择器
|
||||
- 取值:默认当前系统时间
|
||||
|
||||
- **死亡日期**:
|
||||
|
||||
- - 元素类型:日期选择器
|
||||
- 填写规则:根据实际情况填写
|
||||
|
||||
- **病例分类**
|
||||
|
||||
- - 复选框类型: 1疑似病例/2临床诊断病例/3确诊病例/4病原携带/5阳性检测结果
|
||||
- 校验规则:必填
|
||||
|
||||
|
||||
|
||||
#### 5. 报告信息区
|
||||
|
||||
**区域功能**:记录报告单位和责任人信息等
|
||||
**包含元素**:
|
||||
|
||||
- **报告单位**:
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:当前登录医院
|
||||
- 交互行为:只读
|
||||
|
||||
- **联系电话**:
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:当前登录医院的联系电话
|
||||
- 交互行为:可编辑
|
||||
|
||||
- **报告医生**:
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:当前登录医生
|
||||
- 验证规则:必填
|
||||
|
||||
- **填卡日期**
|
||||
|
||||
- - 默认当前系统日期,显示为"YYYY-MM-DD"格式
|
||||
|
||||
- **修订病名**
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:空
|
||||
- 填写:自定义编辑
|
||||
|
||||
- **退卡原因**
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:空
|
||||
- 填写:自定义编辑
|
||||
|
||||
- **备注**
|
||||
|
||||
- - 元素类型:文本输入
|
||||
- 默认值:空
|
||||
- 填写:自定义编辑
|
||||
|
||||
#### 6. 操作按钮区
|
||||
|
||||
**区域位置**:页面底部
|
||||
**包含元素**:
|
||||
|
||||
- **保存按钮**:
|
||||
|
||||
- - 元素类型:主要操作按钮
|
||||
- 交互行为:触发表单验证,通过后保存
|
||||
- 样式特征:蓝色(#3498db),圆角8px
|
||||
|
||||
- **重置按钮**:
|
||||
|
||||
- - 交互行为:清除非基础信息字段
|
||||
- 特殊处理:保留患者姓名、身份证等关键信息
|
||||
|
||||
- **关闭按钮**:
|
||||
|
||||
- - 交互行为:二次确认后关闭页面
|
||||
- 样式特征:红色(#e74c3c)
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 地址联动选择
|
||||
|
||||
**触发条件**:选择省级行政区
|
||||
**操作流程**:
|
||||
|
||||
1. 选择省份→加载该省下所有城市
|
||||
2. 选择城市→加载该市所有区县
|
||||
3. 选择区县→加载街道列表
|
||||
**异常处理**:网络错误时显示"加载失败,请手动输入"
|
||||
|
||||
#### 2. 疾病分型联动
|
||||
|
||||
**触发条件**:选择特定疾病
|
||||
**数据映射**:
|
||||
|
||||
| **疾病类型** | **分型选项** |
|
||||
| ------------ | ---------------------------------- |
|
||||
| 肺结核 | 涂阳/仅培阳/菌阴/未痰检 |
|
||||
| 梅毒 | I期/II期/III期/胎传/隐性 |
|
||||
| 炭疽 | 肺炭疽/皮肤炭疽/胃肠炭疽/未分型 |
|
||||
| 病毒性肝炎 | 甲/乙/丙/戊型 |
|
||||
| 疟疾 | 间日疟/恶性疟/三日疟/卵形疟/未分型 |
|
||||
| 血吸虫病 | 急性/慢性/晚期/未分型 |
|
||||
|
||||
#### 3. 表单验证
|
||||
|
||||
**全局验证**:
|
||||
|
||||
1. 提交时检查必填字段
|
||||
2. 验证身份证号格式
|
||||
3. 确保至少选择一种疾病
|
||||
**字段级验证**:
|
||||
|
||||
- 电话号码:11位数字,错误提示“请输入有效的联系电话”
|
||||
- 发病日期≤诊断日期≤填卡日期,错误提示“发病日期不能晚于诊断日期”
|
||||
- 身份证号18位且符合校验算法,错误提示“请输入有效的身份证号码”
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
**传染病报卡表(infectious_card)**
|
||||
|
||||
| **字段** | **类型** | **国标含义** | **来源****/****说明** |
|
||||
|---------------------| -------------- |-----------------|--------------------------------------|
|
||||
| card_no | VARCHAR(20) PK | 卡片编号 | 机构代码+年月日+4位流水 |
|
||||
| visit_id | BIGINT FK | 本次就诊ID | adm_encounter.id |
|
||||
| diag_id | BIGINT FK | 诊断记录唯一ID | adm_encounter_diagnosis.condition_id |
|
||||
| pat_id | BIGINT FK | 患者主索引 | adm_patient.id |
|
||||
| id_type | TINYINT | 证件类型 | |
|
||||
| id_no | VARCHAR(30) | 证件号码 | 18位校验 |
|
||||
| pat_name | VARCHAR(50) | 患者姓名 | |
|
||||
| parent_name | VARCHAR(50) | 家长姓名 | ≤14岁必填 |
|
||||
| sex | CHAR(1) | 性别 | 1男/2女/0未知 |
|
||||
| birthday | DATE | 出生日期 | |
|
||||
| age | INT | 实足年龄 | 函数计算 |
|
||||
| age_unit | CHAR(1) | 年龄单位 | 岁/月/天-》1岁/2月/3天 |
|
||||
| workplace | VARCHAR(100) | 工作单位 | 学生填学校 |
|
||||
| phone | VARCHAR(20) | 联系电话 | 患者本人电话 |
|
||||
| contact_phone | VARCHAR(20) | 紧急联系人电话 | |
|
||||
| address_prov | VARCHAR(6) | 现住址省 | GB2260 |
|
||||
| address_city | VARCHAR(6) | 现住址市 | 同上 |
|
||||
| address_county | VARCHAR(6) | 现住址县 | 同上 |
|
||||
| address_town | VARCHAR(9) | 现住址街道 | 同上 |
|
||||
| address_village | VARCHAR(80) | 现住址村/居委 | |
|
||||
| address_house | VARCHAR(40) | 现住址门牌号 | |
|
||||
| patient_belong | TINYINT | 病人属于 | 系统判定,1本县区/2本市其他/3本省其他/4外省/5港澳台/6外籍 |
|
||||
| occupation | VARCHAR(4) | 职业 | GB/T 6565,取值于字典管理的字典名称为“职业”维护的数据 |
|
||||
| disease_code | VARCHAR(8) | 疾病名称 | WS 218-2020,见下表 |
|
||||
| disease_type | VARCHAR(8) | 分型 | 见下表,6类必分型疾病必填 |
|
||||
| other_disease | VARCHAR(50) | 其他法定管理以及重点监测传染病 | |
|
||||
| case_class | TINYINT | 病例分类 | 1疑似病例/2临床诊断病例/3确诊病例/4病原携带/5阳性检测结果 |
|
||||
| onset_date | DATE | 发病日期 | 默认诊断时间,病原携带者填初检日期 |
|
||||
| diag_date | DATETIME | 诊断日期 | 精确到小时 |
|
||||
| death_date | DATE | 死亡日期 | 死亡病例必填 |
|
||||
| correct_name | VARCHAR(50) | 订正病名 | 订正报告必填 |
|
||||
| withdraw_reason | VARCHAR(100) | 退卡原因 | 退卡时必填 |
|
||||
| report_org | VARCHAR(18) | 报告单位 | 统一信用代码(医院名称) |
|
||||
| report_org_phone | VARCHAR(20) | 联系电话 | 报告单位电话:医院总值班/防保科座机 |
|
||||
| report_doc | VARCHAR(20) | 报告医生 | 医生姓名 |
|
||||
| report_date | DATE | 填卡日期 | 当天日期 |
|
||||
| status | TINYINT | 状态 | 0暂存1已提交2已审核3已上报4失败5作废 |
|
||||
| fail_msg | VARCHAR(500) | 失败原因 | 国家平台返回 |
|
||||
| xml_content | TEXT | 上报XML | 日志 |
|
||||
| create_time | DATETIME | 创建时间 | |
|
||||
| update_time | DATETIME | 更新时间 | |
|
||||
| card_name_code | TINYINT | 报卡名称代码 | 数值对照(取值于字典管理-》报卡名称代码)1-中华人民共和国传染病报告卡 |
|
||||
| registration source | TINYINT | 登记来源 | 1门诊/2住院 |
|
||||
| dept_id | TINYINT | 科室ID | 患者当前就诊科室 |
|
||||
| doctor_id | TINYINT | 医生ID | 患者当前开单医生 |
|
||||
|
||||
**甲类传染病(2 种)―― 01xxxx**
|
||||
|
||||
| **disease_code** | **疾病名称** | **国家平台码** |
|
||||
| ---------------- | ------------ | -------------- |
|
||||
| 0101 | 鼠疫 | 甲类 |
|
||||
| 0102 | 霍乱 | 甲类 |
|
||||
|
||||
存值示例:`0101`(鼠疫)、`0102`(霍乱)
|
||||
|
||||
|
||||
|
||||
**乙类传染病(27 种)―― 02xxxx**
|
||||
|
||||
| **disease_code** | **疾病名称** | **国家平台码** |
|
||||
| ---------------- | -------------------- | ------------------ |
|
||||
| 0201 | 传染性非典型肺炎 | 乙类(按甲类管理) |
|
||||
| 0202 | 艾滋病 | 乙类 |
|
||||
| 0203 | 病毒性肝炎 | 乙类 |
|
||||
| 0204 | 脊髓灰质炎 | 乙类(按甲类管理) |
|
||||
| 0205 | 人感染高致病性禽流感 | 乙类(按甲类管理) |
|
||||
| 0206 | 麻疹 | 乙类 |
|
||||
| 0207 | 流行性出血热 | 乙类 |
|
||||
| 0208 | 狂犬病 | 乙类 |
|
||||
| 0209 | 流行性乙型脑炎 | 乙类 |
|
||||
| 0210 | 登革热 | 乙类 |
|
||||
| 0211 | 炭疽 | 乙类(按甲类管理) |
|
||||
| 0212 | 细菌性和阿米巴性痢疾 | 乙类 |
|
||||
| 0213 | 肺结核 | 乙类 |
|
||||
| 0214 | 伤寒和副伤寒 | 乙类 |
|
||||
| 0215 | 流行性脑脊髓膜炎 | 乙类 |
|
||||
| 0216 | 百日咳 | 乙类 |
|
||||
| 0217 | 白喉 | 乙类 |
|
||||
| 0218 | 新生儿破伤风 | 乙类 |
|
||||
| 0219 | 猩红热 | 乙类 |
|
||||
| 0220 | 布鲁氏菌病 | 乙类 |
|
||||
| 0221 | 淋病 | 乙类 |
|
||||
| 0222 | 梅毒 | 乙类 |
|
||||
| 0223 | 钩端螺旋体病 | 乙类 |
|
||||
| 0224 | 血吸虫病 | 乙类 |
|
||||
| 0225 | 疟疾 | 乙类 |
|
||||
|
||||
存值示例:乙肝→`0203`;肺结核→`0213`;梅毒→`0222`
|
||||
|
||||
|
||||
|
||||
**丙类传染病(11 种)―― 03xxxx**
|
||||
|
||||
| **disease_code** | **疾病名称** | **国家平台码** |
|
||||
| ---------------- | ---------------------- | -------------- |
|
||||
| 0301 | 流行性感冒 | 丙类 |
|
||||
| 0302 | 流行性腮腺炎 | 丙类 |
|
||||
| 0303 | 风疹 | 丙类 |
|
||||
| 0304 | 急性出血性结膜炎 | 丙类 |
|
||||
| 0305 | 麻风病 | 丙类 |
|
||||
| 0306 | 流行性和地方性斑疹伤寒 | 丙类 |
|
||||
| 0307 | 黑热病 | 丙类 |
|
||||
| 0308 | 包虫病 | 丙类 |
|
||||
| 0309 | 丝虫病 | 丙类 |
|
||||
| 0310 | 其它感染性腹泻病 | 丙类 |
|
||||
| 0311 | 手足口病 | 丙类 |
|
||||
|
||||
存值示例:手足口病→`0311`;流感→`0301`
|
||||
|
||||
|
||||
|
||||
**分型码与名称对照(系统存值用)**
|
||||
|
||||
| **大类疾病** | **disease_code** | **分型中文** | **disease_type** **存值** |
|
||||
| -------------- | ---------------- | ------------ | ------------------------- |
|
||||
| **病毒性肝炎** | 0203 | 甲型 | 020301 |
|
||||
| | | 乙型 | 020302 |
|
||||
| | | 丙型 | 020303 |
|
||||
| | | 戊型 | 020304 |
|
||||
| | | 未分型 | 020305 |
|
||||
| **炭疽** | 0211 | 肺炭疽 | 021101 |
|
||||
| | | 皮肤炭疽 | 021102 |
|
||||
| | | 胃肠炭疽 | 021103 |
|
||||
| | | 未分型 | 021104 |
|
||||
| **肺结核** | 0213 | 涂阳 | 021301 |
|
||||
| | | 仅培阳 | 021302 |
|
||||
| | | 菌阴 | 021303 |
|
||||
| | | 未痰检 | 021304 |
|
||||
| **梅毒** | 0222 | Ⅰ期 | 022201 |
|
||||
| | | Ⅱ期 | 022202 |
|
||||
| | | Ⅲ期 | 022203 |
|
||||
| | | 胎传 | 022204 |
|
||||
| | | 隐性 | 022205 |
|
||||
| **疟疾** | 0225 | 间日疟 | 022501 |
|
||||
| | | 恶性疟 | 022502 |
|
||||
| | | 三日疟 | 022503 |
|
||||
| | | 卵形疟 | 022504 |
|
||||
| | | 未分型 | 022505 |
|
||||
| **血吸虫病** | 0224 | 急性 | 022401 |
|
||||
| | | 慢性 | 022402 |
|
||||
| | | 晚期 | 022403 |
|
||||
| | | 未分型 | 022404 |
|
||||
|
||||
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- 主色调:#3498db(按钮/重要标签)
|
||||
- 错误状态:#e74c3c(边框+文字)
|
||||
- 表单间距:8px垂直间距,16px水平间距
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- 支持Chrome/Firefox/Edge最新版
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 身份证号不需脱敏显示
|
||||
|
||||
|
||||
349
md/需求/103-医生个人报卡管理界面-2026-1-29.md
Normal file
349
md/需求/103-医生个人报卡管理界面-2026-1-29.md
Normal file
@@ -0,0 +1,349 @@
|
||||
## 医生个人报卡管理界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:医生个人报卡管理界面
|
||||
**页面目标**:为医生提供传染病报告卡的管理功能,包括查看、编辑、提交、撤回、导出等操作,并提供数据统计和筛选功能。
|
||||
**适用场景**:医生需要查看/编辑或管理已填写的传染病报告卡,进行批量操作或筛选特定状态的报告卡
|
||||
**页面类型**:列表页(含筛选功能) + 表单页(编辑/查看模态框)。
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 报卡数据统计展示(总报卡数/待处理失败/已成功上报)
|
||||
2. 报卡列表筛选与查询(按日期/状态/关键词)
|
||||
3. 报卡详情查看与编辑
|
||||
4. 批量操作(全选/批量提交/批量删除)
|
||||
5. 报卡导出为Word格式
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 快速掌握个人报卡工作整体情况
|
||||
- 高效管理不同状态的报卡记录
|
||||
- 规范疾病报告卡流程,确保数据及时准确上报
|
||||
**原型图地址**:https://static.pm-ai.cn/prototype/20260129/865d147e5650ff42c054b38244ed8239/index.html
|
||||
**流程图**:
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([医生进入个人报卡管理界面]) --> Load[展示数据统计卡片]
|
||||
Load --> Stats[展示统计卡片\n总报卡数待处理已上报]
|
||||
Stats --> Filter[渲染筛选区日期状态名称]
|
||||
Filter --> Table[展示报卡列表]
|
||||
|
||||
Table --> Op{用户操作选择}
|
||||
|
||||
Op -->|点击查看| View1[弹出只读模态框]
|
||||
View1 --> View2[展示完整报卡信息]
|
||||
View2 --> View3[关闭模态框]
|
||||
View3 --> Table
|
||||
|
||||
Op -->|点击编辑| Edit1{状态是待提交?}
|
||||
Edit1 -->|否| Table
|
||||
Edit1 -->|是| Edit2[弹出编辑模态框]
|
||||
Edit2 --> Edit3[修改表单字段]
|
||||
Edit3 --> Edit4[点击保存]
|
||||
Edit4 --> Edit5{验证必填项}
|
||||
Edit5 -->|失败| Edit6[显示错误原因]
|
||||
Edit6 --> Edit2
|
||||
Edit5 -->|通过| Edit7[保存数据]
|
||||
Edit7 --> Edit8[提示成功]
|
||||
Edit8 --> Table
|
||||
|
||||
Op -->|点击提交| Sub1{状态是待提交?}
|
||||
Sub1 -->|是| Sub2[确认对话框]
|
||||
Sub2 --> Sub3[变更为已提交]
|
||||
Sub3 --> Sub4[刷新表格统计]
|
||||
Sub4 --> Table
|
||||
Sub1 -->|否| Table
|
||||
|
||||
Op -->|点击撤回| Back1{状态是已提交?}
|
||||
Back1 -->|是| Back2[变更为待提交]
|
||||
Back2 --> Table
|
||||
Back1 -->|否| Table
|
||||
|
||||
Op -->|点击导出| Exp1{状态是已上报?}
|
||||
Exp1 -->|是| Exp2[报告卡导出预览]
|
||||
Exp2 --> Exp3[导出Word文档]
|
||||
Exp3 --> Table
|
||||
Exp1 -->|否| Table
|
||||
|
||||
Op -->|应用筛选| Filt1[触发筛选条件]
|
||||
Filt1 --> Filt2[重新加载列表]
|
||||
Filt2 --> Table
|
||||
|
||||
Op -->|批量操作| Batch1{已选记录?}
|
||||
Batch1 -->|否| Batch2[提示请选择记录]
|
||||
Batch2 --> Table
|
||||
Batch1 -->|是| Batch3{操作类型}
|
||||
|
||||
Batch3 -->|批量提交| Batch4{全是待提交?}
|
||||
Batch4 -->|否| Batch5[提示只能提交待提交]
|
||||
Batch5 --> Table
|
||||
Batch4 -->|是| Batch6[确认数量]
|
||||
Batch6 --> Batch7[更新为已提交]
|
||||
Batch7 --> Batch8[刷新统计数据]
|
||||
Batch8 --> Table
|
||||
|
||||
Batch3 -->|批量删除| Batch9{全是待提交?}
|
||||
Batch9 -->|否| Batch10[提示只能删除待提交]
|
||||
Batch10 --> Table
|
||||
Batch9 -->|是| Batch11[确认删除]
|
||||
Batch11 --> Batch12[状态变为作废]
|
||||
Batch12 --> Batch13[刷新数据]
|
||||
Batch13 --> Table
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. **顶部标题区**(5%):页面标题。
|
||||
2. **数据统计区**(15%):展示总报卡数、待处理失败数、已成功上报数。
|
||||
3. **高级筛选区**(15%):提供日期范围、状态、报卡名称等筛选条件。
|
||||
4. **数据表格区**(55%):展示报卡列表,支持多选和操作按钮。
|
||||
5. **底部批量操作区**(10%):全选、批量删除、批量提交功能。
|
||||
|
||||
**布局特点**:上下布局,采用卡片式设计,主内容区为表格展示
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部标题区
|
||||
|
||||
**区域位置**:页面最上方
|
||||
**区域尺寸**:高度60px,宽度100%。
|
||||
**区域功能**:展示页面标题和主要操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **页面标题**:
|
||||
|
||||
- - 元素类型:文本
|
||||
- 显示内容:“我的报卡”
|
||||
- 样式特征:20px/600,深灰色(#1e293b)
|
||||
|
||||
#### 2. 数据统计卡片区
|
||||
|
||||
**区域位置**:标题区下方
|
||||
**区域尺寸**:高度150px,宽度100%。
|
||||
**区域功能**:展示关键统计数据,帮助医生快速了解报卡状态分布。
|
||||
**包含元素**:
|
||||
|
||||
- **总报卡数卡片**:
|
||||
|
||||
- - 元素类型:统计卡片
|
||||
- 显示内容:图标+数值+“总报卡数”
|
||||
- 样式特征:紫色渐变背景,圆角12px
|
||||
|
||||
- **待处理失败卡片**:
|
||||
|
||||
- - 同总报卡数卡片,红色系配色
|
||||
|
||||
- **已成功上报卡片**:
|
||||
|
||||
- - 同总报卡数卡片,绿色系配色
|
||||
|
||||
#### 3. 高级筛选区
|
||||
|
||||
**区域位置**:统计卡片下方
|
||||
**区域尺寸**:高度150px,宽度100%
|
||||
**区域功能**:提供多维筛选条件,支持快速定位目标报卡。
|
||||
**包含元素**:
|
||||
|
||||
- **日期范围选择器**:
|
||||
|
||||
- - 元素类型:表单控件(两个date输入框)
|
||||
- 交互行为:选择日期后触发筛选。
|
||||
- 限制条件:结束日期不能早于开始日期。
|
||||
|
||||
- **状态筛选下拉框**:
|
||||
|
||||
- - 元素类型:下拉选择
|
||||
- 可选值:全部状态/待提交/已提交/已审核/已上报/失败/作废
|
||||
|
||||
- **报卡名称搜索框**:
|
||||
|
||||
- - 元素类型:文本输入框
|
||||
- 占位文本:“输入报卡名称…”
|
||||
|
||||
- **应用筛选按钮**:
|
||||
|
||||
- - 元素类型:主要操作按钮
|
||||
- 交互行为:点击后触发表格数据刷新
|
||||
|
||||
- **重置条件按钮**:
|
||||
|
||||
- - 元素类型:次要操作按钮
|
||||
- 交互行为:清空所有筛选条件
|
||||
|
||||
#### 4. 数据表格区
|
||||
|
||||
**区域位置**:页面中部
|
||||
**区域尺寸**:高度自适应,宽度100%。
|
||||
**区域功能**:展示报卡列表及提供行级操作
|
||||
**包含元素**:
|
||||
|
||||
- **表格头部**:
|
||||
|
||||
**数据主要取值于传染病报卡表(infectious_card)**
|
||||
|
||||
- - 包含字段:选择框、卡片ID、患者姓名、身份证号、联系电话、就诊卡号、报卡名称、提交时间、状态、操作
|
||||
- 样式特征:灰色背景,13px字号,大写字母
|
||||
|
||||
- **表格内容行**:
|
||||
|
||||
- - 展示方式:每行显示一条报卡记录
|
||||
|
||||
- 数据字段:
|
||||
|
||||
- - 卡片ID:文本 - HOSP202601150001 - 不可操作
|
||||
- 患者姓名:文本 - 张三 - 不可操作
|
||||
- 身份证号:不脱敏文本 - 110101199001011234 - 不可操作
|
||||
- 联系电话:文本 - 13800138000 - 不可操作
|
||||
- 就诊卡号:文本 - M12345678 - 不可操作
|
||||
- 报卡名称:文本 - 中华人民共和国传染病报告卡 - 不可操作
|
||||
- 提交时间:时间 - 2026-01-15 14:30 - 不可操作
|
||||
- 状态标签:根据状态值显示不同颜色
|
||||
|
||||
- 操作功能:
|
||||
|
||||
- - 查看按钮:所有状态可见
|
||||
- 编辑按钮:仅"待提交"状态可见
|
||||
- 提交按钮:仅"待提交"状态可见
|
||||
- 撤回按钮:仅"已提交"状态可见
|
||||
- 导出按钮:仅"已上报"状态可见
|
||||
|
||||
#### 5. 底部批量操作区
|
||||
|
||||
**区域位置**:页面底部
|
||||
**区域尺寸**:高度60px,宽度100%。
|
||||
**区域功能**:支持批量操作选中报卡。
|
||||
**包含元素**:
|
||||
|
||||
- **全选复选框**:
|
||||
|
||||
- - 交互行为:勾选后选中当前页所有记录
|
||||
|
||||
- **批量删除按钮**:
|
||||
|
||||
- - 元素类型:文本按钮
|
||||
- 限制条件:仅对"待提交"状态记录有效
|
||||
- 交互行为:提交后状态变为"作废"。
|
||||
|
||||
- **批量提交按钮**:
|
||||
|
||||
- - 元素类型:主要操作按钮
|
||||
- 限制条件:仅对"待提交"状态记录有效
|
||||
- 交互行为:提交后状态变为"已提交"。
|
||||
|
||||
#### 6. 报卡详情弹窗(界面内容功能与需求编号102界面保持一致,建议用同一个界面)
|
||||
|
||||
**区域位置**:页面居中模态框
|
||||
**区域功能**:查看/编辑完整报卡信息
|
||||
**包含元素**:
|
||||
|
||||
- 表单字段(按模块分组):
|
||||
|
||||
- 1. 患者基本信息(姓名/身份证号/联系方式*)
|
||||
2. 临床信息(发病日期/诊断日期*)
|
||||
3. 传染病分类(甲/乙/丙类多选*)
|
||||
4. 报告信息(报告单位/医生*)
|
||||
|
||||
- 操作按钮:
|
||||
|
||||
o 取消:关闭弹窗不保存
|
||||
|
||||
o 保存:验证必填项后保持数据
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 报卡查看功能
|
||||
|
||||
**功能描述**:查看报卡详细信息
|
||||
**触发条件**:点击任意行的"查看"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出模态框展示完整报卡信息
|
||||
2. 所有字段为只读状态
|
||||
3. 点击关闭按钮或蒙层关闭模态框
|
||||
|
||||
#### 2. 报卡编辑功能
|
||||
|
||||
**功能描述**:修改待提交的报卡信息
|
||||
**触发条件**:点击"待提交"状态的"编辑"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出可编辑的报卡表单模态框
|
||||
2. 修改必要字段(带*号为必填项)
|
||||
3. 点击"保存"按钮提交修改
|
||||
4. 成功提示后关闭模态框
|
||||
|
||||
#### 3. 批量提交功能
|
||||
|
||||
**功能描述**:批量提交选中的待提交报卡
|
||||
**触发条件**:勾选记录后点击"批量提交"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 校验是否选中有效记录(状态为待提交)
|
||||
2. 弹出确认对话框显示待提交数量
|
||||
3. 确认后更新记录状态为"已提交"
|
||||
4. 刷新表格数据和统计卡片
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 未选中记录:提示"请选择待提交的记录"
|
||||
- 包含不可提交记录:提示"只能提交待提交状态的记录"
|
||||
|
||||
#### 4. 报卡状态流转
|
||||
|
||||
**触发方式**:点击操作列按钮
|
||||
**执行流程**:
|
||||
|
||||
1. 待提交 → 已提交:点击"提交"按钮 → 弹窗确认 → 状态变更
|
||||
2. 已提交 → 待提交:点击"撤回"按钮 → 状态回滚
|
||||
3. 已上报 → 导出:生成标准疾病报告卡Word文档(含医院红头格式)
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 提交失败:显示具体错误原因(如:必填项未完成)
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
**关键数据字段**:
|
||||
|
||||
**传染病报卡表(infectious_card)**
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:#6366f1(紫色)
|
||||
|
||||
- **状态色**:
|
||||
|
||||
- - 待提交:#f59e0b(橙色)
|
||||
- 已提交:#2563eb(蓝色)
|
||||
- 已上报:#16a34a(绿色)
|
||||
- 失败:#dc2626(红色)
|
||||
|
||||
- **字体规范**:
|
||||
|
||||
- - 标题:20px/600
|
||||
- 正文:14px/400
|
||||
|
||||
- **间距系统**:
|
||||
|
||||
- - 卡片内边距:24px
|
||||
- 元素间距:16px
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- **表格组件**:需支持虚拟滚动(大数据量场景)
|
||||
- **导出功能**:实现Word导出
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 身份证号等敏感信息不需做脱敏处理
|
||||
2. 批量操作需考虑性能优化(分页处理)
|
||||
3. 状态变更需同步更新统计卡片数据
|
||||
4. 移动端需特别处理表格的横向滚动体验
|
||||
5. ‘待提交’状态就是‘暂存’状态
|
||||
6. 只能查询医生本人报卡的数据
|
||||
434
md/需求/104-报卡管理界面_2026-02-05.md
Normal file
434
md/需求/104-报卡管理界面_2026-02-05.md
Normal file
@@ -0,0 +1,434 @@
|
||||
## 报卡管理界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:报卡管理界面
|
||||
**页面目标**:提供传染病报卡的审核、管理、筛选及批量操作功能,帮助疾控人员高效完成报卡审核工作
|
||||
**适用场景**:疾控中心工作人员日常审核医疗机构上报的传染病病例
|
||||
|
||||
- 医院CDC管理员日常审核传染病报卡
|
||||
- 批量处理待审核/退回的报卡
|
||||
- 按条件筛选统计报卡数据
|
||||
**页面类型**:数据管理列表页(含详情抽屉)
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 报卡数据概览统计(今日待审/本月失败/本月成功/本月上报)
|
||||
2. 多维度筛选报卡数据(时间/状态/科室/来源等)
|
||||
3. 报卡列表展示与批量操作(审核/退回/导出)
|
||||
4. 报卡详情查看与单条审核
|
||||
5. 审核记录追溯与意见填写
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 疾控人员可快速处理待审报卡
|
||||
- 支持批量审核提升工作效率
|
||||
- 完整记录审核过程便于追溯
|
||||
- 多维度筛选快速定位目标报卡
|
||||
**原型图地址**:https://static.pm-ai.cn/prototype/20260206/cc9991b716df0303fa3459042e33a1ea/index.html
|
||||
**流程图**:
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["进入报卡管理界面"] --> B["查看报卡概览统计"]
|
||||
B --> C["点击统计卡片"]
|
||||
C --> D["悬停统计卡片"]
|
||||
D --> E["自动设置筛选项"]
|
||||
B --> F["鼠标悬停"]
|
||||
F --> G["筛选报卡数据"]
|
||||
G --> H["卡片上浮+阴影"]
|
||||
E --> I["设置筛选条件"]
|
||||
I --> K["点击重置按钮"]
|
||||
K --> J["清空条件"]
|
||||
I --> L["点击查询按钮"]
|
||||
L --> M["触发筛选"]
|
||||
M --> N["操作报卡列表"]
|
||||
N --> O["勾选报卡"]
|
||||
N --> P["处理单条报卡"]
|
||||
O --> Q["批量操作报卡"]
|
||||
P --> R["点击单条审核"]
|
||||
P --> S["点击单条查看"]
|
||||
Q --> T["点击批量审核"]
|
||||
Q --> U["点击批量退回"]
|
||||
R --> V{"报卡状态"}
|
||||
S --> W{"报卡状态"}
|
||||
V -- 已审核 --> X["打开查看抽屉"]
|
||||
V -- 待审核/失败 --> Y["校验选择状态"]
|
||||
W -- 任意 --> X
|
||||
T --> Z["校验选择状态"]
|
||||
U --> AA["校验选择状态"]
|
||||
Y -- 选择有效 --> AB["打开审核抽屉"]
|
||||
AB-->AN["展示审核记录"]
|
||||
AB-->AO["展示审核记录"]
|
||||
Y -- 未选择 --> AC["提示请选择报卡"]
|
||||
Z -- 选择有效 --> AD{"包含已审核项"}
|
||||
Z -- 未选择 --> AE["提示请选择报卡"]
|
||||
AD -- 是 --> AF["提示只能选择待审核报卡"]
|
||||
AD -- 否 --> AG["弹出审核弹窗"]
|
||||
AA -- 选择有效 --> AH{"包含已审核项"}
|
||||
AA -- 未选择 --> AI["提示请选择报卡"]
|
||||
AH -- 是 --> AF
|
||||
AH -- 否 --> AJ["弹出退回弹窗"]
|
||||
AG --> AK["加载报卡详情"]
|
||||
AJ --> AL["加载报卡详情"]
|
||||
AK -- 加载失败 --> AM["提示数据加载失败"]
|
||||
AL -- 加载失败 --> AM
|
||||
AK -- 成功 --> AN["展示审核记录"]
|
||||
AL -- 成功 --> AO["展示审核记录"]
|
||||
AN --> AP["填写审核意见"]
|
||||
AO --> AQ["填写退回原因"]
|
||||
AP --> AR{"意见是否为空"}
|
||||
AQ --> AS{"原因是否为空"}
|
||||
AR -- 是 --> AT["红字提示必填"]
|
||||
AS -- 是 --> AU["红字提示必填"]
|
||||
AR -- 否 --> AV["点击确认审核"]
|
||||
AS -- 否 --> AW["点击确认退回"]
|
||||
AV --> AX["点击审核通过"]
|
||||
AW --> AY["点击退回修改"]
|
||||
AX --> AZ["更新报卡状态"]
|
||||
AY --> BA["更新报卡状态"]
|
||||
AZ --> BB["生成审核记录"]
|
||||
BA --> BC["生成审核记录"]
|
||||
BB --> BD["按钮置灰"]
|
||||
BC --> BD["按钮置灰"]
|
||||
AX --> BE["提示操作失败,请检查网络"]
|
||||
AY --> BE
|
||||
AZ --> BF["刷新表格数据"]
|
||||
BA --> BF
|
||||
BF --> BG["刷新行状态"]
|
||||
BG --> BH["结束"]
|
||||
BE --> BH
|
||||
```
|
||||
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. **顶部导航栏**(固定高度60px)
|
||||
2. **报卡管理概览区**(统计卡片+快捷操作,高度自适应)
|
||||
3. **筛选控制区**(多条件组合筛选,折叠式布局)
|
||||
4. **报卡列表区**(表格展示,占主体60%高度)
|
||||
**布局特点**:上下层级结构,筛选区支持折叠/展开
|
||||
5. **抽屉详情区**
|
||||
|
||||
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部导航栏
|
||||
|
||||
**区域位置**:页面顶部固定
|
||||
**区域尺寸**:高度60px,100%宽度
|
||||
**区域功能**:展示系统标识和用户信息
|
||||
**包含元素**:
|
||||
|
||||
- **系统Logo**
|
||||
|
||||
- - 元素类型:图标+文字组合
|
||||
- 显示内容:"CDC"图标+"报卡管理"文字
|
||||
- 样式特征:蓝色主色调(#4a6fa5),左侧对齐
|
||||
|
||||
#### 2. 报卡管理概览
|
||||
|
||||
**区域位置**:导航栏下方
|
||||
|
||||
**区域尺寸**:100%宽度,自适应高度
|
||||
**区域功能**:关键数据统计与快速操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **统计卡片组**(4个)
|
||||
|
||||
- - 展示方式:网格布局(4列)
|
||||
- 数据字段:
|
||||
|
||||
| **字段名** | **类型** | **示例值** | **可操作** | **计算逻辑** |
|
||||
| ------------ | -------- | ---------- | ---------- | ------------------------- |
|
||||
| 今日待审核 | 数字 | 12 | 可点击 | 当天created_at+待审状态 |
|
||||
| 本月审核失败 | 数字 | 3 | 可点击 | 当月created_at+失败状态 |
|
||||
| 本月审核成功 | 数字 | 2 | 可点击 | 当月created_at+成功状态 |
|
||||
| 本月已上报 | 数字 | 156 | 可点击 | 当月created_at+已上报状态 |
|
||||
|
||||
o 交互行为:
|
||||
|
||||
- - - 悬停:卡片上浮5px+阴影加深
|
||||
- 点击:自动设置对应筛选项
|
||||
|
||||
- 样式特征:左侧状态色条(蓝/橙/红/绿)
|
||||
|
||||
#### 3. 筛选控制区
|
||||
|
||||
**区域功能**:多维度组合筛选报卡数据
|
||||
|
||||
**区域尺寸**:100%宽度,高度自适应(展开状态)
|
||||
**包含元素**:
|
||||
|
||||
- **筛选条件组**(横向排列→移动端垂直堆叠)
|
||||
|
||||
- - 登记来源(下拉单选):全部/门诊/住院/急诊/体检
|
||||
- 上报时间范围(双日期选择器)--默认值:最近一个月
|
||||
- 患者姓名(文本输入)
|
||||
- 审核状态(下拉单选):全部/待审核/审核通过/审核失败/已上报
|
||||
- 上报科室(树形下拉多选)--全部科室/取值于《科室管理》adm_organization表
|
||||
|
||||
- **操作按钮**:
|
||||
|
||||
- - “查询”(主按钮,触发筛选)
|
||||
- “重置”(次要按钮,清空条件)
|
||||
|
||||
#### 4. 报卡列表区
|
||||
|
||||
**区域功能**:展示报卡数据及操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **表格头部**
|
||||
|
||||
- - 全选复选框(联动所有行选择状态)
|
||||
- 列标题:报卡名称/病种名称/患者信息等11列
|
||||
|
||||
- **快捷操作按钮组**
|
||||
|
||||
- - 包含按钮:
|
||||
|
||||
- - “批量审核”蓝色按钮,(需选择条目)点击弹出填写审核备注弹窗
|
||||
- “批量退回修改”橙色警示按钮,(需选择条目)点击弹出退回原因填写弹窗
|
||||
- “导出当前”(按筛选条件)
|
||||
|
||||
- **表格行**
|
||||
|
||||
- - 数据字段:
|
||||
|
||||
取值于传染病报卡表(infectious_card)
|
||||
|
||||
| **列名** | **数据类型** | **示例值** | **说明** |
|
||||
| -------- | ------------ | ---------------- | --------------- |
|
||||
| 选择框 | boolean | - | 带全选功能 |
|
||||
| 报卡名称 | string | 传染病报告卡 | - |
|
||||
| 病种名称 | string | 病毒性肝炎 | - |
|
||||
| 报卡编号 | string | HOSP202601150001 | 唯一标识 |
|
||||
| 患者姓名 | string | 张某某 | 脱敏显示 |
|
||||
| 性别 | enum | 男 | 男/女/未知 |
|
||||
| 年龄 | number | 32 | - |
|
||||
| 上报科室 | string | 儿科 | - |
|
||||
| 登记来源 | string | 门诊 | - |
|
||||
| 上报时间 | datetime | 2026-01-31 09:23 | - |
|
||||
| 状态 | badge | 待审核 | 待审核<->已提交 |
|
||||
| 操作 | button | 审核/查看 | 根据状态禁用 |
|
||||
|
||||
|
||||
|
||||
- - 行操作按钮:
|
||||
|
||||
- - “审核”(主按钮,打开可编辑抽屉)
|
||||
- “查看”(次要按钮,打开只读抽屉)
|
||||
|
||||
- 交互规则:
|
||||
|
||||
- - 已审核通过的报卡禁用"审核"按钮
|
||||
- 行hover时显示浅蓝色背景
|
||||
|
||||
- 分页功能:
|
||||
|
||||
- - 实现分页功能(可以设置每页5/10/20条)
|
||||
|
||||
#### 5. 抽屉详情区
|
||||
|
||||
**区域位置**:右侧滑出
|
||||
**区域尺寸**:自适应布局
|
||||
**包含元素**:
|
||||
|
||||
· **报卡表单(****根据具体报卡登记的界面内容,比如《中华人民共和国传染病报告卡》内容和功能与需求编号102界面保持一致,建议用同一个界面)**
|
||||
|
||||
- - 字段分组:
|
||||
|
||||
- 1. 患者基本信息(姓名、身份证等)
|
||||
2. 临床信息(发病日期、诊断分类等)
|
||||
3. 疾病选择(甲/乙/丙类传染病复选框)
|
||||
4. 上报信息(报告单位、医生等)
|
||||
|
||||
· **审核记录**
|
||||
|
||||
- - 展示方式:时间轴列表
|
||||
- 数据字段:时间、操作人、操作类型、意见
|
||||
|
||||
· **操作按钮组**
|
||||
|
||||
- - 主按钮:审核通过(绿色)
|
||||
- 次按钮:退回修改(橙色)
|
||||
|
||||
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 批量审核流程
|
||||
|
||||
**触发条件**:勾选多行后点击"批量审核"
|
||||
**操作流程**:
|
||||
|
||||
1. 系统校验:至少选择1条非"已通过"状态的报卡
|
||||
|
||||
2. 弹出审核弹窗(500px居中模态框)
|
||||
|
||||
3. 填写审核意见(必填)
|
||||
|
||||
4. 点击"确认审核":
|
||||
|
||||
5. 批量更新状态为"审核通过",(自动批量写入每一条审核记录(插入infectious_audit 字段详表②、更改表infectious_card. Statu= 2和infectious_card. update_time= now()))
|
||||
|
||||
6. 刷新表格数据
|
||||
|
||||
7. - 成功:更新状态为"审核通过",添加审核记录
|
||||
- 失败:提示"审核失败,请检查网络"
|
||||
- 包含已审核项:提示"只能选择待审核报卡"
|
||||
- 未填写意见:阻止提交并红字提示
|
||||
|
||||
#### 2. 批量退回修改操作
|
||||
|
||||
**触发方式**:勾选多选框后点击"批量退回"
|
||||
**前置校验**:
|
||||
|
||||
- 至少勾选一条非"已审核"状态报卡
|
||||
- 选中已审核报卡时提示"只能操作待审核报卡"
|
||||
|
||||
**执行流程**:
|
||||
|
||||
1. 弹出模态框要求填写退回原因(必填)填写退回原因:阻止提交并红字提示
|
||||
2. 提交后批量更新选中报卡状态
|
||||
3. 每条生成审核记录(①、插入infectious_audit 字段详表②、更改表infectious_card. Statu=5和infectious_card. update_time= now())
|
||||
|
||||
#### 3.单卡审核流程
|
||||
|
||||
**触发方式**:点击操作列"审核"按钮
|
||||
**状态控制**:
|
||||
|
||||
- 待审核/审核失败:可操作
|
||||
- 审核通过:按钮禁用
|
||||
**执行流程**:
|
||||
|
||||
1. 右侧滑出审核抽屉
|
||||
2. 从行数据获取报卡ID自动填充患者报卡信息(异步加载报卡详情数据)
|
||||
3. 展示历史审核记录(如有)
|
||||
4. 填写审核意见/退回原因
|
||||
5. 点击"审核通过"或"退回修改"
|
||||
6. 更新表格行状态(生成审核记录(①、插入infectious_audit 字段详表②、更改表infectious_card. Statu=2/5和infectious_card. update_time= now()))
|
||||
|
||||
**异常处理**:
|
||||
|
||||
· 数据加载失败:提示"数据加载失败,请重试"
|
||||
|
||||
**·** 重复提交:按钮置灰防止重复点击
|
||||
|
||||
**状态变化**:
|
||||
|
||||
- 审核通过:表格行变绿色,按钮禁用,状态变成“审核通过”
|
||||
- 退回修改:表格行变橙色,生成退回记录,状态变成“审核失败”审核失败<->退回
|
||||
|
||||
**数据校验**:
|
||||
|
||||
- 必填字段红框提示
|
||||
- 身份证号格式校验
|
||||
- 日期逻辑校验(发病日期≤诊断日期)
|
||||
|
||||
#### 4. 筛选查询功能
|
||||
|
||||
**触发方式**:点击"查询"按钮
|
||||
**查询逻辑**:
|
||||
|
||||
- 登记来源:精确匹配
|
||||
- 患者姓名:模糊匹配
|
||||
- 时间范围:闭区间查询
|
||||
- 状态筛选:精确匹配
|
||||
- 上报科室:多选
|
||||
**性能优化**:
|
||||
- 500ms防抖处理
|
||||
- 分页加载(可以设置每页5/10/20条)实现分页功能
|
||||
|
||||
#### 5. 报卡详情查看
|
||||
|
||||
**触发条件**:点击行"查看"按钮
|
||||
**抽屉内容**:
|
||||
|
||||
- 只读表单(包含所有报卡字段)
|
||||
- 审核记录时间轴(倒序展示)
|
||||
- 关闭按钮(右上角×图标)
|
||||
**数据加载**:根据行数据获取报卡ID自动填充患者报卡信息(异步加载报卡详情数据)
|
||||
|
||||
#### 6. 筛选联动逻辑
|
||||
|
||||
| **操作** | **系统响应** |
|
||||
| ---------------------- | ------------------------------------------ |
|
||||
| 点击"今日待审核"统计卡 | 自动设置: - 时间=当天 - 状态=待审核 |
|
||||
| 本月审核失败 | 自动设置: - 时间=本月 - 状态=审核失败 |
|
||||
| 本月审核成功 | 自动设置: - 时间=本月 - 状态=审核成功 |
|
||||
| 本月已上报 | 自动设置: - 时间=本月 - 状态=已上报 |
|
||||
|
||||
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
**关键数据表**:
|
||||
|
||||
```
|
||||
|
||||
infectious_card 与报卡审核记录表(infectious_audit)采用 一对多 关联:
|
||||
① 、一张报卡可经历多次审核(初审、复审、退回、重审等)。
|
||||
② 、关联键:infectious_card.card_no → infectious_audit.card_id(FK)。
|
||||
*infectious_card. Statu增加状态5退回=审核失败(当批量退回修改/退回修改时更改表infectious_card. Statu=5 and infectious_card. update_time= now())
|
||||
|
||||
*infectious_audit 字段详表
|
||||
```
|
||||
|
||||
| **字段名** | **中文名称** | **取值说明** | **类型****(PG)** | **约束** |
|
||||
| ----------------- | ------------ | ------------------------------------------------------------ | ---------------- | ---------------------------------------- |
|
||||
| audit_id | 审核记录ID | 主键,自增 | BIGINT | PRIMARY KEY |
|
||||
| card_id | 报卡ID | 关联infectious_card.card_no | BIGINT | NOT NULL, FK |
|
||||
| audit_seq | 审核序号 | 第几次审核,从1开始 | SMALLINT | NOT NULL, ≥1 |
|
||||
| audit_type | 审核类型 | 1批量审核/2单审核通过/3批量退回修改/4单退回修改 /5其他 | CHAR(1) | NOT NULL, IN('1','2','3','4','5') |
|
||||
| audit_status_from | 审核前状态 | 同infectious_card.status(0暂存/1已提交=待审核/2已审核=审核通过/3已上报/4失败/5退回=审核失败) | CHAR(1) | NOT NULL, IN('0','1','2','3','4','5') |
|
||||
| audit_status_to | 审核后状态 | 同上,审核后的新状态 | CHAR(1) | NOT NULL, IN('0','1','2','3','4') |
|
||||
| audit_time | 审核时间 | 精确到秒,当前时间戳 | TIMESTAMP | NOT NULL, DEFAULT now() |
|
||||
| auditor_id | 审核人账号 | 登录账号 | VARCHAR(20) | NOT NULL |
|
||||
| auditor_name | 审核人姓名 | 登录账号的姓名 | VARCHAR(50) | NOT NULL |
|
||||
| audit_opinion | 审核意见 | 审核意见简述 | TEXT | |
|
||||
| Reason_for_return | 退回原因 | 退回原因简述 | TEXT | |
|
||||
| fail_reason_code | 失败原因码 | 字典:001必填项/002逻辑错误/003网络超时等 | VARCHAR(20) | |
|
||||
| fail_reason_desc | 失败详情 | 详细描述,可空 | TEXT | |
|
||||
| is_batch | 是否批量 | 0单条审核/1批量审核 | BOOLEAN | NOT NULL, DEFAULT false |
|
||||
| batch_size | 批量数量 | 批量时涉及报卡数 | INTEGER | NOT NULL, DEFAULT 1, ≥1 |
|
||||
| created_time | 记录创建时间 | 自动生成 | TIMESTAMP | NOT NULL, DEFAULT now() |
|
||||
| updated_time | 记录更新时间 | 自动更新 | TIMESTAMP | NOT NULL, DEFAULT now(), ON UPDATE now() |
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:`#4a6fa5`(导航栏/主按钮)
|
||||
|
||||
- **状态色**:
|
||||
|
||||
- - 待审核:`rgba(74, 111, 165, 0.1)`
|
||||
- 审核失败:`rgba(231, 76, 60, 0.1)`
|
||||
|
||||
- **字体**:
|
||||
|
||||
- - 标题:`16px/1.5 #333`
|
||||
- 表格内容:`14px/1.5 #666`
|
||||
|
||||
**注意事项**:
|
||||
|
||||
- 审核记录需永久保存不可删除
|
||||
|
||||
|
||||
|
||||
### 七、补充说明
|
||||
|
||||
1. **日期格式**:统一使用`YYYY/MM/DD`(符合医疗系统惯例)
|
||||
2. **地址组件**:四级联动(省→市→区→街道)
|
||||
3. **职业选项**:使用国家标准职业分类
|
||||
4. **病种名称**:严格遵循《传染病报告卡》规范用词
|
||||
287
md/需求/94-手术室维护界面_2026-1-9.md
Normal file
287
md/需求/94-手术室维护界面_2026-1-9.md
Normal file
@@ -0,0 +1,287 @@
|
||||
## 手术室维护界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:手术室维护界面
|
||||
**页面目标**:提供手术室基础数据的维护功能,包括新增、编辑、启用/停用手术室信息,为手术安排提供基础数据支持
|
||||
**适用场景**:医院管理员需要新增、修改、启用/停用手术室信息时使用
|
||||
**页面类型**:列表页+表单页(含模态框)
|
||||
|
||||
**原型图地址:**https://static.pm-ai.cn/prototype/20260104/ee5d222231effefcb39624d1646a2e20/index.html
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 手术室列表展示与查询
|
||||
2. 新增手术室信息
|
||||
3. 编辑现有手术室信息
|
||||
4. 启用/停用手术室状态
|
||||
5. 数据有效性校验
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 管理员可集中管理所有手术室基础信息
|
||||
- 确保手术安排时能获取准确的手术室数据
|
||||
- 通过状态管理控制手术室可用性
|
||||
|
||||
**流程图:**
|
||||
|
||||

|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[手术室维护界面] --> B[手术室列表展示]
|
||||
|
||||
B --> C[新增手术室]
|
||||
|
||||
B --> D[编辑手术室]
|
||||
|
||||
B --> E[启用/停用手术室]
|
||||
|
||||
B --> F[查询手术室]
|
||||
|
||||
C --> G[点击新增按钮]
|
||||
|
||||
G --> H[打开新增模态框]
|
||||
|
||||
H --> I[填写表单字段]
|
||||
|
||||
I --> J{必填字段校验}
|
||||
|
||||
J -->|通过| K[提交数据]
|
||||
|
||||
J -->|不通过| L[提示请填写所有必填项]
|
||||
|
||||
K --> M[表格新增数据行]
|
||||
|
||||
D --> N[点击修改按钮]
|
||||
|
||||
N --> O[打开编辑模态框]
|
||||
|
||||
O --> P[修改表单字段]
|
||||
|
||||
P --> Q{必填字段校验}
|
||||
|
||||
Q -->|通过| R[保存数据]
|
||||
|
||||
Q -->|不通过| S[提示请填写所有必填项]
|
||||
|
||||
R --> T[更新表格对应行]
|
||||
|
||||
E --> U[点击启用/停用按钮]
|
||||
|
||||
U --> V{二次确认}
|
||||
|
||||
V -->|确认| W[切换状态标签]
|
||||
|
||||
V -->|取消| X[取消操作]
|
||||
|
||||
W --> Y[更新按钮状态]
|
||||
|
||||
F --> Z[输入查询条件]
|
||||
|
||||
Z --> AA[筛选表格数据]
|
||||
|
||||
K --> AB{房间号重复校验}
|
||||
|
||||
AB -->|不重复| AC[提示房间号已存在]
|
||||
|
||||
AB -->|重复| AD[更新按钮状态]
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. 页头区域(15%高度)
|
||||
2. 表格展示区(85%高度)
|
||||
**布局特点**:上下布局,表格采用固定表头+滚动内容区设计
|
||||
**响应式要求**:移动端适配时改为纵向堆叠布局,操作按钮组变为纵向排列
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 页头区域
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:高度60px,宽度100%
|
||||
**区域功能**:展示标题和主要操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **标题文本**
|
||||
- 元素类型:H1标题
|
||||
- 显示内容:"手术室列表"
|
||||
- 样式特征:1.75rem/600字重,深灰色(#333)
|
||||
- **新增按钮**
|
||||
- 元素类型:主要操作按钮
|
||||
- 显示内容:"新增"(带+图标)
|
||||
- 交互行为:点击触发新增模态框
|
||||
- 样式特征:蓝色背景(#5a7cff),白色文字,8px圆角,悬停上浮1px
|
||||
|
||||
#### 2. 表格展示区(手术室列表表格)
|
||||
|
||||
**区域位置**:页头下方
|
||||
**区域尺寸**:高度自适应,宽度100%
|
||||
**区域功能**:展示手术室数据并支持行级操作
|
||||
**包含元素**:
|
||||
|
||||
- **数据表格**
|
||||
- 展示方式:固定表头表格
|
||||
- 数据字段:
|
||||
- 房间号:文本 - OR01 - 不可操作
|
||||
- 手术室名称:文本 - 第一手术室 - 不可操作
|
||||
- 类型:文本 - 普通/日间/复合 - 不可操作
|
||||
- 所属科室:文本 - 外科 - 不可操作
|
||||
- 状态:标签 - 有效/无效 - 通过操作按钮切换
|
||||
- 操作功能:每行包含"修改"和"状态切换(停用-黄色/启用-绿色)"按钮
|
||||
- **表格样式**:
|
||||
- 表头:浅灰色背景(#f8f9fa),大写字母,14px字号
|
||||
- 行悬停:浅灰色背景(#f8f9fa)
|
||||
- 状态标签:
|
||||
- 有效:绿色背景+文字(#28a745)
|
||||
- 无效:灰色背景+文字(#6c757d)
|
||||
|
||||
#### 3. 新增手术室弹窗
|
||||
|
||||
**区域位置**:页面居中模态弹窗
|
||||
**区域功能**:收集新增手术室所需信息
|
||||
**包含元素**:
|
||||
|
||||
- 表单字段:
|
||||
1. 房间号输入框
|
||||
2. 类型:文本输入
|
||||
3. 必填:是
|
||||
4. 示例值:OR04
|
||||
5. 校验规则:非空校验
|
||||
6. 手术室名称输入框
|
||||
- 类型:文本输入
|
||||
- 必填:是
|
||||
- 示例值:第四手术室
|
||||
1. 手术室类型下拉框
|
||||
- 类型:单选下拉
|
||||
- 选项:普通/日间/复合/特殊
|
||||
- 默认值:普通
|
||||
1. 所属科室下拉框
|
||||
- 类型:单选下拉
|
||||
- 必填:是
|
||||
- 选项:外科/妇产科等8个科室
|
||||
- 默认提示:"请选择科室"
|
||||
- 操作按钮:
|
||||
- 取消按钮(灰色边框)
|
||||
- 确认按钮(蓝色填充)
|
||||
- 校验逻辑:必填字段非空校验
|
||||
- 成功反馈:提示"手术室添加成功"
|
||||
- 失败反馈:提示"请填写所有必填项"
|
||||
|
||||
#### 4. 编辑手术室弹窗
|
||||
|
||||
**区域位置**:页面居中模态弹窗
|
||||
**区域功能**:修改现有手术室信息
|
||||
**包含元素**:
|
||||
|
||||
- 表单字段(同新增弹窗,带初始值)
|
||||
- 操作按钮:
|
||||
- 取消按钮
|
||||
- 保存按钮
|
||||
- 校验逻辑:同新增弹窗
|
||||
- 成功反馈:提示"手术室信息已更新"
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 新增手术室
|
||||
|
||||
**功能描述**:添加新的手术室记录
|
||||
**触发条件**:点击页头"新增"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 打开新增模态框
|
||||
2. 填写必填字段(房间号、名称、科室)
|
||||
3. 点击确认提交(插入his_or_room表)
|
||||
4. 表格末尾新增数据行
|
||||
**异常处理**:
|
||||
- 必填项为空时弹出"请填写所有必填项"提示
|
||||
- 房间号重复需在后端校验并提示
|
||||
|
||||
#### 2. 编辑手术室
|
||||
|
||||
**功能描述**:修改现有手术室信息
|
||||
**触发条件**:点击行内"修改"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 打开编辑模态框(自动填充当前行数据)
|
||||
2. 用户修改数据
|
||||
3. 点击"保存"时校验并更新对应行数据
|
||||
**状态保持**:记录当前编辑行索引确保数据更新准确
|
||||
|
||||
#### 3. 状态切换
|
||||
|
||||
**功能描述**:启用/停用手术室
|
||||
**触发条件**:点击"停用"或"启用"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出二次确认对话框
|
||||
2. 用户确认后切换状态标签
|
||||
3. 按钮变为相反操作(停用↔启用)
|
||||
4. 、停用手术室
|
||||
- **步骤**:
|
||||
1. 查询需要停用的手术室记录。
|
||||
2. 将 valid_flag 设置为 0(无效)。
|
||||
- **示例**:
|
||||
|
||||
UPDATE his_or_room
|
||||
|
||||
SET valid_flag = '0'
|
||||
|
||||
WHERE room_code = 'OR06';
|
||||
|
||||
5\. 启用手术室
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. 查询需要启用的手术室记录。
|
||||
1. 将 valid_flag 设置为 1(有效)。
|
||||
- **示例**:
|
||||
|
||||
UPDATE his_or_room
|
||||
|
||||
SET valid_flag = '1'
|
||||
|
||||
WHERE room_code = 'OR06';
|
||||
|
||||
**防误操作**:所有状态变更需二次确认
|
||||
|
||||
### 五、数据结构说明(HIS_OR_ROOM手术室字典表)
|
||||
|
||||
| **字段名称** | **数据类型** | **是否为空** | **说明/典型值** | **外键/来源** |
|
||||
|--------------|--------------|--------------|-----------------|-------------------------------|
|
||||
| room_id | VARCHAR(10) | N | 主键 | 自增主键 |
|
||||
| room_code | VARCHAR(10) | N | 手术室房间号 | 自定义编码,如 OR01、OR02 |
|
||||
| room_name | VARCHAR(100) | N | 手术室名称 | 如 "第一手术室"、"第二手术室" |
|
||||
| room_type | VARCHAR(10) | N | 手术室类型 | 普通、日间、复合 |
|
||||
| dept_code | VARCHAR(10) | N | 所属科室 | FK → 科室管理的科室代码 |
|
||||
| valid_flag | CHAR(1) | N | 是否有效 | 1有效,0无效 |
|
||||
| created_time | DATETIME | N | 创建时间 | 默认当前时间 |
|
||||
| updated_time | DATETIME | N | 更新时间 | 默认当前时间,自动更新 |
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- 主色调:#5a7cff(按钮/交互元素)
|
||||
- 辅助色:#7b8a8b(次要文本)
|
||||
- 字体:
|
||||
- 标题:1.75rem/600字重
|
||||
- 正文:0.875rem/400字重
|
||||
- 间距系统:
|
||||
- 卡片内边距:24px
|
||||
- 表单字段间距:16px
|
||||
|
||||
**技术要求**:
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 数据安全:
|
||||
- 所有变更操作需记录操作日志
|
||||
- 停用状态的手术室需在前端标记不可预约
|
||||
2. 性能优化:
|
||||
- 表格数据分页加载
|
||||
- 模态框使用懒加载
|
||||
387
md/需求/95-门诊医生站开立会诊申请单界面PRD_2026-01-15.md
Normal file
387
md/需求/95-门诊医生站开立会诊申请单界面PRD_2026-01-15.md
Normal file
@@ -0,0 +1,387 @@
|
||||
## 门诊医生站开立会诊申请单界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:门诊医生站开立会诊申请单界面**页面目标**:帮助门诊医生完成会诊申请单的创建、编辑、提交和作废操作,实现多科室会诊流程的电子化管理**适用场景**:
|
||||
|
||||
1. 门诊医生需要邀请其他科室专家进行会诊时
|
||||
2. 会诊申请单需要修改或补充信息时
|
||||
3. 会诊流程需要跟踪管理时
|
||||
**页面类型**:表单页+列表页复合型界面
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 会诊申请单的新增、保存、提交、作废功能
|
||||
2. 会诊科室/专家可视化选择
|
||||
3. 申请单数据表格展示与交互
|
||||
4. 表单数据自动填充与校验
|
||||
5. 申请单打印输出
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 规范会诊申请流程,减少纸质单据使用
|
||||
- 通过智能填充减少医生重复录入
|
||||
- 实时查看会诊申请状态(新开/已提交/已确认/已签名/已完成/已取消)
|
||||
|
||||
原型图地址:https://static.pm-ai.cn/prototype/20260115/4eb1bd5367f9d5610b32c0ecc6c793f5/index.html
|
||||
|
||||
流程图:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
%% ---------- 开始 ----------
|
||||
START(["开始"]) --> A["医生进入会诊申请单界面"]
|
||||
|
||||
%% ---------- 操作选择 ----------
|
||||
A --> B{"操作选择"}
|
||||
B -->|"打印"| C["选择已有申请单"]
|
||||
B -->|"提交/取消提交"| D{"校验状态为“已提交”?"}
|
||||
B -->|"删除"| E["弹出确认对话框"]
|
||||
B -->|"结束"| F{"校验状态为“已提交”?"}
|
||||
B -->|"编辑"| G["修改表单内容"]
|
||||
B -->|"新增"| H["清空表单(保留患者信息)"]
|
||||
|
||||
%% ---------- 打印分支 ----------
|
||||
C --> I["高亮选中行"]
|
||||
I --> J["生成打印视图"]
|
||||
J --> K["输出打印样式"]
|
||||
K --> L(["取消"])
|
||||
|
||||
%% ---------- 提交/取消提交分支 ----------
|
||||
D -->|"不通过"| M["提示“请完善必填信息”"]
|
||||
D -->|"通过"| N["更新状态为“已提交/新开”"]
|
||||
|
||||
%% ---------- 删除分支 ----------
|
||||
E --> O{"确认?"}
|
||||
O -->|"是"| P["标记状态为“已取消”"]
|
||||
O -->|"否"| L
|
||||
|
||||
%% ---------- 结束分支 ----------
|
||||
F -->|"不通过"| Q["提示“请先提交申请”"]
|
||||
F -->|"通过"| R["标记状态为“已完成”"]
|
||||
|
||||
%% ---------- 编辑分支 ----------
|
||||
G --> S{"校验必填字段"}
|
||||
S -->|"不通过"| M
|
||||
S -->|"通过"| T["保存到表格"]
|
||||
|
||||
%% ---------- 新增/保存通用路径 ----------
|
||||
H --> U["填写表单"]
|
||||
U --> V["选择会诊科室/专家"]
|
||||
V --> W["自动填充邀请对象"]
|
||||
W --> X["填写病史及目的"]
|
||||
X --> Y["点击保存"]
|
||||
Y --> Z{"校验必填字段"}
|
||||
Z -->|"不通过"| M
|
||||
Z -->|"通过"| AA["生成会诊申请记录"]
|
||||
AA --> AB["保存到表格"]
|
||||
AB --> AC["新增/更新记录"]
|
||||
|
||||
%% ---------- 循环 ----------
|
||||
AC --> A
|
||||
N --> A
|
||||
P --> A
|
||||
R --> A
|
||||
T --> A
|
||||
M --> A
|
||||
Q --> A
|
||||
L --> A
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应宽度(主内容区采用7:3比例分割)
|
||||
**主要区域划分**:
|
||||
|
||||
1. 顶部操作栏(48px固定高度)
|
||||
2. 会诊申请单列表区(高度自适应)
|
||||
3. 主内容区(分左右结构,7:3比例)
|
||||
|
||||
- 左侧:会诊申请单表单区
|
||||
- 右侧:会诊科室/专家选择区
|
||||
**布局特点**:响应式上下+左右混合布局,主要对齐方式为左对齐
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部操作栏区域
|
||||
|
||||
**区域位置**:页面顶部固定位置**区域尺寸**:高度48px,宽度100%**区域功能**:提供全局操作功能入口**包含元素**:
|
||||
|
||||
- **打印按钮**
|
||||
- 元素类型:操作按钮
|
||||
- 显示内容:“打印”
|
||||
- 交互行为:点击后生成A4打印视图,自动适配医院抬头格式
|
||||
- 样式特征:绿色背景(\#13C2C2),圆角4px,32px高度
|
||||
- **新增按钮**
|
||||
- 元素类型:操作按钮
|
||||
- 显示内容:“新增”
|
||||
- 交互行为:点击清空表单(保留当前患者基本信息)
|
||||
- 样式特征:蓝色背景(\#1890FF)
|
||||
- **结束按钮**
|
||||
- 元素类型:危险操作按钮
|
||||
- 显示内容:“结束”
|
||||
- 交互行为:点击结束已提交的会诊流程,标记申请单状态为"已结束",禁用后续操作
|
||||
- 样式特征:红色背景(\#FF4D4F)
|
||||
- 限制条件:需先选中已提交的会诊单
|
||||
- **保存按钮**
|
||||
- 元素类型:主要操作按钮
|
||||
- 显示内容:“保存”
|
||||
- 交互行为:点击保存当前表单数据,校验必填字段后保存至表格,自动生成时间戳
|
||||
- 样式特征:绿色背景(\#52C41A)
|
||||
|
||||
#### 2. 会诊申请单列表区
|
||||
|
||||
**区域位置**:顶部操作栏下方**区域尺寸**:高度自适应,宽度100%**区域功能**:展示当前医生的会诊申请记录**包含元素**:
|
||||
|
||||
- **申请单表格**
|
||||
- 展示方式:带边框表格
|
||||
- 数据字段:
|
||||
|
||||
- 序号:文本 - 自增序号 - 不可操作
|
||||
- 急:布尔 - ✓表示紧急 - 不可操作
|
||||
- 申请单号:文本 - CS20260105001 - 不可操作
|
||||
- 会诊时间:日期 - 2026-01-05 15:08 - 不可操作
|
||||
- 邀请对象:文本 - 吴院长 - 不可操作
|
||||
- 申请科室:文本 - 内科 - 不可操作
|
||||
- 申请医师:文本 - 张医生 - 不可操作
|
||||
- 申请时间:日期 - 2026-01-05 15:08 - 不可操作
|
||||
- 提交状态:布尔 - 复选框 - 仅查看
|
||||
- 结束状态:布尔 - 复选框 - 仅查看
|
||||
- 操作功能:
|
||||
|
||||
- - o 提交/取消提交按钮
|
||||
|
||||
```
|
||||
样式要求:蓝色小按钮,禁用状态显示灰色
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
交互行为:切换提交状态,需二次确认
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
o 删除图标
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
样式要求:红色垃圾桶图标,hover时放大10%
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
交互行为:弹出确认对话框后作废该记录
|
||||
```
|
||||
|
||||
|
||||
[删除]**将状态改为“已取消”****
|
||||
|
||||
UPDATE ConsultationRequest
|
||||
SET ConsultationStatus = 50,cancelnatureDate = <作废会诊时间>
|
||||
WHERE ConsultationID = <会诊申请单ID> and ConsultationStatus <> 40 ;
|
||||
|
||||
- 交互特性:
|
||||
- 行点击选中效果(蓝色高亮+左侧边框)
|
||||
- 行hover浅灰色背景
|
||||
- 提交按钮状态联动(切换提交状态,需二次确认)
|
||||
|
||||
#### 3. 会诊申请单表单区
|
||||
|
||||
**区域位置**:主内容区左侧**区域尺寸**:占主内容区70%宽度**区域功能**:会诊申请单的详细表单填写**包含元素**:
|
||||
|
||||
- **基础信息区**
|
||||
- 申请单号:只读文本,【保存】时自动生成规则CS+年月日时分秒+4位随机数
|
||||
- 申请时间:只读文本,自动获取系统当前时间
|
||||
- 病人信息:病人姓名/性别/年龄/就诊卡号/申请医师/申请科室(不可编辑),自动获取当前患者档案信息。
|
||||
- **会诊信息区**
|
||||
- 会诊时间:时间控件可编辑
|
||||
- 紧急标识:复选框控件
|
||||
- 申请医师:默认当前登录医生
|
||||
- 申请科室:默认当前医生登录的开单科室
|
||||
- 门诊诊断:自动获取医生开立的门诊诊断(主诊断)
|
||||
- **病史及目的**
|
||||
- 多行文本域,最小高度100px
|
||||
- **会诊邀请**
|
||||
- 会诊邀请对象:支持多选(逗号分隔)-》(可从右侧会诊邀请对象选择)
|
||||
- **会诊记录区**
|
||||
- 会诊意见:只读文本域
|
||||
- 会诊确认参加医师:只读字段
|
||||
- 所属医生、代表科室、签名医生、签名时间:只读字段
|
||||
|
||||
#### 4. 会诊邀请对象选择区(侧边栏)
|
||||
|
||||
**区域位置**:主内容区右侧**区域尺寸**:占主内容区30%宽度**区域功能**:快速选择会诊科室和专家**包含元素**:
|
||||
|
||||
- **会诊科室列表**
|
||||
- 展示方式:带边框可滚动列表
|
||||
- 交互行为:选择科室后动态加载对应专家
|
||||
- **会诊专家列表**
|
||||
- 展示方式:带边框可滚动列表
|
||||
- 交互行为:点击专家自动填入会诊邀请对象字段(防重复:已选专家提示"请勿重复选择")
|
||||
- 特殊逻辑:支持多选(自动用逗号分隔)
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 会诊申请单提交流程
|
||||
|
||||
**功能描述**:完成会诊申请单的提交操作**触发条件**:点击表格行的"提交"按钮**操作流程**:
|
||||
|
||||
1. 医生点击行内"提交"按钮
|
||||
2. 系统校验必填字段(会诊时间、邀请对象)
|
||||
3. 提交状态复选框变为已勾选
|
||||
4. 按钮文字变为"取消提交"
|
||||
5. 禁用该行编辑功能
|
||||
|
||||
【提交】**将状态从“新开”改为“已提交”**
|
||||
|
||||
UPDATE ConsultationRequest
|
||||
SET ConsultationStatus = 10,ConfirmingPhysician = <提交会诊医生姓名> ,ConfirmingPhysicianID = <提交会诊医生ID> ,ConfirmingDate = <提交会诊时间>
|
||||
WHERE ConsultationID = <会诊申请单ID> and ConsultationStatus = 0 ;
|
||||
|
||||
【取消提交】**将状态从“已提交”改为“新开”**
|
||||
|
||||
UPDATE ConsultationRequest
|
||||
SET ConsultationStatus = 0,ConfirmingPhysician = '',ConfirmingPhysicianID = '',ConfirmingDate = ''
|
||||
WHERE ConsultationID = <会诊申请单ID> and ConsultationStatus = 10 ;
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 必填字段缺失:弹出"请完善会诊时间和邀请对象信息"
|
||||
- 重复提交:提示"该申请已提交,请勿重复操作"
|
||||
|
||||
#### 2. 会诊流程结束功能
|
||||
|
||||
**功能描述**:标记会诊流程已结束**触发条件**:选中已提交的申请单后点击顶部"结束"按钮**操作流程**:
|
||||
|
||||
1. 医生选中已提交的申请单(行高亮)
|
||||
2. 点击顶部"结束"按钮
|
||||
3. 系统校验提交状态为已提交
|
||||
4. 结束状态复选框变为已勾选
|
||||
5. 禁用该行的取消提交功能
|
||||
|
||||
【结束】**将状态从“已签名”改为“已完成”**
|
||||
|
||||
UPDATE ConsultationRequest
|
||||
SET ConsultationStatus = 40,Signature = <结束会诊医生姓名> ,SignatureDate=<结束会诊时间>
|
||||
WHERE ConsultationID = <会诊申请单ID> and ConsultationStatus = 30 ;
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 未选中记录:提示"请先选择要结束的会诊申请"
|
||||
- 未提交记录:提示"请先提交该会诊申请"
|
||||
|
||||
#### 3. 申请单保存功能
|
||||
|
||||
**功能描述**:保存会诊申请单数据**触发条件**:点击顶部"保存"按钮**操作流程**:
|
||||
|
||||
1. 系统自动生成申请单号(如为空)
|
||||
2. 保存当前表单所有字段值
|
||||
3. 新增记录插入表格末尾
|
||||
4. 已有记录更新对应行数据
|
||||
|
||||
【保存】
|
||||
|
||||
①、写入门诊医嘱表(医嘱状态为新开,医嘱名称为"门诊会诊")
|
||||
|
||||
②、写入门诊会诊申请单表(ConsultationRequest)
|
||||
|
||||
**数据校验**:
|
||||
|
||||
- 必填字段:病人姓名、会诊时间、申请科室、会诊时间、会诊邀请对象、简要病史及会诊目的
|
||||
- 未选会诊对象:提示"请至少选择1位会诊专家"
|
||||
- 过期时间:提示"会诊时间不能早于当前时间"
|
||||
|
||||
#### 4. 会诊邀请对象选择联动
|
||||
|
||||
**触发方式**:点击科室列表项
|
||||
**数据联动**:
|
||||
|
||||
1. 根据选中会诊科室过滤会诊专家列表
|
||||
2. 记忆已选专家(跨科室切换时不丢失)
|
||||
|
||||
**技术要点**:
|
||||
|
||||
- 使用对象存储会诊科室-会诊专家映射关系
|
||||
- 采用事件委托处理动态生成的列表项
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
门诊会诊申请单表(ConsultationRequest)
|
||||
|
||||
|
||||
| **字段名称** | **数据类型** | **长度** | **描述** | **取值范围** |
|
||||
|-----------------------------| ------------ | -------- |----------------| --------------------------------------------------------- |
|
||||
| **PatientID** | Text | 20 | 患者唯一标识 | 患者就诊卡号 (取值患者档案) |
|
||||
| **ConsultationID** | Text | 20 | 会诊申请单唯一标识 | 系统自动生成的唯一编号,生成规则CS+年月日时分秒+4位随机数 |
|
||||
| **VisitID** | BIGINT | 20 | 门诊就诊流水号(逻辑外键) | 取值于本次门诊就诊记录表的主键 |
|
||||
| **OrderID** | BIGINT | 20 | 门诊医嘱表主键(一对一外键) | 门诊医嘱表 |
|
||||
| **PatientName** | Text | 50 | 患者姓名 | 患者的姓名 (取值患者档案) |
|
||||
| **Gender** | Text | 10 | 患者性别 | 男/女/其他 (取值患者档案) |
|
||||
| **Age** | Integer | - | 患者年龄 | 取值患者档案 |
|
||||
| **Department** | Text | 50 | 申请会诊的科室 | 当前科室名称 |
|
||||
| **RequestingPhysician** | Text | 50 | 申请会诊的医生 | 当前医生姓名 |
|
||||
| **ConsultationrequestDate** | DateTime | - | 会诊申请时间 | YYYY-MM-DD HH:MM:SS
|
||||
| **ConsultationPurpose** | Text | 255 | 简要病史及会诊目的 | 文本描述,自定义编辑 |
|
||||
| **ProvisionalDiagnosis** | Text | 255 | 门诊诊断 | 文本描述,自动获取医生开立的门诊诊断(主诊断) |
|
||||
| **ConsultationDate** | DateTime | - | 会诊时间 | YYYY-MM-DD HH:MM:SS |
|
||||
| **ConsultationStatus** | Text | 20 | 会诊状态 | 新开/已提交/已确认/已签名/已完成/已取消 |
|
||||
| **ConsultationUrgency** | Text | 20 | 是否紧急 | 勾选框:一般/紧急 |
|
||||
| **ConsultationOpinion** | Text | 255 | 会诊意见 | 文本描述 |
|
||||
| **ConfirmingPhysician** | Text | 50 | 提交会诊的医生 | 医生姓名 |
|
||||
| **ConfirmingPhysicianID** | Text | 20 | 提交会诊的医生ID | 医生唯一标识 |
|
||||
| **ConfirmingDate** | DateTime | - | 提交会诊日期 | YYYY-MM-DD HH:MM:SS |
|
||||
| **Signature** | Text | 50 | 结束会诊医生 | 医生姓名 |
|
||||
| **SignatureDate** | DateTime | - | 结束会诊日期 | YYYY-MM-DD HH:MM:SS |
|
||||
| **cancelnatureDate** | DateTime | - | 作废会诊日期 | YYYY-MM-DD HH:MM:SS |
|
||||
| InvitedObject | Text | 50 | 会诊邀请对象 | |
|
||||
|
||||
**诊状态用于记录会诊申请在不同阶段的状态,以下是常见的会诊状态及其说明:**
|
||||
|
||||
|
||||
| **状态名称** | **状态值** | **描述** |
|
||||
| ------------ | ---------- | ---------------------------------------------------------------------- |
|
||||
| **新开** | 0 | 会诊申请单已保存 |
|
||||
| **已提交** | 10 | 会诊申请已提交,但尚未被会诊医生确认。 |
|
||||
| **已确认** | 20 | 会诊医生已确认会诊申请,并准备进行会诊。 |
|
||||
| **已签名** | 30 | 会诊完成后进行签名 |
|
||||
| **已完成** | 40 | 会诊已经完成,会诊意见已记录。 |
|
||||
| **已取消** | 50 | 会诊申请被取消,可能由于患者情况变化或其他原因,申请医生进行作废操作。 |
|
||||
|
||||
**门诊医嘱表在相关会诊操作步骤的相关事务**
|
||||
|
||||
把“门诊会诊申请”当成**一种特殊医嘱**(OrderType = 'Consult')由系统**在同一事务内**自动插入 门诊医嘱表,再挂到 `ConsultationRequest` **注意:按照现有系统的门诊医嘱表进行设置相关字段的值**
|
||||
|
||||
|
||||
| **节点** | **是否自动** | **说明** |
|
||||
| --------------------- | ------------ | --------------------------------------------------------------------------------------------------- |
|
||||
| 医生点击【保存】 | ✅ | 后台事务:先插门诊医嘱表(医嘱状态为“新开”),再插`ConsultationRequest`.Status=0 |
|
||||
| 医生点击【提交】 | ✅ | 仅更新两表状态 → 门诊医嘱表的医嘱状态和`ConsultationRequest.Status=10` (已提交),不重复生成医嘱 |
|
||||
| 医生点击【作废/删除】 | ✅ | 自动将门诊医嘱表的医嘱状态字段置为“作废”,级联`ConsultationRequest.Status=50` |
|
||||
| 医生点击【结束】 | ✅ | 将 门诊医嘱表的医嘱状态字段置为“已完成”,同时写`ConsultationRequest.Status=40` |
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:\#1890FF(操作按钮)
|
||||
- **辅助色**:\#13C2C2(打印)、\#52C41A(保存)、\#FF4D4F(结束)
|
||||
- **字体规范**:14px/1.5,中文字体优先使用"PingFang SC"
|
||||
- **间距系统**:16px基准,表单行间距12px
|
||||
- **组件样式**:
|
||||
- 按钮:4px圆角,32px高度
|
||||
- 输入框:4px圆角,1px \#D9D9D9边框
|
||||
- 表格行:选中状态\#E6F7FF背景+左侧3px蓝色边框
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- **浏览器兼容**:支持Chrome/Firefox/Edge最新版
|
||||
- **性能要求**:表单提交响应时间\<1秒
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 时间字段需统一处理为YYYY-MM-DD HH:mm:ss格式
|
||||
2. 申请单号生成需加锁防止重复
|
||||
3. 移动端需优化表格横向滚动体验
|
||||
4. 打印功能需特殊样式处理(隐藏操作按钮)
|
||||
310
md/需求/96-门诊医生站会诊申请确认界面_2026-01-15.md
Normal file
310
md/需求/96-门诊医生站会诊申请确认界面_2026-01-15.md
Normal file
@@ -0,0 +1,310 @@
|
||||
## 门诊医生站会诊申请确认界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:门诊医生站会诊申请确认界面
|
||||
**页面目标**:帮助医生完成会诊申请的确认、签名和打印操作,展示会诊申请详细信息
|
||||
**适用场景**:医生在收到会诊申请后,查看申请信息并给出会诊意见
|
||||
**页面类型**:表单页+列表页复合型页面
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 会诊申请单列表展示与选择
|
||||
2. 会诊确认与取消确认功能
|
||||
3. 签名功能
|
||||
4. 会诊记录单打印
|
||||
5. 会诊意见编辑与保存
|
||||
|
||||
**用户价值**:
|
||||
|
||||
- 规范会诊申请流程
|
||||
- 电子化确认和签名提高效率
|
||||
- 完整记录会诊意见便于后续诊疗
|
||||
- 打印功能满足纸质存档需求
|
||||
**原型图地址:**https://static.pm-ai.cn/prototype/20260115/7c45e175239257e0f04c9081bf2ca204/index.html
|
||||
**流程图:**
|
||||
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["医生进入会诊申请确认界面"]) --> LoadList["加载会诊申请列表"]
|
||||
LoadList --> HasUntreated{"是否有未处理申请?"}
|
||||
|
||||
HasUntreated -- "否" --> ShowNoTip["显示无申请提示"]
|
||||
HasUntreated -- "是" --> SelectApp["医生选择会诊申请"]
|
||||
|
||||
SelectApp --> ShowDetail["显示会诊申请详情"]
|
||||
ShowDetail --> EditOpinion["医生编辑会诊意见"]
|
||||
|
||||
EditOpinion --> ConfirmClick{"点击确认按钮?"}
|
||||
ConfirmClick -- "否" --> SignClick{"点击签名按钮?"}
|
||||
ConfirmClick -- "是" --> ValidateConfirm{"校验必填字段"}
|
||||
|
||||
ValidateConfirm -- "不通过" --> TipFill["提示\n请先填写会诊意见"]
|
||||
ValidateConfirm -- "通过" --> CheckConfirmed{"是否已确认?"}
|
||||
|
||||
CheckConfirmed -- "是" --> UpdateConfirmed["更新状态为\n已确认"]
|
||||
UpdateConfirmed --> AutoFill["自动填充医生科室信息"]
|
||||
AutoFill --> DisableCancel["禁用取消确认功能"]
|
||||
|
||||
CheckConfirmed -- "否" --> KeepState["保持当前状态"]
|
||||
|
||||
SignClick -- "否" --> PrintClick{"点击打印按钮?"}
|
||||
SignClick -- "是" --> ValidateSign{"校验通过?"}
|
||||
|
||||
ValidateSign -- "不通过" --> TipConfirmFirst["提示\n请先确认会诊申请"]
|
||||
ValidateSign -- "通过" --> UpdateSigned["更新状态为\n已签名"]
|
||||
UpdateSigned --> RecordSign["记录签名医生和时间"]
|
||||
|
||||
PrintClick -- "否" --> RefreshClick{"点击刷新按钮?"}
|
||||
PrintClick -- "是" --> GenPrintView["生成打印优化视图"]
|
||||
GenPrintView --> BrowserPrint["调用浏览器打印功能"]
|
||||
|
||||
RefreshClick -- "是" --> LoadList
|
||||
RefreshClick -- "否" --> KeepState
|
||||
|
||||
TipFill --> EditOpinion
|
||||
TipConfirmFirst --> EditOpinion
|
||||
KeepState --> End(["结束"])
|
||||
BrowserPrint --> End
|
||||
DisableCancel --> End
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. 顶部标签导航(高度48px)
|
||||
2. 操作按钮区(高度36px+间距)
|
||||
3. 会诊申请列表区(高度自适应)
|
||||
4. 会诊记录单表单区(高度自适应)
|
||||
**布局特点**:上下布局,采用网格系统对齐,左侧对齐为主
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部标签导航区域
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:高度48px,宽度100%
|
||||
**区域功能**:页面导航标识
|
||||
**包含元素**:
|
||||
|
||||
- **会诊确认标签**
|
||||
- 元素类型:文本标签
|
||||
- 显示内容:“会诊确认”
|
||||
- 交互行为:无点击交互(当前页面)
|
||||
- 样式特征:蓝色下划线,16px字体,700字重
|
||||
|
||||
#### 2. 操作按钮区域
|
||||
|
||||
**区域位置**:标签导航下方
|
||||
**区域尺寸**:高度36px,宽度100%
|
||||
**区域功能**:提供页面主要操作入口
|
||||
**包含元素**:
|
||||
|
||||
- **打印按钮**
|
||||
- 元素类型:操作按钮
|
||||
- 显示内容:“打印”
|
||||
- 交互行为:点击触发打印会诊记录单
|
||||
- 样式特征:绿色背景,白色文字,圆角6px
|
||||
- **刷新按钮**
|
||||
- 元素类型:操作按钮
|
||||
- 显示内容:“刷新”
|
||||
- 交互行为:点击重新加载页面数据
|
||||
- 样式特征:白色背景,灰色边框,黑色文字
|
||||
- **确认按钮**
|
||||
- 元素类型:状态切换按钮
|
||||
- 显示内容:“确认”/“取消确认”
|
||||
- 交互行为:
|
||||
- 点击后变为"取消确认"状态(红色样式)
|
||||
- 已签名时禁用取消操作
|
||||
- 样式特征:蓝色背景,白色文字
|
||||
- 限制条件:需选中表格行才可操作
|
||||
- **签名按钮**
|
||||
- 元素类型:操作按钮
|
||||
- 显示内容:“签名”
|
||||
- 交互行为:
|
||||
- 需先确认才能签名
|
||||
- 签名后自动记录签名时间和签名医生
|
||||
- 样式特征:蓝色背景,白色文字
|
||||
- 限制条件:需先完成确认操作
|
||||
|
||||
#### 3. 会诊申请列表区域
|
||||
|
||||
**区域位置**:按钮区域下方
|
||||
**区域尺寸**:高度自适应,宽度100%
|
||||
**区域功能**:展示待处理的会诊申请列表
|
||||
**包含元素**:
|
||||
|
||||
- **申请列表表格** (取值于门诊会诊申请单表(ConsultationRequest))
|
||||
- 检索要求:医生登录门诊医生站打开会诊申请确认界面时只能检索出当前登录医生姓名包含在会诊邀请对象内(只能查看自己受会诊邀请对象)
|
||||
- 展示方式:带斑马纹表格
|
||||
- 表头字段:
|
||||
- 序号 \| 紧急 \| 申请单号 \| 病人姓名 \| 会诊时间 \| 邀请对象 \| 申请科室 \| 申请医师 \| 申请时间 \| 确认 \| 签名
|
||||
- 数据字段:
|
||||
- 序号:文本 - 自动编号 - “1” - 不可操作
|
||||
- 紧急:复选框 - 布尔值 - 未勾选 - 可操作
|
||||
- 申请单号:文本 - 字符串 - “CS20250812001” - 不可操作
|
||||
- 病人姓名:文本 - 字符串 - “陈明” - 不可操作
|
||||
- 会诊时间:日期 - 日期时间 - “2025-08-12 17:48” - 不可操作
|
||||
- 邀请对象:文本 - 字符串 - “演示测试” - 不可操作
|
||||
- 申请科室:文本 - 字符串 - “内科” - 不可操作
|
||||
- 申请医师:文本 - 字符串 - “徐斌” - 不可操作
|
||||
- 申请时间:日期 - 日期时间 - “2025-08-12 17:48” - 不可操作
|
||||
- 确认:复选框 - 布尔值 - 勾选框 – 不可操作
|
||||
- 签名:复选框 - 布尔值 - 勾选框 – 不可操作
|
||||
- 操作功能:点击行选中查看会诊申请详情
|
||||
- 样式特征:斑马纹交替背景,悬停高亮
|
||||
|
||||
#### 4. 会诊记录单表单区域
|
||||
|
||||
**区域位置**:列表区域下方
|
||||
**区域尺寸**:高度自适应,宽度100%
|
||||
**区域功能**:展示和编辑会诊详细信息
|
||||
**包含元素**:
|
||||
|
||||
- **基础信息区**
|
||||
- 布局方式:8列网格
|
||||
- 包含字段:
|
||||
- 病人姓名/性别/年龄/就诊卡号
|
||||
- 申请单号/申请科室
|
||||
- 会诊时间/紧急标志
|
||||
- 会诊邀请对象
|
||||
- 提交医生/提交时间
|
||||
- **病史及目的区**
|
||||
- 元素类型:文本区域
|
||||
- 显示内容:患者主诉和会诊目的
|
||||
- 交互行为:只读展示
|
||||
- **会诊确认参加医师**
|
||||
- **会诊意见区**
|
||||
- 元素类型:可编辑文本域
|
||||
- 显示内容:会诊意见文本
|
||||
- 交互行为:支持多行编辑
|
||||
- 样式特征:浅灰色背景,120px最小高度
|
||||
- **确认/签名信息区**
|
||||
- 包含字段:
|
||||
- 所属医生/代表科室(确认后自动填充当前医生和科室)
|
||||
- 签名医生/签名时间(自动填充签名医生和签名时间(系统当前时间))
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 会诊申请选择功能
|
||||
|
||||
**触发方式**:点击表格行
|
||||
**执行流程**:
|
||||
|
||||
1. 高亮选中行(浅蓝色背景)
|
||||
2. 同步该行数据到下方表单
|
||||
3. 根据确认状态更新按钮文字
|
||||
4. 加载存储的会诊意见到文本域
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 无选中行时禁用确认/签名按钮
|
||||
- 已签名行禁止取消确认
|
||||
|
||||
#### 2. 会诊确认功能
|
||||
|
||||
**触发方式**:点击确认按钮
|
||||
|
||||
**执行流程**:
|
||||
|
||||
1. 校验必填字段(会诊意见、会诊确认参加医师)
|
||||
2. 保存会诊意见等相关内容到行数据(写入门诊会诊申请确认表(ConsultationConfirmation))
|
||||
3. 勾选确认复选框
|
||||
4. 更新按钮为"取消确认"状态
|
||||
5. 所属医生和代表科室(自动填充当前医生和科室)
|
||||
|
||||
**异常处理**:
|
||||
|
||||
- 未填写会诊意见时提示"请先填写会诊意见"
|
||||
- 保存失败时保持原状态并提示错误
|
||||
|
||||
#### 2. 电子签名功能
|
||||
|
||||
**功能描述**:医生对确认的会诊进行电子签名
|
||||
**触发条件**:已确认的会诊申请点击"签名"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 医生确认会诊申请
|
||||
2. 点击"签名"按钮
|
||||
3. 校验确认状态
|
||||
4. 表格中"签名"列复选框被勾选
|
||||
5. 自动记录签名医生(当前用户)
|
||||
6. 自动填充签名时间为系统时间
|
||||
7. 禁用取消确认功能
|
||||
**成功反馈**:表单区显示签名信息
|
||||
**失败处理**:提示"请先确认会诊申请"
|
||||
|
||||
#### 3. 打印会诊记录单
|
||||
|
||||
**功能描述**:打印格式化的会诊记录
|
||||
**触发条件**:点击"打印"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 点击"打印"按钮
|
||||
2. 系统生成打印优化视图
|
||||
3. 调用浏览器打印功能
|
||||
**特殊处理**:隐藏交互元素,优化打印布局
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
**门诊会诊申请确认表(**ConsultationConfirmation**)**
|
||||
|
||||
| **字段名称** | **数据类型** | **长度** | **描述** | **约束/说明** |
|
||||
|-----------------------------|--------------|----------|--------------------|------------------------------------------------------------------------------------|
|
||||
| **ConsultationID** | INTEGER | 20 | 会诊申请单唯一标识 | FOREIGN KEY REFERENCES ConsultationRequest(ConsultationID) |
|
||||
| **ConfirmingPhysicianID** | TEXT | -20 | 确认会诊的医生ID | 操作【确认】按钮的当前医生ID |
|
||||
| **ConfirmingPhysicianName** | TEXT | -20 | 确认会诊的医生姓名 | 操作【确认】按钮的当前医生姓名 |
|
||||
| **ConfirmingDeptName** | TEXT | 20 | 代表科室 | 操作【确认】按钮的当前开单科室 |
|
||||
| **ConfirmingDate** | DateTime | - | 确认会诊的日期 | 操作【确认】按钮当前系统时间 |
|
||||
| **ConsultationStatus** | TEXT | 20 | 会诊状态 | CHECK (ConsultationStatus IN ('已确认', '取消确认', '已签名', '已完成')), NOT NULL |
|
||||
| **ConsultationOpinion** | TEXT | 500 | 会诊意见 | |
|
||||
| **ConfirmingPhysician** | TEXT | 100 | 会诊确认参加医师 | |
|
||||
| **Signature** | TEXT | 20 | 签名医生 | |
|
||||
| **SignatureDate** | DateTime | - | 签名时间 | - |
|
||||
|
||||
ConsultationConfirmation.ConsultationStatu会诊状态
|
||||
|
||||
| **状态值** | **状态名** | **描述** |
|
||||
|------------|------------|-----------------------------------|
|
||||
| **0** | 取消确认 | 作废 |
|
||||
| **20** | 已确认 | 会诊医生已查看/同意,可写初步意见 |
|
||||
| **30** | 已签名 | 已电子签名,意见最终生效 |
|
||||
| **40** | 已完成 | 会诊报告已回写,流程关闭 |
|
||||
|
||||
**按钮涉及的事务**
|
||||
|
||||
| **按钮** | **涉及表** | **执行事务** | **锁/并发** | **成功状态** | **失败处理** |
|
||||
|--------------|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|------------------|--------------------------|
|
||||
| **确认** | 1、ConsultationRequest<br>2、门诊医嘱<br>3、ConsultationConfirmation | 1、ConsultationRequest.ConsultationStatus =20<br>2、医嘱 状态='已执行'<br>3、写入ConsultationConfirmation表相关的数据 | SELECT ... FOR UPDATE | 已提交 → 已确认 | 任何异常 → 整体 ROLLBACK |
|
||||
| **取消确认** | 1、ConsultationRequest<br>2、门诊医嘱<br>3、ConsultationConfirmation | 1、ConsultationRequest.ConsultationStatus =10<br>2、医嘱 状态='已提交'<br>3、ConsultationConfirmation. ConsultationStatus = 0 | 同上 | 已确认→ 取消确认 | 同上回滚 |
|
||||
| **签名** | 1、ConsultationRequest<br>2、门诊医嘱<br>3、ConsultationConfirmation | 1、ConsultationRequest.ConsultationStatus =30<br>2、医嘱 Status='已完成'<br>3、写入ConsultationConfirmation. Signature, SignatureDate,ConsultationStatus =30 | 同上 | 已确认 → 已签名 | 同上回滚 |
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:\#4A89DC(按钮蓝色)
|
||||
- **辅助色**:\#4CAF50(成功绿色)
|
||||
- **字体规范**:14px/1.5 常规,16px 标题
|
||||
- **间距系统**:8px基础间距,24px区块间距
|
||||
- **组件样式**:
|
||||
- 按钮:6px圆角,1px边框
|
||||
- 输入框:4px圆角,1px \#E0E0E0边框
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- **浏览器兼容**:Chrome/Firefox/Edge最新版
|
||||
- **性能要求**:列表加载时间\<1s
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 确认和签名状态需要联动控制
|
||||
2. 打印功能需要特殊样式处理
|
||||
3. 时间字段需统一使用YYYY-MM-DD HH:mm:ss格式
|
||||
4. 移动端需优化表单布局
|
||||
267
md/需求/97-门诊会诊申请管理界面_2026-1-19.md
Normal file
267
md/需求/97-门诊会诊申请管理界面_2026-1-19.md
Normal file
@@ -0,0 +1,267 @@
|
||||
## 门诊会诊申请管理界面PRD文档
|
||||
|
||||
### 一、页面概述
|
||||
|
||||
**页面名称**:门诊会诊申请管理界面
|
||||
**页面目标**:提供会诊申请的全流程管理功能,包括申请记录查询、编辑申请、查看详情、状态变更等核心操作
|
||||
**适用场景**:门诊医生需要查看会诊申请或管理已有申请记录时使用
|
||||
**页面类型**:列表页+表单弹窗复合型页面
|
||||
|
||||
**核心功能**:
|
||||
|
||||
1. 多条件组合筛选会诊申请记录
|
||||
2. 会诊申请表格展示与操作(编辑/查看/删除)
|
||||
3. 会诊申请单的填写与提交
|
||||
4. 会诊状态标记(提交/结束)
|
||||
**用户价值**:规范会诊申请流程,减少纸质单据流转,提高多科室协作效率
|
||||
原型图地址:https://static.pm-ai.cn/prototype/20260116/aed1f102d614677f100c0d1fe3104999/index.html
|
||||
**流程图:**
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([Start]) --> A[进入门诊会诊申请管理界面]
|
||||
A --> B{用户操作类型}
|
||||
B -->|筛选查询| C[设置筛选条件]
|
||||
B -->|编辑申请| D[点击编辑按钮]
|
||||
B -->|查看详情| E[点击查看按钮]
|
||||
B -->|删除申请| G[点击删除按钮]
|
||||
|
||||
C --> H{验证筛选条件}
|
||||
H -->|有效| I[展示筛选结果]
|
||||
H -->|无效| J[显示错误提示]
|
||||
J --> C
|
||||
|
||||
I --> K[用户浏览列表]
|
||||
|
||||
D --> L{检查会诊状态}
|
||||
L -->|未结束| M[打开编辑弹窗]
|
||||
L -->|已结束| N[提示不可编辑]
|
||||
N --> O[关闭弹窗]
|
||||
|
||||
M --> P[修改表单内容]
|
||||
P --> Q{表单验证}
|
||||
Q -->|通过| R[保存修改]
|
||||
Q -->|不通过| S[标红错误字段]
|
||||
S --> P
|
||||
|
||||
E --> T{检查会诊状态}
|
||||
T -->|未结束| U[打开只读弹窗]
|
||||
T -->|已结束| U
|
||||
|
||||
G --> Z{删除验证}
|
||||
Z -->|可删除| AA[确认删除]
|
||||
Z -->|不可删除| AB[提示删除失败]
|
||||
AB --> K
|
||||
|
||||
AA --> AC[更新状态为已取消]
|
||||
AC --> AD[更新列表显示]
|
||||
|
||||
R --> AD
|
||||
AD --> K
|
||||
K --> AE([End])
|
||||
```
|
||||
|
||||
### 二、整体布局分析
|
||||
|
||||
**页面宽度**:自适应布局
|
||||
**主要区域划分**:
|
||||
|
||||
1. 顶部筛选区(高度自适应,约80px)
|
||||
2. 表格展示区(高度自适应,占主要空间)
|
||||
3. 底部页码区(固定高度56px)
|
||||
**布局特点**:上下布局+弹性布局,采用左右对齐方式
|
||||
|
||||
### 三、页面区域详细描述
|
||||
|
||||
#### 1. 顶部筛选区
|
||||
|
||||
**区域位置**:页面顶部
|
||||
**区域尺寸**:100%宽度,高度自适应
|
||||
**区域功能**:提供多维度筛选和快速搜索功能
|
||||
**包含元素**:
|
||||
|
||||
- **时间类型选择器**
|
||||
- 元素类型:下拉选择框
|
||||
- 显示内容:默认"会诊时间",可选"申请时间"
|
||||
- 交互行为:点击展开下拉选项
|
||||
- 样式特征:宽度120px,高度32px,圆角4px
|
||||
- **时间范围选择器**(开始/结束时间)
|
||||
- 元素类型:日期时间输入框
|
||||
- 显示内容:placeholder提示"开始时间"/“结束时间”
|
||||
- 交互行为:点击弹出日期选择面板
|
||||
- 样式特征:宽度180px,高度32px
|
||||
- **申请科室/申请医生选择器**
|
||||
- 元素类型:带datalist的输入框
|
||||
- 显示内容:placeholder提示"选择或输入科室/医生"
|
||||
- 交互行为:输入时显示匹配选项
|
||||
- 数据来源:动态生成申请科室/医生候选列表,取值于门诊会诊申请单表(ConsultationRequest.Department/ RequestingPhysician)
|
||||
- **会诊状态筛选器**
|
||||
- 元素类型:下拉选择框
|
||||
- 可选值:全部/未提交/提交/结束
|
||||
- 默认值:全部
|
||||
- **病人姓名搜索框**
|
||||
- 元素类型:文本输入框
|
||||
- 显示内容:placeholder提示"病人姓名"
|
||||
- 交互行为:支持模糊搜索
|
||||
- **操作按钮组**
|
||||
- 查询按钮
|
||||
- 样式:蓝色背景,带搜索图标
|
||||
- 交互:触发筛选条件应用
|
||||
- 重置按钮
|
||||
- 样式:灰色背景,带刷新图标
|
||||
- 交互:清空所有筛选条件
|
||||
- 打印按钮
|
||||
- 样式:深灰色背景,带打印图标
|
||||
- 交互:调起浏览器打印功能
|
||||
|
||||
#### 2. 表格展示区
|
||||
|
||||
**区域位置**:页面中部
|
||||
**区域尺寸**:100%宽度,高度自适应
|
||||
**区域功能**:展示会诊申请列表数据,支持行内操作
|
||||
**包含元素**:
|
||||
|
||||
取值于门诊会诊申请单表(ConsultationRequest)和门诊会诊申请单表(ConsultationRequest)
|
||||
|
||||
- **数据表格**
|
||||
- 展示方式:11列固定表头表格
|
||||
- 数据字段:
|
||||
- ID:文本 - 15 -申请单号
|
||||
- 急:复选框 - 布尔值 - 示例false – 不可编辑
|
||||
- 病人姓名:文本 - 朱某某 - 红色高亮
|
||||
- 会诊时间:日期 - 2026-01-05 15:08
|
||||
- 申请科室:文本 - 内科
|
||||
- 邀请对象:文本 - 吴院长
|
||||
- 申请时间:日期 - 2026-01-05 15:08
|
||||
- 申请医师:文本 - 演示测试
|
||||
- 提交:复选框 - 布尔值 - 示例false
|
||||
- 结束:复选框 - 布尔值 - 示例false
|
||||
- 操作功能:
|
||||
- 编辑按钮(✏️):点击打开编辑弹窗
|
||||
- 查看按钮(👁️):点击打开只读弹窗
|
||||
- 删除按钮(🗑️):点击确认删除
|
||||
- 【删除】将状态改为“已取消”
|
||||
- UPDATE ConsultationRequest
|
||||
- SET ConsultationStatus = 50,cancelnatureDate = \<作废会诊时间\>
|
||||
- WHERE ConsultationID = \<会诊申请单ID\> and ConsultationStatus \<\> 40 ;
|
||||
- 交互行为:
|
||||
- 行悬停效果:浅蓝色背景
|
||||
- 复选框点击:即时更新状态(需防抖处理)
|
||||
|
||||
#### 3. 底部页码区
|
||||
|
||||
**区域位置**:页面底部
|
||||
**区域尺寸**:100%宽度,固定高度56px
|
||||
**区域功能**:分页控制和数据统计
|
||||
**包含元素**:
|
||||
|
||||
- **总数统计**:总数统计文本(如:“总数:15”)
|
||||
- **分页控制器**:
|
||||
- 上一页按钮(\<)
|
||||
- 当前页按钮(1)active状态
|
||||
- 下一页按钮(\>)
|
||||
- 交互反馈:hover时边框变蓝
|
||||
|
||||
#### 4. 会诊申请弹窗(模态框)
|
||||
|
||||
**触发方式**:点击表格行操作列的编辑/查看按钮
|
||||
**区域功能**:展示/编辑会诊申请详细信息
|
||||
**包含元素**:
|
||||
|
||||
- 头部区域
|
||||
- 标题:“会诊申请单”
|
||||
- 关闭按钮(×图标)
|
||||
- 表单区域(分两栏布局)
|
||||
- 基础信息区:
|
||||
- 申请单号(只读)
|
||||
- 申请时间(不可编辑)
|
||||
- 病人姓名(不可编辑)
|
||||
- 性别/年龄(不可编辑)
|
||||
- 就诊卡号(不可编辑)
|
||||
- 会诊信息区:
|
||||
- 会诊时间(日期时间选择器)
|
||||
- 申请医师(不可编辑)
|
||||
- 紧急程度(复选框)
|
||||
- 申请科室(不可编辑)
|
||||
- 门诊诊断(不可编辑)
|
||||
- 会诊邀请对象
|
||||
- 会诊确认参加医师
|
||||
- 所属医生
|
||||
- 代表科室
|
||||
- 签名医生
|
||||
- 签名时间
|
||||
- 文本域:
|
||||
- 病史及会诊目的(多行文本)
|
||||
- 会诊意见(多行文本)
|
||||
- 底部按钮区:
|
||||
- 取消按钮(左对齐)
|
||||
- 保存按钮(右对齐,蓝色)
|
||||
|
||||
### 四、交互功能详细说明
|
||||
|
||||
#### 1. 会诊申请编辑功能
|
||||
|
||||
**功能描述**:修改已有会诊申请信息
|
||||
**触发条件**:点击表格行中的"✏️"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 检查会诊状态是否为"结束",若已结束则提示不可编辑
|
||||
2. 弹出会诊申请编辑弹窗,填充当前行数据的会诊申请和确认相关的数据
|
||||
3. 用户修改表单内容(必填字段校验)
|
||||
4. 点击"保存"按钮提交修改
|
||||
**异常处理**:
|
||||
- 必填字段为空时,标红提示
|
||||
- 保存失败时显示toast提示"保存失败,请重试"
|
||||
|
||||
#### 2. 会诊申请查看功能
|
||||
|
||||
**功能描述**:查看会诊申请详细信息
|
||||
**触发条件**:点击表格行中的"👁️"按钮
|
||||
**操作流程**:
|
||||
|
||||
1. 弹出只读弹窗,显示完整申请信息
|
||||
2. 所有字段禁用编辑
|
||||
3. 仅显示"取消"按钮用于关闭弹窗
|
||||
|
||||
#### 3. 数据筛选功能
|
||||
|
||||
**功能描述**:多条件组合查询会诊记录
|
||||
**触发条件**:点击"查询"按钮
|
||||
**数据过滤逻辑**:
|
||||
|
||||
- 时间范围:根据选择的时间类型(会诊/申请)进行筛选
|
||||
- 申请科室/申请医生:支持模糊匹配
|
||||
- 会诊状态筛选:支持多选逻辑(未提交/提交/结束)
|
||||
1. 收集所有筛选条件值
|
||||
2. 发起异步请求(示例中为前端过滤)
|
||||
3. 更新表格数据展示
|
||||
**异常处理**:
|
||||
- 时间范围不合法:提示"结束时间不能早于开始时间"
|
||||
- 无查询结果:显示空白表格+提示文字
|
||||
**性能优化**:前端本地缓存数据,减少服务器请求
|
||||
|
||||
### 五、数据结构说明
|
||||
|
||||
门诊会诊申请单表(ConsultationRequest)和门诊会诊申请单表(ConsultationRequest)
|
||||
|
||||
### 六、开发实现要点
|
||||
|
||||
**样式规范**:
|
||||
|
||||
- **主色调**:\#5D9CEC(按钮/交互元素)
|
||||
- **辅助色**:\#8E8E8E(次要按钮)
|
||||
- **字体规范**:14px/1.5(主要内容),16px/1.5(标题)
|
||||
- **间距系统**:16px(元素间距),24px(区块间距)
|
||||
- **组件样式**:
|
||||
- 按钮:圆角6px,内边距0 16px
|
||||
- 输入框:1px实线边框\#D9D9D9,圆角4px
|
||||
|
||||
**技术要求**:
|
||||
|
||||
- **浏览器兼容**:支持Chrome/Firefox/Edge最新版
|
||||
- **性能要求**:列表数据筛选响应时间\<200ms
|
||||
|
||||
**注意事项**:
|
||||
|
||||
1. 状态变更逻辑:已结束的记录不可编辑
|
||||
2. 时间字段需要做时区转换处理
|
||||
3. 申请科室/申请医生选择器需要支持拼音首字母检索
|
||||
62
md/需求/99-门诊手术中计费界面PRD_2026-1-22.md
Normal file
62
md/需求/99-门诊手术中计费界面PRD_2026-1-22.md
Normal file
@@ -0,0 +1,62 @@
|
||||
**门诊手术中计费PRD文档**
|
||||
|
||||
**目标:**
|
||||
|
||||
支持手术中追加计费(耗材、药品等)、退费等场景使用
|
||||
|
||||
术后一站式结算(发票、清单、医保等)
|
||||
|
||||
**流程图:**
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["医生开立手术申请单"] --> B{"系统生成计费包"}
|
||||
B --> C["患者缴费"]
|
||||
C --> D["手术室确认"]
|
||||
D --> E{"术中追加/退费?"}
|
||||
|
||||
E -- "是" --> F{"术中计费"}
|
||||
F -- "耗材" --> F2["护士扫码追加耗材\n实时计价 更新库存"]
|
||||
F -- "药品" --> F3["麻醉师追加药品\n实时计价 更新库存"]
|
||||
F -- "诊疗项目" --> F4["追加麻醉时长/项目\n实时计价"]
|
||||
|
||||
|
||||
F2 --> F6["生成术中追加计费单"]
|
||||
F3 --> F6
|
||||
F4 --> F6
|
||||
|
||||
|
||||
F6 --> G{"患者支付?"}
|
||||
G -- "是" --> P["提示支付成功"]--> J
|
||||
G -- "否" --> H["提示支付失败\n保持待支付"]
|
||||
H --> D
|
||||
|
||||
E -- "否" --> I["手术完成"]
|
||||
I --> J["术后统一结算"]
|
||||
J --> K["发票/清单/分割单"]
|
||||
K --> L["财务对账"]
|
||||
```
|
||||
|
||||
**注意:**待门诊手术安排界面(禅道需求编号:93)完成后再执行
|
||||
|
||||

|
||||
|
||||
图1:门诊手术安排界面(禅道需求编号:93)
|
||||
|
||||

|
||||
|
||||
图2:门诊管理-》门诊划价:手术计费界面复制《门诊划价》界面红色框内容
|
||||
|
||||
1、如上图1、2所示:在门诊手术安排界面增加【计费】按钮,实现对门诊手术中追加的费用进行记账,手术计费界面如图2所示复制《门诊划价》界面红色框内容进行个性化改造,患者信息:取值于手术安排界面选中行的患者信息,计费账号为当前系统登录的账号。
|
||||
|
||||
\*比如:在手术计费界面给患者1计费成功后,重新从手术按钮界面选中患者1点击【计费】打开界面时显示当前患者已计费成功的手术费用。
|
||||
|
||||
写入事务注意:
|
||||
|
||||
adm_charge_item费用项管理表
|
||||
|
||||
①、术中费用仍走“门诊就诊管理”的就诊ID(adm_encounter.id = adm_charge_item.encounter_id)。
|
||||
|
||||
2\. 为了事后能追溯“这些费用是术中发生的”,在费用项管理表明细上加一个 “来源业务单据(SourceBillNo)” 字段(adm_charge_item.generate_source_enum = 2(帐单生成来源为手术计费),SourceBillNo = 手术申请单号)。
|
||||
|
||||
3\. 其他内容按照《门诊划价》的业务数据流程走。
|
||||
BIN
md/需求/media/2756f39fb624c7f686d56b675b4d4d10.png
Normal file
BIN
md/需求/media/2756f39fb624c7f686d56b675b4d4d10.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 224 KiB |
BIN
md/需求/media/4fa3fca6b8362de7b938ded77d6e4982.png
Normal file
BIN
md/需求/media/4fa3fca6b8362de7b938ded77d6e4982.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 219 KiB |
BIN
md/需求/media/clip_image001.png
Normal file
BIN
md/需求/media/clip_image001.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 268 KiB |
BIN
md/需求/media/e577cd26f9a82835f3ac3690259eb357.png
Normal file
BIN
md/需求/media/e577cd26f9a82835f3ac3690259eb357.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 216 KiB |
@@ -1,2 +0,0 @@
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">OpenHis v0.0.1</h1>
|
||||
|
||||
45
openhis-server-new/com/openhis/tool/DatabaseFieldAdder.java
Normal file
45
openhis-server-new/com/openhis/tool/DatabaseFieldAdder.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.openhis.tool;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* Database field adder tool
|
||||
*/
|
||||
public class DatabaseFieldAdder {
|
||||
public static void main(String[] args) {
|
||||
String url = "jdbc:postgresql://192.168.110.252:15432/postgresql?currentSchema=public";
|
||||
String username = "postgresql";
|
||||
String password = "Jchl1528";
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(url, username, password);
|
||||
Statement stmt = conn.createStatement()) {
|
||||
|
||||
// Check if field exists
|
||||
String checkSql = "SELECT column_name FROM information_schema.columns " +
|
||||
"WHERE table_name = 'adm_healthcare_service' AND column_name = 'practitioner_id'";
|
||||
|
||||
boolean fieldExists = stmt.executeQuery(checkSql).next();
|
||||
|
||||
if (!fieldExists) {
|
||||
// Add field
|
||||
String addSql = "ALTER TABLE \"public\".\"adm_healthcare_service\" " +
|
||||
"ADD COLUMN \"practitioner_id\" int8";
|
||||
stmt.execute(addSql);
|
||||
|
||||
// Add comment
|
||||
String commentSql = "COMMENT ON COLUMN \"public\".\"adm_healthcare_service\".\"practitioner_id\" IS 'practitioner_id'";
|
||||
stmt.execute(commentSql);
|
||||
|
||||
System.out.println("Successfully added practitioner_id field to adm_healthcare_service table");
|
||||
} else {
|
||||
System.out.println("practitioner_id field already exists");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error executing SQL: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.openhis</groupId>
|
||||
<artifactId>openhis-server</artifactId>
|
||||
@@ -25,6 +25,11 @@
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger3-->
|
||||
<dependency>
|
||||
@@ -38,9 +43,10 @@
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Mysql驱动包 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 核心模块-->
|
||||
@@ -66,45 +72,12 @@
|
||||
<groupId>com.core</groupId>
|
||||
<artifactId>core-flowable</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.core</groupId>
|
||||
<artifactId>core-common</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- <build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||
<!-- <version>2.5.15</version>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <fork>true</fork> <!– 如果没有该配置,devtools不会生效 –>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>repackage</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-war-plugin</artifactId>-->
|
||||
<!-- <version>3.1.0</version>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <failOnMissingWebXml>false</failOnMissingWebXml>-->
|
||||
<!-- <warName>${project.artifactId}</warName>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <source>8</source>-->
|
||||
<!-- <target>8</target>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!-- <finalName>${project.artifactId}</finalName>-->
|
||||
<!-- </build>-->
|
||||
|
||||
</project>
|
||||
@@ -1,18 +1,5 @@
|
||||
package com.core.web.controller.common;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.constant.Constants;
|
||||
@@ -22,6 +9,17 @@ import com.core.common.utils.sign.Base64;
|
||||
import com.core.common.utils.uuid.IdUtils;
|
||||
import com.core.system.service.ISysConfigService;
|
||||
import com.google.code.kaptcha.Producer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 验证码操作处理
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.core.web.controller.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.file.FileUploadUtils;
|
||||
import com.core.common.utils.file.FileUtils;
|
||||
import com.core.framework.config.ServerConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -16,13 +17,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.file.FileUploadUtils;
|
||||
import com.core.common.utils.file.FileUtils;
|
||||
import com.core.framework.config.ServerConfig;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通用请求处理
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.core.web.controller.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.core.common.annotation.Anonymous;
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -16,6 +8,13 @@ import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.file.FileUploadUtils;
|
||||
import com.core.common.utils.file.FileUtils;
|
||||
import com.core.framework.config.ServerConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/file")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.core.web.controller.common;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* 前端路由 fallback 控制器
|
||||
* 处理 Vue Router History 模式下的路由
|
||||
*
|
||||
* @author
|
||||
*/
|
||||
@Controller
|
||||
public class FrontRouterController {
|
||||
|
||||
/**
|
||||
* 处理前端路由,将所有前端路由请求转发到 index.html
|
||||
*/
|
||||
@RequestMapping(value = {
|
||||
"/ybmanagement/**",
|
||||
"/system/**",
|
||||
"/monitor/**",
|
||||
"/tool/**",
|
||||
"/doctorstation/**",
|
||||
"/features/**",
|
||||
"/todo/**",
|
||||
"/appoinmentmanage/**",
|
||||
"/clinicmanagement/**",
|
||||
"/medicationmanagement/**",
|
||||
"/yb/**",
|
||||
"/patient/**",
|
||||
"/charge/**",
|
||||
"/nurse/**",
|
||||
"/pharmacy/**",
|
||||
"/report/**",
|
||||
"/document/**",
|
||||
"/triage/**",
|
||||
"/check/**",
|
||||
"/lab/**",
|
||||
"/financial/**",
|
||||
"/crosssystem/**",
|
||||
"/workflow/**"
|
||||
})
|
||||
public String index() {
|
||||
return "forward:/index.html";
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.core.web.controller.monitor;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.system.domain.SysCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.system.domain.SysCache;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 缓存监控
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.core.web.controller.monitor;
|
||||
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.framework.web.domain.Server;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.framework.web.domain.Server;
|
||||
|
||||
/**
|
||||
* 服务器监控
|
||||
*
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.core.web.controller.monitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -17,15 +9,23 @@ import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.framework.web.service.SysPasswordService;
|
||||
import com.core.system.domain.SysLogininfor;
|
||||
import com.core.system.service.ISysLogininforService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统访问记录
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/logininfor")
|
||||
|
||||
public class SysLogininforController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ISysLogininforService logininforService;
|
||||
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.core.web.controller.monitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -16,6 +8,12 @@ import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.system.domain.SysOperLog;
|
||||
import com.core.system.service.ISysOperLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志记录
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.monitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
@@ -20,6 +11,14 @@ import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.system.domain.SysUserOnline;
|
||||
import com.core.system.service.ISysUserOnlineService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 在线用户监控
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -17,6 +8,13 @@ import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.system.domain.SysConfig;
|
||||
import com.core.system.service.ISysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 参数配置 信息操作处理
|
||||
@@ -63,7 +61,25 @@ public class SysConfigController extends BaseController {
|
||||
*/
|
||||
@GetMapping(value = "/configKey/{configKey}")
|
||||
public AjaxResult getConfigKey(@PathVariable String configKey) {
|
||||
return success(configService.selectConfigByKey(configKey));
|
||||
String configValue = configService.selectConfigByKey(configKey);
|
||||
// 确保即使返回 null 或空字符串,也明确设置 data 字段
|
||||
// 如果 configValue 是 null,转换为空字符串
|
||||
if (configValue == null) {
|
||||
configValue = "";
|
||||
}
|
||||
// 直接创建 AjaxResult 并明确设置 data 字段,确保 data 字段始终存在
|
||||
AjaxResult result = new AjaxResult();
|
||||
result.put("code", 200);
|
||||
result.put("msg", "操作成功");
|
||||
result.put("data", configValue); // 明确设置 data 字段,即使值为空字符串
|
||||
System.out.println("=== getConfigKey 调试信息 ===");
|
||||
System.out.println("configKey: " + configKey);
|
||||
System.out.println("configValue: [" + configValue + "]");
|
||||
System.out.println("result.data: " + result.get("data"));
|
||||
System.out.println("result.msg: " + result.get("msg"));
|
||||
System.out.println("result.code: " + result.get("code"));
|
||||
System.out.println("============================");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.constant.UserConstants;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
@@ -16,6 +8,13 @@ import com.core.common.core.domain.entity.SysDept;
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.system.service.ISysDeptService;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门信息
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -20,6 +10,14 @@ import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.system.service.ISysDictDataService;
|
||||
import com.core.system.service.ISysDictTypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据字典信息
|
||||
@@ -62,11 +60,12 @@ public class SysDictDataController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典类型查询字典数据信息
|
||||
* 根据字典类型查询字典数据信息(支持拼音搜索)
|
||||
*/
|
||||
@GetMapping(value = "/type/{dictType}")
|
||||
public AjaxResult dictType(@PathVariable String dictType) {
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
|
||||
public AjaxResult dictType(@PathVariable String dictType,
|
||||
@RequestParam(value = "searchKey", required = false) String searchKey) {
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType, searchKey);
|
||||
if (StringUtils.isNull(data)) {
|
||||
data = new ArrayList<SysDictData>();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -17,6 +8,13 @@ import com.core.common.core.page.TableDataInfo;
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.system.service.ISysDictTypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据字典信息
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 首页
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.core.domain.entity.SysMenu;
|
||||
@@ -20,6 +11,15 @@ import com.core.framework.web.service.SysLoginService;
|
||||
import com.core.framework.web.service.SysPermissionService;
|
||||
import com.core.framework.web.service.TokenService;
|
||||
import com.core.system.service.ISysMenuService;
|
||||
import com.core.system.service.ISysTenantService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**已评审
|
||||
* 登录验证
|
||||
@@ -40,6 +40,9 @@ public class SysLoginController {
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private ISysTenantService tenantService;
|
||||
|
||||
/**已评审
|
||||
* 登录方法
|
||||
*
|
||||
@@ -73,12 +76,22 @@ public class SysLoginController {
|
||||
loginUser.setPermissions(permissions);
|
||||
tokenService.refreshToken(loginUser);
|
||||
}
|
||||
// 获取租户名称
|
||||
String tenantName = null;
|
||||
if (loginUser.getTenantId() != null) {
|
||||
com.core.system.domain.SysTenant tenant = tenantService.getById(loginUser.getTenantId());
|
||||
if (tenant != null) {
|
||||
tenantName = tenant.getTenantName();
|
||||
}
|
||||
}
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("optionJson", loginUser.getOptionJson());
|
||||
ajax.put("optionMap", loginUser.getOptionMap());
|
||||
ajax.put("practitionerId", String.valueOf(loginUser.getPractitionerId()));
|
||||
ajax.put("user", user);
|
||||
ajax.put("roles", roles);
|
||||
ajax.put("permissions", permissions);
|
||||
ajax.put("tenantName", tenantName);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.constant.UserConstants;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
@@ -15,6 +8,12 @@ import com.core.common.core.domain.entity.SysMenu;
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.system.service.ISysMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单信息
|
||||
@@ -34,7 +33,9 @@ public class SysMenuController extends BaseController {
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(SysMenu menu) {
|
||||
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
|
||||
return success(menus);
|
||||
// 构建带完整路径的菜单树
|
||||
List<SysMenu> menuTreeWithFullPath = menuService.buildMenuTreeWithFullPath(menus);
|
||||
return success(menuTreeWithFullPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,4 +117,47 @@ public class SysMenuController extends BaseController {
|
||||
}
|
||||
return toAjax(menuService.deleteMenuById(menuId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单完整路径
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:menu:query')")
|
||||
@GetMapping("/fullPath/{menuId}")
|
||||
public AjaxResult getFullPath(@PathVariable("menuId") Long menuId) {
|
||||
String fullPath = menuService.getMenuFullPath(menuId);
|
||||
return success(fullPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成完整路径
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:menu:query')")
|
||||
@PostMapping("/generateFullPath")
|
||||
public AjaxResult generateFullPath(@RequestParam(required = false) Long parentId,
|
||||
@RequestParam String currentPath) {
|
||||
String fullPath = menuService.generateFullPath(parentId, currentPath);
|
||||
return success(fullPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新菜单缓存
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:menu:list')")
|
||||
@Log(title = "菜单管理", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/refreshCache")
|
||||
public AjaxResult refreshCache() {
|
||||
menuService.refreshMenuCache();
|
||||
return success("菜单缓存已刷新");
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制刷新当前用户菜单缓存
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:menu:list')")
|
||||
@Log(title = "菜单管理", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/refreshCurrentUserMenuCache")
|
||||
public AjaxResult refreshCurrentUserMenuCache() {
|
||||
menuService.clearMenuCacheByUserId(getUserId());
|
||||
return success("当前用户菜单缓存已刷新");
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,21 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.core.domain.entity.SysUser;
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
import com.core.common.core.page.TableDataInfo;
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.system.domain.SysNotice;
|
||||
import com.core.system.service.ISysNoticeReadService;
|
||||
import com.core.system.service.ISysNoticeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.core.page.TableDataInfo;
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.system.domain.SysNotice;
|
||||
import com.core.system.service.ISysNoticeService;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公告 信息操作处理
|
||||
@@ -26,6 +28,9 @@ public class SysNoticeController extends BaseController {
|
||||
@Autowired
|
||||
private ISysNoticeService noticeService;
|
||||
|
||||
@Autowired
|
||||
private ISysNoticeReadService noticeReadService;
|
||||
|
||||
/**
|
||||
* 获取通知公告列表
|
||||
*/
|
||||
@@ -37,6 +42,108 @@ public class SysNoticeController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的公告列表(公开接口)
|
||||
* 公告类型:通常 noticeType = '1' 代表通知,noticeType = '2' 代表公告
|
||||
*/
|
||||
@GetMapping("/public/list")
|
||||
public TableDataInfo getPublicList(SysNotice notice) {
|
||||
// 只查询状态为正常(0)且已发布(1)的公告
|
||||
notice.setStatus("0");
|
||||
notice.setPublishStatus("1");
|
||||
// 公告类型设置为 '2'(公告)
|
||||
notice.setNoticeType("2");
|
||||
// 设置分页参数
|
||||
startPage();
|
||||
List<SysNotice> list = noticeService.selectNoticeList(notice);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的通知列表(公开接口)
|
||||
* 通知类型:通常 noticeType = '1' 代表通知,noticeType = '2' 代表公告
|
||||
* 返回已发布且状态正常的所有公告和通知,并标注已读状态
|
||||
* 按优先级排序,高优先级在前
|
||||
*/
|
||||
@GetMapping("/public/notice")
|
||||
public AjaxResult getUserNotices() {
|
||||
// 获取当前用户信息
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
|
||||
// 查询已发布且状态正常的所有公告和通知
|
||||
SysNotice notice = new SysNotice();
|
||||
notice.setStatus("0");
|
||||
notice.setPublishStatus("1");
|
||||
|
||||
List<SysNotice> list = noticeService.selectNoticeList(notice);
|
||||
|
||||
// 按优先级排序(1高 2中 3低),相同优先级按创建时间降序
|
||||
list.sort((a, b) -> {
|
||||
String priorityA = a.getPriority() != null ? a.getPriority() : "3";
|
||||
String priorityB = b.getPriority() != null ? b.getPriority() : "3";
|
||||
int priorityCompare = priorityA.compareTo(priorityB);
|
||||
if (priorityCompare != 0) {
|
||||
return priorityCompare;
|
||||
}
|
||||
// 相同优先级,按创建时间降序
|
||||
return b.getCreateTime().compareTo(a.getCreateTime());
|
||||
});
|
||||
|
||||
// 获取用户已读的公告/通知ID列表
|
||||
List<Long> readIds = noticeReadService.selectReadNoticeIdsByUserId(currentUser.getUserId());
|
||||
|
||||
// 为每个公告/通知添加已读状态
|
||||
for (SysNotice item : list) {
|
||||
boolean isRead = readIds.contains(item.getNoticeId());
|
||||
item.setIsRead(isRead);
|
||||
}
|
||||
|
||||
return success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户未读公告/通知数量(公开接口)
|
||||
*/
|
||||
@GetMapping("/public/unread/count")
|
||||
public AjaxResult getUnreadCount() {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
int count = noticeReadService.getUnreadCount(currentUser.getUserId());
|
||||
return success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记公告/通知为已读(公开接口)
|
||||
*/
|
||||
@PostMapping("/public/read/{noticeId}")
|
||||
public AjaxResult markAsRead(@PathVariable Long noticeId) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
return noticeReadService.markAsRead(noticeId, currentUser.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量标记公告/通知为已读(公开接口)
|
||||
*/
|
||||
@PostMapping("/public/read/all")
|
||||
public AjaxResult markAllAsRead(@RequestBody Long[] noticeIds) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
return noticeReadService.markAllAsRead(noticeIds, currentUser.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户已读公告/通知ID列表(公开接口)
|
||||
*/
|
||||
@GetMapping("/public/read/ids")
|
||||
public AjaxResult getReadNoticeIds() {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
List<Long> readIds = noticeReadService.selectReadNoticeIdsByUserId(currentUser.getUserId());
|
||||
return success(readIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通知公告编号获取详细信息
|
||||
*/
|
||||
@@ -54,6 +161,14 @@ public class SysNoticeController extends BaseController {
|
||||
@PostMapping
|
||||
public AjaxResult add(@Validated @RequestBody SysNotice notice) {
|
||||
notice.setCreateBy(getUsername());
|
||||
// 新建的公告默认为未发布状态
|
||||
if (notice.getPublishStatus() == null || notice.getPublishStatus().isEmpty()) {
|
||||
notice.setPublishStatus("0");
|
||||
}
|
||||
// 设置默认优先级为中(2)
|
||||
if (notice.getPriority() == null || notice.getPriority().isEmpty()) {
|
||||
notice.setPriority("2");
|
||||
}
|
||||
return toAjax(noticeService.insertNotice(notice));
|
||||
}
|
||||
|
||||
@@ -77,4 +192,42 @@ public class SysNoticeController extends BaseController {
|
||||
public AjaxResult remove(@PathVariable Long[] noticeIds) {
|
||||
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布公告/通知
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:notice:edit')")
|
||||
@Log(title = "发布公告", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/publish/{noticeId}")
|
||||
public AjaxResult publish(@PathVariable Long noticeId) {
|
||||
SysNotice notice = noticeService.selectNoticeById(noticeId);
|
||||
if (notice == null) {
|
||||
return error("公告不存在");
|
||||
}
|
||||
if ("1".equals(notice.getPublishStatus())) {
|
||||
return error("该公告已发布");
|
||||
}
|
||||
notice.setPublishStatus("1");
|
||||
notice.setUpdateBy(getUsername());
|
||||
return toAjax(noticeService.updateNotice(notice));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消发布公告/通知
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('system:notice:edit')")
|
||||
@Log(title = "取消发布", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/unpublish/{noticeId}")
|
||||
public AjaxResult unpublish(@PathVariable Long noticeId) {
|
||||
SysNotice notice = noticeService.selectNoticeById(noticeId);
|
||||
if (notice == null) {
|
||||
return error("公告不存在");
|
||||
}
|
||||
if ("0".equals(notice.getPublishStatus())) {
|
||||
return error("该公告未发布");
|
||||
}
|
||||
notice.setPublishStatus("0");
|
||||
notice.setUpdateBy(getUsername());
|
||||
return toAjax(noticeService.updateNotice(notice));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -17,6 +8,13 @@ import com.core.common.enums.BusinessType;
|
||||
import com.core.common.utils.poi.ExcelUtil;
|
||||
import com.core.system.domain.SysPost;
|
||||
import com.core.system.service.ISysPostService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 岗位信息操作处理
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.config.CoreConfig;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
@@ -17,6 +13,9 @@ import com.core.common.utils.file.FileUploadUtils;
|
||||
import com.core.common.utils.file.MimeTypeUtils;
|
||||
import com.core.framework.web.service.TokenService;
|
||||
import com.core.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 个人信息 业务处理
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.core.domain.model.RegisterBody;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.framework.web.service.SysRegisterService;
|
||||
import com.core.system.service.ISysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 注册验证
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -26,6 +17,13 @@ import com.core.system.domain.SysUserRole;
|
||||
import com.core.system.service.ISysDeptService;
|
||||
import com.core.system.service.ISysRoleService;
|
||||
import com.core.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色信息
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.core.common.annotation.Anonymous;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
@@ -13,6 +7,11 @@ import com.core.common.core.domain.R;
|
||||
import com.core.common.core.domain.entity.SysUser;
|
||||
import com.core.system.domain.SysTenant;
|
||||
import com.core.system.service.ISysTenantService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户信息controller
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.system.domain.dto.SaveTenantOptionDetailDto;
|
||||
import com.core.system.domain.dto.TenantOptionDto;
|
||||
import com.core.system.service.ISysTenantOptionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户配置项信息controller
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
package com.core.web.controller.system;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.core.common.annotation.Log;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
@@ -27,6 +15,16 @@ import com.core.system.service.ISysDeptService;
|
||||
import com.core.system.service.ISysPostService;
|
||||
import com.core.system.service.ISysRoleService;
|
||||
import com.core.system.service.ISysUserService;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package com.core.web.controller.tool;
|
||||
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import io.swagger.annotations.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
import io.swagger.annotations.*;
|
||||
|
||||
/**
|
||||
* swagger 用户测试方法
|
||||
*
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
package com.core.web.core.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.models.auth.In;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.core.common.config.CoreConfig;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.models.auth.In;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
@@ -20,6 +15,9 @@ import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Swagger2的接口配置
|
||||
*
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.core.web.util;
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
import com.core.common.enums.TenantOptionDict;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 租户配置工具类
|
||||
@@ -30,7 +31,12 @@ public class TenantOptionUtil {
|
||||
if (loginUser.getOptionMap() == null || loginUser.getOptionMap().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return loginUser.getOptionMap().get(optionDict.getCode());
|
||||
// return loginUser.getOptionMap().get(optionDict.getCode());
|
||||
|
||||
// TODO:2025/10/17 李永兴提出的sys_option切换TenantOption临时防止报错方案,最晚2025年11月底删除
|
||||
String newValue = loginUser.getOptionMap().get(optionDict.getCode());
|
||||
String oldValue = loginUser.getOptionJson().getString(optionDict.getCode());
|
||||
return StringUtils.isEmpty(newValue) ? oldValue : newValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,33 @@
|
||||
common通用工具
|
||||
</description>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
<arg>--add-modules</arg>
|
||||
<arg>java.base</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.34</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- mybatis-plus 增强CRUD -->
|
||||
@@ -54,6 +81,12 @@
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- jsr250 annotations -->
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 自定义验证注解 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -77,10 +110,6 @@
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- io常用工具类 -->
|
||||
<dependency>
|
||||
@@ -140,6 +169,12 @@
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
<version>2.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
import com.core.common.enums.DataSourceType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义多数据源切换注解
|
||||
*
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import com.core.common.utils.poi.ExcelHandlerAdapter;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
|
||||
import com.core.common.utils.poi.ExcelHandlerAdapter;
|
||||
|
||||
/**
|
||||
* 自定义导出Excel数据注解
|
||||
*
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* Excel额外表头信息注解
|
||||
*
|
||||
* @author swb
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ExcelExtra {
|
||||
/**
|
||||
* 表头名称
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* 日期格式,如:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
String dateFormat() default "";
|
||||
|
||||
/**
|
||||
* 排序(越小越靠前)
|
||||
*/
|
||||
int sort() default 0;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
String defaultValue() default "";
|
||||
|
||||
/**
|
||||
* 是否导出
|
||||
*/
|
||||
boolean isExport() default true;
|
||||
|
||||
/**
|
||||
* 精度 默认:-1(默认不开启BigDecimal格式化)
|
||||
*/
|
||||
int scale() default -1;
|
||||
|
||||
/**
|
||||
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
|
||||
*/
|
||||
int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
|
||||
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
import com.core.common.enums.BusinessType;
|
||||
import com.core.common.enums.OperatorType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.enums.LimitType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 限流注解
|
||||
*
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.core.common.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.core.common.config.serializer.SensitiveJsonSerializer;
|
||||
import com.core.common.enums.DesensitizedType;
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 数据脱敏注解
|
||||
*
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package com.core.common.config.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.core.common.annotation.Sensitive;
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
import com.core.common.enums.DesensitizedType;
|
||||
@@ -14,6 +11,9 @@ import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 数据脱敏序列化过滤
|
||||
*
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.core.common.constant;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
package com.core.common.core.controller;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
|
||||
import com.core.common.constant.HttpStatus;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
@@ -22,6 +13,14 @@ import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.sql.SqlUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* web层通用数据处理
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.core.common.constant.HttpStatus;
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 操作消息提醒
|
||||
*
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Data
|
||||
@@ -28,6 +28,7 @@ public class HisBaseEntity implements Serializable {
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
@@ -36,6 +37,7 @@ public class HisBaseEntity implements Serializable {
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/** 租户ID */
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页结果类
|
||||
*
|
||||
* @author
|
||||
* @date 2026-02-02
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PageResult<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 数据列表
|
||||
*/
|
||||
private List<T> rows;
|
||||
|
||||
/**
|
||||
* 总数
|
||||
*/
|
||||
private long total;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.core.common.constant.HttpStatus;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 响应信息主体
|
||||
*
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.core.common.core.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.core.common.core.domain.entity.SysDept;
|
||||
import com.core.common.core.domain.entity.SysMenu;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Treeselect树结构实体类
|
||||
*
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门表 sys_dept
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.core.common.annotation.Excel;
|
||||
import com.core.common.annotation.Excel.ColumnType;
|
||||
import com.core.common.constant.UserConstants;
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 字典数据表 sys_dict_data
|
||||
@@ -53,6 +52,9 @@ public class SysDictData extends BaseEntity {
|
||||
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
|
||||
private String status;
|
||||
|
||||
/** 拼音首字母 */
|
||||
private String pyStr;
|
||||
|
||||
public Long getDictCode() {
|
||||
return dictCode;
|
||||
}
|
||||
@@ -136,13 +138,21 @@ public class SysDictData extends BaseEntity {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getPyStr() {
|
||||
return pyStr;
|
||||
}
|
||||
|
||||
public void setPyStr(String pyStr) {
|
||||
this.pyStr = pyStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("dictCode", getDictCode())
|
||||
.append("dictSort", getDictSort()).append("dictLabel", getDictLabel()).append("dictValue", getDictValue())
|
||||
.append("dictType", getDictType()).append("cssClass", getCssClass()).append("listClass", getListClass())
|
||||
.append("isDefault", getIsDefault()).append("status", getStatus()).append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime()).append("updateBy", getUpdateBy())
|
||||
.append("isDefault", getIsDefault()).append("status", getStatus()).append("pyStr", getPyStr())
|
||||
.append("createBy", getCreateBy()).append("createTime", getCreateTime()).append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime()).append("remark", getRemark()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.core.common.annotation.Excel;
|
||||
import com.core.common.annotation.Excel.ColumnType;
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* 字典类型表 sys_dict_type
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单权限表 sys_menu
|
||||
@@ -71,6 +69,9 @@ public class SysMenu extends BaseEntity {
|
||||
/** 子菜单 */
|
||||
private List<SysMenu> children = new ArrayList<SysMenu>();
|
||||
|
||||
/** 完整路径 */
|
||||
private String fullPath;
|
||||
|
||||
public Long getMenuId() {
|
||||
return menuId;
|
||||
}
|
||||
@@ -214,6 +215,14 @@ public class SysMenu extends BaseEntity {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public String getFullPath() {
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public void setFullPath(String fullPath) {
|
||||
this.fullPath = fullPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("menuId", getMenuId())
|
||||
@@ -221,8 +230,8 @@ public class SysMenu extends BaseEntity {
|
||||
.append("path", getPath()).append("component", getComponent()).append("query", getQuery())
|
||||
.append("routeName", getRouteName()).append("isFrame", getIsFrame()).append("IsCache", getIsCache())
|
||||
.append("menuType", getMenuType()).append("visible", getVisible()).append("status ", getStatus())
|
||||
.append("perms", getPerms()).append("icon", getIcon()).append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime()).append("updateBy", getUpdateBy())
|
||||
.append("perms", getPerms()).append("icon", getIcon()).append("fullPath", getFullPath())
|
||||
.append("createBy", getCreateBy()).append("createTime", getCreateTime()).append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime()).append("remark", getRemark()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.core.common.annotation.Excel;
|
||||
import com.core.common.annotation.Excel.ColumnType;
|
||||
import com.core.common.core.domain.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 角色表 sys_role
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
package com.core.common.core.domain.entity;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.core.common.annotation.Excel;
|
||||
import com.core.common.annotation.Excel.ColumnType;
|
||||
import com.core.common.annotation.Excel.Type;
|
||||
@@ -19,8 +11,15 @@ import com.core.common.core.domain.BaseEntity;
|
||||
import com.core.common.xss.Xss;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户对象 sys_user
|
||||
@@ -32,6 +31,7 @@ public class SysUser extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 用户ID */
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
|
||||
private Long userId;
|
||||
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package com.core.common.core.domain.model;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.core.common.core.domain.entity.SysRole;
|
||||
import com.core.common.core.domain.entity.SysUser;
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.core.common.core.domain.entity.SysRole;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.core.common.core.domain.entity.SysUser;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登录用户身份权限
|
||||
*
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package com.core.common.core.redis;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.core.common.exception.UtilException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* spring redis 工具类
|
||||
*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.core.common.core.text;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 字符集工具类
|
||||
*
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.core.common.core.text;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
@@ -8,10 +11,6 @@ import java.nio.charset.Charset;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
*
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.core.common.enums;
|
||||
|
||||
/**
|
||||
* Desc: 调价类型枚举
|
||||
* @Author raymond
|
||||
* @Date 09:14 2025/10/16
|
||||
* @return
|
||||
**/
|
||||
public enum AdjustPriceEnum {
|
||||
|
||||
MEDICINE(0, "药品"),
|
||||
CONSUMABLES(1, "耗材"),
|
||||
DIAGNOSIS(2, "诊疗"),
|
||||
REGISTER(3, "挂号");
|
||||
|
||||
|
||||
private final Integer code;
|
||||
private final String info;
|
||||
|
||||
AdjustPriceEnum(Integer code, String info) {
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package com.openhis.common.enums;
|
||||
package com.core.common.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 删除标识
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Getter
|
||||
public enum DelFlag {
|
||||
/**
|
||||
* 未删除
|
||||
@@ -25,6 +28,23 @@ public enum DelFlag {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public static DelFlag getByValue(Integer value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
for (DelFlag val : values()) {
|
||||
if (val.value.equals(value)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 手动添加 getter 方法以解决 Lombok 兼容性问题
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
@@ -32,20 +52,4 @@ public enum DelFlag {
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static DelFlag getByValue(Integer value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
for (DelFlag val : values()) {
|
||||
if (val.getValue().equals(value)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.core.common.enums;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.core.common.utils.DesensitizedUtil;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 脱敏类型
|
||||
*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.core.common.enums;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* 请求方式
|
||||
*
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package com.core.common.enums;
|
||||
|
||||
/**
|
||||
* 删除标志
|
||||
*
|
||||
* @author system
|
||||
* 角色枚举
|
||||
*
|
||||
* @author swb
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
public enum DeleteFlag {
|
||||
NOT_DELETED("0", "未删除"), DELETED("1", "已删除");
|
||||
|
||||
public enum RoleEnum {
|
||||
DOCTOR("doctor", "医生"),
|
||||
NURSE("nurse", "护士"),
|
||||
ADMIN("admin", "管理员");
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
DeleteFlag(String code, String info) {
|
||||
RoleEnum(String code, String info) {
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
@@ -6,98 +6,39 @@ package com.core.common.enums;
|
||||
* @author system
|
||||
*/
|
||||
public enum TenantOptionDict {
|
||||
|
||||
/**
|
||||
* 医院名称
|
||||
*/
|
||||
HOSPITAL_NAME("hospitalName", "医院名称", 0),
|
||||
YB_HOSPITAL_NAME("hospitalName", "医保-医院名称", 0),
|
||||
/**
|
||||
* 医疗机构等级
|
||||
* 医保-医疗机构等级(3101接口)
|
||||
*/
|
||||
MEDINS_LV("medinsLv", "医疗机构等级", 1),
|
||||
YB_MEDINS_LV("medinsLv", "医保_医疗机构等级", 1),
|
||||
/**
|
||||
* 定点医药机构编号
|
||||
*/
|
||||
FIXMEDINS_CODE("fixmedinsCode", "定点医药机构编号", 2),
|
||||
YB_FIXMEDINS_CODE("fixmedinsCode", "医保_定点医药机构编号", 2),
|
||||
/**
|
||||
* 电子发票appid
|
||||
*/
|
||||
APP_ID("app_id", "电子发票appid", 3),
|
||||
EINVOICE_APP_ID("app_id", "电子发票-appid", 3),
|
||||
/**
|
||||
* 电子发票key
|
||||
*/
|
||||
KEY("key", "电子发票key", 4),
|
||||
EINVOICE_KEY("key", "电子发票-key", 4),
|
||||
/**
|
||||
* 电子发票url
|
||||
*/
|
||||
URL("url", "电子发票url", 5),
|
||||
EINVOICE_URL("url", "电子发票-url", 5),
|
||||
/**
|
||||
* 医保开关
|
||||
*/
|
||||
YB_SWITCH("yb_switch", "医保开关", 6),
|
||||
/**
|
||||
* 客户端私钥
|
||||
*/
|
||||
CLI_PRV_KEY("cliPrvKey", "客户端私钥", 7),
|
||||
/**
|
||||
* 客户端公钥
|
||||
*/
|
||||
CLI_PUB_KEY("cliPubKey", "客户端公钥", 8),
|
||||
/**
|
||||
* 服务端公钥
|
||||
*/
|
||||
SERVER_PUB_KEY("serverPubKey", "服务端公钥", 9),
|
||||
/**
|
||||
* 定点医药机构名称
|
||||
*/
|
||||
FIXMEDINS_NAME("fixmedinsName", "定点医药机构名称", 10),
|
||||
/**
|
||||
* 行政区划
|
||||
*/
|
||||
ADMVS("admvs", "行政区划", 11),
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
SCOPE("scope", "授权范围", 12),
|
||||
/**
|
||||
* 授权类型
|
||||
*/
|
||||
GRANT_TYPE("grantType", "授权类型", 13),
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
PASSWORD("password", "密码", 14),
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
USERNAME("username", "用户名", 15),
|
||||
/**
|
||||
* 客户端安全码
|
||||
*/
|
||||
CLIENT_SECRET("clientSecret", "客户端安全码", 16),
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
CLIENT_ID("clientId", "客户端ID", 17),
|
||||
/**
|
||||
* 生产环境客户端公钥
|
||||
*/
|
||||
PROD_CLI_PUB_KEY("prod_cliPubKey", "生产环境客户端公钥", 18),
|
||||
/**
|
||||
* 生产环境客户端私钥
|
||||
*/
|
||||
PROD_CLI_PRV_KEY("prod_cliPrvKey", "生产环境客户端私钥", 19),
|
||||
/**
|
||||
* 生产环境客户端ID
|
||||
*/
|
||||
PROD_CLIENT_ID("prod_clientId", "生产环境客户端ID", 20),
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
FILE_PATH("filePath", "文件路径", 21),
|
||||
/**
|
||||
* 电子地址
|
||||
*/
|
||||
ELE_ADDRESS("eleAddress", "电子地址", 22),
|
||||
ELE_ADDRESS("eleAddress", "电子处方-请求地址", 22),
|
||||
/**
|
||||
* 服务地址
|
||||
*/
|
||||
@@ -109,63 +50,35 @@ public enum TenantOptionDict {
|
||||
/**
|
||||
* 是否加密
|
||||
*/
|
||||
IS_ENCRYPT("isEncrypt", "是否加密", 25),
|
||||
YB_IS_ENCRYPT("isEncrypt", "医保-是否加密", 25),
|
||||
/**
|
||||
* 医保区划
|
||||
*/
|
||||
INSUPLC_ADMDVS("insuplc_admdvs", "医保区划", 26),
|
||||
YB_INSUPLC_ADMDVS("insuplc_admdvs", "医保-区划", 26),
|
||||
/**
|
||||
* 电子处方appId
|
||||
*/
|
||||
PRE_APP_ID("pre_app_id", "电子处方appId", 27),
|
||||
ELE_PRE_APP_ID("pre_app_id", "电子处方-appId", 27),
|
||||
/**
|
||||
* 电子处方appSecret
|
||||
*/
|
||||
PRE_APP_SECRET("pre_app_secret", "电子处方appSecret", 28),
|
||||
ELE_PRE_APP_SECRET("pre_app_secret", "电子处方-appSecret", 28),
|
||||
/**
|
||||
* 电子处方私钥
|
||||
*/
|
||||
APP_PRVKEY("APP_PRVKEY", "电子处方私钥", 29),
|
||||
ELE_APP_PRVKEY("APP_PRVKEY", "电子处方-私钥", 29),
|
||||
/**
|
||||
* 电子处方公钥
|
||||
*/
|
||||
PLAF_PUBKEY("PLAF_PUBKEY", "电子处方公钥", 30),
|
||||
/**
|
||||
* 医保客户端ID
|
||||
*/
|
||||
YB_CLIENT_ID("ybClientId", "医保客户端ID", 31),
|
||||
/**
|
||||
* 医保客户端安全码
|
||||
*/
|
||||
YB_CLIENT_SECRET("ybClientSecret", "医保客户端安全码", 32),
|
||||
/**
|
||||
* 医保用户名
|
||||
*/
|
||||
YB_USERNAME("ybUsername", "医保用户名", 33),
|
||||
/**
|
||||
* 医保密码
|
||||
*/
|
||||
YB_PASSWORD("ybPassword", "医保密码", 34),
|
||||
/**
|
||||
* 医保授权类型
|
||||
*/
|
||||
YB_GRANT_TYPE("ybGrantType", "医保授权类型", 35),
|
||||
/**
|
||||
* 医保授权范围
|
||||
*/
|
||||
YB_SCOPE("ybScope", "医保授权范围", 36),
|
||||
/**
|
||||
* 医保密钥
|
||||
*/
|
||||
YB_CLI_PRV_KEY("ybCliPrvKey", "医保密钥", 37),
|
||||
/**
|
||||
* 医保服务URL
|
||||
*/
|
||||
YB_URL("ybUrl", "医保服务URL", 38),
|
||||
ELE_PLAF_PUBKEY("PLAF_PUBKEY", "电子处方-公钥", 30),
|
||||
/**
|
||||
* 医院等级
|
||||
*/
|
||||
HOSPITAL_LV("hospital_lv", "医院等级", 39),
|
||||
EINVOICE_HOSPITAL_LV("hospital_lv", "电子发票-医院等级", 39),
|
||||
/**
|
||||
* 无视LIS&PACS报错
|
||||
*/
|
||||
LIS_PACS_ERROR_IGNORE("lisPacsErrorIgnore", "无视LIS&PACS报错", 40),
|
||||
/**
|
||||
* LIS接口地址
|
||||
*/
|
||||
@@ -191,13 +104,13 @@ public enum TenantOptionDict {
|
||||
*/
|
||||
PACS_APP_SECRET("pacsAppSecret", "PACSAppSecret", 45),
|
||||
/**
|
||||
* PACSAppSecret
|
||||
* 电子发票-中转服务的路径
|
||||
*/
|
||||
INVOICE_URL("invoiceUrl", "电子发票中转服务的路径", 46),
|
||||
INVOICE_FORWARD_URL("invoiceUrl", "电子发票-中转服务的路径", 46),
|
||||
/**
|
||||
* PACSAppSecret
|
||||
* 电子发票-中转服务开关
|
||||
*/
|
||||
FORWARD_SWITCH("forwardSwitch", "电子发票中转服务开关", 47),
|
||||
FORWARD_SWITCH("forwardSwitch", "电子发票-中转服务开关", 47),
|
||||
/**
|
||||
* 食源性开关
|
||||
*/
|
||||
@@ -229,7 +142,164 @@ public enum TenantOptionDict {
|
||||
/**
|
||||
* BPC请求URL
|
||||
*/
|
||||
BPC_REQUEST_URL("bpcRequestUrl", "BPC请求URL", 55);
|
||||
BPC_REQUEST_URL("bpcRequestUrl", "BPC请求URL", 55),
|
||||
/**
|
||||
* 电子发票开关
|
||||
*/
|
||||
INVOICE_SWITCH("invoiceSwitch", "电子发票开关", 56),
|
||||
/**
|
||||
* 医嘱定价来源
|
||||
*/
|
||||
ORDER_PRICING_SOURCE("orderPricingSource", "定价来源 batchSellingPrice/retailPrice", 57),
|
||||
/**
|
||||
* 三方支付(签到)
|
||||
*/
|
||||
THREE_PART_SIGN_URL("threePartSignUrl", "三方支付【签到】请求路径", 58),
|
||||
/**
|
||||
* 三方支付(签到)
|
||||
*/
|
||||
THREE_PART_SIGN_STATIC_PARAM("threePartSignStaticParam", "三方支付【签到】固定参数", 59),
|
||||
/**
|
||||
* 三方支付(签到)
|
||||
*/
|
||||
THREE_PART_SIGN_ACTIVE_PARAM("threePartSignActiveParam", "三方支付【签到】可变参数", 60),
|
||||
/**
|
||||
* 三方支付(签到)
|
||||
*/
|
||||
THREE_PART_SIGN_MAPPING_METHOD("threePartSignMappingMethod", "三方支付【签到】请求方式", 61),
|
||||
/**
|
||||
* 三方支付(消费)
|
||||
*/
|
||||
THREE_PART_PAY_URL("threePartPayUrl", "三方支付【消费】请求路径", 62),
|
||||
/**
|
||||
* 三方支付(消费)
|
||||
*/
|
||||
THREE_PART_PAY_STATIC_PARAM("threePartPayStaticParam", "三方支付【消费】固定参数", 63),
|
||||
/**
|
||||
* 三方支付(消费)
|
||||
*/
|
||||
THREE_PART_PAY_ACTIVE_PARAM("threePartPayActiveParam", "三方支付【消费】可变参数", 64),
|
||||
/**
|
||||
* 三方支付(消费)
|
||||
*/
|
||||
THREE_PART_PAY_MAPPING_METHOD("threePartPayMappingMethod", "三方支付【消费】请求方式", 65),
|
||||
/**
|
||||
* 三方支付(退费)
|
||||
*/
|
||||
THREE_PART_RETURN_URL("threePartReturnUrl", "三方支付【退费】请求路径", 66),
|
||||
/**
|
||||
* 三方支付(退费)
|
||||
*/
|
||||
THREE_PART_RETURN_STATIC_PARAM("threePartReturnStaticParam", "三方支付【退费】固定参数", 67),
|
||||
/**
|
||||
* 三方支付(退费)
|
||||
*/
|
||||
THREE_PART_RETURN_ACTIVE_PARAM("threePartReturnActiveParam", "三方支付【退费】可变参数", 68),
|
||||
/**
|
||||
* 三方支付(退费)
|
||||
*/
|
||||
THREE_PART_RETURN_MAPPING_METHOD("threePartReturnMappingMethod", "三方支付【退费】请求方式", 69),
|
||||
/**
|
||||
* 三方支付(隔天退费)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_URL("threePartNextDayReturnUrl", "三方支付【隔天退费】请求路径", 70),
|
||||
/**
|
||||
* 三方支付(隔天退费)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_STATIC_PARAM("threePartNextDayReturnStaticParam", "三方支付【隔天退费】固定参数", 71),
|
||||
/**
|
||||
* 三方支付(隔天退费)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_ACTIVE_PARAM("threePartNextDayReturnActiveParam", "三方支付【隔天退费】可变参数", 72),
|
||||
/**
|
||||
* 三方支付(隔天退费)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_MAPPING_METHOD("threePartNextDayReturnMappingMethod", "三方支付【隔天退费】请求方式", 73),
|
||||
/**
|
||||
* 三方支付路径(支付结果查询)
|
||||
*/
|
||||
THREE_PART_PAY_QUERY_URL("threePartPayQueryUrl", "三方支付【支付结果查询】请求路径", 74),
|
||||
/**
|
||||
* 三方支付(支付结果查询)
|
||||
*/
|
||||
THREE_PART_PAY_QUERY_STATIC_PARAM("threePartPayQueryStaticParam", "三方支付【支付结果查询】固定参数", 75),
|
||||
/**
|
||||
* 三方支付(支付结果查询)
|
||||
*/
|
||||
THREE_PART_PAY_QUERY_ACTIVE_PARAM("threePartPayQueryActiveParam", "三方支付【支付结果查询】可变参数", 76),
|
||||
/**
|
||||
* 三方支付(支付结果查询)
|
||||
*/
|
||||
THREE_PART_PAY_QUERY_MAPPING_METHOD("threePartPayQueryMappingMethod", "三方支付【支付结果查询】请求方式", 77),
|
||||
/**
|
||||
* 三方支付路径(退费结果查询)
|
||||
*/
|
||||
THREE_PART_RETURN_QUERY_URL("threePartReturnQueryUrl", "三方支付【退费结果查询】请求路径", 78),
|
||||
/**
|
||||
* 三方支付(退费结果查询)
|
||||
*/
|
||||
THREE_PART_RETURN_QUERY_STATIC_PARAM("threePartReturnQueryStaticParam", "三方支付【退费结果查询】固定参数", 79),
|
||||
/**
|
||||
* 三方支付(退费结果查询)
|
||||
*/
|
||||
THREE_PART_RETURN_QUERY_ACTIVE_PARAM("threePartReturnQueryActiveParam", "三方支付【退费结果查询】可变参数", 80),
|
||||
/**
|
||||
* 三方支付(退费结果查询)
|
||||
*/
|
||||
THREE_PART_RETURN_QUERY_MAPPING_METHOD("threePartReturnQueryMappingMethod", "三方支付【退费结果查询】请求方式", 81),
|
||||
/**
|
||||
* 三方支付路径(隔天退费结果查询)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_QUERY_URL("threePartNextDayReturnQueryUrl", "三方支付【隔天退费结果查询】请求路径", 82),
|
||||
/**
|
||||
* 三方支付(隔天退费结果查询)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_QUERY_STATIC_PARAM("threePartNextDayReturnQueryStaticParam", "三方支付【隔天退费结果查询】固定参数", 83),
|
||||
/**
|
||||
* 三方支付(隔天退费结果查询)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_QUERY_ACTIVE_PARAM("threePartNextDayReturnQueryActiveParam", "三方支付【隔天退费结果查询】可变参数", 84),
|
||||
/**
|
||||
* 三方支付(隔天退费结果查询)
|
||||
*/
|
||||
THREE_PART_NEXT_DAY_RETURN_QUERY_MAPPING_METHOD("threePartNextDayReturnQueryMappingMethod", "三方支付【隔天退费结果查询】请求方式",
|
||||
85),
|
||||
/**
|
||||
* 三方支付(签出)
|
||||
*/
|
||||
THREE_PART_SIGN_OUT_URL("threePartSignOutUrl", "三方支付【签出】请求路径", 86),
|
||||
/**
|
||||
* 三方支付(签出)
|
||||
*/
|
||||
THREE_PART_SIGN_OUT_STATIC_PARAM("threePartSignOutStaticParam", "三方支付【签出】固定参数", 87),
|
||||
/**
|
||||
* 三方支付(签出)
|
||||
*/
|
||||
THREE_PART_SIGN_OUT_ACTIVE_PARAM("threePartSignOutActiveParam", "三方支付【签出】可变参数", 88),
|
||||
/**
|
||||
* 三方支付(签出)
|
||||
*/
|
||||
THREE_PART_SIGN_OUT_MAPPING_METHOD("threePartSignOutMappingMethod", "三方支付【签出】请求方式", 89),
|
||||
/**
|
||||
* 三方支付(签出)
|
||||
*/
|
||||
YB_INPATIENT_SETTLEMENT_UP_URL("ybInpatientSetlUp", "选填4101或4101A", 90),
|
||||
/**
|
||||
* PACS查看报告地址
|
||||
*/
|
||||
PACS_REPORT_URL("pacsReportUrl", "PACS查看报告地址", 91),
|
||||
/**
|
||||
* LIS查看报告地址
|
||||
*/
|
||||
LIS_REPORT_URL("lisReportUrl", "LIS查看报告地址", 92),
|
||||
/**
|
||||
* 开药时药房允许多选开关
|
||||
*/
|
||||
PHARMACY_MULTIPLE_CHOICE_SWITCH("pharmacyMultipleChoiceSwitch", "开药时药房允许多选开关", 93),
|
||||
/**
|
||||
* PEIS服务地址
|
||||
*/
|
||||
PEIS_SERVER_URL("peisServerUrl", "PEIS服务地址", 94);
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
@@ -241,18 +311,6 @@ public enum TenantOptionDict {
|
||||
this.sort = sort;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public static TenantOptionDict getByCode(String code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
@@ -264,4 +322,16 @@ public enum TenantOptionDict {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getSort() {
|
||||
return sort;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class ServiceException extends RuntimeException {
|
||||
/**
|
||||
* 错误明细,内部调试错误
|
||||
*
|
||||
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
|
||||
* 和
|
||||
*/
|
||||
private String detailMessage;
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.core.common.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Repeatable 过滤器
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package com.core.common.filter;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.utils.http.HttpHelper;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.utils.http.HttpHelper;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* 构建可重复读取inputStream的request
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.core.common.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.core.common.enums.HttpMethod;
|
||||
import com.core.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.core.common.enums.HttpMethod;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 防止XSS攻击的过滤器
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
package com.core.common.filter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.html.EscapeUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.html.EscapeUtil;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* XSS过滤处理
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.core.common.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.core.common.utils.AuditFieldUtil;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 包含审计字段自动设置功能的基础服务类
|
||||
*
|
||||
* @param <M> Mapper 类型,必须继承 BaseMapper<T>
|
||||
* @param <T> 实体类型
|
||||
*/
|
||||
public abstract class BaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {
|
||||
|
||||
/**
|
||||
* 重写保存方法,自动设置创建审计字段
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean save(T entity) {
|
||||
// 在保存前设置创建审计字段
|
||||
AuditFieldUtil.setCreateInfo(entity);
|
||||
return super.save(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写批量保存方法,自动设置创建审计字段
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean saveBatch(Collection<T> entityList) {
|
||||
// 为每个实体设置创建审计字段
|
||||
entityList.forEach(AuditFieldUtil::setCreateInfo);
|
||||
return super.saveBatch(entityList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写更新方法,自动设置更新审计字段
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean updateById(T entity) {
|
||||
// 在更新前设置更新审计字段
|
||||
AuditFieldUtil.setUpdateInfo(entity);
|
||||
return super.updateById(entity);
|
||||
}
|
||||
}
|
||||
@@ -33,67 +33,125 @@ public final class AgeCalculatorUtil {
|
||||
return period.getYears();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 当前年龄取得(床位列表表示年龄用)
|
||||
// */
|
||||
// public static String getAge(Date date) {
|
||||
// // 将 Date 转换为 LocalDateTime
|
||||
// LocalDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
// LocalDateTime now = LocalDateTime.now();
|
||||
// int years = now.getYear() - dateTime.getYear();
|
||||
// if (years > 2) {
|
||||
// return String.format("%d岁", years);
|
||||
// }
|
||||
//
|
||||
// Period period = Period.between(dateTime.toLocalDate(), now.toLocalDate());
|
||||
// int months = period.getMonths();
|
||||
// int days = period.getDays();
|
||||
// long hours = ChronoUnit.HOURS.between(dateTime, now) - (days * 24L);
|
||||
//
|
||||
// if (hours < 0) {
|
||||
// hours += 24;
|
||||
// days--;
|
||||
// }
|
||||
// if (days < 0) {
|
||||
// months--;
|
||||
// days = getLastDayOfMonth(dateTime) - dateTime.getDayOfMonth() + now.getDayOfMonth();
|
||||
// }
|
||||
// if (months < 0) {
|
||||
// months += 12;
|
||||
// years--;
|
||||
// }
|
||||
// if (years < 0) {
|
||||
// return "1小时";
|
||||
// }
|
||||
//
|
||||
// if (years > 0 && months > 0) {
|
||||
// return String.format("%d岁%d月", years, months);
|
||||
// }
|
||||
// if (years > 0) {
|
||||
// return String.format("%d岁", years);
|
||||
// }
|
||||
// if (months > 0 && days > 0) {
|
||||
// return String.format("%d月%d天", months, days);
|
||||
// }
|
||||
// if (months > 0) {
|
||||
// return String.format("%d月", months);
|
||||
// }
|
||||
// if (days > 0 && hours > 0) {
|
||||
// return String.format("%d天%d小时", days, hours);
|
||||
// }
|
||||
// if (days > 0) {
|
||||
// return String.format("%d天", days);
|
||||
// }
|
||||
// if (hours > 0) {
|
||||
// return String.format("%d小时", hours);
|
||||
// }
|
||||
// return "1小时";
|
||||
// }
|
||||
/**
|
||||
* 当前年龄取得(床位列表表示年龄用)
|
||||
* 复刻Oracle函数FUN_GET_AGE的核心逻辑:返回年龄字符串
|
||||
*
|
||||
* @param birthDate 出生日期
|
||||
* @return 年龄字符串(如:29岁、3岁5月、2月15天、18天),出生日期晚于当前日期返回空字符串
|
||||
*/
|
||||
public static String getAge(Date date) {
|
||||
// 添加空值检查
|
||||
if (date == null) {
|
||||
public static String getAge(Date birthDate) {
|
||||
// 入参校验
|
||||
if (birthDate == null) {
|
||||
return "";
|
||||
}
|
||||
// 将 Date 转换为 LocalDateTime
|
||||
LocalDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
int years = now.getYear() - dateTime.getYear();
|
||||
if (years > 2) {
|
||||
return String.format("%d岁", years);
|
||||
|
||||
// 将Date转换为LocalDate(使用系统默认时区)
|
||||
LocalDate birthLocalDate = birthDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
|
||||
// 计算总天数(对应Oracle中的IDAY)
|
||||
long totalDays = ChronoUnit.DAYS.between(birthLocalDate, currentDate);
|
||||
|
||||
// 若出生日期晚于当前日期,返回空字符串
|
||||
if (totalDays < 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Period period = Period.between(dateTime.toLocalDate(), now.toLocalDate());
|
||||
int months = period.getMonths();
|
||||
int days = period.getDays();
|
||||
long hours = ChronoUnit.HOURS.between(dateTime, now) - (days * 24L);
|
||||
// 计算年份(复刻Oracle的闰年补偿逻辑:(当前年-出生年)/4 补偿闰年天数)
|
||||
int birthYear = birthLocalDate.getYear();
|
||||
int currentYear = currentDate.getYear();
|
||||
long leapYearCompensation = (currentYear - birthYear) / 4;
|
||||
long adjustedDays = totalDays - leapYearCompensation;
|
||||
|
||||
if (hours < 0) {
|
||||
hours += 24;
|
||||
days--;
|
||||
}
|
||||
if (days < 0) {
|
||||
months--;
|
||||
days = getLastDayOfMonth(dateTime) - dateTime.getDayOfMonth() + now.getDayOfMonth();
|
||||
}
|
||||
if (months < 0) {
|
||||
months += 12;
|
||||
years--;
|
||||
}
|
||||
if (years < 0) {
|
||||
return "1小时";
|
||||
}
|
||||
// 计算年、月、天(按365天/年、30天/月粗略折算,与Oracle逻辑一致)
|
||||
int iYear = (int) (adjustedDays / 365);
|
||||
long remainingDaysAfterYear = adjustedDays - iYear * 365;
|
||||
int iMonth = (int) (remainingDaysAfterYear / 30);
|
||||
int iDay = (int) (remainingDaysAfterYear - iMonth * 30);
|
||||
|
||||
if (years > 0 && months > 0) {
|
||||
return String.format("%d岁%d月", years, months);
|
||||
// 按原函数规则拼接返回字符串
|
||||
if (iYear <= 0) {
|
||||
// 小于1岁
|
||||
if (iMonth <= 0) {
|
||||
// 小于1个月,返回X天
|
||||
return iDay + "天";
|
||||
} else {
|
||||
// 1个月及以上,返回X月X天
|
||||
return iMonth + "月" + iDay + "天";
|
||||
}
|
||||
} else {
|
||||
// 1岁及以上
|
||||
if (iYear < 5) {
|
||||
// 1-4岁
|
||||
if (iMonth <= 0) {
|
||||
// 无整月,返回X岁X天
|
||||
return iYear + "岁" + iDay + "天";
|
||||
} else {
|
||||
// 有整月,返回X岁X月
|
||||
return iYear + "岁" + iMonth + "月";
|
||||
}
|
||||
} else {
|
||||
// 5岁及以上,仅返回X岁
|
||||
return iYear + "岁";
|
||||
}
|
||||
}
|
||||
if (years > 0) {
|
||||
return String.format("%d岁", years);
|
||||
}
|
||||
if (months > 0 && days > 0) {
|
||||
return String.format("%d月%d天", months, days);
|
||||
}
|
||||
if (months > 0) {
|
||||
return String.format("%d月", months);
|
||||
}
|
||||
if (days > 0 && hours > 0) {
|
||||
return String.format("%d天%d小时", days, hours);
|
||||
}
|
||||
if (days > 0) {
|
||||
return String.format("%d天", days);
|
||||
}
|
||||
if (hours > 0) {
|
||||
return String.format("%d小时", hours);
|
||||
}
|
||||
return "1小时";
|
||||
}
|
||||
|
||||
private static int getLastDayOfMonth(LocalDateTime dateTime) {
|
||||
int[] daysInMonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
if (isLeapYear(dateTime.getYear()) && dateTime.getMonthValue() == 2) {
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
*/
|
||||
package com.core.common.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.redis.RedisCache;
|
||||
import com.core.common.exception.UtilException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.redis.RedisCache;
|
||||
import com.core.common.exception.UtilException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 排番组件
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 审计字段工具类
|
||||
* 用于手动设置创建人、创建时间、更新人、更新时间等审计字段
|
||||
*/
|
||||
@Component
|
||||
public class AuditFieldUtil {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AuditFieldUtil.class);
|
||||
|
||||
/**
|
||||
* 为实体设置创建相关的审计字段
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
public static void setCreateInfo(Object entity) {
|
||||
if (entity == null) return;
|
||||
|
||||
try {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
String username = loginUser != null ? loginUser.getUsername() : "system";
|
||||
Date currentTime = new Date();
|
||||
|
||||
// 使用反射设置字段值
|
||||
Field createByField = getField(entity.getClass(), "createBy");
|
||||
if (createByField != null) {
|
||||
createByField.setAccessible(true);
|
||||
// 只有当字段值为 null 或空字符串时才设置
|
||||
if (createByField.get(entity) == null || "".equals(createByField.get(entity))) {
|
||||
createByField.set(entity, username);
|
||||
}
|
||||
}
|
||||
|
||||
Field createTimeField = getField(entity.getClass(), "createTime");
|
||||
if (createTimeField != null) {
|
||||
createTimeField.setAccessible(true);
|
||||
// 只有当字段值为 null 时才设置
|
||||
if (createTimeField.get(entity) == null) {
|
||||
createTimeField.set(entity, currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理下划线命名的字段
|
||||
Field createByFieldUnderscore = getField(entity.getClass(), "create_by");
|
||||
if (createByFieldUnderscore != null) {
|
||||
createByFieldUnderscore.setAccessible(true);
|
||||
// 只有当字段值为 null 或空字符串时才设置
|
||||
if (createByFieldUnderscore.get(entity) == null || "".equals(createByFieldUnderscore.get(entity))) {
|
||||
createByFieldUnderscore.set(entity, username);
|
||||
}
|
||||
}
|
||||
|
||||
Field createTimeFieldUnderscore = getField(entity.getClass(), "create_time");
|
||||
if (createTimeFieldUnderscore != null) {
|
||||
createTimeFieldUnderscore.setAccessible(true);
|
||||
// 只有当字段值为 null 时才设置
|
||||
if (createTimeFieldUnderscore.get(entity) == null) {
|
||||
createTimeFieldUnderscore.set(entity, currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("设置创建审计字段时发生异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为实体设置更新相关的审计字段
|
||||
* @param entity 实体对象
|
||||
*/
|
||||
public static void setUpdateInfo(Object entity) {
|
||||
if (entity == null) return;
|
||||
|
||||
try {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
String username = loginUser != null ? loginUser.getUsername() : "system";
|
||||
Date currentTime = new Date();
|
||||
|
||||
// 设置更新人字段
|
||||
Field updateByField = getField(entity.getClass(), "updateBy");
|
||||
if (updateByField != null) {
|
||||
updateByField.setAccessible(true);
|
||||
updateByField.set(entity, username);
|
||||
}
|
||||
|
||||
// 设置更新时间字段
|
||||
Field updateTimeField = getField(entity.getClass(), "updateTime");
|
||||
if (updateTimeField != null) {
|
||||
updateTimeField.setAccessible(true);
|
||||
updateTimeField.set(entity, currentTime);
|
||||
}
|
||||
|
||||
// 处理下划线命名的字段
|
||||
Field updateByFieldUnderscore = getField(entity.getClass(), "update_by");
|
||||
if (updateByFieldUnderscore != null) {
|
||||
updateByFieldUnderscore.setAccessible(true);
|
||||
updateByFieldUnderscore.set(entity, username);
|
||||
}
|
||||
|
||||
Field updateTimeFieldUnderscore = getField(entity.getClass(), "update_time");
|
||||
if (updateTimeFieldUnderscore != null) {
|
||||
updateTimeFieldUnderscore.setAccessible(true);
|
||||
updateTimeFieldUnderscore.set(entity, currentTime);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("设置更新审计字段时发生异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用反射获取字段,支持父类字段
|
||||
* @param clazz 类
|
||||
* @param fieldName 字段名
|
||||
* @return 字段对象
|
||||
*/
|
||||
private static Field getField(Class<?> clazz, String fieldName) {
|
||||
try {
|
||||
return clazz.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// 如果在当前类中找不到,尝试在父类中查找
|
||||
if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
|
||||
return getField(clazz.getSuperclass(), fieldName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -9,14 +13,15 @@ import java.time.format.DateTimeParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
/**
|
||||
* 时间工具类
|
||||
*
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DateUtils.class);
|
||||
|
||||
public static String YYYY = "yyyy";
|
||||
|
||||
public static String YYYY_MM = "yyyy-MM";
|
||||
@@ -227,7 +232,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
||||
return endTime;
|
||||
}
|
||||
} catch (DateTimeParseException e) {
|
||||
e.printStackTrace();
|
||||
log.warn("日期解析失败: {}", strDate, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -250,7 +255,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
||||
// 检查日期是否是未来的时间
|
||||
return dateToCheck.isAfter(currentDate);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.warn("日期解析失败: {}", dateString, e);
|
||||
// 解析失败或其他异常,返回 false 或根据需要处理异常
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.core.common.constant.CacheConstants;
|
||||
import com.core.common.core.domain.entity.SysDictData;
|
||||
import com.core.common.core.redis.RedisCache;
|
||||
import com.core.common.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字典工具类
|
||||
*
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
|
||||
/**
|
||||
* 错误信息处理类。
|
||||
*
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import com.core.common.utils.spring.SpringUtils;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
||||
import com.core.common.utils.spring.SpringUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,18 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.constant.HttpStatus;
|
||||
import com.core.common.core.domain.entity.SysRole;
|
||||
import com.core.common.core.domain.model.LoginUser;
|
||||
import com.core.common.exception.ServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 安全服务工具类
|
||||
@@ -55,6 +54,17 @@ public class SecurityUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户昵称
|
||||
**/
|
||||
public static String getNickName() {
|
||||
try {
|
||||
return getLoginUser().getUser().getNickName();
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("获取用户昵称异常", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
**/
|
||||
@@ -66,6 +76,25 @@ public class SecurityUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全获取用户名(失败时返回默认值)
|
||||
**/
|
||||
public static String getUsernameSafe() {
|
||||
try {
|
||||
Authentication authentication = getAuthentication();
|
||||
if (authentication != null && authentication.getPrincipal() != null) {
|
||||
if (authentication.getPrincipal() instanceof LoginUser) {
|
||||
return ((LoginUser) authentication.getPrincipal()).getUsername();
|
||||
} else {
|
||||
return authentication.getPrincipal().toString();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 静默处理异常,返回默认值
|
||||
}
|
||||
return "anonymous";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Authentication
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
package com.core.common.utils;
|
||||
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.core.text.Convert;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
@@ -8,24 +20,15 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import com.core.common.constant.Constants;
|
||||
import com.core.common.core.text.Convert;
|
||||
|
||||
/**
|
||||
* 客户端工具类
|
||||
*
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
public class ServletUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ServletUtils.class);
|
||||
|
||||
/**
|
||||
* 获取String参数
|
||||
*/
|
||||
@@ -132,7 +135,7 @@ public class ServletUtils {
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.getWriter().print(string);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("渲染响应字符串失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user