[tag] 实现了部门和设施功能,修改了一些图表,封装了一些API

This commit is contained in:
LYC 2025-04-26 18:08:23 +08:00
parent 2317030f2b
commit 76e92b461d
10 changed files with 665 additions and 75 deletions

4
.env
View File

@ -2,9 +2,9 @@
# if use a sub directory, it must be end with "/", like "/admin/" but not "/admin"
VITE_BASE_URL=/
VITE_APP_TITLE=SoybeanAdmin
VITE_APP_TITLE=Admin
VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template
VITE_APP_DESC=Admin is a fresh and elegant admin template
# the prefix of the icon name
VITE_ICON_PREFIX=icon

View File

@ -1 +1,203 @@
<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg"><path d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z" fill="#646cff"/><path d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" fill="#646cff"/></svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="128.000000pt" height="128.000000pt" viewBox="0 0 128.000000 128.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,128.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M520 1255 c-128 -26 -235 -82 -324 -173 -117 -117 -174 -247 -183
-412 -10 -184 49 -334 187 -472 61 -62 95 -86 163 -119 184 -88 375 -87 556 2
111 54 229 169 279 271 126 257 84 525 -113 725 -65 66 -97 90 -165 122 -136
65 -265 83 -400 56z m96 -16 c18 8 31 8 45 1 12 -7 25 -7 37 -1 12 6 23 5 37
-5 12 -9 30 -12 46 -9 19 4 28 1 33 -11 4 -11 14 -15 31 -12 16 3 30 -1 41
-13 10 -11 27 -19 40 -19 13 0 28 -9 34 -20 6 -11 20 -20 31 -20 11 0 23 -10
29 -24 5 -14 19 -26 32 -28 14 -2 24 -11 26 -24 2 -12 14 -26 28 -32 14 -7 24
-20 24 -31 0 -11 9 -25 20 -31 11 -6 20 -21 20 -35 0 -13 10 -31 21 -39 14
-10 19 -21 15 -32 -4 -10 0 -25 10 -35 10 -11 14 -27 11 -41 -4 -13 0 -29 9
-39 12 -14 13 -22 5 -38 -9 -15 -8 -26 1 -41 10 -16 10 -24 0 -40 -9 -15 -10
-26 -1 -41 8 -16 7 -24 -5 -38 -9 -10 -13 -26 -9 -40 4 -16 1 -26 -11 -33 -13
-7 -16 -17 -11 -35 4 -19 1 -29 -15 -40 -11 -8 -20 -25 -20 -38 0 -15 -7 -26
-20 -30 -13 -4 -20 -15 -20 -31 0 -17 -8 -27 -25 -34 -15 -6 -25 -17 -25 -30
0 -13 -9 -22 -26 -26 -14 -4 -30 -17 -34 -30 -7 -16 -17 -24 -34 -24 -15 0
-25 -7 -29 -20 -3 -13 -14 -20 -30 -20 -13 0 -30 -7 -37 -15 -7 -8 -26 -15
-42 -15 -17 0 -31 -6 -35 -16 -4 -10 -13 -13 -32 -9 -16 3 -34 0 -46 -9 -14
-10 -23 -11 -37 -2 -14 8 -23 8 -38 -2 -12 -7 -26 -9 -33 -5 -12 7 -64 13
-124 14 -18 0 -34 7 -37 15 -3 8 -18 14 -34 14 -16 0 -35 7 -42 15 -7 8 -23
15 -36 15 -13 0 -28 9 -34 20 -6 11 -20 20 -31 20 -11 0 -24 10 -30 24 -7 14
-22 27 -35 30 -15 4 -24 14 -24 26 0 13 -10 24 -25 30 -15 6 -25 17 -25 30 0
11 -9 25 -20 32 -11 7 -20 23 -20 35 0 12 -10 29 -21 37 -14 10 -19 21 -15 32
4 10 0 25 -10 35 -10 11 -14 27 -11 41 4 13 0 29 -9 39 -12 14 -13 22 -5 38 9
15 8 26 -1 41 -10 16 -10 24 0 40 9 15 10 26 1 41 -8 16 -7 24 5 38 9 10 13
26 9 39 -3 14 1 30 10 40 10 10 14 27 11 39 -4 15 0 25 15 32 12 7 21 22 21
36 0 14 8 29 20 35 11 6 20 20 20 31 0 11 10 24 24 31 14 6 26 20 28 32 2 13
12 22 25 24 15 2 25 13 29 28 4 17 13 24 30 24 13 0 28 9 34 20 6 12 21 20 35
20 14 0 30 9 37 19 9 15 19 18 40 14 20 -4 29 -1 34 12 5 12 14 15 31 10 14
-3 33 1 45 9 16 12 25 13 35 4 10 -8 20 -8 39 1z"/>
<path d="M549 1214 c-8 -10 -21 -13 -37 -9 -16 4 -31 0 -43 -11 -10 -9 -27
-14 -37 -12 -12 3 -23 -2 -31 -13 -6 -11 -22 -19 -36 -19 -14 0 -29 -8 -35
-20 -6 -11 -20 -20 -31 -20 -12 0 -23 -8 -26 -20 -3 -11 -16 -23 -28 -26 -13
-3 -26 -16 -29 -29 -3 -12 -15 -25 -26 -28 -12 -3 -20 -14 -20 -26 0 -11 -9
-25 -20 -31 -12 -6 -20 -21 -20 -35 0 -14 -8 -29 -20 -35 -15 -8 -19 -17 -14
-34 3 -14 -1 -27 -11 -36 -11 -9 -14 -22 -10 -40 4 -18 1 -31 -9 -39 -12 -10
-13 -18 -5 -32 6 -13 6 -25 -1 -39 -8 -14 -8 -26 0 -40 7 -14 7 -26 1 -39 -8
-14 -7 -22 5 -32 10 -8 13 -21 9 -37 -4 -16 0 -31 11 -43 9 -10 14 -25 10 -35
-4 -11 1 -22 14 -31 11 -8 20 -25 20 -38 0 -14 9 -29 20 -35 11 -6 20 -20 20
-31 0 -12 8 -23 20 -26 11 -3 23 -16 26 -29 4 -15 13 -24 25 -24 12 0 23 -10
29 -25 7 -17 17 -25 34 -25 15 0 25 -7 29 -20 3 -13 14 -20 30 -20 13 0 30 -7
37 -15 7 -8 23 -15 35 -15 12 0 28 -7 35 -15 8 -9 21 -13 36 -9 13 4 31 1 38
-5 8 -7 25 -9 40 -5 16 4 32 1 41 -6 12 -10 18 -10 30 0 9 7 25 10 41 6 15 -4
32 -2 40 5 7 6 25 9 38 5 15 -4 28 0 36 9 7 8 23 15 35 15 12 0 28 7 35 15 7
8 23 15 36 15 14 0 25 8 29 20 4 13 15 20 31 20 17 0 27 8 34 25 6 15 17 25
29 25 12 0 21 9 25 24 3 13 15 26 26 29 12 3 20 13 20 26 0 11 9 26 20 33 11
7 20 23 20 35 0 12 9 28 20 36 13 9 18 20 14 31 -4 10 1 25 10 35 11 12 15 27
11 43 -4 16 -1 29 9 37 12 10 13 18 5 32 -6 13 -6 25 1 39 8 14 8 26 0 40 -7
14 -7 26 -1 39 8 14 7 22 -5 32 -10 8 -13 21 -9 37 4 16 0 31 -11 43 -9 10
-14 27 -12 37 3 12 -2 23 -13 31 -11 6 -19 22 -19 36 0 14 -8 29 -20 35 -11 6
-20 20 -20 31 0 12 -8 23 -20 26 -11 3 -23 16 -26 28 -3 13 -16 26 -29 29 -12
3 -25 15 -28 26 -3 13 -13 20 -30 20 -17 0 -28 7 -32 20 -4 13 -15 20 -31 20
-13 0 -29 8 -35 19 -8 11 -19 16 -31 13 -10 -2 -27 3 -37 12 -12 11 -27 15
-43 11 -16 -4 -29 -1 -37 9 -10 12 -16 13 -32 3 -15 -9 -23 -9 -39 1 -16 10
-24 10 -40 0 -16 -10 -24 -10 -39 -1 -16 10 -22 9 -32 -3z m275 -52 c128 -47
251 -154 310 -270 81 -159 76 -370 -12 -522 -100 -174 -282 -280 -482 -280
-230 0 -443 149 -522 365 -27 75 -36 243 -18 313 55 203 198 349 400 408 70
21 251 13 324 -14z"/>
<path d="M560 1135 c0 -8 -4 -15 -10 -15 -5 0 -10 5 -10 10 0 6 -4 10 -9 10
-9 0 20 -69 29 -70 3 0 6 18 7 40 1 22 0 40 -3 40 -2 0 -4 -7 -4 -15z"/>
<path d="M647 1143 c-11 -10 -8 -73 3 -73 6 0 10 5 10 11 0 7 7 17 17 24 9 7
14 19 10 29 -6 16 -28 22 -40 9z m28 -12 c3 -5 1 -12 -5 -16 -5 -3 -10 1 -10
9 0 18 6 21 15 7z"/>
<path d="M706 1133 c-11 -28 -6 -61 10 -67 26 -10 30 -6 11 8 -18 14 -18 15 0
25 10 6 12 11 6 11 -19 0 -15 18 5 22 14 3 13 5 -5 10 -14 4 -24 1 -27 -9z"/>
<path d="M610 1119 c0 -13 5 -31 10 -39 7 -11 8 -5 4 20 -8 43 -14 51 -14 19z"/>
<path d="M470 1120 c-8 -5 -10 -10 -4 -10 6 0 17 -15 26 -32 l16 -33 -2 42
c-1 43 -9 51 -36 33z"/>
<path d="M760 1104 c-13 -32 -13 -51 -1 -38 10 11 24 64 16 64 -3 0 -10 -12
-15 -26z"/>
<path d="M792 1079 l-1 -40 23 33 c13 18 21 35 19 38 -2 2 -8 -2 -13 -10 -8
-13 -10 -12 -10 3 0 37 -18 15 -18 -24z"/>
<path d="M430 1105 c0 -11 32 -67 36 -63 6 7 -19 68 -28 68 -4 0 -8 -2 -8 -5z"/>
<path d="M842 1070 c-24 -32 -28 -45 -12 -35 6 4 19 -4 30 -17 20 -23 20 -23
36 -3 16 19 16 19 12 -7 -3 -16 -2 -28 2 -28 8 0 33 27 45 50 8 13 7 13 -8 1
-15 -12 -17 -10 -17 15 l-1 29 -30 -35 -31 -35 7 41 c8 52 -5 62 -33 24z m28
-4 c0 -3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z"/>
<path d="M387 1083 c-13 -13 -7 -24 20 -34 22 -8 24 -12 13 -19 -8 -5 -11 -12
-8 -15 11 -11 28 5 28 26 0 13 -7 19 -21 19 -15 0 -19 5 -15 15 5 15 -5 20
-17 8z"/>
<path d="M332 1047 c-8 -10 -5 -20 14 -42 16 -19 23 -23 20 -12 -5 15 -2 17
15 12 21 -7 21 -6 -2 24 -25 34 -32 37 -47 18z m28 -17 c0 -5 -2 -10 -4 -10
-3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z"/>
<path d="M281 1007 c-8 -10 -4 -20 18 -41 26 -25 29 -26 42 -10 12 16 12 17
-4 11 -15 -6 -17 -3 -12 13 5 16 3 19 -11 13 -13 -5 -16 -3 -11 10 8 20 -6 22
-22 4z"/>
<path d="M952 998 c-16 -16 -15 -43 2 -57 10 -9 16 -8 26 4 7 9 10 19 6 22 -4
4 -11 1 -16 -7 -12 -19 -24 -6 -16 16 4 11 14 15 32 11 15 -3 23 0 21 7 -5 16
-40 19 -55 4z"/>
<path d="M601 972 c-29 -23 -44 -27 -103 -27 l-68 0 -14 -35 c-8 -19 -19 -54
-25 -78 -11 -40 -10 -43 15 -65 25 -22 25 -24 10 -40 -10 -9 -24 -17 -33 -17
-26 0 -9 -112 27 -186 32 -66 127 -163 192 -198 36 -20 37 -20 75 0 48 24 164
138 188 184 40 77 59 200 31 200 -8 0 -22 8 -32 17 -15 16 -15 18 10 40 25 22
26 25 15 65 -6 24 -18 59 -26 80 l-15 36 -53 -5 c-53 -6 -76 1 -135 39 -24 16
-27 15 -59 -10z m59 -6 c21 -27 97 -49 140 -42 38 6 40 5 54 -27 28 -69 30
-97 6 -122 -26 -27 -20 -60 12 -71 18 -5 20 -12 16 -63 -6 -81 -48 -159 -123
-230 -34 -31 -77 -63 -95 -71 -30 -12 -37 -11 -77 10 -65 35 -157 138 -182
205 -28 73 -28 141 -2 150 31 10 36 43 11 70 -24 25 -22 53 6 122 14 32 16 33
54 27 43 -7 119 15 140 42 7 7 16 14 20 14 4 0 13 -7 20 -14z"/>
<path d="M591 927 c-23 -14 -52 -21 -90 -22 l-55 -1 -15 -46 c-13 -44 -13 -48
8 -73 28 -36 27 -51 -8 -85 -25 -26 -27 -33 -21 -72 14 -94 102 -214 192 -262
32 -17 39 -18 69 -6 46 20 139 116 168 175 13 27 26 69 29 94 3 40 0 49 -22
70 -31 29 -33 61 -5 87 21 19 20 38 -2 94 -9 23 -15 26 -62 26 -37 0 -65 7
-91 22 -45 26 -51 26 -95 -1z m-66 -185 c0 -112 -8 -162 -26 -162 -7 0 -9 9
-5 23 4 12 9 58 11 102 4 76 3 78 -7 33 -6 -27 -15 -48 -20 -48 -13 0 -9 43 7
90 8 23 15 54 15 68 0 21 2 24 13 13 8 -8 12 -47 12 -119z m71 34 c16 -56 18
-86 6 -86 -5 0 -14 21 -20 48 -10 44 -11 42 -7 -38 2 -47 7 -93 10 -102 4 -10
3 -18 -3 -18 -17 0 -24 32 -29 135 -3 68 -1 109 8 130 l13 30 3 -25 c3 -14 11
-47 19 -74z m116 79 c4 -5 8 -20 8 -32 0 -13 5 -23 11 -23 8 0 10 12 6 35 -3
19 -2 35 3 35 10 0 20 -24 21 -53 1 -14 5 -8 11 16 13 47 31 49 22 2 -4 -23
-2 -35 5 -35 6 0 11 -4 11 -10 0 -5 -7 -10 -15 -10 -21 0 -19 -30 3 -30 15 -1
15 -2 -2 -15 -20 -15 -20 -15 0 -30 17 -13 17 -14 2 -15 -15 0 -18 -9 -18 -55
0 -30 -4 -55 -10 -55 -5 0 -10 23 -10 50 0 43 -3 52 -22 60 l-23 9 23 7 c12 3
22 10 22 14 0 4 -10 11 -22 14 l-23 7 23 9 c27 12 28 26 2 33 -11 3 -20 1 -20
-4 0 -5 -4 -9 -10 -9 -5 0 -11 19 -11 43 -1 31 -4 22 -11 -33 -4 -41 -7 -91
-5 -110 3 -25 4 -20 5 18 3 76 22 64 22 -14 0 -41 -4 -63 -10 -59 -5 3 -10 -3
-10 -14 0 -32 -20 -25 -21 7 0 15 -3 21 -6 15 -12 -31 -23 -8 -23 51 0 48 4
65 15 70 8 3 15 13 15 21 0 9 -4 13 -10 10 -5 -3 -10 3 -10 13 0 11 -3 33 -6
50 -6 28 -5 30 27 29 19 -1 37 -6 41 -12z m-162 -365 c0 -22 -4 -40 -10 -40
-5 0 -10 18 -10 40 0 22 5 40 10 40 6 0 10 -18 10 -40z m75 0 c0 -31 -3 -35
-27 -38 -26 -3 -28 -1 -28 31 0 40 7 49 35 45 16 -2 20 -10 20 -38z m72 24 c8
-22 -13 -64 -33 -64 -13 0 -14 3 -5 14 10 11 8 16 -5 24 -22 12 -11 42 16 42
11 0 23 -7 27 -16z m63 6 c0 -5 -8 -10 -17 -11 -14 0 -12 -3 5 -10 32 -12 25
-43 -11 -47 -15 -2 -27 1 -27 7 0 6 6 8 14 5 8 -3 17 0 21 6 4 7 -2 14 -14 17
-21 5 -28 23 -14 36 10 11 43 8 43 -3z"/>
<path d="M590 469 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M263 962 c23 -25 21 -35 -2 -22 -23 12 -31 13 -31 2 0 -10 61 -33 71
-26 10 6 -30 64 -44 64 -6 0 -3 -8 6 -18z"/>
<path d="M1017 922 c-40 -44 -2 -71 44 -32 29 24 18 26 -17 4 -36 -24 -44 -7
-11 22 16 14 22 24 14 24 -8 0 -21 -8 -30 -18z"/>
<path d="M210 923 c0 -10 53 -43 67 -43 4 0 -1 8 -12 16 -31 24 -55 36 -55 27z"/>
<path d="M200 891 c0 -5 6 -12 13 -14 6 -3 2 -6 -10 -6 -32 -1 -29 -18 7 -36
37 -19 50 -19 24 0 -19 14 -18 14 4 15 31 0 28 17 -8 35 -16 9 -30 11 -30 6z"/>
<path d="M1048 864 c-34 -18 -37 -28 -6 -18 20 6 21 5 9 -9 -23 -28 -8 -36 29
-16 26 15 28 18 10 13 -24 -6 -24 -6 -7 13 31 36 14 44 -35 17z"/>
<path d="M160 824 c0 -3 14 -10 30 -15 43 -16 38 -33 -7 -25 -28 5 -34 4 -23
-3 8 -6 27 -11 43 -11 36 0 37 32 2 48 -28 13 -45 15 -45 6z"/>
<path d="M1073 800 c-13 -5 -23 -12 -23 -16 0 -8 53 5 65 17 12 12 -12 11 -42
-1z"/>
<path d="M1093 772 c-46 -22 -43 -42 7 -42 22 0 40 5 40 10 0 6 -10 10 -22 10
-22 1 -22 1 -4 15 28 21 16 25 -21 7z"/>
<path d="M155 730 c19 -9 19 -9 -2 -16 -32 -9 -29 -20 8 -28 46 -9 58 -6 29 6
-25 11 -25 11 -2 15 42 8 17 34 -31 32 -21 0 -21 -1 -2 -9z"/>
<path d="M1103 712 c-25 -2 -33 -8 -33 -23 0 -10 5 -19 10 -19 6 0 9 3 9 8 -4
21 3 24 16 6 14 -18 14 -18 15 0 0 15 3 16 15 6 12 -10 15 -10 15 3 0 20 -8
23 -47 19z"/>
<path d="M130 660 c0 -5 16 -10 35 -10 19 0 35 5 35 10 0 6 -16 10 -35 10 -19
0 -35 -4 -35 -10z"/>
<path d="M1075 651 c-3 -6 2 -11 12 -11 17 -1 17 -1 0 -14 -16 -12 -13 -14 23
-14 33 -1 40 3 40 19 0 12 -7 19 -19 19 -11 0 -26 3 -34 6 -8 3 -18 1 -22 -5z
m65 -21 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10
-10z"/>
<path d="M135 630 c-3 -6 5 -10 19 -10 13 0 33 -3 43 -7 16 -6 16 -5 4 10 -15
19 -56 23 -66 7z"/>
<path d="M168 592 c-21 -2 -38 -8 -38 -13 0 -6 9 -7 23 -3 22 7 22 6 3 -15
-25 -27 -17 -35 25 -22 30 8 31 9 9 10 l-25 1 25 20 c30 23 26 26 -22 22z"/>
<path d="M1071 582 c-1 -26 27 -41 40 -21 8 12 10 12 18 0 6 -10 10 -10 16 -1
13 20 -13 36 -35 22 -26 -16 -28 -15 -33 6 -4 12 -5 11 -6 -6z"/>
<path d="M1070 531 c25 -14 70 -22 70 -12 0 4 -14 11 -31 15 -42 8 -57 7 -39
-3z"/>
<path d="M178 509 c-16 -11 -28 -25 -28 -30 0 -11 48 -11 75 1 18 8 18 9 2 9
-14 1 -17 6 -12 21 8 25 -3 25 -37 -1z"/>
<path d="M1065 488 c11 -6 26 -17 32 -26 14 -17 18 -16 27 13 5 18 1 20 -36
22 -35 1 -39 -1 -23 -9z"/>
<path d="M200 450 c-19 -11 -30 -19 -23 -20 18 0 63 22 63 32 0 10 1 11 -40
-12z"/>
<path d="M1031 442 c0 -4 14 -18 32 -32 23 -18 29 -20 25 -8 -4 9 -2 19 5 21
7 2 10 6 7 9 -9 9 -70 18 -69 10z"/>
<path d="M213 416 c-27 -10 -29 -14 -18 -29 13 -18 27 -23 23 -8 -2 4 8 18 22
29 28 24 21 25 -27 8z"/>
<path d="M1029 391 c13 -12 28 -21 34 -21 12 0 11 0 -28 24 l-30 17 24 -20z"/>
<path d="M870 321 c0 -12 -4 -21 -9 -21 -10 0 -9 -26 2 -36 4 -4 7 0 7 9 0 10
8 17 21 17 11 0 17 -4 14 -10 -3 -5 -1 -10 4 -10 18 0 12 19 -9 30 -11 6 -18
15 -15 20 3 5 1 11 -5 15 -5 3 -10 -3 -10 -14z"/>
<path d="M400 305 c-7 -9 -21 -13 -31 -10 -11 4 -19 2 -19 -4 0 -6 5 -11 11
-11 5 0 8 -4 4 -9 -3 -5 8 -3 25 5 16 9 30 19 30 24 0 5 8 11 18 13 13 4 13 5
-4 6 -12 0 -27 -6 -34 -14z"/>
<path d="M390 251 c0 -11 4 -22 9 -25 4 -3 6 6 3 19 -5 30 -12 33 -12 6z"/>
<path d="M540 260 c0 -5 5 -10 11 -10 5 0 7 5 4 10 -3 6 -8 10 -11 10 -2 0 -4
-4 -4 -10z"/>
<path d="M555 218 c-19 -66 -20 -90 -1 -65 7 9 18 17 24 17 6 0 14 5 18 11 4
8 0 9 -15 4 -26 -8 -27 5 -2 34 11 13 17 29 14 37 -10 26 -22 14 -38 -38z"/>
<path d="M711 235 c0 -17 -7 -37 -13 -44 -10 -11 -10 -13 0 -7 16 9 16 -6 0
-24 -9 -11 -8 -11 3 0 20 19 41 70 30 70 -5 0 -12 8 -14 18 -3 9 -5 3 -6 -13z"/>
<path d="M900 238 c-11 -12 -18 -24 -15 -26 4 -5 45 36 45 45 0 8 -11 1 -30
-19z"/>
<path d="M867 243 c-4 -3 -7 -11 -7 -17 0 -6 5 -5 12 2 6 6 9 14 7 17 -3 3 -9
2 -12 -2z"/>
<path d="M530 219 c0 -5 5 -7 10 -4 6 3 10 8 10 11 0 2 -4 4 -10 4 -5 0 -10
-5 -10 -11z"/>
<path d="M509 183 c-13 -16 -12 -17 4 -4 16 13 21 21 13 21 -2 0 -10 -8 -17
-17z"/>
<path d="M745 180 c4 -6 11 -8 16 -5 14 9 11 15 -7 15 -8 0 -12 -5 -9 -10z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -199,7 +199,9 @@ const local: App.I18n.Schema = {
plan: "计划管理",
department: "部门管理",
orders_create: "创建工单",
orders_list: "工单列表"
orders_list: "工单列表",
ai: "AI服务状态",
employee_list: "人员列表"
},
page: {
login: {

View File

@ -56,7 +56,8 @@ export const generatedRoutes: GeneratedRoute[] = [
component: 'layout.base$view.ai',
meta: {
title: 'ai',
i18nKey: 'route.ai'
i18nKey: 'route.ai',
order: 25
}
},
{

View File

@ -112,6 +112,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
//console.log(error?.status == 200)
if (error?.status == 200) {
console.log("200")
let info: Api.Auth.UserInfo = {
userId: data.employeeId.toString(),
userName: data.name,

View File

@ -18,6 +18,7 @@ declare module 'vue' {
ADivider: typeof import('ant-design-vue/es')['Divider']
ADrawer: typeof import('ant-design-vue/es')['Drawer']
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
AEmpty: typeof import('ant-design-vue/es')['Empty']
AForm: typeof import('ant-design-vue/es')['Form']
AFormItem: typeof import('ant-design-vue/es')['FormItem']
AInput: typeof import('ant-design-vue/es')['Input']

19
src/utils/api.ts Normal file
View File

@ -0,0 +1,19 @@
// api.ts
import axios from 'axios';
import { localStg } from '@/utils/storage';
// 封装网络请求的接口
export const apiRequest = async (path: string, data: any) => {
let url = "http://localhost:8080" + path;
const token = localStg.get('token'); // 获取 token
try {
const response = await axios.post(url, data, {
headers: {
Authorization: `Bearer ${token}`, // 添加 Authorization 头
},
});
return response.data; // 返回响应数据
} catch (error) {
throw new Error('请求失败'); // 抛出错误
}
};

View File

@ -1,7 +1,92 @@
<script setup lang="ts"></script>
<template>
<div>ai</div>
<div class="ai-monitoring-container">
<a-row :gutter="16">
<a-col v-for="service in services" :key="service.id" :span="8">
<a-card :title="service.name" hoverable class="service-card">
<template #extra>
<a-tag :color="service.status === 'Running' ? 'green' : 'red'">
{{ service.status }}
</a-tag>
</template>
<div class="service-info">
<p><strong>响应时间:</strong> {{ service.responseTime }} ms</p>
<p><strong>服务状态:</strong> {{ service.health }}</p>
<p><strong>上次更新:</strong> {{ service.lastUpdated }}</p>
</div>
<template #actions>
<a-button type="primary" size="small" @click="refreshStatus(service)">
刷新
</a-button>
</template>
</a-card>
</a-col>
</a-row>
</div>
</template>
<style scoped></style>
<script setup>
import { ref, onMounted } from 'vue';
import { Row as ARow, Col as ACol, Card as ACard, Tag as ATag, Button as AButton } from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
//
const services = ref([
{
id: 1,
name: '图像识别模型',
status: 'Running',
responseTime: 120,
health: 'Healthy',
lastUpdated: new Date().toLocaleTimeString(),
},
{
id: 2,
name: '大语言模型',
status: 'Running',
responseTime: 0,
health: 'Healthy',
lastUpdated: new Date().toLocaleTimeString(),
}
]);
//
const refreshStatus = (service) => {
// API
service.status = Math.random() > 0.003 ? 'Running' : 'Stopped';
service.responseTime = service.status === 'Running' ? Math.floor(Math.random() * 500) : 0;
service.health = service.status === 'Running' ? 'Healthy' : 'Unhealthy';
service.lastUpdated = new Date().toLocaleTimeString();
};
//
onMounted(() => {
setInterval(() => {
services.value.forEach((service) => {
if (Math.random() > 0.7) {
refreshStatus(service);
}
});
}, 5000); // 5
});
</script>
<style scoped>
.ai-monitoring-container {
padding: 20px;
}
.service-card {
margin-bottom: 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.service-info {
margin-bottom: 16px;
}
.service-info p {
margin: 8px 0;
color: #666;
}
</style>

View File

@ -1,7 +1,235 @@
<script setup lang="ts"></script>
<template>
<div>department</div>
<div class="department-management">
<a-row :gutter="16">
<a-col :span="24">
<a-card title="部门管理" :bordered="false">
<div class="toolbar">
<a-button type="primary" @click="showAddModal(null)">添加部门</a-button>
</div>
<a-tree
v-if="treeData.length > 0"
:tree-data="treeData"
show-line
:default-expand-all="true"
:selected-keys.sync="selectedKeys"
>
<template #title="{ dataRef }">
<div class="tree-node">
<span>{{ dataRef.departmentName }}</span>
<div class="node-actions">
<a-button
size="small"
type="link"
@click="showAddModal(dataRef)"
>
添加子部门
</a-button>
<a-button
size="small"
type="link"
@click="showEditModal(dataRef)"
>
编辑
</a-button>
<a-button
size="small"
type="link"
danger
@click="confirmDelete(dataRef)"
>
删除
</a-button>
</div>
</div>
</template>
</a-tree>
<a-empty v-else description="暂无数据" />
</a-card>
</a-col>
</a-row>
<!-- 添加/编辑部门弹窗 -->
<a-modal
v-model:visible="modalVisible"
:title="modalTitle"
@ok="handleSubmit"
:confirm-loading="confirmLoading"
>
<a-form :model="formState" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
<a-form-item label="部门名称" required>
<a-input v-model:value="formState.departmentName" placeholder="请输入部门名称" />
</a-form-item>
<a-form-item label="区域">
<a-input v-model:value="formState.area" placeholder="请输入区域" />
</a-form-item>
<a-form-item label="负责人">
<a-input v-model:value="formState.managerName" placeholder="请输入负责人姓名" />
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<style scoped></style>
<script setup>
import { ref, onMounted } from 'vue';
import { message, Modal } from 'ant-design-vue';
import axios from 'axios';
//
const treeData = ref([]);
//
const modalVisible = ref(false);
const modalTitle = ref('添加部门');
const confirmLoading = ref(false);
const formState = ref({
departmentName: '',
area: '',
managerName: '',
departmentId: null,
parentId: null,
});
//
const currentDept = ref(null);
//
const selectedKeys = ref([]);
//
const fetchDepartments = async () => {
try {
const response = await axios.get('http://localhost:8080/api/departments');
if (response.data.success) {
//
const deptMap = new Map();
response.data.data.forEach((dept) => {
if (!deptMap.has(dept.departmentId)) {
deptMap.set(dept.departmentId, {
key: dept.departmentId,
departmentName: dept.departmentName,
area: dept.area,
manager: dept.manager,
children: dept.children.map(child => ({
key: child.departmentId,
departmentName: child.departmentName,
area: child.area,
manager: child.manager,
children: child.children || [],
})),
});
}
});
treeData.value = Array.from(deptMap.values()).filter(dept => dept.key === 1); // departmentId=1
} else {
message.error(response.data.errorMsg || '获取部门数据失败');
}
} catch (error) {
message.error('请求失败: ' + error.message);
}
};
//
const showAddModal = (dept) => {
modalTitle.value = dept ? `添加${dept.departmentName}的子部门` : '添加部门';
modalVisible.value = true;
formState.value = {
departmentName: '',
area: '',
managerName: '',
departmentId: null,
parentId: dept ? dept.key : null,
};
currentDept.value = null;
};
//
const showEditModal = (dept) => {
modalTitle.value = '编辑部门';
modalVisible.value = true;
formState.value = {
departmentName: dept.departmentName,
area: dept.area || '',
managerName: dept.manager ? dept.manager.name : '',
departmentId: dept.key,
parentId: null,
};
currentDept.value = dept;
};
//
const handleSubmit = async () => {
if (!formState.value.departmentName) {
message.error('部门名称不能为空');
return;
}
confirmLoading.value = true;
try {
const payload = {
departmentName: formState.value.departmentName,
area: formState.value.area,
manager: {
name: formState.value.managerName,
},
parentId: formState.value.parentId,
};
if (formState.value.departmentId) {
await axios.put(`http://localhost:8080/api/departments/${formState.value.departmentId}`, payload);
message.success('编辑成功');
} else {
await axios.post('http://localhost:8080/api/departments', payload);
message.success('添加成功');
}
modalVisible.value = false;
fetchDepartments(); //
} catch (error) {
message.error('操作失败: ' + error.message);
} finally {
confirmLoading.value = false;
}
};
//
const confirmDelete = (dept) => {
Modal.confirm({
title: '确认删除',
content: `确定要删除部门 ${dept.departmentName} 吗?`,
async onOk() {
try {
await axios.delete(`http://localhost:8080/api/departments/${dept.key}`);
message.success('删除成功');
fetchDepartments(); //
} catch (error) {
message.error('删除失败: ' + error.message);
}
},
});
};
//
onMounted(() => {
fetchDepartments();
});
</script>
<style scoped>
.department-management {
padding: 16px;
}
.toolbar {
margin-bottom: 16px;
text-align: right;
}
.tree-node {
display: flex;
justify-content: space-between;
align-items: center;
}
.node-actions {
display: none;
}
.tree-node:hover .node-actions {
display: block;
}
</style>

View File

@ -1,127 +1,178 @@
<!-- order.vue -->
<template>
<a-table
:columns="columns"
:data-source="tableData"
:pagination="pagination"
@change="handleTableChange"
>
<!-- 如果需要自定义列可以在这里添加 slot -->
</a-table>
<div class="order-container">
<a-table
:columns="columns"
:data-source="dataSource"
:loading="loading"
:pagination="pagination"
@change="handleTableChange"
>
<template #status="{ record }">
<a-tag :color="getStatusColor(record.status)">
{{ record.status }}
</a-tag>
</template>
<template #createTime="{ text }">
{{ formatDate(text) }}
</template>
<template #completeTime="{ text }">
{{ text ? formatDate(text) : '-' }}
</template>
</a-table>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { Table, message } from 'ant-design-vue'; // Table message
import axios from 'axios'; // HTTP
import { Table as ATable, Tag as ATag } from 'ant-design-vue';
import axios from 'axios';
import { localStg } from '@/utils/storage';
//
//
const columns = [
{
title: 'ID',
title: '工单ID',
dataIndex: 'id',
key: 'id',
},
{
title: 'Facility Code',
title: '设备编码',
dataIndex: 'facilityCode',
key: 'facilityCode',
},
{
title: 'Facility Type',
title: '设备类型',
dataIndex: 'facilityType',
key: 'facilityType',
},
{
title: 'Creator Name',
title: '创建者',
dataIndex: 'creatorName',
key: 'creatorName',
},
{
title: 'Assignee Name',
title: '负责人',
dataIndex: 'assigneeName',
key: 'assigneeName',
},
{
title: 'Description',
title: '描述',
dataIndex: 'description',
key: 'description',
},
{
title: 'Status',
title: '状态',
dataIndex: 'status',
key: 'status',
slots: { customRender: 'status' },
},
{
title: 'Create Time',
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
slots: { customRender: 'createTime' },
},
{
title: 'Complete Time',
title: '完成时间',
dataIndex: 'completeTime',
key: 'completeTime',
slots: { customRender: 'completeTime' },
},
{
title: 'Cost',
title: '成本',
dataIndex: 'cost',
key: 'cost',
},
];
//
const tableData = ref([]); // API data.content
//
const dataSource = ref([]);
const loading = ref(false);
const pagination = ref({
current: 1, // 1
pageSize: 10, //
total: 0, //
showSizeChanger: true, //
showQuickJumper: true, //
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50'],
});
// API
const fetchData = async (page = 1, size = 10) => {
try {
const token = localStg.get('token'); // token
const response = await axios.get('http://localhost:8080/api/work-orders/my-orders', {
params: {
page: page - 1, // pageNumber 0 1 1
size: size,
},
headers: {
Authorization: `Bearer ${token}`, // Authorization
},
});
if (response.data.success) {
tableData.value = response.data.data.content; //
pagination.value.total = response.data.data.totalElements; //
pagination.value.current = response.data.data.number + 1; //
pagination.value.pageSize = response.data.data.size; //
} else {
message.error(response.data.errorMsg || '请求失败');
}
} catch (error) {
message.error('网络错误或服务器异常');
console.error(error);
//
const getStatusColor = (status) => {
switch (status) {
case 'PENDING':
return 'orange';
case 'IN_PROGRESS':
return 'blue';
case 'COMPLETED':
return 'green';
default:
return 'red';
}
};
//
const handleTableChange = (pagination) => {
fetchData(pagination.current, pagination.pageSize);
//
const formatDate = (dateStr) => {
if (!dateStr) return '-';
const date = new Date(dateStr);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
};
//
//
const fetchData = async (page = 1, pageSize = 10) => {
loading.value = true;
const token = localStg.get('token'); // token
try {
const response = await axios.get('http://localhost:8080/api/work-orders/my-orders', {
params: {
page: page - 1, // 0
size: pageSize,
},
headers: {
Authorization: `Bearer ${token}` // Authorization
}
});
if (response.data.success) {
dataSource.value = response.data.data.content;
pagination.value = {
current: response.data.data.pageable.pageNumber + 1,
pageSize: response.data.data.pageable.pageSize,
total: response.data.data.totalElements,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50'],
};
}
} catch (error) {
console.error('Failed to fetch orders:', error);
} finally {
loading.value = false;
}
};
//
const handleTableChange = (pag, filters, sorter) => {
pagination.value.current = pag.current;
pagination.value.pageSize = pag.pageSize;
fetchData(pag.current, pag.pageSize);
};
//
onMounted(() => {
fetchData(); //
fetchData();
});
</script>
<style scoped>
/* 可选:添加一些样式 */
.a-table {
margin-top: 20px;
.order-container {
padding: 20px;
}
</style>