mirror of
https://github.com/flipped-aurora/gin-vue-admin.git
synced 2026-09-25 05:50:19 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9260111312 | ||
|
|
877f8f4fcf | ||
|
|
273d7bd50e | ||
|
|
39abc7b632 | ||
|
|
e19ddf6600 | ||
|
|
9db3bcfac5 | ||
|
|
a6b6b5d4aa | ||
|
|
23f9227da1 | ||
|
|
857ba194e5 | ||
|
|
6e27e3a114 | ||
|
|
d5b4bbfa84 | ||
|
|
72ee8fb6fc | ||
|
|
2ec2e9a66e | ||
|
|
bf095c38e9 | ||
|
|
cee3b54b4c | ||
|
|
ff7e002049 | ||
|
|
a1c8f6bc55 | ||
|
|
ca24945af6 | ||
|
|
ea7455e092 | ||
|
|
a5e1170af0 | ||
|
|
44751357b4 | ||
|
|
e58d40ab83 | ||
|
|
f7c3d76d37 | ||
|
|
55bf69c810 | ||
|
|
b4232a8f27 | ||
|
|
8d6dcc6b07 | ||
|
|
e3a57bdc69 | ||
|
|
0eee6a3cc2 | ||
|
|
174721bc55 | ||
|
|
ba63bf2371 | ||
|
|
2f07e9271f | ||
|
|
3e9602ff7e | ||
|
|
30763b48de | ||
|
|
c3b75933b8 | ||
|
|
ff08d45f25 | ||
|
|
be0e4e97f7 | ||
|
|
b916c7951b | ||
|
|
0ebb3d4195 | ||
|
|
e7680c43ac | ||
|
|
2f80eaaf9c | ||
|
|
2dfe9d7f4b | ||
|
|
cbc504cc0b | ||
|
|
99550cbc37 | ||
|
|
4a53864738 | ||
|
|
b731b9df78 | ||
|
|
1f3a8ea2eb | ||
|
|
2bd82ead97 | ||
|
|
9f1f72fce5 | ||
|
|
38ed8bb399 | ||
|
|
2d98fdf321 | ||
|
|
214e108591 | ||
|
|
b197a84ef7 | ||
|
|
09603c436e | ||
|
|
d4c883535b | ||
|
|
6323688fca | ||
|
|
7a7c811311 | ||
|
|
81e178b267 | ||
|
|
70c9a715d4 | ||
|
|
28bd6fef7e | ||
|
|
35e3f820c0 | ||
|
|
e847aa9e75 | ||
|
|
fcfa55b39a | ||
|
|
8be390b2cf | ||
|
|
3ad83cbcd6 | ||
|
|
41826f5e5c | ||
|
|
0ccd6dc750 | ||
|
|
8c2ce8587d | ||
|
|
5e35fcea58 | ||
|
|
54595d46e5 | ||
|
|
09cb29da17 | ||
|
|
ecf1b5bc56 | ||
|
|
da71231be9 | ||
|
|
63feecf4aa | ||
|
|
a6255557ee | ||
|
|
84a3c3ba7c | ||
|
|
90c8a240a1 | ||
|
|
07c694e24d | ||
|
|
7c1c392710 | ||
|
|
379f5fe841 | ||
|
|
0ab15cc5e2 | ||
|
|
8f7a8a9e6d | ||
|
|
d5dc42c71e | ||
|
|
6ae5b2384e | ||
|
|
07c9e97bf5 | ||
|
|
5a53da62e3 | ||
|
|
11748da7a9 | ||
|
|
b0e15b86f5 | ||
|
|
1d1ad23bc0 | ||
|
|
ac54446769 | ||
|
|
5fe5caaf2b | ||
|
|
e111b01f16 | ||
|
|
fd2ac3f7f1 | ||
|
|
4e57b75640 | ||
|
|
e439bff2bc | ||
|
|
e210002bff | ||
|
|
4e735beb2f | ||
|
|
d747edc1f3 | ||
|
|
8bec94336b | ||
|
|
83eb193f1b | ||
|
|
9806f72ca6 | ||
|
|
7e7ec52290 | ||
|
|
98746fbca5 | ||
|
|
c0f65386bd | ||
|
|
cef6fce2c9 | ||
|
|
4964518486 | ||
|
|
06ec433b4e | ||
|
|
85681af8b8 | ||
|
|
4b12ecdf4b | ||
|
|
e8eacb02d6 | ||
|
|
e9dd55f4f9 | ||
|
|
a79df727c9 | ||
|
|
ca47b1c4f5 | ||
|
|
ab75bc7f59 | ||
|
|
f776a061ce | ||
|
|
1456f95b2c | ||
|
|
c5767f6ad5 | ||
|
|
3f8dedba80 | ||
|
|
121d62f20f | ||
|
|
2c08265210 | ||
|
|
82e397f136 | ||
|
|
730ee0205e | ||
|
|
a4716d5db0 | ||
|
|
06f166b70a | ||
|
|
f2ea36ac0d | ||
|
|
a8e706a395 | ||
|
|
f608bfa191 | ||
|
|
e494e22c07 | ||
|
|
d40c815760 | ||
|
|
ea39d83907 | ||
|
|
dae38d9b18 | ||
|
|
1e7cf9e65d | ||
|
|
831bd61e02 | ||
|
|
fe2b846dbc | ||
|
|
8c47d2b179 | ||
|
|
afe6b234cf | ||
|
|
1743c763d2 | ||
|
|
21237f8be1 | ||
|
|
d19e446416 | ||
|
|
8b93ede959 | ||
|
|
cb23254152 | ||
|
|
601aa6e245 | ||
|
|
532d282509 | ||
|
|
93c0525ea5 | ||
|
|
2bf423b42f | ||
|
|
f6c2ce45c1 | ||
|
|
d24eeefc86 | ||
|
|
876d4187d9 | ||
|
|
2412e7151f | ||
|
|
07c21caf8d | ||
|
|
69ddb2ddff | ||
|
|
283143e1bf | ||
|
|
80c54ad890 | ||
|
|
3272f3c8cc | ||
|
|
6bfbfc4762 | ||
|
|
8d2735f6e9 | ||
|
|
d72984be7e | ||
|
|
39212666c5 | ||
|
|
c909d32c56 | ||
|
|
8073e989f5 | ||
|
|
4671013ea6 | ||
|
|
b954457ae4 | ||
|
|
f7889b9709 | ||
|
|
a9894acd51 | ||
|
|
51e1c62ee6 | ||
|
|
fbd0f4b9c6 | ||
|
|
58204373aa | ||
|
|
710257da65 | ||
|
|
f63803529a | ||
|
|
7d9af64f6d | ||
|
|
87a4ce17e1 | ||
|
|
fae6f413a5 | ||
|
|
d8e36ab0f8 | ||
|
|
35fd5c8d65 | ||
|
|
5604424e6f | ||
|
|
c4c5f01ee5 | ||
|
|
e6d203d567 | ||
|
|
e75fa0bd84 | ||
|
|
b2cfbb95b6 | ||
|
|
0d84ea9523 | ||
|
|
e99fe70164 | ||
|
|
8bd337e08f | ||
|
|
12124eb1aa | ||
|
|
e036395d18 | ||
|
|
41ba7ad6a5 | ||
|
|
3452eafe4f | ||
|
|
e515ad3074 | ||
|
|
255f138bdb | ||
|
|
08496c2c61 | ||
|
|
25a996fe51 | ||
|
|
9ba39f2eda | ||
|
|
4a70b38a99 | ||
|
|
0dc66adc0d | ||
|
|
c2c11b29a7 | ||
|
|
071f48c3ca | ||
|
|
65cef0b40f | ||
|
|
f30912e02f | ||
|
|
1b74dc8afd | ||
|
|
1840b343b2 | ||
|
|
4f8030ecae | ||
|
|
bb6c0be9de | ||
|
|
a2d4c43047 | ||
|
|
60184f12bd | ||
|
|
4ffa30e31a | ||
|
|
7fff2833c3 | ||
|
|
d1da92d040 | ||
|
|
6bb8f8a030 | ||
|
|
dcd0eb20e1 | ||
|
|
7d6270079a | ||
|
|
05242c0ad7 | ||
|
|
30fb3a97d7 | ||
|
|
4dec8cfb17 | ||
|
|
bb8210b88e | ||
|
|
b69858b6f7 | ||
|
|
f191601ab4 | ||
|
|
7d62a55a92 | ||
|
|
eadcda4e30 | ||
|
|
45382d1446 | ||
|
|
0fd4f0bd7c | ||
|
|
c3fd7b9077 | ||
|
|
0f6aa3df83 | ||
|
|
48333c2ad2 | ||
|
|
9786886c3f | ||
|
|
b0eedfd6f1 | ||
|
|
1753bf96a8 | ||
|
|
67315bf88e | ||
|
|
4a3dcf24e1 | ||
|
|
c1b18fe478 | ||
|
|
e918af0a0c | ||
|
|
a847ad292f | ||
|
|
efac72ecbb | ||
|
|
ed5611810f | ||
|
|
b8d5e79c03 | ||
|
|
3e72ea0650 | ||
|
|
8b8a0b61af | ||
|
|
f237ac981e | ||
|
|
0ce5a63c1d | ||
|
|
a483ac9174 | ||
|
|
91e4c89962 | ||
|
|
c34e3b4282 | ||
|
|
6e38eb1d70 | ||
|
|
5d227d8d72 | ||
|
|
ccdf725957 | ||
|
|
86cffba4aa | ||
|
|
2086a73557 | ||
|
|
a5e8980b23 | ||
|
|
360af93d8d | ||
|
|
4c46bdaa7f | ||
|
|
b98094ceee | ||
|
|
03330537fc | ||
|
|
2c7809b134 | ||
|
|
af287dcdce | ||
|
|
ed840a96e6 | ||
|
|
04cfd0eb38 | ||
|
|
6386034c65 | ||
|
|
9b26d6c504 | ||
|
|
3529297fa4 | ||
|
|
ad699fa23c | ||
|
|
0fd9e951b9 | ||
|
|
66bcd32ae7 | ||
|
|
f0d91b0058 | ||
|
|
3d58213f0b | ||
|
|
528d7411e1 | ||
|
|
a6651ffe48 | ||
|
|
a8e6dc3a3a | ||
|
|
8733b2463c | ||
|
|
37b0ef4599 | ||
|
|
c72ed970fb | ||
|
|
e9e42be139 | ||
|
|
b55ecd2808 | ||
|
|
f2a8829d1d | ||
|
|
c20ea7e030 | ||
|
|
df3fc0a9ef | ||
|
|
3c7a05b572 | ||
|
|
a155bcd11a | ||
|
|
57f13f59b1 | ||
|
|
894cf8e6c3 | ||
|
|
fa3b952af3 | ||
|
|
b26db1910b | ||
|
|
aab865be96 | ||
|
|
866fa5643e | ||
|
|
87ced16d63 | ||
|
|
ed5463360e | ||
|
|
27edfac161 | ||
|
|
7f70e69c8e | ||
|
|
c70fedfb43 | ||
|
|
85d7b5fd5d | ||
|
|
cbace6f97e | ||
|
|
bec5dc4476 | ||
|
|
f7ddd8bbbb | ||
|
|
43d0c291ed | ||
|
|
0956edd0d0 | ||
|
|
c9477d37fa | ||
|
|
3b5c96d7cb | ||
|
|
c3c049b225 | ||
|
|
6fedb9773b | ||
|
|
332a8de2e9 | ||
|
|
7121968081 | ||
|
|
a44133d0c9 | ||
|
|
3c3d9487d0 | ||
|
|
15b5083d17 | ||
|
|
e25cafe2b4 | ||
|
|
b5c44e47ff | ||
|
|
5d04b8deea | ||
|
|
1207291249 | ||
|
|
06bf641e7a | ||
|
|
ce764082b8 | ||
|
|
aebc301b05 | ||
|
|
3b93a073c3 | ||
|
|
a4a7b44da9 | ||
|
|
e65be6ee36 | ||
|
|
2d0b9ecac0 | ||
|
|
5a5b86aeec | ||
|
|
ff41fe0577 | ||
|
|
c97b60b2da | ||
|
|
2645dcdddf | ||
|
|
6debb09b0f | ||
|
|
62b84d454a | ||
|
|
26dc3f32d9 | ||
|
|
84f8b6e1da | ||
|
|
70e3d40c3e | ||
|
|
432b2f04d7 | ||
|
|
63c82cf705 | ||
|
|
5c7d121e67 | ||
|
|
055198ccd5 | ||
|
|
0993e81e00 | ||
|
|
15d22b7726 | ||
|
|
bb3a54a312 | ||
|
|
7ad6b9c32a | ||
|
|
4814f21017 | ||
|
|
1f962f21b3 | ||
|
|
397e1e2bf1 | ||
|
|
b10c7297fd | ||
|
|
7f9194f475 | ||
|
|
0fc1edf895 | ||
|
|
c973c0cce5 | ||
|
|
48f3bdc80c | ||
|
|
0fc43fcf42 | ||
|
|
e593ec604e | ||
|
|
1494bc9db3 | ||
|
|
4512aa7ff8 | ||
|
|
de782e629f | ||
|
|
b7c6a7ffd9 | ||
|
|
ca4118cc8e | ||
|
|
a561e7dc2b | ||
|
|
b3a0f187d7 | ||
|
|
39be2d0351 | ||
|
|
5492e0db50 | ||
|
|
db038c29e8 | ||
|
|
4fe1f5c225 | ||
|
|
ac374bab22 | ||
|
|
01f6814a25 | ||
|
|
6e4dc10c49 | ||
|
|
6b3a9024d3 | ||
|
|
b4841843f7 | ||
|
|
35efc07b2e | ||
|
|
954160ebd9 | ||
|
|
ea1633ad52 | ||
|
|
fb5d5ea1be | ||
|
|
02f5d6fea2 | ||
|
|
227755b892 | ||
|
|
eebd8771bd | ||
|
|
36fed0cc6f | ||
|
|
08f3b64243 | ||
|
|
59cfe96fe3 | ||
|
|
128e810f77 | ||
|
|
bbe9322f75 | ||
|
|
35186b41ff | ||
|
|
0c846f0fea | ||
|
|
d497e96407 | ||
|
|
a4f139f855 | ||
|
|
e386b28ba4 | ||
|
|
aa8ef48246 | ||
|
|
6bac462359 | ||
|
|
24e4d05157 | ||
|
|
737c051466 | ||
|
|
4ab50882a4 | ||
|
|
06a07865f3 | ||
|
|
5607702be9 | ||
|
|
e9be009f49 | ||
|
|
bb4e938bd2 | ||
|
|
45f723c07f | ||
|
|
640f44fd10 | ||
|
|
821dd02aa4 | ||
|
|
6e2140258e | ||
|
|
b628bd7769 | ||
|
|
f23cd22110 | ||
|
|
8ef4f408bf | ||
|
|
01139a2e6b | ||
|
|
08606f740d | ||
|
|
42c6bc11cc | ||
|
|
d6703e82e2 | ||
|
|
8f1692e394 | ||
|
|
3e55234a24 | ||
|
|
7df246c25a | ||
|
|
fbffbce090 | ||
|
|
18e9b6d84c | ||
|
|
03e5bc515f | ||
|
|
b336529d42 | ||
|
|
bbf716b28e | ||
|
|
725f6fe3ec | ||
|
|
f773a02ce0 | ||
|
|
21266be1ed | ||
|
|
53d0338218 | ||
|
|
2f67c23c5c | ||
|
|
e64be755f9 | ||
|
|
23952c5f5f | ||
|
|
02fc5036d7 | ||
|
|
a6a65ed9f4 | ||
|
|
369f657aa6 | ||
|
|
1801e5b30f | ||
|
|
b10d5103f3 | ||
|
|
9964bfef8b | ||
|
|
9945a19f2c | ||
|
|
a5d43e6f14 | ||
|
|
b61b9a06dd | ||
|
|
f28570fa98 | ||
|
|
fb53d639be | ||
|
|
42de9257c3 | ||
|
|
0fba597a61 | ||
|
|
d0393c4e9f | ||
|
|
a21d2a591e | ||
|
|
de54688c56 | ||
|
|
3c486d9117 | ||
|
|
e8128250f4 | ||
|
|
58a1b72910 | ||
|
|
ee00d29afd | ||
|
|
5cfcc538a8 | ||
|
|
e7c8a9d420 | ||
|
|
6b07ffe8f7 | ||
|
|
0d17340445 | ||
|
|
2a0b92713b | ||
|
|
fb22eb4178 | ||
|
|
136fb2f394 | ||
|
|
c515805f0a | ||
|
|
613ba9ba20 | ||
|
|
f6314d3581 | ||
|
|
043f5c78c2 | ||
|
|
0f9e519b0e | ||
|
|
0d17a2351f | ||
|
|
1b388664cb | ||
|
|
1edb0c529f | ||
|
|
f07a58bff4 | ||
|
|
c054840aec | ||
|
|
e259418398 | ||
|
|
df1d68a724 | ||
|
|
9d58390e11 | ||
|
|
db4c7a8bda | ||
|
|
ab163fc0ef | ||
|
|
0265801830 | ||
|
|
5fa7bbbc0f | ||
|
|
e15351e1c5 | ||
|
|
5eb0133b5c | ||
|
|
ff8344d671 | ||
|
|
d9a43ea1d6 | ||
|
|
6c62d73afb | ||
|
|
d23d6c342a | ||
|
|
90549a09e1 | ||
|
|
17d3639443 | ||
|
|
e8a096b8fe | ||
|
|
fea136e513 | ||
|
|
f3a4095462 | ||
|
|
d7d25cf69b | ||
|
|
3b33fe83e6 | ||
|
|
56f4d223ab | ||
|
|
c07317a619 | ||
|
|
4798f7688b | ||
|
|
24db0eb5aa | ||
|
|
1ece13c43d | ||
|
|
48268309b9 | ||
|
|
4074a52b1b | ||
|
|
61dd524c26 | ||
|
|
61a678a318 | ||
|
|
8ecec6a14f | ||
|
|
e3f8b8a394 | ||
|
|
eebddbafcc | ||
|
|
50cbce0f7a | ||
|
|
f9974a8971 | ||
|
|
baa48a1679 | ||
|
|
032910f87a | ||
|
|
773ef95b70 | ||
|
|
18c2f84771 | ||
|
|
ea721a71b5 | ||
|
|
b1b7427c6e | ||
|
|
7bc7c30510 | ||
|
|
d1e055430d | ||
|
|
736534379a | ||
|
|
f6b71e157c | ||
|
|
53e9f931f2 | ||
|
|
c226a9476f | ||
|
|
8ca5600286 | ||
|
|
9729bc00a0 | ||
|
|
f9c9af8261 | ||
|
|
c9e64373fb | ||
|
|
262febf486 | ||
|
|
eca9c4d7f8 | ||
|
|
a20083bb9c | ||
|
|
d31b01415b | ||
|
|
26cdb472f0 | ||
|
|
3c2595aaf9 | ||
|
|
ad323a0dff | ||
|
|
9a0417b1a7 | ||
|
|
3324a816ee | ||
|
|
cc4135a2d7 | ||
|
|
2d884c83cc | ||
|
|
619c5b5e1d | ||
|
|
33afa9adfc | ||
|
|
0c141cc6f7 | ||
|
|
efdff2ab0c | ||
|
|
ebefb0eba4 | ||
|
|
d4b9c2c97b | ||
|
|
d4db16b501 | ||
|
|
a5cbd7387b | ||
|
|
99d6b4a361 | ||
|
|
18365689e6 | ||
|
|
8ea827412a | ||
|
|
4d8979c4ad | ||
|
|
236357baa8 | ||
|
|
5ef4b21858 | ||
|
|
3b3441851c | ||
|
|
5517987e14 | ||
|
|
7e98f61bec | ||
|
|
e2d360e8b1 | ||
|
|
57cfedfd7c | ||
|
|
50b1d21d13 | ||
|
|
7b79ec6c66 | ||
|
|
7a5b31530f | ||
|
|
e9100a9542 | ||
|
|
421304d4a3 | ||
|
|
10d61bbbb3 | ||
|
|
095709fb19 | ||
|
|
725f4150fc | ||
|
|
93ac2e70d2 | ||
|
|
f4c2b50ca5 | ||
|
|
3354edbb1c | ||
|
|
d3600499af | ||
|
|
35e2c2cfe8 | ||
|
|
1e4970469f | ||
|
|
4cbfd7c9b1 | ||
|
|
deb32fa0fa | ||
|
|
f17a738780 | ||
|
|
2f53d0efae | ||
|
|
3e43c2e6e6 | ||
|
|
96919a9f79 | ||
|
|
a23fb627cd | ||
|
|
aae915b092 | ||
|
|
160c8e814b | ||
|
|
88f48baba1 | ||
|
|
7835efbf37 | ||
|
|
455fbb505e | ||
|
|
df3f7090e8 | ||
|
|
632b3c200c | ||
|
|
5b203326ae | ||
|
|
fd87aca57d | ||
|
|
b9b7e556e3 | ||
|
|
5b9a7e6a2a | ||
|
|
d278e19367 | ||
|
|
342030ca47 | ||
|
|
f90e241cc9 | ||
|
|
ff6bcc437c | ||
|
|
e32dbb5125 | ||
|
|
06701cc7d1 | ||
|
|
ccb31bc1b4 | ||
|
|
7e2e29e2e8 | ||
|
|
0c76995f6d | ||
|
|
17cab8fcb7 | ||
|
|
d64753859d | ||
|
|
48b1c24c95 | ||
|
|
7e5e12b139 | ||
|
|
59ba4752c0 | ||
|
|
189219c673 | ||
|
|
4b54262edd | ||
|
|
458b035a7e | ||
|
|
abe85cf6e7 | ||
|
|
379b63275a | ||
|
|
07cde689b1 | ||
|
|
26606f138d | ||
|
|
24c4774f7e | ||
|
|
6bbb4f577e | ||
|
|
4890de5052 | ||
|
|
746af37899 | ||
|
|
0136ce7034 | ||
|
|
5ca47a91a6 | ||
|
|
d849df41be | ||
|
|
a2269bcdd5 | ||
|
|
d41394c70a | ||
|
|
756f73bbd2 | ||
|
|
95eb17b6d1 | ||
|
|
773fd1f221 | ||
|
|
c95b436680 | ||
|
|
3f47151678 | ||
|
|
dbf1e7136c | ||
|
|
84b44eef91 | ||
|
|
686ada1e49 | ||
|
|
d9f6bc058a | ||
|
|
6f531793f0 | ||
|
|
f8794bef5f | ||
|
|
9daf103669 | ||
|
|
26fa047fe4 | ||
|
|
1a04bb535d | ||
|
|
ad41b7b434 | ||
|
|
6791b1dbdc | ||
|
|
dc1b84130c | ||
|
|
e70a933090 | ||
|
|
08617f2fd4 | ||
|
|
8aefb5db8e | ||
|
|
e1d214b91a | ||
|
|
0285de50e5 | ||
|
|
5f7caa0535 | ||
|
|
df9d2bc472 | ||
|
|
a923b6beca | ||
|
|
760ef77593 | ||
|
|
64f703856e | ||
|
|
36eba36bf2 | ||
|
|
332176a619 | ||
|
|
cd5b60c8cc | ||
|
|
5ea8947fc9 | ||
|
|
474a5c8e42 | ||
|
|
952062d5be | ||
|
|
c071564de4 | ||
|
|
b2fa7563d3 | ||
|
|
22f68fedcb | ||
|
|
0a4cda26cb | ||
|
|
54eb84e690 | ||
|
|
5cd33814fc | ||
|
|
90f19679e7 | ||
|
|
38ade9e498 | ||
|
|
4c77831001 | ||
|
|
722fe556e3 | ||
|
|
98b83c0078 | ||
|
|
85646b5ffa | ||
|
|
d3f5ed7d60 | ||
|
|
e0a8e93704 | ||
|
|
3aab5e9eb7 | ||
|
|
2307ac88cb | ||
|
|
0f2018d913 | ||
|
|
8b9a75ba5a | ||
|
|
7872e0ce38 | ||
|
|
d28ac73987 | ||
|
|
2c8c7a8b51 | ||
|
|
f98fc6bf3c | ||
|
|
d42958734f | ||
|
|
6f2c785713 | ||
|
|
05a1ce51f0 | ||
|
|
58b063770d | ||
|
|
6f9a83709d | ||
|
|
bd2a3ddfba | ||
|
|
4433b6623e | ||
|
|
e1ca17637f | ||
|
|
5ef0e43312 | ||
|
|
aa6ca95f13 | ||
|
|
2523467c97 | ||
|
|
b38eb6709e | ||
|
|
f6dacdb046 | ||
|
|
cc0903f74d | ||
|
|
72936fc0d1 | ||
|
|
4b7f552885 | ||
|
|
9b2fc60d79 | ||
|
|
3e5a26b95a | ||
|
|
a5f3139784 | ||
|
|
9ca9fcdb09 | ||
|
|
913db35b23 | ||
|
|
8eba3ba4f7 | ||
|
|
5bd0f24a84 | ||
|
|
e8fb3180db | ||
|
|
232aaad090 | ||
|
|
b3dbb8d4be | ||
|
|
3caf070056 | ||
|
|
1e24bbc3e2 | ||
|
|
18694fd24a | ||
|
|
10dc003f20 | ||
|
|
809e2496c0 | ||
|
|
c1c37901b5 | ||
|
|
44e115f211 | ||
|
|
217cc338a8 | ||
|
|
81eccc177d | ||
|
|
4ea00b7e7b | ||
|
|
844699263d | ||
|
|
d72a548852 | ||
|
|
722ed9bece | ||
|
|
8852367837 | ||
|
|
5559f9b9af | ||
|
|
39526edafd | ||
|
|
a4f86354d3 | ||
|
|
636204bbaf | ||
|
|
08494834c2 | ||
|
|
2247f34b89 | ||
|
|
5c84412238 | ||
|
|
13112aa4d8 | ||
|
|
836a165ff2 | ||
|
|
f36e0b39ed | ||
|
|
74e2ec74e0 | ||
|
|
bcb6243f3b | ||
|
|
c00b628fb4 | ||
|
|
2fbed17ebc | ||
|
|
7bfea23958 | ||
|
|
91c567779b | ||
|
|
c4aeeb419e | ||
|
|
7808fbb852 | ||
|
|
9e64bd474b | ||
|
|
25a6aef472 | ||
|
|
203ba521b0 | ||
|
|
287685420a | ||
|
|
a6ae0ba4b0 | ||
|
|
208346a480 | ||
|
|
0d5c55a3b5 | ||
|
|
4fcd2bf14c | ||
|
|
deea1aba7f | ||
|
|
3e31666cd6 | ||
|
|
197c4c46ab | ||
|
|
33cb2ed43d | ||
|
|
b56e521c5f | ||
|
|
639b930ac9 | ||
|
|
607235eb01 | ||
|
|
dbfeb4b0fa | ||
|
|
432725b80d | ||
|
|
91c2909c4a | ||
|
|
699a2f7956 | ||
|
|
7c2751ad37 | ||
|
|
50b524fa7a | ||
|
|
aee26bc9b2 | ||
|
|
78de254230 | ||
|
|
22fe4053e9 | ||
|
|
e73f9ac8f2 | ||
|
|
19987234e5 | ||
|
|
33239f28f8 | ||
|
|
350f4572ed | ||
|
|
ab29267d64 | ||
|
|
b410820868 | ||
|
|
b1268e0001 | ||
|
|
9fe661269d | ||
|
|
a715a77e76 | ||
|
|
20933f77f5 | ||
|
|
c618fcafaa | ||
|
|
350ce2ad35 | ||
|
|
eef8580e89 | ||
|
|
406fc05970 | ||
|
|
2b6cb775d8 | ||
|
|
fe27fd4c86 | ||
|
|
784dca2baa | ||
|
|
6cff6414c2 | ||
|
|
b84b6c3464 | ||
|
|
bd3931d62d | ||
|
|
7ababb626b | ||
|
|
62b2833c2f | ||
|
|
190c82bbe6 | ||
|
|
b8055d45e7 | ||
|
|
fe09bb3c91 | ||
|
|
84d0a91c44 | ||
|
|
9d95f660e3 | ||
|
|
2d76d1f50c | ||
|
|
df3b921654 | ||
|
|
e98fccdcfd | ||
|
|
7b9b940b6a | ||
|
|
3a4b750d93 | ||
|
|
40e3555d13 | ||
|
|
4b6adb3919 | ||
|
|
66aece580f | ||
|
|
09fc200d55 | ||
|
|
b17b56dba0 | ||
|
|
a9d0531a56 | ||
|
|
a7a2c85f82 | ||
|
|
83a06fcd2b | ||
|
|
d2d7b22a8f | ||
|
|
92b78ab3c8 | ||
|
|
0bed3bab98 | ||
|
|
a60637fb79 | ||
|
|
f1218264be | ||
|
|
18cf63facc | ||
|
|
9f8e1775af | ||
|
|
0e39f3ad05 | ||
|
|
4fc90c0168 | ||
|
|
57b4f539f9 | ||
|
|
8667ce5fb4 | ||
|
|
0ed922bb29 | ||
|
|
80eff97be3 | ||
|
|
e5cfe5cd99 | ||
|
|
1d8b952a6d | ||
|
|
c204f7a514 | ||
|
|
6e2ef1e29c | ||
|
|
5f0402043a | ||
|
|
6ad7ccdd6e | ||
|
|
90a2fd7f19 | ||
|
|
58c8b11f85 | ||
|
|
4d700be9ae | ||
|
|
da0d02b990 | ||
|
|
854cb59f6b | ||
|
|
33cbee23d4 | ||
|
|
0497cf384d | ||
|
|
acd8fa3810 | ||
|
|
9d024bca3b | ||
|
|
7434c9db55 | ||
|
|
a3ab0b3243 | ||
|
|
64608f6b05 | ||
|
|
a207c982b7 | ||
|
|
072acac399 | ||
|
|
8049466dff | ||
|
|
80077ba94d | ||
|
|
bd4744557f | ||
|
|
d8072634ef | ||
|
|
27158f7075 | ||
|
|
f06f1fb7f1 | ||
|
|
8bb7b75f05 | ||
|
|
0c9e92abb0 | ||
|
|
7a8787b1a0 | ||
|
|
78f71c8b13 | ||
|
|
a0a35e8253 | ||
|
|
e892e3f9e1 | ||
|
|
2dadc98485 | ||
|
|
1bd2b4629e | ||
|
|
ce52cbf6ac | ||
|
|
0abcb5aba1 | ||
|
|
ca7bdc913e | ||
|
|
2de7d34b4a | ||
|
|
0eea78f796 | ||
|
|
95fa7e8130 | ||
|
|
fd78876dd3 | ||
|
|
eaa3075516 | ||
|
|
92338fd219 | ||
|
|
26d32c02ea | ||
|
|
e03efc33d7 | ||
|
|
2d1188af11 | ||
|
|
66666ed5fd | ||
|
|
dfcb283899 | ||
|
|
24215f8b28 | ||
|
|
ddc2b4c2ad | ||
|
|
10cef483f4 | ||
|
|
51dde2f71e | ||
|
|
5e0117e7c6 | ||
|
|
3b3535faec | ||
|
|
3e1067faba | ||
|
|
722382f60e | ||
|
|
e47a512fc8 | ||
|
|
0627359b6e | ||
|
|
01d1e4c7f5 | ||
|
|
3f564e8179 | ||
|
|
b6f3038a73 | ||
|
|
e67354f34c | ||
|
|
a04982425f | ||
|
|
2e6f99edf0 | ||
|
|
9307d08bb6 | ||
|
|
2cdcd98e08 | ||
|
|
7540ee942f | ||
|
|
7bfad03b2e | ||
|
|
9dacd7056b | ||
|
|
4ebe66a29c | ||
|
|
6ebed9eff6 | ||
|
|
cc13685062 | ||
|
|
6b28490d7b | ||
|
|
27ba592434 | ||
|
|
cf5daffe69 | ||
|
|
192c0e529d | ||
|
|
c300e16de9 | ||
|
|
e46eecfc8e | ||
|
|
1e2add4b97 | ||
|
|
975f515691 | ||
|
|
05f8ae2aae | ||
|
|
525b3a0da9 | ||
|
|
03265e03fc | ||
|
|
28c928890a | ||
|
|
6f3e8683a0 | ||
|
|
ba7a16250b | ||
|
|
1cbbce741a | ||
|
|
9f9f6b7a08 | ||
|
|
3ec4823533 | ||
|
|
31d316f5b2 | ||
|
|
8f31d6fcbd | ||
|
|
7b80ea528c | ||
|
|
ee388b01db | ||
|
|
2d4b16db46 | ||
|
|
a7715648d0 | ||
|
|
4ebc4e01cd | ||
|
|
fd0625f2eb | ||
|
|
ef35c53712 | ||
|
|
b5c79be625 | ||
|
|
ee7b9b0cff | ||
|
|
3289405b17 | ||
|
|
b9a30b9ffe | ||
|
|
f606c7c891 | ||
|
|
c76eb01b68 | ||
|
|
34b6e5ebae | ||
|
|
7d771a56e6 | ||
|
|
f1017e345b | ||
|
|
091b61bd10 | ||
|
|
ed9ca764d4 | ||
|
|
70c6480ae9 | ||
|
|
a0ebb3ef58 | ||
|
|
1efb68b11f | ||
|
|
9c564df350 | ||
|
|
767e7650e0 | ||
|
|
f32ed3a5c8 | ||
|
|
7e7c869fc4 | ||
|
|
9da64c34ff | ||
|
|
23266d12ec | ||
|
|
3920d151af | ||
|
|
9551cdf18a | ||
|
|
1ec90895da | ||
|
|
bd67b8bf7f | ||
|
|
53c116309e | ||
|
|
5a53ae0d34 | ||
|
|
207c0e3708 | ||
|
|
7b7d76e977 | ||
|
|
a1d3b5c887 | ||
|
|
796bcb34ad | ||
|
|
9f274308ca | ||
|
|
7feb152b35 | ||
|
|
4fad8b77bf | ||
|
|
2c90c90610 | ||
|
|
9ac66f57fa | ||
|
|
82fcc196df | ||
|
|
c7dbcbf336 | ||
|
|
5591c60c14 | ||
|
|
dcdcf0bbbe | ||
|
|
e899f85101 | ||
|
|
96ef70b943 | ||
|
|
1f24e135d9 | ||
|
|
26d0cb1f3d | ||
|
|
5256e468db | ||
|
|
82ade2a8f3 | ||
|
|
f0d31fd48d | ||
|
|
14de145c02 | ||
|
|
060cc38e84 | ||
|
|
453a9b30e9 | ||
|
|
73d982ebad | ||
|
|
e6ba8e94db | ||
|
|
05f13c61fc | ||
|
|
d52d909171 | ||
|
|
d6c6f39387 | ||
|
|
31946032ba | ||
|
|
609e3d42a1 | ||
|
|
016b7d231a | ||
|
|
7c61961c55 | ||
|
|
89746b3338 | ||
|
|
64ab6a28b3 | ||
|
|
4bf872d292 | ||
|
|
063ceffb11 | ||
|
|
f68ca5ab73 | ||
|
|
eb47b5d08a | ||
|
|
2665ea1203 | ||
|
|
b2dc150f03 | ||
|
|
70ff8ead90 | ||
|
|
0610419e38 | ||
|
|
cd68d1f198 | ||
|
|
091f83ff59 | ||
|
|
8504e9bf74 | ||
|
|
013d1ed056 | ||
|
|
8d7d6eee76 | ||
|
|
cba2ed5424 | ||
|
|
d913ce8e1a | ||
|
|
84e7c4df49 | ||
|
|
71a2f4c284 | ||
|
|
777f49002e | ||
|
|
1e6dfbff96 | ||
|
|
053f414ef6 | ||
|
|
6321564bed | ||
|
|
76be6b8847 | ||
|
|
9205a39d3e | ||
|
|
1471f165de | ||
|
|
e40d785e4e | ||
|
|
b6e2cf645b | ||
|
|
759fb6622d | ||
|
|
7c7ca8d757 | ||
|
|
0f3ff7bdbb | ||
|
|
e0280a56ce | ||
|
|
9da394f711 | ||
|
|
582c39611d | ||
|
|
7d82785ade | ||
|
|
4e8544ce97 | ||
|
|
a8d746e831 | ||
|
|
9d8df566fc | ||
|
|
99156155b3 | ||
|
|
17fe4ac327 | ||
|
|
3b6e6495c5 | ||
|
|
b20a54f7e9 | ||
|
|
3bb4d74fab | ||
|
|
4dd9c06850 | ||
|
|
2ca9322d82 | ||
|
|
5e304a5a6b | ||
|
|
21eb039978 | ||
|
|
6026ac31b1 | ||
|
|
72e11a7d31 | ||
|
|
b0656e70b8 | ||
|
|
83141b3564 | ||
|
|
b25c128051 | ||
|
|
afc9d13d45 | ||
|
|
7e106f3468 | ||
|
|
e74a102700 | ||
|
|
1037a1749b | ||
|
|
8c19622db2 | ||
|
|
0eae201401 | ||
|
|
3de83d1178 | ||
|
|
c17ebddcef | ||
|
|
95fd9f92cd | ||
|
|
fda1a2a728 | ||
|
|
98dc95d105 | ||
|
|
c5da8d154d | ||
|
|
95209af8f9 | ||
|
|
35255fdaee | ||
|
|
cd7ad06a7d | ||
|
|
d0b8cd8221 | ||
|
|
1aac17aeff | ||
|
|
ccf0769f43 | ||
|
|
076e1092f0 | ||
|
|
670df8c0cb | ||
|
|
a817dceb24 | ||
|
|
227bcd509f | ||
|
|
1e6605ecd3 | ||
|
|
84f35f55d4 | ||
|
|
43d1aa17a3 | ||
|
|
fc0958e511 | ||
|
|
bfe3a861f5 | ||
|
|
658ca60f58 | ||
|
|
e4709c599b | ||
|
|
02ffe71d80 | ||
|
|
3ef3084070 | ||
|
|
250fcf4bd6 | ||
|
|
86baabc452 | ||
|
|
6126aa146b | ||
|
|
64ce7fedcd | ||
|
|
6c85af386c | ||
|
|
7ff58c4e6d | ||
|
|
ecef8ddd72 | ||
|
|
2f96e27adb | ||
|
|
10bd7e9485 | ||
|
|
f6fa4c3064 | ||
|
|
64a525133b | ||
|
|
485b9f32df | ||
|
|
dc6859f4f0 | ||
|
|
f861f2ba3f | ||
|
|
3a9b39b94b | ||
|
|
9a5d3461fe | ||
|
|
6add2094a6 | ||
|
|
843e5a9ad4 | ||
|
|
a8d41e289c | ||
|
|
3a591a5574 | ||
|
|
6076b4cde1 | ||
|
|
b158849d07 | ||
|
|
e4d448a661 | ||
|
|
42b51243a7 | ||
|
|
8dd87d0172 | ||
|
|
c92a94bdd2 | ||
|
|
c7ce98f1d5 | ||
|
|
6fb6ac2d6c | ||
|
|
fe539baa34 | ||
|
|
9aa7399484 | ||
|
|
eaa97e7eb8 | ||
|
|
dd7e37ef6e | ||
|
|
64c46118b0 | ||
|
|
bdc5f69ae0 | ||
|
|
35616394bc | ||
|
|
f463e76f5e | ||
|
|
fb7b57210a | ||
|
|
6ccd791574 | ||
|
|
13b12d80da | ||
|
|
571de25e81 | ||
|
|
08c2b02be9 | ||
|
|
6e0a3387cd | ||
|
|
c5f6e1262f | ||
|
|
27212da8df | ||
|
|
9d89d33701 | ||
|
|
5754979918 | ||
|
|
bf66fa386b | ||
|
|
e91338a2e6 | ||
|
|
58616d4927 | ||
|
|
2b2ac20feb | ||
|
|
7c11f8ab37 | ||
|
|
cc7fde9a27 | ||
|
|
ed56a73821 | ||
|
|
7e7fa6af65 | ||
|
|
5d591bca35 | ||
|
|
0b8e15cad1 | ||
|
|
d96b963385 | ||
|
|
671040a3a7 | ||
|
|
429353fa54 | ||
|
|
8003603ffd | ||
|
|
f8e767511b | ||
|
|
6a97980a18 | ||
|
|
2ab0df8e17 | ||
|
|
97a3ca223f | ||
|
|
bee9f61aa9 | ||
|
|
c193eb155e | ||
|
|
cc5ac0c659 | ||
|
|
752d063d5f | ||
|
|
06229d0d1f | ||
|
|
4ac8f5a354 | ||
|
|
6628715e40 | ||
|
|
d84dc0dd48 | ||
|
|
253e2a58be | ||
|
|
5f8daf56b1 | ||
|
|
cdd5aedadd | ||
|
|
52809a01d8 | ||
|
|
b459413c0e | ||
|
|
b147c4faaa | ||
|
|
e63ccb0541 | ||
|
|
ea878ca627 | ||
|
|
2dc2a998ce | ||
|
|
f747e01285 | ||
|
|
d9a53805ee | ||
|
|
9c3fc0dede | ||
|
|
cc409fbab6 | ||
|
|
8de71ff2d3 | ||
|
|
457768bb10 | ||
|
|
046b89efc5 | ||
|
|
e7f7772a74 | ||
|
|
0082ebfdb1 | ||
|
|
a9f0c41cae | ||
|
|
30b16984ed | ||
|
|
c8ce379163 | ||
|
|
f5bfb0255c | ||
|
|
f2b92cc6e0 | ||
|
|
6a97f39f66 | ||
|
|
f389ff701a | ||
|
|
648df02624 | ||
|
|
4cee98bcce | ||
|
|
7e33dc7e25 | ||
|
|
6f68fbfd6d | ||
|
|
7fe3c2b285 | ||
|
|
a07ba498d6 | ||
|
|
d7222c8e31 | ||
|
|
9426049095 | ||
|
|
edec8788c3 | ||
|
|
1a66f52f75 | ||
|
|
ccab152fe3 | ||
|
|
e2e5ef7a93 | ||
|
|
c9b6b74020 | ||
|
|
e353f9c295 | ||
|
|
f2a24d0713 | ||
|
|
8423c124d7 | ||
|
|
a9dec9fe4d | ||
|
|
343d3aaaf2 | ||
|
|
1bec261878 | ||
|
|
33cffb015e | ||
|
|
b5da0c6043 | ||
|
|
dfc24c3c33 | ||
|
|
12fb1e7891 | ||
|
|
781f8d7961 | ||
|
|
895cb65c10 | ||
|
|
fb1196785d | ||
|
|
4c8ac48af0 | ||
|
|
e8d0b39b5d | ||
|
|
6dbcd55727 | ||
|
|
40f5dfeb42 | ||
|
|
c5b96954bf | ||
|
|
debd8afe31 | ||
|
|
46dc47727b | ||
|
|
7a2380ffe8 | ||
|
|
ca1f4ba227 | ||
|
|
dbf45502d1 | ||
|
|
44892d9401 | ||
|
|
82b32f8b65 | ||
|
|
6026422056 | ||
|
|
69ff39a46c | ||
|
|
f90a51bf40 | ||
|
|
9ea885d908 | ||
|
|
ece494e897 | ||
|
|
85ca35684c | ||
|
|
8d34adee14 | ||
|
|
3a74c9483e | ||
|
|
727caf3f4f | ||
|
|
eca5967b4d | ||
|
|
7dce65100a | ||
|
|
40d78ab69a | ||
|
|
9196caec97 | ||
|
|
5fa6e32bbd | ||
|
|
bb5c65cf4e | ||
|
|
f512bc0870 | ||
|
|
b3b8de1c4c | ||
|
|
b4b5eb9266 | ||
|
|
9ddd280271 | ||
|
|
b5f16ee34d | ||
|
|
bf0511efa4 | ||
|
|
236d3c7f33 | ||
|
|
7fd4b1d0f5 | ||
|
|
8825a18b22 | ||
|
|
df9dc477ed | ||
|
|
8c2b6b2bc0 | ||
|
|
512e91e2bc | ||
|
|
812c51804b | ||
|
|
93185149b3 | ||
|
|
6298f31a91 | ||
|
|
49af66fb4f | ||
|
|
abcd1c54b4 | ||
|
|
d2eaf0b38c | ||
|
|
f0957c615e | ||
|
|
ce5d5d13a3 | ||
|
|
274eb56d05 | ||
|
|
6bf3835728 | ||
|
|
be2681a114 | ||
|
|
019829d0db | ||
|
|
2ff07055b3 | ||
|
|
b8bac2ffb8 | ||
|
|
382ae1f5ec | ||
|
|
5223281db6 | ||
|
|
f64eb528ab | ||
|
|
1549bb6dc5 | ||
|
|
9422a25804 | ||
|
|
fd4df8e841 | ||
|
|
4d17c8d1e5 | ||
|
|
60402a298f | ||
|
|
3113494c0f | ||
|
|
ef974be05e | ||
|
|
3d5b2f70e1 | ||
|
|
1912f6b69c | ||
|
|
9670b53197 | ||
|
|
1727c4ef35 | ||
|
|
ab4d2a4482 | ||
|
|
7ec6fffac6 | ||
|
|
22121f0026 | ||
|
|
6b9c9225eb | ||
|
|
9705629b78 | ||
|
|
9c37a7be9d | ||
|
|
d51888f445 | ||
|
|
5a83207b32 | ||
|
|
8830f59f74 | ||
|
|
1e2d1796fe | ||
|
|
8bcd7a7a2c | ||
|
|
f899b927cf | ||
|
|
d8704ad398 | ||
|
|
a18c0d9653 | ||
|
|
3c3d642f6b | ||
|
|
a442ad090e | ||
|
|
9030b9b75e | ||
|
|
a6546138ea | ||
|
|
8791206a5c | ||
|
|
c39b6f3958 | ||
|
|
255dba330d | ||
|
|
35ace1b970 | ||
|
|
827bef4f91 | ||
|
|
bee4d4cf21 | ||
|
|
85a1eb8215 | ||
|
|
ed52dd5411 | ||
|
|
649b5fbe8a | ||
|
|
bbc615ea5f | ||
|
|
ca008145af | ||
|
|
32314bc464 | ||
|
|
fc003dbc16 | ||
|
|
0fe4750991 | ||
|
|
8b94b8b043 | ||
|
|
6a9a159642 | ||
|
|
2b9365da17 | ||
|
|
ff850b7156 | ||
|
|
283d962d96 | ||
|
|
b5853a09ec | ||
|
|
5796287d88 | ||
|
|
77cd35a52a | ||
|
|
a3dd9e9e02 | ||
|
|
1037ee5798 | ||
|
|
21965dfce3 | ||
|
|
931e144e43 | ||
|
|
57fd8d6dde | ||
|
|
db3d16af36 | ||
|
|
fa0c1430c3 | ||
|
|
23304c7a9a | ||
|
|
86c5f9184a | ||
|
|
4a2ded7b8a | ||
|
|
99ae4056bc | ||
|
|
da64403829 | ||
|
|
b4eb8c0add | ||
|
|
f9c5c33f68 | ||
|
|
2ac97ea099 | ||
|
|
619c54ca17 | ||
|
|
1d43216b40 | ||
|
|
aa309ce62c | ||
|
|
a146265de5 | ||
|
|
6b69972230 | ||
|
|
6cc495de95 | ||
|
|
9d019ca329 | ||
|
|
77a9b20346 | ||
|
|
b88a1f91f7 | ||
|
|
81682914ff | ||
|
|
8ef9e19a64 | ||
|
|
b8698cdcff | ||
|
|
ff4121510c | ||
|
|
7c72ab9dcb | ||
|
|
d156165d59 | ||
|
|
ed2e254cf4 | ||
|
|
98703f192a | ||
|
|
b12a18a693 | ||
|
|
f19e719cbb | ||
|
|
1744c0b44d | ||
|
|
a4f77cbc3d | ||
|
|
7a6c78af6a | ||
|
|
0d9f9e41bb | ||
|
|
16e1829730 | ||
|
|
f73b891272 | ||
|
|
3a017741d2 | ||
|
|
0a111f7c33 | ||
|
|
6f24b8b448 | ||
|
|
94f12d538b | ||
|
|
e057568bbb | ||
|
|
edd81c548c | ||
|
|
c6cf4d06bc | ||
|
|
9a840328aa | ||
|
|
e12c1b7b8d | ||
|
|
7c4496d097 | ||
|
|
9898491ce7 | ||
|
|
cd41d3b5c7 | ||
|
|
ae4ffc72d1 | ||
|
|
c877102f26 | ||
|
|
c150c5242e | ||
|
|
da3fddf6c4 | ||
|
|
0e0c563faf | ||
|
|
d07f59d061 | ||
|
|
c7fede0d15 | ||
|
|
09dc0918c7 | ||
|
|
5a5487894f | ||
|
|
f999aa1faa | ||
|
|
8d0977e36b | ||
|
|
0081c7e47f | ||
|
|
7d8c99bc1b | ||
|
|
351b307074 | ||
|
|
706e6fe288 | ||
|
|
b5fa7604c6 | ||
|
|
61614e12fd | ||
|
|
533efe5a44 | ||
|
|
8873f8d555 | ||
|
|
a90ddacb64 | ||
|
|
df928b49b7 | ||
|
|
e059a7e84d | ||
|
|
1f0cd6ef98 | ||
|
|
757b04957d | ||
|
|
2c9a1656b6 | ||
|
|
b1c6d26a0f | ||
|
|
1d1401c620 | ||
|
|
666fe5bc28 | ||
|
|
9b7db8ad09 | ||
|
|
cc8facbda3 | ||
|
|
bdce75c2ea | ||
|
|
c4ef22f4a3 | ||
|
|
d3e175beb8 | ||
|
|
feec9e9ebf | ||
|
|
67c429a09c | ||
|
|
a36d5f238c | ||
|
|
1cf455cfee | ||
|
|
2f46581ada | ||
|
|
c57eedf020 | ||
|
|
ad5b9c1e80 | ||
|
|
8f8bef9ea2 | ||
|
|
1457876698 | ||
|
|
1d52614691 | ||
|
|
01eb096920 | ||
|
|
5b7c1fb8fe | ||
|
|
7466ef21e5 | ||
|
|
8cc56c7db5 | ||
|
|
d4914d6eca | ||
|
|
9dc78174a9 | ||
|
|
22df94e6a0 | ||
|
|
d78f147889 | ||
|
|
25ae9f4dd2 | ||
|
|
338664452b | ||
|
|
98a257b7e3 | ||
|
|
2f402fe26d | ||
|
|
c5daed4a70 | ||
|
|
46442f4a65 | ||
|
|
2c06ca34c0 | ||
|
|
51e26a00a4 | ||
|
|
54e3e5cb90 | ||
|
|
9ee8c3ca38 | ||
|
|
0193e61d72 | ||
|
|
d4258eea9a | ||
|
|
634e395902 | ||
|
|
8ba6eee597 | ||
|
|
cd576a1e02 | ||
|
|
70d9ef63db | ||
|
|
d69243d720 | ||
|
|
c3480b3c49 | ||
|
|
ff79b2aa0f | ||
|
|
2cbb87baaa | ||
|
|
6a8e35379a | ||
|
|
203e999ec4 | ||
|
|
528d45e58a | ||
|
|
d04ee96111 | ||
|
|
508691535f | ||
|
|
edf38ae8ee | ||
|
|
a2f2b4178a | ||
|
|
b297129a26 | ||
|
|
e3bfa9ccd9 | ||
|
|
132c1b68b1 | ||
|
|
d85b481e68 | ||
|
|
a5b989d278 | ||
|
|
b61c8f0b19 | ||
|
|
5e3df6c742 | ||
|
|
ea9d6d4e4c | ||
|
|
fbd5fcbefd | ||
|
|
9c57f5f877 | ||
|
|
8b08758b85 | ||
|
|
98c5e8d774 | ||
|
|
bca1bcb42d | ||
|
|
55b7003aa9 | ||
|
|
fd8f63161f | ||
|
|
c1800b685f | ||
|
|
0f18854c40 | ||
|
|
d80edb16df | ||
|
|
beb39cc5c7 | ||
|
|
f6155302e8 | ||
|
|
81b773bee6 | ||
|
|
725d779682 | ||
|
|
b903ff7e78 | ||
|
|
517c5b60a8 | ||
|
|
88fd6c719a | ||
|
|
76a6c8c255 | ||
|
|
fb57e864e1 | ||
|
|
4a1a294658 | ||
|
|
6d74d7c9f6 | ||
|
|
5b56ebb5fd | ||
|
|
dd4d42295b | ||
|
|
56c26e35b5 | ||
|
|
2bf7b78d39 | ||
|
|
3a5f8f8a1e | ||
|
|
9e17fbb807 | ||
|
|
440bc3b730 | ||
|
|
863d0826a7 | ||
|
|
e564eff45a | ||
|
|
6cb9ab45d9 | ||
|
|
3706937d4a | ||
|
|
ccce04df1c | ||
|
|
f2e5e56fdb | ||
|
|
c993e2d070 | ||
|
|
fffc2b7a57 | ||
|
|
59eb684b47 | ||
|
|
f0969e09d3 | ||
|
|
108959c84c | ||
|
|
a2bf105ba9 | ||
|
|
ff1b004a2c | ||
|
|
a54144d4e1 | ||
|
|
81f31a4ba8 | ||
|
|
8bf77ff52c | ||
|
|
f16d8455a8 | ||
|
|
aee0fecaed | ||
|
|
4587e49ff6 | ||
|
|
2dc2ef4f0c | ||
|
|
98d0e69173 | ||
|
|
ceddd99dc4 | ||
|
|
833a31ae14 | ||
|
|
1c4a774765 | ||
|
|
6f2fcdcf65 | ||
|
|
3d502b6414 | ||
|
|
d275ed1942 | ||
|
|
5b4e113b71 | ||
|
|
2fc2cea1cc | ||
|
|
bf37b6a132 | ||
|
|
a16f0cb894 | ||
|
|
d06e2aa5e6 | ||
|
|
2a4f2cf396 | ||
|
|
b2005ae82a | ||
|
|
fbf67e1a34 | ||
|
|
63702633a9 | ||
|
|
5df0fa3853 | ||
|
|
2997bccd6c | ||
|
|
ff2868883d | ||
|
|
37ea0f5fb6 | ||
|
|
fd730e32ed | ||
|
|
0c9f05147e | ||
|
|
373ac3ec24 | ||
|
|
e5cf5695ff | ||
|
|
f0f332481a | ||
|
|
ed5cb4776c | ||
|
|
6d83b62153 | ||
|
|
0971012dca | ||
|
|
1afc5191c4 | ||
|
|
947433c57c | ||
|
|
42f69f0a5e | ||
|
|
a0f3b79479 | ||
|
|
0b19de6d94 | ||
|
|
024e5fa210 | ||
|
|
d0d13aa287 | ||
|
|
e606cc9323 | ||
|
|
fa70742a35 | ||
|
|
ebca96d95c | ||
|
|
815ebd038e | ||
|
|
a785f12fb3 | ||
|
|
2824a946f8 | ||
|
|
d82ac9fc1a | ||
|
|
f76793f50b | ||
|
|
bfd4714df9 | ||
|
|
c94c6c49a8 | ||
|
|
70eb2175d1 | ||
|
|
e200dd908d | ||
|
|
ff9ab4b0b6 | ||
|
|
03c9798e71 | ||
|
|
91c015943e | ||
|
|
594b3923c3 | ||
|
|
c352735dc8 | ||
|
|
0598b5cead | ||
|
|
611026d8ea | ||
|
|
11db344a23 | ||
|
|
3a38ad62a6 | ||
|
|
cc0dcaa27b | ||
|
|
15ffc705f4 | ||
|
|
4c6d3008bc | ||
|
|
e2e8acec3b | ||
|
|
91be5e57d0 | ||
|
|
836a3d0957 | ||
|
|
bcf0d4352a | ||
|
|
4998831c1f | ||
|
|
076b70d031 | ||
|
|
f5171528d6 | ||
|
|
e01bf225c4 | ||
|
|
8ec2e5f6b6 | ||
|
|
f807dc228b | ||
|
|
a98d6fb31a | ||
|
|
14fd932829 | ||
|
|
55ba5d2fef | ||
|
|
4f98686595 | ||
|
|
b36c58bd03 | ||
|
|
8080c38936 | ||
|
|
88a2fd63a8 | ||
|
|
f5677e6858 | ||
|
|
9838725a3f | ||
|
|
2ef1205b06 | ||
|
|
92e4ddee93 | ||
|
|
b83e35adf5 | ||
|
|
6725f6c73a | ||
|
|
b4158075e3 | ||
|
|
e59e29bf31 | ||
|
|
bb27385a3a | ||
|
|
070e70d801 | ||
|
|
4a2390f147 | ||
|
|
6845acd8fa | ||
|
|
090a1a0727 | ||
|
|
3b9e48d305 | ||
|
|
26a7b77bf8 | ||
|
|
9a32684dc9 | ||
|
|
f9fa512ff3 | ||
|
|
732143b9bb | ||
|
|
5964d70023 | ||
|
|
f5e0268d0f | ||
|
|
d99efa76b3 | ||
|
|
bf0110c94b | ||
|
|
32363e78f6 | ||
|
|
df7163a78e | ||
|
|
73b8b9d098 | ||
|
|
c430ec317a | ||
|
|
fe57d6adfd | ||
|
|
fb1a243db7 | ||
|
|
5fe92dcc89 | ||
|
|
a70b2b67ac | ||
|
|
59ffff1a6a | ||
|
|
265e42f513 | ||
|
|
adc7f567f9 | ||
|
|
20876243ed | ||
|
|
c7f4429b67 | ||
|
|
920b89cf8f | ||
|
|
f5717d0361 | ||
|
|
deddd00d67 | ||
|
|
3a98ebdbd4 | ||
|
|
a69eeaea15 | ||
|
|
5c034fd6b0 | ||
|
|
7e4bfc4034 | ||
|
|
14f869bf23 | ||
|
|
548961870f | ||
|
|
65838a4a52 | ||
|
|
6afe848210 | ||
|
|
8294264f87 | ||
|
|
ae2fcbb19c | ||
|
|
3147c7fd74 | ||
|
|
6638db45a5 | ||
|
|
fac6671841 | ||
|
|
da89d4611a | ||
|
|
86a84fe1c2 | ||
|
|
faafe15629 | ||
|
|
d75b2ce7d6 | ||
|
|
edb8f51fd0 | ||
|
|
344dd74874 | ||
|
|
71605850c2 | ||
|
|
ce67438ef0 | ||
|
|
ac18cd6902 | ||
|
|
cbf73f24ae | ||
|
|
181b3a985e | ||
|
|
60d8abf816 | ||
|
|
32c0fd50dd | ||
|
|
513003a8bb | ||
|
|
c5c8032975 | ||
|
|
f00d1667b8 | ||
|
|
e96f39c652 | ||
|
|
deccff5d46 | ||
|
|
b60b3ce4ee | ||
|
|
2e2ad1350d | ||
|
|
3fd24d1931 | ||
|
|
e747ac52c2 | ||
|
|
6d034776eb | ||
|
|
a85ae1a46a | ||
|
|
b07de7632f | ||
|
|
6ee60e3f95 | ||
|
|
122dcf0324 | ||
|
|
ba0313c54a | ||
|
|
2a69372caa | ||
|
|
db25af7ae9 | ||
|
|
51779ecf80 | ||
|
|
8118b901d7 | ||
|
|
12772763ef | ||
|
|
4aaa3079de | ||
|
|
f0eca216ad | ||
|
|
9698545b27 | ||
|
|
70b6a410d4 | ||
|
|
9fa293c596 | ||
|
|
197cf21210 | ||
|
|
134534dc09 | ||
|
|
3d2c3b508c | ||
|
|
8bcd9e7f65 | ||
|
|
3d822c525e | ||
|
|
1d11b9a0c0 | ||
|
|
3e17357185 | ||
|
|
e9786b53c9 | ||
|
|
2c5b9909a2 | ||
|
|
b655ea27f9 | ||
|
|
3ba262ac53 | ||
|
|
880e1d5c9f | ||
|
|
2175d2c53d | ||
|
|
5d7bbcc034 | ||
|
|
7085c6c7db | ||
|
|
6fe19ab6ae | ||
|
|
462bc8b5fb | ||
|
|
051b064f21 | ||
|
|
0e8b66b183 | ||
|
|
3c64b12e89 | ||
|
|
444c47f678 | ||
|
|
b5a175b097 | ||
|
|
7477c97b39 | ||
|
|
aadc3acdec | ||
|
|
8f9ecebf41 | ||
|
|
da40de9ad2 | ||
|
|
d02b71fe4f | ||
|
|
4f306ffaab | ||
|
|
69e9b153b8 | ||
|
|
91d2c2f71e | ||
|
|
957a138df8 | ||
|
|
60748b4843 | ||
|
|
152cb4ec01 | ||
|
|
b758edb28e | ||
|
|
2e2d916b6f | ||
|
|
05983fcfb1 | ||
|
|
a332527ad3 | ||
|
|
f383f025f2 | ||
|
|
cf4ecd5ff9 | ||
|
|
b83ad51dd7 | ||
|
|
ba05ef0e57 | ||
|
|
7b6b610a74 | ||
|
|
12ac8b6337 | ||
|
|
c7de76b849 | ||
|
|
b5c1babec9 | ||
|
|
73a8052c08 | ||
|
|
e69d79cdb8 | ||
|
|
cb8f8ddb16 | ||
|
|
d9dde27aa0 | ||
|
|
2b1ea2947d | ||
|
|
065b0d711d | ||
|
|
f4275d9243 | ||
|
|
739e8bb06c | ||
|
|
3434b2ba5e | ||
|
|
2de1d42a30 | ||
|
|
83465f4b10 | ||
|
|
e82cfa6d26 | ||
|
|
607022bc08 | ||
|
|
b67e17d8ff | ||
|
|
e0f314d862 | ||
|
|
ced5b914d2 | ||
|
|
982c4f4d67 | ||
|
|
df3c6be36c | ||
|
|
1a665f3c14 | ||
|
|
7fcdaa523c | ||
|
|
beedef280c | ||
|
|
b841919e01 | ||
|
|
ba77a808df | ||
|
|
e160920e53 | ||
|
|
43e4c76f83 | ||
|
|
07ec0841c9 | ||
|
|
2242f57627 | ||
|
|
ff506730de | ||
|
|
e01a0aed49 | ||
|
|
194c671ec0 | ||
|
|
14371c0e45 | ||
|
|
686163808d | ||
|
|
76d38c1108 | ||
|
|
bbf6549490 | ||
|
|
e2d13aa238 | ||
|
|
1f4b265dbc | ||
|
|
d520f84ba1 | ||
|
|
8ce6c76a7b | ||
|
|
7431457ebe | ||
|
|
c13acf641d | ||
|
|
073994bca7 | ||
|
|
34494b00ff | ||
|
|
3d6c0d2a14 | ||
|
|
3271542a9b | ||
|
|
44e7b643f9 | ||
|
|
b87d9613f5 | ||
|
|
0683c99f00 | ||
|
|
0298d1df76 | ||
|
|
0c4ca3ecb0 | ||
|
|
d5e5088778 | ||
|
|
e7a0bb473a | ||
|
|
d239aa1f1d | ||
|
|
a4623373a7 | ||
|
|
af595f9cf0 | ||
|
|
2ac327acea | ||
|
|
f112a056be | ||
|
|
c05cfada13 | ||
|
|
8f3291e6da | ||
|
|
488332c74d | ||
|
|
6b487a4afd | ||
|
|
6869c9350b | ||
|
|
b7485f1335 | ||
|
|
39badd53b1 | ||
|
|
e8beb157b9 | ||
|
|
0ac3b20736 | ||
|
|
377501efcf | ||
|
|
fd4072155b | ||
|
|
e31ecc6852 | ||
|
|
d78185cb64 | ||
|
|
4260a2eab9 | ||
|
|
c7781be21d | ||
|
|
73edd03aa4 | ||
|
|
6f7a7b7d4c | ||
|
|
110fb33c24 | ||
|
|
57c6ba3624 | ||
|
|
fee7165079 | ||
|
|
1cc5f53324 | ||
|
|
17a95c45cc | ||
|
|
35a3b3e372 | ||
|
|
362f1a5311 | ||
|
|
eb5298a6bd | ||
|
|
c9c8a4ff7a | ||
|
|
07d7a518c6 | ||
|
|
4b7b07cd57 | ||
|
|
4d383d53fe | ||
|
|
c0dd212b41 | ||
|
|
37993f3246 | ||
|
|
13ea198fcd | ||
|
|
7a68c5c6cf | ||
|
|
df75dae39d | ||
|
|
4a39a2f81c | ||
|
|
e253ee0970 | ||
|
|
5599eeb9c9 | ||
|
|
c90d04dbbd | ||
|
|
567256160e | ||
|
|
d0ad41c935 | ||
|
|
cc535b7a0d | ||
|
|
40d75ce42a | ||
|
|
16cbb7a03e | ||
|
|
440e13a07b | ||
|
|
6f8810ec60 | ||
|
|
fad9733802 | ||
|
|
8c9170d365 | ||
|
|
dc79c106e2 | ||
|
|
84c430c819 | ||
|
|
ca45b3ee01 | ||
|
|
be640251c5 | ||
|
|
0535f8b55f | ||
|
|
67dcec4c9a | ||
|
|
5ed1292503 | ||
|
|
9f5b59c4b5 | ||
|
|
dfcf1609ed | ||
|
|
eb6175b2d5 | ||
|
|
74cff901c8 | ||
|
|
04b3125894 | ||
|
|
7e1348cb41 | ||
|
|
1772c1ccfc | ||
|
|
a2737af68f | ||
|
|
ebf7a11ffb | ||
|
|
3af12113b2 | ||
|
|
c044fcd2dd | ||
|
|
a2551e86f4 | ||
|
|
ed926452f0 | ||
|
|
d824a6b7b0 | ||
|
|
4cdc9ed6cd | ||
|
|
93b373d37a | ||
|
|
deee053883 | ||
|
|
38a5da1cd0 | ||
|
|
d4268e1a54 | ||
|
|
ac0158605c | ||
|
|
4b159fe5f4 | ||
|
|
b99fe53c6b | ||
|
|
da0d5d2413 | ||
|
|
cb85f1c78a | ||
|
|
0371765357 | ||
|
|
73ecd371df | ||
|
|
1907de840c | ||
|
|
2c29220645 | ||
|
|
04d7aa9ab4 | ||
|
|
2cffefcf1c | ||
|
|
74d6c237cd | ||
|
|
0cd3555904 | ||
|
|
3eed60996e | ||
|
|
f6865ba6ba | ||
|
|
fc19b81104 | ||
|
|
6b79d7c38d | ||
|
|
9364f2a24a | ||
|
|
427294ec25 | ||
|
|
86bfa374bb | ||
|
|
aac76dcd58 | ||
|
|
5cc87c5b6c | ||
|
|
c09533052d | ||
|
|
e716a31880 | ||
|
|
7c3b0b9b8d | ||
|
|
44c65a6812 | ||
|
|
bea9b5d04d | ||
|
|
3de30b45ed | ||
|
|
ca9579fa6d | ||
|
|
2c9b228eb5 | ||
|
|
a2b6bb37bf | ||
|
|
6943ccb7db | ||
|
|
3b563252ff | ||
|
|
f4e0aa8575 | ||
|
|
34808cae7a | ||
|
|
d9b7661946 | ||
|
|
f0369ecf18 | ||
|
|
5a2fb90420 | ||
|
|
6bf4a9943c | ||
|
|
b9e0a9e126 | ||
|
|
8ec0eb5166 | ||
|
|
f001b518f9 | ||
|
|
4c7c91a2d5 | ||
|
|
ad785fb3e3 | ||
|
|
8516dbbcaf | ||
|
|
4902101cbe | ||
|
|
9b47c8f57c | ||
|
|
1dbba19cac | ||
|
|
a9c9199bf4 | ||
|
|
a84433520d | ||
|
|
9aa34bff89 | ||
|
|
e4b177f5f7 | ||
|
|
a9946732a2 | ||
|
|
90f4c85034 | ||
|
|
72a6b2148f | ||
|
|
ec393100d0 | ||
|
|
f521e3fbc9 | ||
|
|
98a3e9abb2 | ||
|
|
d83da1fa08 | ||
|
|
c082403868 | ||
|
|
b708e70f8f | ||
|
|
2f0465a1a1 | ||
|
|
3932a8fbf3 | ||
|
|
1f4f5a9a2c | ||
|
|
3ffe0d89d8 | ||
|
|
d3fee1bf3e | ||
|
|
d1009704d8 | ||
|
|
4d00bb9d21 | ||
|
|
1dff8eb945 | ||
|
|
f947b3fa60 | ||
|
|
8eef4717cc | ||
|
|
1de437dc5a | ||
|
|
747ffc43d9 | ||
|
|
8f1885f56e | ||
|
|
eeac49157f | ||
|
|
ffc19c7fbf | ||
|
|
e03f0cc4b0 | ||
|
|
70044a88a0 | ||
|
|
4a279ffa29 | ||
|
|
979c9c193f | ||
|
|
f603ebb09f | ||
|
|
7d93bc7256 | ||
|
|
89fa2c1061 | ||
|
|
aba0eeea80 | ||
|
|
5a0aa6422f | ||
|
|
b59f068c7d | ||
|
|
ad6311d244 | ||
|
|
645d6799b2 | ||
|
|
758c1f8306 | ||
|
|
905297907a | ||
|
|
6fb241af4b | ||
|
|
0cf29d7488 | ||
|
|
615aa3ad23 | ||
|
|
c756d26592 | ||
|
|
0f45d3830a | ||
|
|
c37ea861eb | ||
|
|
aaa53d9a35 | ||
|
|
3d59181d2a | ||
|
|
ef11b6caa7 | ||
|
|
563a1fc1a4 | ||
|
|
5625444fbc | ||
|
|
169205f132 | ||
|
|
447d824da6 | ||
|
|
c3ad90dde5 | ||
|
|
f218695bef | ||
|
|
9b758084bf | ||
|
|
8159aa1a88 | ||
|
|
18cf39529e | ||
|
|
a54e7a5654 | ||
|
|
4392f0ffac | ||
|
|
732cd54578 | ||
|
|
0de1fe1132 | ||
|
|
3e85645e44 | ||
|
|
39fdc43ada | ||
|
|
acda4470bc | ||
|
|
0fb3d16c49 | ||
|
|
228882d8c4 | ||
|
|
186aa89476 | ||
|
|
f9296d90d4 | ||
|
|
258c2afa32 | ||
|
|
105adfe7e9 | ||
|
|
d2104fade2 | ||
|
|
739eed6a01 | ||
|
|
bffe222e1b | ||
|
|
ceb5b9e4d6 | ||
|
|
e49bd514f7 | ||
|
|
39fb8b7c5d | ||
|
|
2b0a565120 | ||
|
|
2399c97c51 | ||
|
|
eb1911232b | ||
|
|
0fe70c5e1c | ||
|
|
483da629e9 | ||
|
|
129f4e6281 | ||
|
|
683355d773 | ||
|
|
cb28f6f438 | ||
|
|
c9f2301335 | ||
|
|
751a10d91e | ||
|
|
7c821bf673 | ||
|
|
be2b584cee | ||
|
|
f39048fad0 | ||
|
|
4e9ce0de7e | ||
|
|
6e78abb34e | ||
|
|
ae5ec006ba | ||
|
|
c9d1e424e9 | ||
|
|
f48f39e024 | ||
|
|
3dde9cfdc6 | ||
|
|
85d6e954ae | ||
|
|
146b0b2925 | ||
|
|
4faa807c53 | ||
|
|
ea998db824 | ||
|
|
7334ad9f33 | ||
|
|
f32d725773 | ||
|
|
fb9bec8623 | ||
|
|
b7847e6198 | ||
|
|
4307abf274 | ||
|
|
8206e5cbad | ||
|
|
73cc49448e | ||
|
|
a2f4d58648 | ||
|
|
5b290ef0b1 | ||
|
|
b9a9c5d917 | ||
|
|
3112f0afe8 | ||
|
|
0a3696ee01 | ||
|
|
03431dee58 | ||
|
|
8f33b3de5e | ||
|
|
9e0f95ec48 | ||
|
|
7668e7fdde | ||
|
|
0df2b3ea1c | ||
|
|
4f726f1eb8 | ||
|
|
752e9f917e | ||
|
|
a4493021e2 | ||
|
|
13d823ec57 | ||
|
|
a6736e6e30 | ||
|
|
9b26947849 | ||
|
|
0af29cfcae | ||
|
|
c63904aedf | ||
|
|
076538a6b6 | ||
|
|
8deefff08a | ||
|
|
1cae92b119 | ||
|
|
b5dbde8ad1 | ||
|
|
45d552ac8c | ||
|
|
bdce16a582 | ||
|
|
7bf3294113 | ||
|
|
26dbd1446c | ||
|
|
74796f3546 | ||
|
|
48bb3b6452 | ||
|
|
c4ec7f562a | ||
|
|
733874316a | ||
|
|
b5efcd251a | ||
|
|
b74ea58172 | ||
|
|
707dbac2ca | ||
|
|
184b1a903f | ||
|
|
4a995a1c56 | ||
|
|
e6768d5e17 | ||
|
|
e3057c4bd9 | ||
|
|
87f101a7bf | ||
|
|
ab435d131c | ||
|
|
674ae4c4a0 | ||
|
|
f3a84e2ca8 | ||
|
|
835dd15c47 | ||
|
|
c983370162 | ||
|
|
00b5024f20 | ||
|
|
ae0af55d17 | ||
|
|
f19b398c93 | ||
|
|
8743b63869 | ||
|
|
4af1627116 | ||
|
|
5d4c4d53fc | ||
|
|
62bc8092e2 | ||
|
|
4cea6f9f5d | ||
|
|
decee13bf1 | ||
|
|
60bfe48307 | ||
|
|
bca54282c9 | ||
|
|
db933cecb6 | ||
|
|
3f06c8ba7d | ||
|
|
f7fb34ec16 | ||
|
|
b691d53523 | ||
|
|
5396aa40cb | ||
|
|
1a43b89674 | ||
|
|
fb570acf7c | ||
|
|
8c5d0ad64b | ||
|
|
74a92b08d8 | ||
|
|
3e6a3d97bb | ||
|
|
b3e4666108 | ||
|
|
a344f2bdb7 | ||
|
|
4b6eb80ddb | ||
|
|
5226a2a26f | ||
|
|
e8bb532cdc | ||
|
|
171be652eb | ||
|
|
c410125c8f | ||
|
|
0f6613c4a1 | ||
|
|
d278344dd4 | ||
|
|
c47b3eee2c | ||
|
|
162b8df569 | ||
|
|
55e2109091 | ||
|
|
11efbe7699 | ||
|
|
329d094e2a | ||
|
|
414766001b | ||
|
|
e05e16dce4 | ||
|
|
3549f4cf1f | ||
|
|
bedbd3c872 | ||
|
|
296110f969 | ||
|
|
f60b0f1750 | ||
|
|
6ad13c5930 | ||
|
|
6a1b53e3d4 | ||
|
|
21ef7bdcc0 | ||
|
|
718574cdf3 | ||
|
|
18571ca224 | ||
|
|
41c164a8ef | ||
|
|
f82acdb478 | ||
|
|
40b56b6bf5 | ||
|
|
f259d69910 | ||
|
|
3952d5ec14 | ||
|
|
c1745f6f40 | ||
|
|
0940a70d86 | ||
|
|
7abe6987a5 | ||
|
|
7baa2c84a3 | ||
|
|
6867eb2c05 | ||
|
|
3d01706fb6 | ||
|
|
7707d4c99d | ||
|
|
b66d7a4e7a | ||
|
|
8a67795faf | ||
|
|
64299e6912 | ||
|
|
fdd522e56a | ||
|
|
1c257fa830 | ||
|
|
3d9fbbac63 | ||
|
|
f83332b2c8 | ||
|
|
b8d187bb35 | ||
|
|
9567564bf4 | ||
|
|
d05bf07db8 | ||
|
|
5adb89694b | ||
|
|
e21146d048 | ||
|
|
4c7f04536d | ||
|
|
71d0883c3d | ||
|
|
ee9022f9e3 | ||
|
|
cc0a894162 | ||
|
|
d27f2ec966 | ||
|
|
83b7927c4b | ||
|
|
e1975682a9 | ||
|
|
f914f96b9a | ||
|
|
35a21d4e24 | ||
|
|
3e58190112 | ||
|
|
39150b2b2b | ||
|
|
f2b287f933 | ||
|
|
e458e583ee | ||
|
|
74c1fd5b7d | ||
|
|
2547ba88ae | ||
|
|
5c78ecc2d3 | ||
|
|
9c934917d0 | ||
|
|
1132723355 | ||
|
|
26261001f5 | ||
|
|
2e3a1582ab | ||
|
|
5d1bcb3575 | ||
|
|
6c7d49b323 | ||
|
|
843a585b7f | ||
|
|
8df6fa6a33 | ||
|
|
9ccb5439df | ||
|
|
928d816c68 | ||
|
|
27df9862ea | ||
|
|
d428ed6876 | ||
|
|
72fd7beec0 | ||
|
|
7613b85271 | ||
|
|
23eac98551 | ||
|
|
8bd245b1f1 | ||
|
|
b13bbfced1 | ||
|
|
645c788512 | ||
|
|
9f6c8f5e22 | ||
|
|
9a4667fa46 | ||
|
|
338d81e101 | ||
|
|
336d7473f7 | ||
|
|
265cd4d885 | ||
|
|
cab8de721f | ||
|
|
4030cd325c | ||
|
|
d796a39aa7 | ||
|
|
04d8303f28 | ||
|
|
5eec28a964 | ||
|
|
a5e5c588ba | ||
|
|
34e6ccc6e2 | ||
|
|
6a028e13cb | ||
|
|
176e9d09b6 | ||
|
|
7ddcf97efd | ||
|
|
e19bda949b | ||
|
|
b09d142091 | ||
|
|
e102f820c1 | ||
|
|
36627e4ca5 | ||
|
|
9c6e6ca1b2 | ||
|
|
f32fdbf543 | ||
|
|
7342788339 | ||
|
|
15d6ff0144 | ||
|
|
9718b16e39 | ||
|
|
e80842207f | ||
|
|
58585afdf6 | ||
|
|
a3eee91cef | ||
|
|
9098eaf22e | ||
|
|
2d3b039f71 | ||
|
|
864c468440 | ||
|
|
cc295fad32 | ||
|
|
b4e0dc800d | ||
|
|
5e7078e3a6 | ||
|
|
2829d7b653 | ||
|
|
ba834592a7 | ||
|
|
1607e6a0a9 | ||
|
|
f936029d59 | ||
|
|
9f1552f508 | ||
|
|
c00d465709 | ||
|
|
c2a55931bb | ||
|
|
e957e5ebc9 | ||
|
|
1357e22330 | ||
|
|
8a282cd743 | ||
|
|
6ca7f62ce6 | ||
|
|
6ee7ad8069 | ||
|
|
307b1bf496 | ||
|
|
61f50980e1 | ||
|
|
5293222ac0 | ||
|
|
411a21d0f7 | ||
|
|
8a5d788e73 | ||
|
|
3e48fa55c7 | ||
|
|
cd735e727e | ||
|
|
1eb69c696a | ||
|
|
8208ccf5a3 | ||
|
|
1591944756 | ||
|
|
8e87ae55a9 | ||
|
|
85fce8f01e | ||
|
|
7475bc56c9 | ||
|
|
7af2dffb7a | ||
|
|
15f2d149df | ||
|
|
c09924dbdc | ||
|
|
1ddd6dac4f | ||
|
|
b45afe9669 | ||
|
|
1e85e03713 | ||
|
|
43eef673bc | ||
|
|
41ce276dbd | ||
|
|
d6e078f3d6 | ||
|
|
a487266f5b | ||
|
|
0286d56e9c | ||
|
|
4c2f43b4cf | ||
|
|
9bbcb62505 | ||
|
|
5bb840c1ce | ||
|
|
8f221b6b0b | ||
|
|
ac4398873b | ||
|
|
2fad9035d3 | ||
|
|
ef03c95f40 | ||
|
|
eb7a6411d1 | ||
|
|
e02e70ff26 | ||
|
|
b6843e04d5 | ||
|
|
5e4c82b94a | ||
|
|
1f411ec6e0 | ||
|
|
a890bd2d38 | ||
|
|
7a47f59945 | ||
|
|
830c2cf29b | ||
|
|
86593943d3 | ||
|
|
7c188fa7ce | ||
|
|
a9432b5d9c | ||
|
|
0bebb7f65b | ||
|
|
6536caed75 | ||
|
|
4863b2c5be | ||
|
|
86afc0ddf4 | ||
|
|
bf6f469dad | ||
|
|
68677e1b5b | ||
|
|
f4709f00ab | ||
|
|
8392398b1c | ||
|
|
b4355b4399 | ||
|
|
b12bbc74ff | ||
|
|
d3dbca0e00 | ||
|
|
81e0e4dde7 | ||
|
|
fba9ab0ae6 | ||
|
|
e18518b4d3 | ||
|
|
074a7145d2 | ||
|
|
46372f0e6c | ||
|
|
1acd2e3238 | ||
|
|
a2e7827aa8 | ||
|
|
ac71aafe83 | ||
|
|
0b1cc913d9 | ||
|
|
84b967ae82 | ||
|
|
cf9002a377 | ||
|
|
829fa4dac5 | ||
|
|
5529d5f46d | ||
|
|
08e9c6b38a | ||
|
|
5c94c73004 | ||
|
|
8ebb1fda77 | ||
|
|
96380bd031 | ||
|
|
c342e63e63 | ||
|
|
4fa43c232d | ||
|
|
d07cbc8783 | ||
|
|
f7667ad3e1 | ||
|
|
5fe66b7abc | ||
|
|
856c09c38d | ||
|
|
b947f043ee | ||
|
|
ebd515f057 | ||
|
|
636faaf93b | ||
|
|
ed1c6c7a47 | ||
|
|
e4340641ad | ||
|
|
35738cfda8 | ||
|
|
e749adaa10 | ||
|
|
26a1a89d60 | ||
|
|
2daa65f00d | ||
|
|
d2579d390c | ||
|
|
261e34a5c2 | ||
|
|
b4bad21e35 | ||
|
|
699f53e8b2 | ||
|
|
820c9f733f | ||
|
|
99bd217080 | ||
|
|
c86c05f380 | ||
|
|
544901bf45 | ||
|
|
8db0e2fb06 | ||
|
|
c5ed47192e | ||
|
|
3d56cb7eb2 | ||
|
|
ada8818960 | ||
|
|
2f97f4b979 | ||
|
|
0a4e81138a | ||
|
|
c61350643a | ||
|
|
9f59275652 | ||
|
|
1da644b96a | ||
|
|
1de825ee43 | ||
|
|
2e18f3f5e1 | ||
|
|
653f73b989 | ||
|
|
9c5b9729d8 | ||
|
|
6950e493f2 | ||
|
|
286f0b74da | ||
|
|
a1191abc43 | ||
|
|
75799b81e8 | ||
|
|
511a187f49 | ||
|
|
01ecfcdf8d | ||
|
|
14a55fcb83 | ||
|
|
49c146b3dc | ||
|
|
e2c5988bea | ||
|
|
4828dc3dae | ||
|
|
8413f0e8d3 | ||
|
|
3d2e9ef063 | ||
|
|
28c7d178c4 | ||
|
|
5bfc5563b3 | ||
|
|
d6bc0572c2 | ||
|
|
32abd69c16 | ||
|
|
024f461e94 | ||
|
|
a25823f5b5 | ||
|
|
4d4d8e4955 | ||
|
|
7488db81c1 | ||
|
|
e8c6d388f2 | ||
|
|
02f155f497 | ||
|
|
c570c095b9 | ||
|
|
10d8d7f28a | ||
|
|
0e1a820c3a | ||
|
|
bf21fec50e | ||
|
|
4e514dc83e | ||
|
|
3f52783b30 | ||
|
|
16bab848e1 | ||
|
|
986406a880 | ||
|
|
2946c8ce34 | ||
|
|
fef12cb747 | ||
|
|
b710f6a5df | ||
|
|
840723c592 | ||
|
|
6f63290e74 | ||
|
|
4d8d4b77c1 | ||
|
|
10b009bb7e | ||
|
|
7cb172d60a | ||
|
|
8350dfe2c9 | ||
|
|
970b2d21a9 | ||
|
|
e9c5ac6ec0 | ||
|
|
f7804b627e | ||
|
|
247487529b | ||
|
|
5ef5af4723 | ||
|
|
2188f79e77 | ||
|
|
a7bb4a7ac4 | ||
|
|
06c67c1024 | ||
|
|
03024f192a | ||
|
|
b1baccf0a5 | ||
|
|
ad047f4c06 | ||
|
|
dc1cc2ec10 | ||
|
|
6f589d7af9 | ||
|
|
eeaaa40259 | ||
|
|
e394a3afdf | ||
|
|
45cc0aec93 | ||
|
|
0bd80ad900 | ||
|
|
1214241dab | ||
|
|
28dbad6c1f | ||
|
|
84e35753cf | ||
|
|
6a03008ac9 | ||
|
|
cc215d6ad0 | ||
|
|
e28217e5ec | ||
|
|
cebb9b3002 | ||
|
|
0d8edbbb64 | ||
|
|
4abcbeb420 | ||
|
|
77aea09d5f | ||
|
|
2baf392129 | ||
|
|
c56e0416f2 | ||
|
|
d478246edc | ||
|
|
ea375a026d | ||
|
|
9101d5bdb8 | ||
|
|
811df12524 | ||
|
|
3ee469aef3 | ||
|
|
7b503337b1 | ||
|
|
dd65a4a716 | ||
|
|
45f2bd4a15 | ||
|
|
1848ceb8f7 | ||
|
|
938c598cfb | ||
|
|
bea9ede941 | ||
|
|
6c4b217b1b | ||
|
|
f1de3e6b84 | ||
|
|
6cc9a420bf | ||
|
|
5b1eb546fd | ||
|
|
3c9d81756b | ||
|
|
51b6c1086e | ||
|
|
63012b31ac | ||
|
|
9865d53ea7 | ||
|
|
f5c6f95b27 | ||
|
|
b7fd730c5e | ||
|
|
3df918ef00 | ||
|
|
a200c2ebe0 | ||
|
|
a471bae727 | ||
|
|
9f73219c85 | ||
|
|
5a474585b5 | ||
|
|
213d1a700f | ||
|
|
c48048bd32 | ||
|
|
8fd8296c69 | ||
|
|
e18f0cae1a | ||
|
|
973da4df7e | ||
|
|
130910308d | ||
|
|
b9f7783878 | ||
|
|
56cc369a77 | ||
|
|
8aee3b27af | ||
|
|
63edd741ba | ||
|
|
d7007eec59 | ||
|
|
277a732df0 | ||
|
|
a4b15b4731 | ||
|
|
07c6bbd7e1 | ||
|
|
ad504a17e0 | ||
|
|
d16ca6967f | ||
|
|
785fde0eaf | ||
|
|
af761f7472 | ||
|
|
5235511041 | ||
|
|
272f6c7b39 | ||
|
|
22bc9f43bd | ||
|
|
c2747590e0 | ||
|
|
794f8a631c | ||
|
|
04c0071b83 | ||
|
|
e5de639757 | ||
|
|
553980cf73 | ||
|
|
ff7390f1e6 | ||
|
|
4927f414f7 | ||
|
|
329d3fc622 | ||
|
|
1b6d80dfe9 | ||
|
|
dd45558e6a | ||
|
|
dc273edf3c | ||
|
|
621069eee7 | ||
|
|
a385d41cc3 | ||
|
|
9e6414fcb1 | ||
|
|
f6a3c65129 | ||
|
|
d930a9e95a | ||
|
|
3dea48b54e | ||
|
|
f1c00c6b20 | ||
|
|
099ff42404 | ||
|
|
f8e1832172 | ||
|
|
9e19684d40 | ||
|
|
56c226919e | ||
|
|
c6d6180c3c | ||
|
|
9265397f29 | ||
|
|
7aea8d71aa | ||
|
|
40f8ab6101 | ||
|
|
d7f490a0e8 | ||
|
|
01a5b859a9 | ||
|
|
bafe18f6e1 | ||
|
|
cd310eac17 | ||
|
|
cbdf1cd92e | ||
|
|
759dd34c76 | ||
|
|
3fbb2ab0ca | ||
|
|
ad107aadf1 | ||
|
|
e6e0f1d5db | ||
|
|
d3dfdace9f | ||
|
|
88abbc26d1 | ||
|
|
095b2ff27e | ||
|
|
28f03c3d7e | ||
|
|
3db0cedf7e | ||
|
|
11fdd96352 | ||
|
|
b6dfb393a1 | ||
|
|
268af2e84e | ||
|
|
225ef0fc8d | ||
|
|
d382d15f78 | ||
|
|
0833c09e98 | ||
|
|
3e62007e6a | ||
|
|
d5550bf99c | ||
|
|
1bdf0cb2ea | ||
|
|
e3ccccd1f3 | ||
|
|
ecfc8cd1e7 | ||
|
|
ba0bcefec4 | ||
|
|
93d1fdae31 | ||
|
|
35d0ab10a9 | ||
|
|
d9db6c1b36 | ||
|
|
096fa511f4 | ||
|
|
df69c96bd3 | ||
|
|
9b40ea5913 | ||
|
|
c9b484bec2 | ||
|
|
c6700a72bc | ||
|
|
630300cf37 | ||
|
|
fd0f741a01 | ||
|
|
6631aa35db | ||
|
|
e9ef8f7882 | ||
|
|
be9c85ae42 | ||
|
|
a8b01b6314 | ||
|
|
513259f65f | ||
|
|
11cde72962 | ||
|
|
fb6dfcbd72 | ||
|
|
734ff79890 | ||
|
|
2fdb014717 | ||
|
|
377777e2c1 | ||
|
|
e810a08c0e | ||
|
|
14ea27749c | ||
|
|
012f2569b1 | ||
|
|
01c4206443 | ||
|
|
a46859987e | ||
|
|
34bc072efd | ||
|
|
d7813c3507 | ||
|
|
0403ec3ffe | ||
|
|
f8cb44b51d | ||
|
|
b31a8d34d6 | ||
|
|
2c5a19fe8f | ||
|
|
67ec569fc1 | ||
|
|
ccdb695c06 | ||
|
|
db0bddf1d4 | ||
|
|
c1dc629daf | ||
|
|
dd789b3991 | ||
|
|
be8bac1ea1 | ||
|
|
602a64b879 | ||
|
|
3a8ea28ea2 | ||
|
|
39e7b641ea | ||
|
|
a104453aae | ||
|
|
59af022125 | ||
|
|
e92df293d5 | ||
|
|
4805879702 | ||
|
|
f90d4745c1 | ||
|
|
f53f8ddc65 | ||
|
|
6ec20fce3a | ||
|
|
88e7b46f32 | ||
|
|
f707f70f80 | ||
|
|
16722ccd31 | ||
|
|
7e1cfc6f09 | ||
|
|
d6fe1339b2 | ||
|
|
aab91dec6c | ||
|
|
40e2344629 | ||
|
|
8fb0df69b9 | ||
|
|
8a45a686a0 | ||
|
|
d4101f7f34 | ||
|
|
cf73dbd0d9 | ||
|
|
6c9f8b5eba | ||
|
|
5a9247509a | ||
|
|
98d5cab1d5 | ||
|
|
87ee4436ea | ||
|
|
2bbb51c41e | ||
|
|
7fca9c7ce0 | ||
|
|
aee6748c49 | ||
|
|
ee9b19bb0b | ||
|
|
f69b40a532 | ||
|
|
48e6ac39e2 | ||
|
|
363ff3ba70 |
-119
@@ -1,119 +0,0 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.pnp.*
|
||||
|
||||
**/node_modules
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
*.sql linguist-language=GO
|
||||
*.sql linguist-language=GO
|
||||
*.html linguist-language=GO
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
open_collective: gin-vue-admin
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: http://doc.henrongyi.top/more/coffee.html#%E6%8D%90%E8%B5%A0
|
||||
custom: https://www.gin-vue-admin.com/docs/coffee
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
name: 🐛 Bug report
|
||||
description: Report a bug to help us improve Gin-Vue-Admin
|
||||
title: "[Bug]: "
|
||||
labels: [bug]
|
||||
assignees:
|
||||
- pixelmaxQm
|
||||
- songzhibin97
|
||||
- SliverHorn
|
||||
- bypanghu
|
||||
body:
|
||||
- type: input
|
||||
id: gva
|
||||
attributes:
|
||||
label: gin-vue-admin 版本
|
||||
description: 请输入您当前使用的项目版本?
|
||||
placeholder: 2.4.5Beta
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: node
|
||||
attributes:
|
||||
label: Node 版本
|
||||
description: 请输入您当前使用的NODE版本?
|
||||
placeholder: v14.16.0
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: golang
|
||||
attributes:
|
||||
label: Golang 版本
|
||||
description: 请输入您当前使用的GOLANG版本?
|
||||
placeholder: go 1.16
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: reappearance
|
||||
attributes:
|
||||
label: 是否依旧存在
|
||||
description: 是否可以在master分支复现此bug?
|
||||
options:
|
||||
- 可以
|
||||
- 不可以
|
||||
- 未测试
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: bug描述
|
||||
description: 请简要描述bug以及复现过程.
|
||||
placeholder: |
|
||||
1. 首先...
|
||||
2. 然后...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: advise
|
||||
attributes:
|
||||
label: 修改建议
|
||||
description: 您有好的建议或者修改方案可以提供给我们。
|
||||
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Document
|
||||
url: https://www.gin-vue-admin.com
|
||||
about: If you have any questions about the use, you can check our official documents first
|
||||
@@ -0,0 +1,22 @@
|
||||
name: 🚀 Feature request
|
||||
description: Suggest an idea for Gin-Vue-Admin
|
||||
title: "[Feature]: "
|
||||
labels: [feature]
|
||||
assignees:
|
||||
- pixelmaxQm
|
||||
body:
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: 功能描述以及必要性描述
|
||||
description: 您觉得此新功能会为框架带来什么便利.
|
||||
placeholder: |
|
||||
1. 首先...
|
||||
2. 然后...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: advise
|
||||
attributes:
|
||||
label: 建议和方案
|
||||
description: 您有好的建议或者修改方案可以提供给我们。
|
||||
@@ -1,66 +0,0 @@
|
||||
name: gin-vue-admin build test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- './db/**'
|
||||
- '**.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- './db/**'
|
||||
- '**.md'
|
||||
|
||||
jobs:
|
||||
frontend:
|
||||
name: Frontend build
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Build test
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
working-directory: ./web
|
||||
|
||||
backend:
|
||||
name: Backend build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
working-directory: ./server
|
||||
|
||||
- name: Test and Build
|
||||
run: |
|
||||
go build -v -race
|
||||
working-directory: ./server
|
||||
@@ -0,0 +1,269 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
release:
|
||||
types: [ created, edited ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
gva_version:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
init:
|
||||
if: github.repository_owner == 'flipped-aurora'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: init
|
||||
run: |
|
||||
echo "flipped-aurora"
|
||||
frontend:
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'release'
|
||||
name: Frontend node ${{ matrix.node-version }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.16.0]
|
||||
steps:
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Build test
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
working-directory: ./web
|
||||
|
||||
backend:
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'release'
|
||||
name: Backend go
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.22]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
id: go
|
||||
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
working-directory: ./server
|
||||
|
||||
- name: Test and Build
|
||||
run: |
|
||||
go build -v -race
|
||||
working-directory: ./server
|
||||
|
||||
devops-test:
|
||||
if: github.ref == 'refs/heads/test'
|
||||
name: devops-test
|
||||
needs:
|
||||
- init
|
||||
- backend
|
||||
- frontend
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.16.0]
|
||||
go-version: [1.22]
|
||||
steps:
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
- name: Sed Config
|
||||
env:
|
||||
PROD: ${{ secrets.PROD }}
|
||||
TESTING: ${{ secrets.TESTING }}
|
||||
shell: bash
|
||||
run: |
|
||||
git branch
|
||||
ls -l
|
||||
sed -i "s/${PROD}/${TESTING}/g" web/.env.production
|
||||
sed -i 's/${basePath}:${basePort}/${basePath}/g' web/src/view/systemTools/formCreate/index.vue
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Build-Node
|
||||
run: |
|
||||
cd web/ && yarn install && yarn run build
|
||||
- name: Use Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Build-go
|
||||
run: |
|
||||
cd server/ && go mod tidy && CGO_ENABLED=0 go build && mkdir ../web/ser && mv server ../web/ser/ && cd ../web/ser/ && ls -s
|
||||
- name: restart
|
||||
env:
|
||||
KEY: ${{ secrets.KEY }}
|
||||
HOST: ${{ secrets.HOST }}
|
||||
USER: ${{ secrets.USER }}
|
||||
PROT: ${{ secrets.PROT }}
|
||||
MKDIRTEST: ${{ secrets.MKDIRTEST }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh/ && echo "$KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r web/dist/* ${USER}@${HOST}:${MKDIRTEST}dist/
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r web/ser/* ${USER}@${HOST}:${MKDIRTEST}
|
||||
ssh -p ${PROT} -o StrictHostKeyChecking=no ${USER}@${HOST} "cd ${MKDIRTEST}resource/ && rm -rf ${MKDIRTEST}resource/*"
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r server/resource/* ${USER}@${HOST}:${MKDIRTEST}resource/
|
||||
ssh -p ${PROT} -o StrictHostKeyChecking=no ${USER}@${HOST} "cd ${MKDIRTEST} && bash restart.sh > /dev/null 2>&1 &"
|
||||
|
||||
release-pr:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository_owner == 'flipped-aurora'}}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
- name: Sed Config
|
||||
env:
|
||||
GVA_VERSION: ${{ inputs.gva_version }}
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/当前版本.*`$/当前版本:v'${GVA_VERSION##v}'`/' web/src/core/config.js
|
||||
sed -i 's/当前版本.*$/当前版本:v'${GVA_VERSION##v}'/' server/core/server.go
|
||||
sed -i 's/当前版本.*$/当前版本:v'${GVA_VERSION##v}'/' web/src/core/gin-vue-admin.js
|
||||
sed -i 's/"version": ".*",$/"version": "'${GVA_VERSION##v}'",/' web/package.json
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git add . && git commit -m "release: v${GVA_VERSION##v}"
|
||||
- name: Push
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ github.ref }}
|
||||
- uses: google-github-actions/release-please-action@v3
|
||||
with:
|
||||
command: release-pr
|
||||
release-type: simple
|
||||
changelog-path: docs/CHANGELOG.md
|
||||
release-as: ${{ inputs.gva_version }}
|
||||
package-name: gin-vue-admin
|
||||
changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]'
|
||||
|
||||
release-please:
|
||||
if: github.ref == 'refs/heads/main' || github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- init
|
||||
- backend
|
||||
- frontend
|
||||
outputs:
|
||||
release_created: ${{ steps.release_please.outputs.release_created }}
|
||||
tag_name: ${{ steps.release_please.outputs.tag_name }}
|
||||
steps:
|
||||
- uses: google-github-actions/release-please-action@v3
|
||||
id: release_please
|
||||
with:
|
||||
#token: ${{ secrets.GAV_TOKEN }}
|
||||
command: github-release
|
||||
#signoff: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
|
||||
release-type: simple
|
||||
changelog-path: docs/CHANGELOG.md
|
||||
#release-as: ${{ inputs.deploy_target }}
|
||||
package-name: gin-vue-admin
|
||||
#extra-files: |
|
||||
# x-release-please-version.json
|
||||
changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]'
|
||||
|
||||
devops-prod:
|
||||
if: needs.release-please.outputs.release_created || github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- init
|
||||
- release-please
|
||||
name: devops-prod
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ['18.x']
|
||||
go-version: ['1.22']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: tag major and minor versions
|
||||
run: |
|
||||
echo " ${{ needs.release-please.outputs.tag_name }}"
|
||||
- name: Sed Config
|
||||
shell: bash
|
||||
run: |
|
||||
git branch
|
||||
ls -l
|
||||
sed -i 's/${basePath}:${basePort}/${basePath}/g' web/src/view/systemTools/formCreate/index.vue
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Build-Node
|
||||
run: |
|
||||
cd web/ && yarn install && yarn run build
|
||||
- name: Use Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Build-go
|
||||
run: |
|
||||
cd server/ && go mod tidy && CGO_ENABLED=0 go build && mkdir ../web/ser && mv server ../web/ser/ && cd ../web/ser/ && ls -s
|
||||
- name: restart
|
||||
env:
|
||||
KEY: ${{ secrets.KEY }}
|
||||
HOST: ${{ secrets.HOST }}
|
||||
USER: ${{ secrets.USER }}
|
||||
PROT: ${{ secrets.PROT }}
|
||||
MKDIR: ${{ secrets.MKDIR }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh/ && echo "$KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r web/dist/* ${USER}@${HOST}:${MKDIR}dist/
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r web/ser/* ${USER}@${HOST}:${MKDIR}
|
||||
ssh -p ${PROT} -o StrictHostKeyChecking=no ${USER}@${HOST} "cd ${MKDIR}resource/ && rm -rf ${MKDIR}resource/*"
|
||||
scp -P ${PROT} -o StrictHostKeyChecking=no -r server/resource/* ${USER}@${HOST}:${MKDIR}resource/
|
||||
ssh -p ${PROT} -o StrictHostKeyChecking=no ${USER}@${HOST} "cd ${MKDIR} && bash restart.sh > /dev/null 2>&1 &"
|
||||
|
||||
docker:
|
||||
name: docker
|
||||
if: github.ref == 'refs/heads/stop-stop-stop'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- init
|
||||
- release-please
|
||||
steps:
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
- name: Login to Aliyun Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ${{ secrets.ALIYUN_REGISTRY }}
|
||||
username: ${{ secrets.ALIYUN_DOCKERHUB_USER }}
|
||||
password: ${{ secrets.ALIYUN_DOCKERHUB_PASSWORD }}
|
||||
- name: Sed Config
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 56c"\ && yarn install && yarn build" Makefile
|
||||
make image TAGS_OPT="latest"
|
||||
sed -i 's#./entrypoint.sh"#./entrypoint.sh","actions"#g' deploy/docker/Dockerfile
|
||||
sed -i "s#COPY build/ /usr/share/nginx/html/#COPY . /opt/gva#g" deploy/docker/Dockerfile
|
||||
sed -i 16c"\ && cd /opt/gva/server/ && go mod tidy && cd /opt/gva/web/ && yarn" deploy/docker/Dockerfile
|
||||
sed -i "s#open: true#open: false#g" web/vite.config.js
|
||||
make images TAGS_OPT="latest"
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/gva/gin-vue-admin:latest
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/gva/web:latest
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/gva/server:latest
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/gva/all:latest
|
||||
+15
-2
@@ -1,4 +1,3 @@
|
||||
.idea/
|
||||
/web/node_modules
|
||||
/web/dist
|
||||
|
||||
@@ -22,8 +21,22 @@ yarn-error.log*
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
go.sum
|
||||
rm_file/
|
||||
/server/log/
|
||||
/server/gva
|
||||
/server/server
|
||||
/server/latest_log
|
||||
/server/__debug_bin*
|
||||
server/uploads/
|
||||
|
||||
*.iml
|
||||
web/.pnpm-debug.log
|
||||
web/pnpm-lock.yaml
|
||||
|
||||
# binary files
|
||||
*.exe
|
||||
|
||||
# SQLite database files
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
FROM golang:alpine as builder
|
||||
RUN apk add --update --no-cache yarn make g++
|
||||
RUN yarn global add cross-env node-sass
|
||||
|
||||
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||
GO111MODULE=on \
|
||||
CGO_ENABLED=1
|
||||
WORKDIR /go/src/gin-vue-admin
|
||||
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
|
||||
COPY server/ ./
|
||||
RUN go env && go list && go build -v -a -ldflags "-extldflags \"-static\" " -o gvadmin .
|
||||
|
||||
WORKDIR /web
|
||||
COPY web/ ./
|
||||
RUN yarn install && yarn run build
|
||||
|
||||
|
||||
FROM nginx:alpine
|
||||
LABEL MAINTAINER="rikugun"
|
||||
|
||||
RUN apk add --no-cache gettext tzdata && \
|
||||
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo "Asia/Shanghai" > /etc/timezone && \
|
||||
date && \
|
||||
apk del tzdata
|
||||
|
||||
COPY docker/etc/nginx/nginx.conf.tpl /etc/nginx/nginx.conf.tpl
|
||||
WORKDIR /app
|
||||
#copy web
|
||||
COPY --from=builder /web/dist/ /var/www/
|
||||
#copy go app
|
||||
COPY --from=builder /go/src/gin-vue-admin/gvadmin ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/db.db ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/config.yaml ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/resource ./resource
|
||||
COPY docker/docker-start.sh ./
|
||||
|
||||
ENV API_SERVER="http://localhost:8888/"
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["./docker-start.sh"]
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2019 JiZhao Jiang
|
||||
Copyright 2019 北京翻转极光科技有限责任公司
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
SHELL = /bin/bash
|
||||
|
||||
#SCRIPT_DIR = $(shell pwd)/etc/script
|
||||
#请选择golang版本
|
||||
BUILD_IMAGE_SERVER = golang:1.22
|
||||
#请选择node版本
|
||||
BUILD_IMAGE_WEB = node:20
|
||||
#项目名称
|
||||
PROJECT_NAME = github.com/flipped-aurora/gin-vue-admin/server
|
||||
#配置文件目录
|
||||
CONFIG_FILE = config.yaml
|
||||
#镜像仓库命名空间
|
||||
IMAGE_NAME = gva
|
||||
#镜像地址
|
||||
REPOSITORY = registry.cn-hangzhou.aliyuncs.com/${IMAGE_NAME}
|
||||
#镜像版本
|
||||
TAGS_OPT ?= latest
|
||||
PLUGIN ?= email
|
||||
|
||||
#容器环境前后端共同打包
|
||||
build: build-web build-server
|
||||
docker run --name build-local --rm -v $(shell pwd):/go/src/${PROJECT_NAME} -w /go/src/${PROJECT_NAME} ${BUILD_IMAGE_SERVER} make build-local
|
||||
|
||||
#容器环境打包前端
|
||||
build-web:
|
||||
docker run --name build-web-local --rm -v $(shell pwd):/go/src/${PROJECT_NAME} -w /go/src/${PROJECT_NAME} ${BUILD_IMAGE_WEB} make build-web-local
|
||||
|
||||
#容器环境打包后端
|
||||
build-server:
|
||||
docker run --name build-server-local --rm -v $(shell pwd):/go/src/${PROJECT_NAME} -w /go/src/${PROJECT_NAME} ${BUILD_IMAGE_SERVER} make build-server-local
|
||||
|
||||
#构建web镜像
|
||||
build-image-web:
|
||||
@cd web/ && docker build -t ${REPOSITORY}/web:${TAGS_OPT} .
|
||||
|
||||
#构建server镜像
|
||||
build-image-server:
|
||||
@cd server/ && docker build -t ${REPOSITORY}/server:${TAGS_OPT} .
|
||||
|
||||
#本地环境打包前后端
|
||||
build-local:
|
||||
if [ -d "build" ];then rm -rf build; else echo "OK!"; fi \
|
||||
&& if [ -f "/.dockerenv" ];then echo "OK!"; else make build-web-local && make build-server-local; fi \
|
||||
&& mkdir build && cp -r web/dist build/ && cp server/server build/ && cp -r server/resource build/resource
|
||||
|
||||
#本地环境打包前端
|
||||
build-web-local:
|
||||
@cd web/ && if [ -d "dist" ];then rm -rf dist; else echo "OK!"; fi \
|
||||
&& yarn config set registry http://mirrors.cloud.tencent.com/npm/ && yarn install && yarn build
|
||||
|
||||
#本地环境打包后端
|
||||
build-server-local:
|
||||
@cd server/ && if [ -f "server" ];then rm -rf server; else echo "OK!"; fi \
|
||||
&& go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct \
|
||||
&& go env -w CGO_ENABLED=0 && go env && go mod tidy \
|
||||
&& go build -ldflags "-B 0x$(shell head -c20 /dev/urandom|od -An -tx1|tr -d ' \n') -X main.Version=${TAGS_OPT}" -v
|
||||
|
||||
#打包前后端二合一镜像
|
||||
image: build
|
||||
docker build -t ${REPOSITORY}/gin-vue-admin:${TAGS_OPT} -f deploy/docker/Dockerfile .
|
||||
|
||||
#尝鲜版
|
||||
images: build build-image-web build-image-server
|
||||
docker build -t ${REPOSITORY}/all:${TAGS_OPT} -f deploy/docker/Dockerfile .
|
||||
|
||||
#swagger 文档生成
|
||||
doc:
|
||||
@cd server && swag init
|
||||
|
||||
#插件快捷打包: make plugin PLUGIN="这里是插件文件夹名称,默认为email"
|
||||
plugin:
|
||||
if [ -d ".plugin" ];then rm -rf .plugin ; else echo "OK!"; fi && mkdir -p .plugin/${PLUGIN}/{server/plugin,web/plugin} \
|
||||
&& if [ -d "server/plugin/${PLUGIN}" ];then cp -r server/plugin/${PLUGIN} .plugin/${PLUGIN}/server/plugin/ ; else echo "OK!"; fi \
|
||||
&& if [ -d "web/src/plugin/${PLUGIN}" ];then cp -r web/src/plugin/${PLUGIN} .plugin/${PLUGIN}/web/plugin/ ; else echo "OK!"; fi \
|
||||
&& cd .plugin && zip -r ${PLUGIN}.zip ${PLUGIN} && mv ${PLUGIN}.zip ../ && cd ..
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
|
||||
<div align=center>
|
||||
<img src="http://qmplusimg.henrongyi.top/gvalogo.jpg" width="300" height="300" />
|
||||
</div>
|
||||
<div align=center>
|
||||
<img src="https://img.shields.io/badge/golang-1.18-blue"/>
|
||||
<img src="https://img.shields.io/badge/gin-1.9.1-lightBlue"/>
|
||||
<img src="https://img.shields.io/badge/vue-3.3.4-brightgreen"/>
|
||||
<img src="https://img.shields.io/badge/element--plus-2.3.8-green"/>
|
||||
<img src="https://img.shields.io/badge/gorm-1.25.2-red"/>
|
||||
</div>
|
||||
|
||||
English | [简体中文](./README.md)
|
||||
|
||||
[gitee](https://gitee.com/pixelmax/gin-vue-admin): https://gitee.com/pixelmax/gin-vue-admin
|
||||
|
||||
[github](https://github.com/flipped-aurora/gin-vue-admin): https://github.com/flipped-aurora/gin-vue-admin
|
||||
|
||||
# Project Guidelines
|
||||
[Online Documentation](https://www.gin-vue-admin.com/) : https://www.gin-vue-admin.com/
|
||||
|
||||
[From the environment to the deployment of teaching videos](https://www.bilibili.com/video/BV1fV411y7dT)
|
||||
|
||||
[Development Steps](https://www.gin-vue-admin.com/guide/start-quickly/env.html) (Contributor: <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
|
||||
|
||||
## 1. Basic Introduction
|
||||
|
||||
### 1.1 Project Introduction
|
||||
|
||||
> Gin-vue-admin is a backstage management system based on [vue](https://vuejs.org) and [gin](https://gin-gonic.com), which separates the front and rear of the full stack. It integrates jwt authentication, dynamic routing, dynamic menu, casbin authentication, form generator, code generator and other functions. It provides a variety of sample files, allowing you to focus more time on business development.
|
||||
|
||||
[Online Demo](http://demo.gin-vue-admin.com): http://demo.gin-vue-admin.com
|
||||
|
||||
username:admin
|
||||
|
||||
password:123456
|
||||
|
||||
### 1.2 Contributing Guide
|
||||
|
||||
Hi! Thank you for choosing gin-vue-admin.
|
||||
|
||||
Gin-vue-admin is a full-stack (frontend and backend separation) framework for developers, designers and product managers.
|
||||
|
||||
We are excited that you are interested in contributing to gin-vue-admin. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
|
||||
|
||||
#### 1.2.1 Issue Guidelines
|
||||
|
||||
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
|
||||
|
||||
- Before submitting an issue, please check if similar problems have already been issued.
|
||||
|
||||
#### 1.2.2 Pull Request Guidelines
|
||||
|
||||
- Fork this repository to your own account. Do not create branches here.
|
||||
|
||||
- Commit info should be formatted as `[File Name]: Info about commit.` (e.g. `README.md: Fix xxx bug`)
|
||||
|
||||
- <font color=red>Make sure PRs are created to `develop` branch instead of `master` branch.</font>
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
- Merging a PR takes two maintainers: one approves the changes after reviewing, and then the other reviews and merges.
|
||||
|
||||
### 1.3 Version list
|
||||
|
||||
- master: 2.0 code, for prod
|
||||
- develop: 2.0 dev code, for test
|
||||
- [gin-vue-admin_v2_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v2_dev) (v2.0 [GormV1](https://v1.gorm.io) Stable branch)
|
||||
- [gva_gormv2_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gva_gormv2_dev) (v2.0 [GormV2](https://v2.gorm.io) Development branch)
|
||||
|
||||
## 2. Getting started
|
||||
|
||||
```
|
||||
- node version > v8.6.0
|
||||
- golang version >= v1.14
|
||||
- IDE recommendation: Goland
|
||||
- initialization project: different versions of the database are not initialized. See synonyms at initialization https://www.gin-vue-admin.com/docs/first
|
||||
- Replace the Qiniuyun public key, private key, warehouse name and default url address in the project to avoid data confusion in the test file.
|
||||
```
|
||||
|
||||
### 2.1 server project
|
||||
|
||||
use `Goland` And other editing tools,open server catalogue,You can't open it. `gin-vue-admin` root directory
|
||||
|
||||
```bash
|
||||
# clone the project
|
||||
git clone https://github.com/flipped-aurora/gin-vue-admin.git
|
||||
|
||||
# open server catalogue
|
||||
cd server
|
||||
|
||||
# use go mod And install the go dependency package
|
||||
go generate
|
||||
|
||||
# Compile
|
||||
go build -o server main.go (windows the compile command is go build -o server.exe main.go )
|
||||
|
||||
# Run binary
|
||||
./server (windows The run command is server.exe)
|
||||
```
|
||||
|
||||
### 2.1 web project
|
||||
|
||||
```bash
|
||||
# enter the project directory
|
||||
cd web
|
||||
|
||||
# install dependency
|
||||
npm install
|
||||
|
||||
# develop
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### 2.2 Server
|
||||
|
||||
```bash
|
||||
# using go.mod
|
||||
|
||||
# install go modules
|
||||
go list (go mod tidy)
|
||||
|
||||
# build the server
|
||||
go build
|
||||
```
|
||||
|
||||
### 2.3 API docs auto-generation using swagger
|
||||
|
||||
#### 2.3.1 install swagger
|
||||
|
||||
##### (1) Using VPN or outside mainland China
|
||||
````
|
||||
go get -u github.com/swaggo/swag/cmd/swag
|
||||
````
|
||||
|
||||
##### (2) In mainland China
|
||||
|
||||
In mainland China, access to go.org/x is prohibited,we recommend [goproxy.io](https://goproxy.io/zh/) or [goproxy.cn](https://goproxy.cn)
|
||||
|
||||
````bash
|
||||
# If you are using a version of Go 1.13 - 1.15 Need to set up manually GO111MODULE=on, The opening mode is as follows, If your Go version is 1.16 ~ Latest edition You can ignore the following step one
|
||||
# Step one、Enable Go Modules Function
|
||||
go env -w GO111MODULE=on
|
||||
# Step two、Configuration GOPROXY Environment variable
|
||||
go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
|
||||
|
||||
# If you dislike trouble,You can use the go generate Automatically execute code before compilation, But this can't be used command line terminal of `Goland` or `Vscode`
|
||||
cd server
|
||||
go generate -run "go env -w .*?"
|
||||
|
||||
# 使用如下命令下载swag
|
||||
go get -u github.com/swaggo/swag/cmd/swag
|
||||
````
|
||||
|
||||
#### 2.3.2 API docs generation
|
||||
|
||||
````
|
||||
cd server
|
||||
swag init
|
||||
````
|
||||
|
||||
> After executing the above command,server directory will appear in the docs folder `docs.go`, `swagger.json`, `swagger.yaml` Three file updates,After starting the go service, type in the browser [http://localhost:8888/swagger/index.html](http://localhost:8888/swagger/index.html) You can view swagger document
|
||||
|
||||
|
||||
## 3. Technical selection
|
||||
|
||||
- Frontend: using [Element](https://github.com/ElemeFE/element) based on [Vue](https://vuejs.org),to code the page.
|
||||
- Backend: using [Gin](https://gin-gonic.com/) to quickly build basic RESTful API. [Gin](https://gin-gonic.com/)is a web framework written in Go (Golang).
|
||||
- DB: `MySql`(5.6.44),using [gorm](http://gorm.io)` to implement data manipulation, added support for SQLite databases.
|
||||
- Cache: using `Redis` to implement the recording of the JWT token of the currently active user and implement the multi-login restriction.
|
||||
- API: using Swagger to auto generate APIs docs。
|
||||
- Config: using [fsnotify](https://github.com/fsnotify/fsnotify) and [viper](https://github.com/spf13/viper) to implement `yaml` config file。
|
||||
- Log: using [zap](https://github.com/uber-go/zap) record logs。
|
||||
|
||||
## 4. Project Architecture
|
||||
|
||||
### 4.1 Architecture Diagram
|
||||
|
||||

|
||||
|
||||
### 4.2 Front-end Detailed Design Diagram (Contributor: <a href="https://github.com/baobeisuper">baobeisuper</a>)
|
||||
|
||||

|
||||
|
||||
### 4.3 Project Layout
|
||||
|
||||
```
|
||||
├── server
|
||||
├── api (api entrance)
|
||||
│ └── v1 (v1 version interface)
|
||||
├── config (configuration package)
|
||||
├── core (core document)
|
||||
├── docs (swagger document directory)
|
||||
├── global (global object)
|
||||
├── initialize (initialization)
|
||||
│ └── internal (initialize internal function)
|
||||
├── middleware (middleware layer)
|
||||
├── model (model layer)
|
||||
│ ├── request (input parameter structure)
|
||||
│ └── response (out-of-parameter structure)
|
||||
├── packfile (static file packaging)
|
||||
├── resource (static resource folder)
|
||||
│ ├── excel (excel import and export default path)
|
||||
│ ├── page (form generator)
|
||||
│ └── template (template)
|
||||
├── router (routing layer)
|
||||
├── service (service layer)
|
||||
├── source (source layer)
|
||||
└── utils (tool kit)
|
||||
├── timer (timer interface encapsulation)
|
||||
└── upload (oss interface encapsulation)
|
||||
|
||||
└─web (frontend)
|
||||
├─public (deploy templates)
|
||||
└─src (source code)
|
||||
├─api (frontend APIs)
|
||||
├─assets (static files)
|
||||
├─components(components)
|
||||
├─router (frontend routers)
|
||||
├─store (vuex state management)
|
||||
├─style (common styles)
|
||||
├─utils (frontend common utilitie)
|
||||
└─view (pages)
|
||||
|
||||
```
|
||||
|
||||
## 5. Features
|
||||
|
||||
- Authority management: Authority management based on `jwt` and `casbin`.
|
||||
- File upload and download: implement file upload operations based on `Qiniuyun', `Aliyun 'and `Tencent Cloud` (please develop your own application for each platform corresponding to `token` or `key` ).
|
||||
- Pagination Encapsulation:The frontend uses `mixins` to encapsulate paging, and the paging method can call `mixins` .
|
||||
- User management: The system administrator assigns user roles and role permissions.
|
||||
- Role management: Create the main object of permission control, and then assign different API permissions and menu permissions to the role.
|
||||
- Menu management: User dynamic menu configuration implementation, assigning different menus to different roles.
|
||||
- API management: Different users can call different API permissions.
|
||||
- Configuration management: the configuration file can be modified in the foreground (this feature is not available in the online experience site).
|
||||
- Conditional search: Add an example of conditional search.
|
||||
- Restful example: You can see sample APIs in user management module.
|
||||
- Front-end file reference: [web/src/view/superAdmin/api/api.vue](https://github.com/flipped-aurora/gin-vue-admin/blob/master/web/src/view/superAdmin/api/api.vue).
|
||||
- Stage reference: [server/router/sys_api.go](https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/router/sys_api.go).
|
||||
- Multi-login restriction: Change `user-multipoint` to true in `system` in `config.yaml` (You need to configure redis and redis parameters yourself. During the test period, please report in time if there is a bug).
|
||||
- Upload file by chunk:Provides examples of file upload and large file upload by chunk.
|
||||
- Form Builder:With the help of [@form-generator](https://github.com/JakHuang/form-generator).
|
||||
- Code generator: Providing backend with basic logic and simple curd code generator.
|
||||
|
||||
## 6. Knowledge base
|
||||
|
||||
### 6.1 Team blog
|
||||
|
||||
> https://www.yuque.com/flipped-aurora
|
||||
>
|
||||
>There are video courses about frontend framework in our blo. If you think the project is helpful to you, you can add my personal WeChat:shouzi_1994,your comments is welcomed。
|
||||
|
||||
### 6.2 Video courses
|
||||
|
||||
(1) Development environment course
|
||||
|
||||
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/
|
||||
|
||||
(2) Template course
|
||||
|
||||
> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/
|
||||
|
||||
(3) 2.0 version introduction and development experience
|
||||
|
||||
> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
|
||||
|
||||
(4) Golang basic course
|
||||
|
||||
> https://space.bilibili.com/322210472/channel/detail?cid=108884
|
||||
|
||||
(5) gin frame basic teaching
|
||||
|
||||
> bilibili:https://space.bilibili.com/322210472/channel/detail?cid=126418&ctype=0
|
||||
|
||||
(6) gin-vue-admin version update introduction video
|
||||
> bilibili:https://space.bilibili.com/322210472/channel/detail?cid=126418&ctype=0
|
||||
|
||||
## 7.Contacts
|
||||
|
||||
### 7.1 Groups
|
||||
|
||||
#### QQ group: 622360840
|
||||
|
||||
| QQ group |d
|
||||
| :---: |
|
||||
| <img src="http://qmplusimg.henrongyi.top/qq.jpg" width="180"/> |
|
||||
|
||||
|
||||
#### Wechat group: comment "加入gin-vue-admin交流群"
|
||||
|
||||
| Wechat |
|
||||
| :---: |
|
||||
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png">
|
||||
|
||||
#### [About Us](https://www.gin-vue-admin.com/about/join.html)
|
||||
|
||||
## 8. Contributors
|
||||
|
||||
Thank you for considering your contribution to gin-vue-admin!
|
||||
|
||||
<a href="https://openomy.app/github/flipped-aurora/gin-vue-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
||||
<img src="https://openomy.app/svg?repo=flipped-aurora/gin-vue-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/flipped-aurora/gin-vue-admin/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=flipped-aurora/gin-vue-admin" />
|
||||
</a>
|
||||
|
||||
## 9. Donate
|
||||
|
||||
If you find this project useful, you can buy author a glass of juice :tropical_drink: [here](https://www.gin-vue-admin.com/coffee/index.html)
|
||||
|
||||
## 10. Commercial considerations
|
||||
|
||||
If you use this project for commercial purposes, please comply with the Apache2.0 agreement and retain the author's technical support statement.
|
||||
|
||||
-313
@@ -1,313 +0,0 @@
|
||||
|
||||
<div align=center>
|
||||
<img src="http://qmplusimg.henrongyi.top/gvalogo.jpg" width=300" height="300" />
|
||||
</div>
|
||||
<div align=center>
|
||||
<img src="https://img.shields.io/badge/golang-1.12-blue"/>
|
||||
<img src="https://img.shields.io/badge/gin-1.4.0-lightBlue"/>
|
||||
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen"/>
|
||||
<img src="https://img.shields.io/badge/element--ui-2.12.0-green"/>
|
||||
<img src="https://img.shields.io/badge/gorm-1.9.12-red"/>
|
||||
</div>
|
||||
|
||||
[English](./README.md) | 简体中文
|
||||
|
||||
# 项目文档
|
||||
[在线文档](http://doc.henrongyi.top/)
|
||||
|
||||
[开发教学](http://doc.henrongyi.top/help/) (贡献者: <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
|
||||
- 前端UI框架:[element-ui](https://github.com/ElemeFE/element)
|
||||
- 后台框架:[gin](https://github.com/gin-gonic/gin)
|
||||
|
||||
## 1. 基本介绍
|
||||
|
||||
### 1.1 项目介绍
|
||||
|
||||
[在线预览](http://demo.gin-vue-admin.com/)
|
||||
|
||||
测试用户名:admin
|
||||
|
||||
测试密码:123456
|
||||
|
||||
> Gin-vue-admin是一个基于vue和gin开发的全栈前后端分离的后台管理系统,集成jwt鉴权,动态路由,动态菜单,casbin鉴权,表单生成器,代码生成器等功能,提供多种示例文件,让您把更多时间专注在业务开发上。
|
||||
|
||||
### 1.2 贡献指南
|
||||
Hi! 首先感谢你使用 gin-vue-admin。
|
||||
|
||||
Gin-vue-admin 是一套为后台管理平台准备的一整套前后端分离架构式的开源框架,旨在快速搭建后台管理系统。
|
||||
|
||||
Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-admin 贡献代码或提供建议,请阅读以下内容。
|
||||
|
||||
#### 1.2.1 Issue 规范
|
||||
- issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。如果你在使用时产生了疑问,请到 Slack 或 [Gitter](https://gitter.im/ElemeFE/element) 里咨询。
|
||||
|
||||
- 在提交 issue 之前,请搜索相关内容是否已被提出。
|
||||
|
||||
#### 1.2.2 Pull Request 规范
|
||||
- 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。
|
||||
|
||||
- commit 信息要以`[文件名]: 描述信息` 的形式填写,例如 `README.md: fix xxx bug`。
|
||||
|
||||
- <font color=red>确保 PR 是提交到 `develop` 分支,而不是 `master` 分支。</font>
|
||||
|
||||
- 如果是修复 bug,请在 PR 中给出描述信息。
|
||||
|
||||
- 合并代码需要两名维护人员参与:一人进行 review 后 approve,另一人再次 review,通过后即可合并。
|
||||
|
||||
### 1.3 版本列表
|
||||
|
||||
- master: 2.0, 用于生产环境
|
||||
|
||||
- develop: 2.0, 用于测试环境
|
||||
|
||||
- [gin-vue-admin_v2.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v2_dev) (v2.0 不再兼容 v1.0)
|
||||
|
||||
- [gin-vue-admin_v1.0_stable](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v1_stable) (v1.0停止维护)
|
||||
|
||||
- [gin-vue-admin_v1.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v1_dev) (v1.0停止维护)
|
||||
|
||||
|
||||
## 2. 使用说明
|
||||
|
||||
> 使用docker-compose体验本项目
|
||||
- 安装 docker-compose [官方文档](https://docs.docker.com/compose/install/)
|
||||
- ```shell script
|
||||
# 在Linux安装
|
||||
# 1.1 运行此命令以下载Docker Compose的当前稳定版本
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
# 1.2 将可执行权限应用于二进制文件
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
```
|
||||
- ```shell script
|
||||
# 使用Python的pip安装
|
||||
pip3 install docker-compose -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
```
|
||||
- 使用 Docker Desktop
|
||||
- Windows: https://hub.docker.com/editions/community/docker-ce-desktop-windows
|
||||
- Mac: https://hub.docker.com/editions/community/docker-ce-desktop-mac/
|
||||
|
||||
- 使用git克隆本项目
|
||||
- ```git
|
||||
git clone https://github.com/flipped-aurora/gin-vue-admin.git
|
||||
```
|
||||
- 使用docker-compose up一键启动启动项目
|
||||
- ```shell script
|
||||
# 使用docker-compose启动四个容器
|
||||
docker-compose up
|
||||
# 如果您修改了某些配置选项,可以使用此命令重新打包镜像
|
||||
docker-compose up --build
|
||||
# 使用docker-compose 后台启动
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
- web项目预览 [http://127.0.0.1:8888/admin](http://127.0.0.1:8888/admin)
|
||||
|
||||
- swagger文档 [http://127.0.0.1:8888/swagger/index.html](http://127.0.0.1:8888/swagger/index.html)
|
||||
|
||||
```
|
||||
- node版本 > v8.6.0
|
||||
- golang版本 >= v1.11
|
||||
- IDE推荐:Goland
|
||||
- 各位在clone项目以后,把db文件导入自己创建的库后,最好前往七牛云申请自己的空间地址。
|
||||
- 替换掉项目中的七牛云公钥,私钥,仓名和默认url地址,以免发生测试文件数据错乱
|
||||
```
|
||||
|
||||
### 2.1 web端
|
||||
|
||||
```bash
|
||||
# clone the project
|
||||
git clone https://github.com/piexlmax/gin-vue-admin.git
|
||||
|
||||
# enter the project directory
|
||||
cd web
|
||||
|
||||
# install dependency
|
||||
npm install
|
||||
|
||||
# develop
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### 2.2 server端
|
||||
|
||||
```bash
|
||||
# 使用 go.mod
|
||||
|
||||
# 安装go依赖包
|
||||
go list (go mod tidy)
|
||||
|
||||
# 编译
|
||||
go build
|
||||
```
|
||||
|
||||
### 2.3 swagger自动化API文档
|
||||
|
||||
#### 2.3.1 安装 swagger
|
||||
|
||||
##### (1)可以翻墙
|
||||
````
|
||||
go get -u github.com/swaggo/swag/cmd/swag
|
||||
````
|
||||
|
||||
##### (2)无法翻墙
|
||||
|
||||
由于国内没法安装 go.org/x 包下面的东西,推荐使用 [goproxy.io](https://goproxy.io/zh/)
|
||||
|
||||
```bash
|
||||
如果您使用的 Go 版本是 1.13 及以上(推荐)
|
||||
# 启用 Go Modules 功能
|
||||
go env -w GO111MODULE=on
|
||||
# 配置 GOPROXY 环境变量
|
||||
go env -w GOPROXY=https://goproxy.io,direct
|
||||
|
||||
# 执行
|
||||
go get -g -v github.com/swaggo/swag/cmd/swag
|
||||
|
||||
# 到GOPATH的/src/github.com/swaggo/swag/cmd/swag路径下执行
|
||||
go install
|
||||
```
|
||||
|
||||
#### 2.3.2 生成API文档
|
||||
|
||||
````
|
||||
cd server
|
||||
swag init
|
||||
````
|
||||
执行上面的命令后,server目录下会出现docs文件夹,登录http://localhost:8888/swagger/index.html,即可查看swagger文档
|
||||
|
||||
|
||||
## 3. 技术选型
|
||||
|
||||
- 前端:用基于`vue`的`Element-UI`构建基础页面。
|
||||
- 后端:用`Gin`快速搭建基础restful风格API,`Gin`是一个go语言编写的Web框架。
|
||||
- 数据库:采用`MySql`(5.6.44)版本,使用`gorm`实现对数据库的基本操作,已添加对sqlite数据库的支持。
|
||||
- 缓存:使用`Redis`实现记录当前活跃用户的`jwt`令牌并实现多点登录限制。
|
||||
- API文档:使用`Swagger`构建自动化文档。
|
||||
- 配置文件:使用`fsnotify`和`viper`实现`yaml`格式的配置文件。
|
||||
- 日志:使用`go-logging`实现日志记录。
|
||||
|
||||
|
||||
## 4. 项目架构
|
||||
### 4.1 系统架构图
|
||||
|
||||

|
||||
|
||||
### 4.2 前端详细设计图 (提供者:<a href="https://github.com/baobeisuper">baobeisuper</a>)
|
||||
|
||||

|
||||
|
||||
### 4.3 目录结构
|
||||
|
||||
```
|
||||
├─server (后端文件夹)
|
||||
│ ├─api (API)
|
||||
│ ├─config (配置包)
|
||||
│ ├─core (內核)
|
||||
│ ├─db (数据库脚本)
|
||||
│ ├─docs (swagger文档目录)
|
||||
│ ├─global (全局对象)
|
||||
│ ├─initialiaze (初始化)
|
||||
│ ├─middleware (中间件)
|
||||
│ ├─model (结构体层)
|
||||
│ ├─resource (资源)
|
||||
│ ├─router (路由)
|
||||
│ ├─service (服务)
|
||||
│ └─utils (公共功能)
|
||||
└─web (前端文件)
|
||||
├─public (发布模板)
|
||||
└─src (源码包)
|
||||
├─api (向后台发送ajax的封装层)
|
||||
├─assets (静态文件)
|
||||
├─components(组件)
|
||||
├─router (前端路由)
|
||||
├─store (vuex 状态管理仓)
|
||||
├─style (通用样式文件)
|
||||
├─utils (前端工具库)
|
||||
└─view (前端页面)
|
||||
|
||||
```
|
||||
|
||||
## 5. 主要功能
|
||||
|
||||
- 权限管理:基于`jwt`和`casbin`实现的权限管理
|
||||
- 文件上传下载:实现基于七牛云的文件上传操作(为了方便大家测试,我公开了自己的七牛测试号的各种重要token,恳请大家不要乱传东西)
|
||||
- 分页封装:前端使用mixins封装分页,分页方法调用mixins即可
|
||||
- 用户管理:系统管理员分配用户角色和角色权限。
|
||||
- 角色管理:创建权限控制的主要对象,可以给角色分配不同api权限和菜单权限。
|
||||
- 菜单管理:实现用户动态菜单配置,实现不同角色不同菜单。
|
||||
- api管理:不同用户可调用的api接口的权限不同。
|
||||
- 配置管理:配置文件可前台修改(测试环境不开放此功能)。
|
||||
- 富文本编辑器:MarkDown编辑器功能嵌入。
|
||||
- 条件搜索:增加条件搜索示例。
|
||||
- restful示例:可以参考用户管理模块中的示例API。
|
||||
```
|
||||
前端文件参考: src\view\superAdmin\api\api.vue
|
||||
后台文件参考: model\dnModel\api.go
|
||||
```
|
||||
- 多点登录限制:需要在`config.yaml`中把`system`中的`useMultipoint`修改为true(需要自行配置Redis和Config中的Redis参数,测试阶段,有bug请及时反馈)。
|
||||
- 分片长传:提供文件分片上传和大文件分片上传功能示例。
|
||||
- 表单生成器:表单生成器借助 [@form-generator](https://github.com/JakHuang/form-generator)。
|
||||
- 代码生成器:后台基础逻辑以及简单curd的代码生成器。
|
||||
|
||||
## 6. 计划任务
|
||||
|
||||
- [ ] 导入,导出Excel
|
||||
- [ ] Echart图表支持
|
||||
- [ ] 工作流,任务交接功能开发
|
||||
- [ ] 单独前端使用模式以及数据模拟
|
||||
|
||||
## 7. 知识库
|
||||
## 7.1 团队博客
|
||||
|
||||
> https://www.yuque.com/flipped-aurora
|
||||
>
|
||||
>内有前端框架教学视频。如果觉得项目对您有所帮助可以添加我的个人微信:shouzi_1994,欢迎您提出宝贵的需求。
|
||||
|
||||
## 7.2 教学视频
|
||||
|
||||
(1)环境搭建
|
||||
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/ (v1.0版本视频,v2.0操作相同目录不同)
|
||||
|
||||
(2)模板使用
|
||||
> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/ (v1.0版本视频,v2.0操作相同目录不同)
|
||||
|
||||
(3)2.0目录以及开发体验
|
||||
> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
|
||||
|
||||
(4)golang基础教学视频录制中...
|
||||
> https://space.bilibili.com/322210472/channel/detail?cid=108884
|
||||
|
||||
## 8. 联系方式
|
||||
|
||||
### 8.1 技术群
|
||||
|
||||
### QQ交流群:622360840
|
||||
| QQ 群(满) |
|
||||
| :---: |
|
||||
| <img src="http://qmplusimg.henrongyi.top/qq.jpg" width="180"/> |
|
||||
|
||||
### 微信交流群
|
||||
可以添加上面任意一位开发者,备注"加入gin-vue-admin交流群"
|
||||
|
||||
### 8.2 项目组成员
|
||||
| 蒋 | 严 | 尹 | 杜 | 印 | 宋 |
|
||||
| :---: | :---: | :---: | :---: | :---: | :---: |
|
||||
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryr.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryx.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrdjl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrygl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrsong.png"> |
|
||||
|
||||
| 昵称 | 项目职务 | 姓 |
|
||||
| ---- | ---- | ---- |
|
||||
| [@piexlmax](https://github.com/piexlmax) | 项目发起者 | 蒋 |
|
||||
| [@Ruio9244](https://github.com/Ruio9244) | 架构师 | 严 |
|
||||
| [@granty1](https://github.com/granty1) | 后台开发 | 印 |
|
||||
| [@1319612909](https://github.com/1319612909) | 前端UI开发 | 杜 |
|
||||
| [@krank666](https://github.com/krank666) | 前端开发 | 尹 |
|
||||
| [@chen-chen-up](https://github.com/chen-chen-up) | 新手开发 | 宋 |
|
||||
| [@SliverHorn](https://github.com/SliverHorn) | 社区管理员 | 赖 |
|
||||
|
||||
## 9. 捐赠
|
||||
|
||||
如果你觉得这个项目对你有帮助,你可以请作者喝饮料 :tropical_drink: [点我](http://doc.henrongyi.top/more/coffee.html)
|
||||
|
||||
## 10. 商用注意事项
|
||||
|
||||
如果您将此项目用于商业用途,请遵守Apache2.0协议并保留作者技术支持声明。
|
||||
@@ -1,322 +1,384 @@
|
||||
|
||||
|
||||
<div align=center>
|
||||
<img src="http://qmplusimg.henrongyi.top/gvalogo.jpg" width=300" height="300" />
|
||||
</div>
|
||||
<div align=center>
|
||||
<img src="https://img.shields.io/badge/golang-1.12-blue"/>
|
||||
<img src="https://img.shields.io/badge/gin-1.4.0-lightBlue"/>
|
||||
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen"/>
|
||||
<img src="https://img.shields.io/badge/element--ui-2.12.0-green"/>
|
||||
<img src="https://img.shields.io/badge/gorm-1.9.12-red"/>
|
||||
<img src="http://qmplusimg.henrongyi.top/gvalogo.jpg" width="300" height="300" />
|
||||
</div>
|
||||
|
||||
English | [简体中文](./README-zh_CN.md)
|
||||
<div align=center>
|
||||
<img src="https://img.shields.io/badge/golang-1.20-blue"/>
|
||||
<img src="https://img.shields.io/badge/gin-1.9.1-lightBlue"/>
|
||||
<img src="https://img.shields.io/badge/vue-3.3.4-brightgreen"/>
|
||||
<img src="https://img.shields.io/badge/element--plus-2.3.8-green"/>
|
||||
<img src="https://img.shields.io/badge/gorm-1.25.2-red"/>
|
||||
<img src="https://gitcode.com/flipped-aurora/gin-vue-admin/star/badge.svg"/>
|
||||
</div>
|
||||
|
||||
# Project Guidelines
|
||||
[Online Documentation](http://doc.henrongyi.top/)
|
||||
<div align=center>
|
||||
<a href="https://trendshift.io/repositories/3250" target="_blank"><img src="https://trendshift.io/api/badge/repositories/3250" alt="Calcium-Ion%2Fnew-api | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
</div>
|
||||
|
||||
[Development Steps](http://doc.henrongyi.top/help/) (Contributor: <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
|
||||
- Web UI Framework:[element-ui](https://github.com/ElemeFE/element)
|
||||
- Server Framework:[gin](https://github.com/gin-gonic/gin)
|
||||
[English](./README-en.md) | 简体中文
|
||||
|
||||
## 1. Basic Introduction
|
||||
## ✨一分钟生成前后端基础代码
|
||||
|
||||
### 1.1 Project Introduction
|
||||
|
||||
[Online Demo](http://demo.gin-vue-admin.com/)
|
||||
|
||||
username:admin
|
||||
|
||||
password:123456
|
||||
|
||||
> Gin-vue-admin is a full-stack (frontend and backend separation) framework designed for management system.
|
||||
> It integrates multiple functions, such as JWT authentication, dynamic routing, dynamic menu, casbin authentication, form generator, code generator, etc. So that you can focus more time on your business Requirements.
|
||||
|
||||
Hi! Thank you for choosing gin-vue-admin.
|
||||
|
||||
Gin-vue-admin is a full-stack (frontend and backend separation) framework for developers, designers and product managers.
|
||||
|
||||
We are excited that you are interested in contributing to gin-vue-admin. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
|
||||
|
||||
### 1.2 Contributing Guide
|
||||
#### 1.2.1 Issue Guidelines
|
||||
|
||||
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
|
||||
|
||||
- Before submitting an issue, please check if similar problems have already been issued.
|
||||
|
||||
#### 1.2.2 Pull Request Guidelines
|
||||
|
||||
- Fork this repository to your own account. Do not create branches here.
|
||||
|
||||
- Commit info should be formatted as `[File Name]: Info about commit.` (e.g. `README.md: Fix xxx bug`)
|
||||
|
||||
- <font color=red>Make sure PRs are created to `develop` branch instead of `master` branch.</font>
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
- Merging a PR takes two maintainers: one approves the changes after reviewing, and then the other reviews and merges.
|
||||
|
||||
### 1.3 Version list
|
||||
|
||||
- master: 2.0 code, for prod
|
||||
|
||||
- develop: 2.0 dev code, for test
|
||||
|
||||
- [gin-vue-admin_v2.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v2_dev) (v2.0 is no longer compatible with v1.0)
|
||||
|
||||
- [gin-vue-admin_v1.0_stable](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v1_stable) (stop maintenance)
|
||||
|
||||
- [gin-vue-admin_v1.0_dev](https://github.com/flipped-aurora/gin-vue-admin/tree/gin-vue-admin_v1_dev) (stop maintenance)
|
||||
<table>
|
||||
<tr>
|
||||
<td width="200">
|
||||
<p>📄 创建基础模板</p>
|
||||
<p>🤖 AI生成结构</p>
|
||||
<p>⏰ 生成代码</p>
|
||||
<p>🏷️ 分配权限</p>
|
||||
<p>🎉 基础CURD生成完成</p>
|
||||
</td>
|
||||
<td>
|
||||
<video src="https://private-user-images.githubusercontent.com/165128580/384700666-4d039215-af29-4f86-bb4f-60dbab38f58e.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzEyNTIxNDYsIm5iZiI6MTczMTI1MTg0NiwicGF0aCI6Ii8xNjUxMjg1ODAvMzg0NzAwNjY2LTRkMDM5MjE1LWFmMjktNGY4Ni1iYjRmLTYwZGJhYjM4ZjU4ZS5tcDQ_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExMFQxNTE3MjZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00NjJkMDcwZjJkMjAyMmU1N2I2MzQxY2RhODFlNzgzNGRiMDFhMmY2NTYyM2ZmODdhNDVmMWE1NzlhMDdlOTI5JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.ZJbswpLzF2RHjemcGirKOP0L1fvpl3FUqIiQ_-yjeUo" data-canonical-src="https://private-user-images.githubusercontent.com/165128580/384700666-4d039215-af29-4f86-bb4f-60dbab38f58e.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzEyNTIxNDYsIm5iZiI6MTczMTI1MTg0NiwicGF0aCI6Ii8xNjUxMjg1ODAvMzg0NzAwNjY2LTRkMDM5MjE1LWFmMjktNGY4Ni1iYjRmLTYwZGJhYjM4ZjU4ZS5tcDQ_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMTEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTExMFQxNTE3MjZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00NjJkMDcwZjJkMjAyMmU1N2I2MzQxY2RhODFlNzgzNGRiMDFhMmY2NTYyM2ZmODdhNDVmMWE1NzlhMDdlOTI5JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.ZJbswpLzF2RHjemcGirKOP0L1fvpl3FUqIiQ_-yjeUo" controls="controls" muted="muted" class="d-block rounded-bottom-2 border-top width-fit" style="max-height:640px; min-height: 200px">
|
||||
</video>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## 2. Getting started
|
||||
# 项目文档
|
||||
[在线文档](https://www.gin-vue-admin.com) : https://www.gin-vue-admin.com
|
||||
|
||||
> Use docker-compose to experience this project
|
||||
- Installation docker-compose [Official document](https://docs.docker.com/compose/install/)
|
||||
- ```shell script
|
||||
# Install on Linux
|
||||
# 1.1 Run this command to download the current stable version of Docker Compose
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
# 1.2 Apply executable permissions to binary files
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
```
|
||||
- ```shell script
|
||||
# Use Python's pip installation
|
||||
pip3 install docker-compose -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
```
|
||||
- Use Docker Desktop
|
||||
- Windows: https://hub.docker.com/editions/community/docker-ce-desktop-windows
|
||||
- Mac: https://hub.docker.com/editions/community/docker-ce-desktop-mac/
|
||||
[初始化](https://www.gin-vue-admin.com/guide/start-quickly/initialization.html)
|
||||
|
||||
[从环境到部署教学视频](https://www.bilibili.com/video/BV1Rg411u7xH)
|
||||
|
||||
- Use git to clone this project
|
||||
- ```git
|
||||
git clone https://github.com/flipped-aurora/gin-vue-admin.git
|
||||
```
|
||||
- Use docker-compose up to start the startup project with one click
|
||||
- ```shell script
|
||||
# Use docker-compose to start four containers
|
||||
docker-compose up
|
||||
# If you modify some configuration options, you can use this command to repackage the image
|
||||
docker-compose up --build
|
||||
# Use docker-compose to start in the background
|
||||
docker-compose up -d
|
||||
```
|
||||
[开发教学](https://www.gin-vue-admin.com/guide/start-quickly/env.html) (贡献者: <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
|
||||
|
||||
- Web project preview [http://127.0.0.1:8888/admin](http://127.0.0.1:8888/admin)
|
||||
[交流社区](https://support.qq.com/products/371961)
|
||||
|
||||
- swagger APIs [http://127.0.0.1:8888/swagger/index.html](http://127.0.0.1:8888/swagger/index.html)
|
||||
[插件市场](https://plugin.gin-vue-admin.com/)
|
||||
|
||||
[软件著作权证书](https://www.gin-vue-admin.com/copyright.pdf)
|
||||
|
||||
# 重要提示
|
||||
|
||||
1.本项目从起步到开发到部署均有文档和详细视频教程
|
||||
|
||||
2.本项目需要您有一定的golang和vue基础
|
||||
|
||||
3.您完全可以通过我们的教程和文档完成一切操作,因此我们不再提供免费的技术服务,如需服务请进行[付费支持](https://www.gin-vue-admin.com/coffee/payment.html)
|
||||
|
||||
4.如果您将此项目用于商业用途,请遵守Apache2.0协议并保留作者技术支持声明。您需保留如下版权声明信息,以及日志和代码中所包含的版权声明信息。所需保留信息均为文案性质,不会影响任何业务内容,如决定商用【产生收益的商业行为均在商用行列】或者必须剔除请[购买授权](https://www.gin-vue-admin.com/empower/index.html)
|
||||
\
|
||||
<img src="https://qmplusimg.henrongyi.top/openSource/login.jpg" width="1000">
|
||||
|
||||
<img src="https://qmplusimg.henrongyi.top/openSource/dashboard.jpg" width="1000">
|
||||
|
||||
## 1. 基本介绍
|
||||
|
||||
### 1.1 项目介绍
|
||||
|
||||
> Gin-vue-admin是一个基于 [vue](https://vuejs.org) 和 [gin](https://gin-gonic.com) 开发的全栈前后端分离的开发基础平台,集成jwt鉴权,动态路由,动态菜单,casbin鉴权,表单生成器,代码生成器等功能,提供多种示例文件,让您把更多时间专注在业务开发上。
|
||||
|
||||
[在线预览](http://demo.gin-vue-admin.com): http://demo.gin-vue-admin.com
|
||||
|
||||
测试用户名:admin
|
||||
|
||||
测试密码:123456
|
||||
|
||||
### 1.2 贡献指南
|
||||
Hi! 首先感谢你使用 gin-vue-admin。
|
||||
|
||||
Gin-vue-admin 是一套为快速研发准备的一整套前后端分离架构式的开源框架,旨在快速搭建中小型项目。
|
||||
|
||||
Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-admin 贡献代码或提供建议,请阅读以下内容。
|
||||
|
||||
#### 1.2.1 Issue 规范
|
||||
- issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。
|
||||
|
||||
- 在提交 issue 之前,请搜索相关内容是否已被提出。
|
||||
|
||||
#### 1.2.2 Pull Request 规范
|
||||
- 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。
|
||||
|
||||
- commit 信息要以`[文件名]: 描述信息` 的形式填写,例如 `README.md: fix xxx bug`。
|
||||
|
||||
- 如果是修复 bug,请在 PR 中给出描述信息。
|
||||
|
||||
- 合并代码需要两名维护人员参与:一人进行 review 后 approve,另一人再次 review,通过后即可合并。
|
||||
|
||||
## 2. 使用说明
|
||||
|
||||
```
|
||||
- node version > v8.6.0
|
||||
- golang version >= v1.11
|
||||
- IDE recommendation: Goland
|
||||
- After you clone the project, use the scripts in directory db to create your own database.
|
||||
- We recommend you to apply for your own cloud service in QINIU. Replace the public key, private key, warehouse name and default url address with your own, so as not to mess up the test database.
|
||||
- node版本 > v18.16.0
|
||||
- golang版本 >= v1.22
|
||||
- IDE推荐:Goland
|
||||
```
|
||||
|
||||
### 2.1 Web
|
||||
### 2.1 server项目
|
||||
|
||||
使用 `Goland` 等编辑工具,打开server目录,不可以打开 gin-vue-admin 根目录
|
||||
|
||||
```bash
|
||||
# clone the project
|
||||
git clone https://github.com/piexlmax/gin-vue-admin.git
|
||||
|
||||
# enter the project directory
|
||||
# 克隆项目
|
||||
git clone https://github.com/flipped-aurora/gin-vue-admin.git
|
||||
# 进入server文件夹
|
||||
cd server
|
||||
|
||||
# 使用 go mod 并安装go依赖包
|
||||
go generate
|
||||
|
||||
# 运行
|
||||
go run .
|
||||
|
||||
```
|
||||
|
||||
### 2.2 web项目
|
||||
|
||||
```bash
|
||||
# 进入web文件夹
|
||||
cd web
|
||||
|
||||
# install dependency
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# develop
|
||||
# 启动web项目
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### 2.2 Server
|
||||
### 2.3 swagger自动化API文档
|
||||
|
||||
```bash
|
||||
# using go.mod
|
||||
#### 2.3.1 安装 swagger
|
||||
|
||||
# install go modules
|
||||
go list (go mod tidy)
|
||||
|
||||
# build the server
|
||||
go build
|
||||
``` shell
|
||||
go install github.com/swaggo/swag/cmd/swag@latest
|
||||
```
|
||||
|
||||
### 2.3 API docs auto-generation using swagger
|
||||
#### 2.3.2 生成API文档
|
||||
|
||||
#### 2.3.1 install swagger
|
||||
|
||||
##### (1) Using VPN or outside mainland China
|
||||
````
|
||||
go get -u github.com/swaggo/swag/cmd/swag
|
||||
````
|
||||
|
||||
##### (2) In mainland China
|
||||
|
||||
In mainland China, access to go.org/x is prohibited,we recommend [goproxy.io](https://goproxy.io/zh/)
|
||||
|
||||
````bash
|
||||
|
||||
If you are using Go version 1.13 and above (recommended)
|
||||
# Enable Go Modules function
|
||||
go env -w GO111MODULE=on
|
||||
# Configure GOPROXY environment variables
|
||||
go env -w GOPROXY=https://goproxy.io,direct
|
||||
If you are using Go version 1.12 and below
|
||||
go env -w GO111MODULE=on
|
||||
go env -w GOPROXY=https://goproxy.io
|
||||
|
||||
# get swag
|
||||
go get -g -v github.com/swaggo/swag/cmd/swag
|
||||
|
||||
# cd GOPATH/src/github.com/swaggo/swag/cmd/swag
|
||||
go install
|
||||
````
|
||||
|
||||
#### 2.3.2 API docs generation
|
||||
|
||||
````
|
||||
```` shell
|
||||
cd server
|
||||
swag init
|
||||
````
|
||||
After executing the above command,`docs` will show in `server/`,then open your browser, jump into `http://localhost:8888/swagger/index.html` to see the swagger APIs.
|
||||
|
||||
> 执行上面的命令后,server目录下会出现docs文件夹里的 `docs.go`, `swagger.json`, `swagger.yaml` 三个文件更新,启动go服务之后, 在浏览器输入 [http://localhost:8888/swagger/index.html](http://localhost:8888/swagger/index.html) 即可查看swagger文档
|
||||
|
||||
## 3. Technical selection
|
||||
### 2.4 VSCode工作区
|
||||
|
||||
- Frontend: using `Element-UI` based on vue,to code the page.
|
||||
- Backend: using `Gin` to quickly build basic RESTful API. `Gin` is a web framework written in Go (Golang).
|
||||
- DB: `MySql`(5.6.44),using `gorm` to implement data manipulation, added support for SQLite databases.
|
||||
- Cache: using `Redis` to implement the recording of the JWT token of the currently active user and implement the multi-login restriction.
|
||||
- API: using Swagger to auto generate APIs docs。
|
||||
- Config: using `fsnotify` and `viper` to implement `yaml` config file。
|
||||
- Log: using `go-logging` record logs。
|
||||
#### 2.4.1 开发
|
||||
|
||||
## 4. Project Architecture
|
||||
使用`VSCode`打开根目录下的工作区文件`gin-vue-admin.code-workspace`,在边栏可以看到三个虚拟目录:`backend`、`frontend`、`root`。
|
||||
|
||||
### 4.1 Architecture Diagram
|
||||
#### 2.4.2 运行/调试
|
||||
|
||||

|
||||
在运行和调试中也可以看到三个task:`Backend`、`Frontend`、`Both (Backend & Frontend)`。运行`Both (Backend & Frontend)`可以同时启动前后端项目。
|
||||
|
||||
### 4.2 Front-end Detailed Design Diagram (Contributor: <a href="https://github.com/baobeisuper">baobeisuper</a>)
|
||||
#### 2.4.3 settings
|
||||
|
||||

|
||||
在工作区配置文件中有`go.toolsEnvVars`字段,是用于`VSCode`自身的go工具环境变量。此外在多go版本的系统中,可以通过`gopath`、`go.goroot`指定运行版本。
|
||||
|
||||
### 4.3 Project Layout
|
||||
```json
|
||||
"go.gopath": null,
|
||||
"go.goroot": null,
|
||||
```
|
||||
|
||||
## 3. 技术选型
|
||||
|
||||
- 前端:用基于 [Vue](https://vuejs.org) 的 [Element](https://github.com/ElemeFE/element) 构建基础页面。
|
||||
- 后端:用 [Gin](https://gin-gonic.com/) 快速搭建基础restful风格API,[Gin](https://gin-gonic.com/) 是一个go语言编写的Web框架。
|
||||
- 数据库:采用`MySql` > (5.7) 版本 数据库引擎 InnoDB,使用 [gorm](http://gorm.cn) 实现对数据库的基本操作。
|
||||
- 缓存:使用`Redis`实现记录当前活跃用户的`jwt`令牌并实现多点登录限制。
|
||||
- API文档:使用`Swagger`构建自动化文档。
|
||||
- 配置文件:使用 [fsnotify](https://github.com/fsnotify/fsnotify) 和 [viper](https://github.com/spf13/viper) 实现`yaml`格式的配置文件。
|
||||
- 日志:使用 [zap](https://github.com/uber-go/zap) 实现日志记录。
|
||||
|
||||
## 4. 项目架构
|
||||
|
||||
### 4.1 系统架构图
|
||||
|
||||

|
||||
|
||||
### 4.2 前端详细设计图 (提供者:<a href="https://github.com/baobeisuper">baobeisuper</a>)
|
||||
|
||||

|
||||
|
||||
### 4.3 目录结构
|
||||
|
||||
```
|
||||
├─server (backend)
|
||||
│ ├─api (API entrance)
|
||||
│ ├─config (config file)
|
||||
│ ├─core (core code)
|
||||
│ ├─db (db scripts)
|
||||
│ ├─docs (swagger APIs docs)
|
||||
│ ├─global (global objet)
|
||||
│ ├─initialiaze (initialiazation)
|
||||
│ ├─middleware (middle ware)
|
||||
│ ├─model (model and services)
|
||||
│ ├─resource (resources, such as static pages, templates)
|
||||
│ ├─router (routers)
|
||||
│ ├─service (services)
|
||||
│ └─utils (common utilities)
|
||||
└─web (frontend)
|
||||
├─public (deploy templates)
|
||||
└─src (source code)
|
||||
├─api (frontend APIs)
|
||||
├─assets (static files)
|
||||
├─components(components)
|
||||
├─router (frontend routers)
|
||||
├─store (vuex state management)
|
||||
├─style (common styles)
|
||||
├─utils (frontend common utilitie)
|
||||
└─view (pages)
|
||||
├── server
|
||||
├── api (api层)
|
||||
│ └── v1 (v1版本接口)
|
||||
├── config (配置包)
|
||||
├── core (核心文件)
|
||||
├── docs (swagger文档目录)
|
||||
├── global (全局对象)
|
||||
├── initialize (初始化)
|
||||
│ └── internal (初始化内部函数)
|
||||
├── middleware (中间件层)
|
||||
├── model (模型层)
|
||||
│ ├── request (入参结构体)
|
||||
│ └── response (出参结构体)
|
||||
├── packfile (静态文件打包)
|
||||
├── resource (静态资源文件夹)
|
||||
│ ├── excel (excel导入导出默认路径)
|
||||
│ ├── page (表单生成器)
|
||||
│ └── template (模板)
|
||||
├── router (路由层)
|
||||
├── service (service层)
|
||||
├── source (source层)
|
||||
└── utils (工具包)
|
||||
├── timer (定时器接口封装)
|
||||
└── upload (oss接口封装)
|
||||
|
||||
web
|
||||
├── babel.config.js
|
||||
├── Dockerfile
|
||||
├── favicon.ico
|
||||
├── index.html -- 主页面
|
||||
├── limit.js -- 助手代码
|
||||
├── package.json -- 包管理器代码
|
||||
├── src -- 源代码
|
||||
│ ├── api -- api 组
|
||||
│ ├── App.vue -- 主页面
|
||||
│ ├── assets -- 静态资源
|
||||
│ ├── components -- 全局组件
|
||||
│ ├── core -- gva 组件包
|
||||
│ │ ├── config.js -- gva网站配置文件
|
||||
│ │ ├── gin-vue-admin.js -- 注册欢迎文件
|
||||
│ │ └── global.js -- 统一导入文件
|
||||
│ ├── directive -- v-auth 注册文件
|
||||
│ ├── main.js -- 主文件
|
||||
│ ├── permission.js -- 路由中间件
|
||||
│ ├── pinia -- pinia 状态管理器,取代vuex
|
||||
│ │ ├── index.js -- 入口文件
|
||||
│ │ └── modules -- modules
|
||||
│ │ ├── dictionary.js
|
||||
│ │ ├── router.js
|
||||
│ │ └── user.js
|
||||
│ ├── router -- 路由声明文件
|
||||
│ │ └── index.js
|
||||
│ ├── style -- 全局样式
|
||||
│ │ ├── base.scss
|
||||
│ │ ├── basics.scss
|
||||
│ │ ├── element_visiable.scss -- 此处可以全局覆盖 element-plus 样式
|
||||
│ │ ├── iconfont.css -- 顶部几个icon的样式文件
|
||||
│ │ ├── main.scss
|
||||
│ │ ├── mobile.scss
|
||||
│ │ └── newLogin.scss
|
||||
│ ├── utils -- 方法包库
|
||||
│ │ ├── asyncRouter.js -- 动态路由相关
|
||||
│ │ ├── btnAuth.js -- 动态权限按钮相关
|
||||
│ │ ├── bus.js -- 全局mitt声明文件
|
||||
│ │ ├── date.js -- 日期相关
|
||||
│ │ ├── dictionary.js -- 获取字典方法
|
||||
│ │ ├── downloadImg.js -- 下载图片方法
|
||||
│ │ ├── format.js -- 格式整理相关
|
||||
│ │ ├── image.js -- 图片相关方法
|
||||
│ │ ├── page.js -- 设置页面标题
|
||||
│ │ ├── request.js -- 请求
|
||||
│ │ └── stringFun.js -- 字符串文件
|
||||
| ├── view -- 主要view代码
|
||||
| | ├── about -- 关于我们
|
||||
| | ├── dashboard -- 面板
|
||||
| | ├── error -- 错误
|
||||
| | ├── example --上传案例
|
||||
| | ├── iconList -- icon列表
|
||||
| | ├── init -- 初始化数据
|
||||
| | | ├── index -- 新版本
|
||||
| | | ├── init -- 旧版本
|
||||
| | ├── layout -- layout约束页面
|
||||
| | | ├── aside
|
||||
| | | ├── bottomInfo -- bottomInfo
|
||||
| | | ├── screenfull -- 全屏设置
|
||||
| | | ├── setting -- 系统设置
|
||||
| | | └── index.vue -- base 约束
|
||||
| | ├── login --登录
|
||||
| | ├── person --个人中心
|
||||
| | ├── superAdmin -- 超级管理员操作
|
||||
| | ├── system -- 系统检测页面
|
||||
| | ├── systemTools -- 系统配置相关页面
|
||||
| | └── routerHolder.vue -- page 入口页面
|
||||
├── vite.config.js -- vite 配置文件
|
||||
└── yarn.lock
|
||||
|
||||
```
|
||||
|
||||
## 5. Features
|
||||
## 5. 主要功能
|
||||
|
||||
- Authority management: Authority management based on `jwt` and `casbin`.
|
||||
- File upload & download: File upload operation based on Qiniu Cloud (In order to make it easier for everyone to test, I have provided various important tokens of my Qiniu test number, and I urge you not to make things a mess).
|
||||
- Pagination Encapsulation:The frontend uses mixins to encapsulate paging, and the paging method can call mixins
|
||||
- User management: The system administrator assigns user roles and role permissions.
|
||||
- Role management: Create the main object of permission control, and then assign different API permissions and menu permissions to the role.
|
||||
- Menu management: User dynamic menu configuration implementation, assigning different menus to different roles.
|
||||
- API management: Different users can call different API permissions.
|
||||
- Configuration management: The configuration file can be modified in the web page (the test environment does not provide this function).
|
||||
- Rich text editor: Embed MarkDown editor function.
|
||||
- Conditional search: Add an example of conditional search.
|
||||
- Restful example: You can see sample APIs in user management module.
|
||||
- 权限管理:基于`jwt`和`casbin`实现的权限管理。
|
||||
- 文件上传下载:实现基于`七牛云`, `阿里云`, `腾讯云` 的文件上传操作(请开发自己去各个平台的申请对应 `token` 或者对应`key`)。
|
||||
- 分页封装:前端使用 `mixins` 封装分页,分页方法调用 `mixins` 即可。
|
||||
- 用户管理:系统管理员分配用户角色和角色权限。
|
||||
- 角色管理:创建权限控制的主要对象,可以给角色分配不同api权限和菜单权限。
|
||||
- 菜单管理:实现用户动态菜单配置,实现不同角色不同菜单。
|
||||
- api管理:不同用户可调用的api接口的权限不同。
|
||||
- 配置管理:配置文件可前台修改(在线体验站点不开放此功能)。
|
||||
- 条件搜索:增加条件搜索示例。
|
||||
- restful示例:可以参考用户管理模块中的示例API。
|
||||
- 前端文件参考: [web/src/view/superAdmin/api/api.vue](https://github.com/flipped-aurora/gin-vue-admin/blob/master/web/src/view/superAdmin/api/api.vue)
|
||||
- 后台文件参考: [server/router/sys_api.go](https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/router/sys_api.go)
|
||||
- 多点登录限制:需要在`config.yaml`中把`system`中的`use-multipoint`修改为true(需要自行配置Redis和Config中的Redis参数,测试阶段,有bug请及时反馈)。
|
||||
- 分片上传:提供文件分片上传和大文件分片上传功能示例。
|
||||
- 表单生成器:表单生成器借助 [@Variant Form](https://github.com/vform666/variant-form) 。
|
||||
- 代码生成器:后台基础逻辑以及简单curd的代码生成器。
|
||||
|
||||
```
|
||||
fontend code file: src\view\superAdmin\api\api.vue
|
||||
backend code file: model\dnModel\api.go
|
||||
```
|
||||
- Multi-login restriction: Change `userMultipoint` to true in `system` in `config.yaml` (You need to configure redis and redis parameters yourself. During the test period, please report in time if there is a bug).
|
||||
- Upload file by chunk:Provides examples of file upload and large file upload by chunk.
|
||||
- Form Builder:With the help of [@form-generator](https://github.com/JakHuang/form-generator).
|
||||
- Code generator: Providing backend with basic logic and simple curd code generator.
|
||||
## 6. 知识库
|
||||
|
||||
## 6. To-do list
|
||||
|
||||
- [ ] upload & export Excel
|
||||
- [ ] e-chart
|
||||
- [ ] workflow, task transfer function
|
||||
- [ ] frontend independent mode, mock
|
||||
|
||||
## 7. Knowledge base
|
||||
|
||||
### 7.1 Team blog
|
||||
## 6.1 团队博客
|
||||
|
||||
> https://www.yuque.com/flipped-aurora
|
||||
>
|
||||
>There are video courses about frontend framework in our blo. If you think the project is helpful to you, you can add my personal WeChat:shouzi_1994,your comments is welcomed。
|
||||
>内有前端框架教学视频。如果觉得项目对您有所帮助可以添加我的个人微信:shouzi_1994,欢迎您提出宝贵的需求。
|
||||
|
||||
### 7.2 Video courses
|
||||
## 6.2 教学视频
|
||||
|
||||
(1) Development environment course
|
||||
> Bilibili:https://www.bilibili.com/video/BV1Fg4y187Bw/
|
||||
|
||||
(2) Template course
|
||||
> Bilibili:https://www.bilibili.com/video/BV16K4y1r7BD/
|
||||
(1)手把手教学视频
|
||||
|
||||
(3)2.0 version introduction and development experience
|
||||
> Bilibili:https://www.bilibili.com/video/BV1aV411d7Gm#reply2831798461
|
||||
> https://www.bilibili.com/video/BV1Rg411u7xH/
|
||||
|
||||
(4) Golang basic course (coming soon)
|
||||
(2)后端目录结构调整介绍以及使用方法
|
||||
|
||||
> https://space.bilibili.com/322210472/channel/detail?cid=108884
|
||||
> https://www.bilibili.com/video/BV1x44y117TT/
|
||||
|
||||
## 8. Contacts
|
||||
### 8.1 Groups
|
||||
#### QQ group: 622360840
|
||||
(3)golang基础教学视频
|
||||
|
||||
| QQ group |
|
||||
| :---: |
|
||||
| <img src="http://qmplusimg.henrongyi.top/qq.jpg" width="180"/> |
|
||||
> bilibili:https://space.bilibili.com/322210472/channel/detail?cid=108884
|
||||
|
||||
(4)gin框架基础教学
|
||||
|
||||
#### Wechat group: add anyone above, comment "加入gin-vue-admin交流群"
|
||||
> bilibili:https://space.bilibili.com/322210472/channel/detail?cid=126418&ctype=0
|
||||
|
||||
### 8.2 Team members
|
||||
| Jiang | Yan | Yin | Du | Yin | Song |
|
||||
| :---: | :---: | :---: | :---: | :---: | :---: |
|
||||
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryr.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qryx.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrdjl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrygl.png"> | <img width="150" src="http://qmplusimg.henrongyi.top/qrsong.png"> |
|
||||
(5)gin-vue-admin 版本更新介绍视频
|
||||
|
||||
| Nick name | Project position | First name |
|
||||
| ---- | ---- | ---- |
|
||||
| [@piexlmax](https://github.com/piexlmax) | Project sponsor | Jiang |
|
||||
| [@Ruio9244](https://github.com/Ruio9244) | Architect | Yan |
|
||||
| [@granty1](https://github.com/granty1) | Backend developer | Yin |
|
||||
| [@1319612909](https://github.com/1319612909) | UI developer | Du |
|
||||
| [@krank666](https://github.com/krank666) | Frontend developer | Yin |
|
||||
| [@chen-chen-up](https://github.com/chen-chen-up) | Novice developer | Song |
|
||||
| [@SliverHorn](https://github.com/SliverHorn) | Community Administrator | Lai |
|
||||
> bilibili:https://www.bilibili.com/video/BV1kv4y1g7nT
|
||||
|
||||
## 9. Donate
|
||||
## 7. 联系方式
|
||||
|
||||
If you find this project useful, you can buy author a glass of juice :tropical_drink: [here](http://doc.henrongyi.top/more/coffee.html)
|
||||
### 7.1 技术群
|
||||
|
||||
## 10. Commercial considerations
|
||||
### QQ交流群:971857775
|
||||
|
||||
If you use this project for commercial purposes, please comply with the Apache2.0 agreement and retain the author's technical support statement.
|
||||
### 微信交流群
|
||||
| 微信 |
|
||||
| :---: |
|
||||
| <img width="150" src="http://qmplusimg.henrongyi.top/qrjjz.png">
|
||||
|
||||
防止广告进群,添加微信,输入以下代码执行结果(请勿转码为string)
|
||||
|
||||
```
|
||||
str := "5Yqg5YWlR1ZB5Lqk5rWB576k"
|
||||
decodeBytes, err := base64.StdEncoding.DecodeString(str)
|
||||
fmt.Println(decodeBytes, err)
|
||||
```
|
||||
|
||||
### [关于我们](https://www.gin-vue-admin.com/about/join.html)
|
||||
|
||||
## 8. 贡献者
|
||||
|
||||
感谢您对gin-vue-admin的贡献!
|
||||
|
||||
<a href="https://openomy.app/github/flipped-aurora/gin-vue-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
||||
<img src="https://openomy.app/svg?repo=flipped-aurora/gin-vue-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
||||
</a>
|
||||
|
||||
## 9. 捐赠
|
||||
|
||||
如果你觉得这个项目对你有帮助,你可以请作者喝饮料 :tropical_drink: [点我](https://www.gin-vue-admin.com/coffee/index.html)
|
||||
|
||||
## 10. 注意事项
|
||||
|
||||
请严格遵守Apache 2.0协议并保留作品声明,去除版权信息请务必[获取授权](https://www.gin-vue-admin.com/empower/)
|
||||
未授权去除版权信息将依法追究法律责任
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security issues to qimiaojiangjizhao@gmail.com
|
||||
@@ -0,0 +1,90 @@
|
||||
version: "3"
|
||||
|
||||
# 声明一个名为network的networks,subnet为network的子网地址,默认网关是177.7.0.1
|
||||
networks:
|
||||
network:
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: '177.7.0.0/16'
|
||||
|
||||
# 设置mysql,redis持久化保存
|
||||
volumes:
|
||||
mysql:
|
||||
redis:
|
||||
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: ../../web
|
||||
dockerfile: ./Dockerfile
|
||||
container_name: gva-web
|
||||
restart: always
|
||||
ports:
|
||||
- '8080:8080'
|
||||
depends_on:
|
||||
- server
|
||||
command: [ 'nginx-debug', '-g', 'daemon off;' ]
|
||||
networks:
|
||||
network:
|
||||
ipv4_address: 177.7.0.11
|
||||
|
||||
server:
|
||||
build:
|
||||
context: ../../server
|
||||
dockerfile: ./Dockerfile
|
||||
container_name: gva-server
|
||||
restart: always
|
||||
ports:
|
||||
- '8888:8888'
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
links:
|
||||
- mysql
|
||||
- redis
|
||||
networks:
|
||||
network:
|
||||
ipv4_address: 177.7.0.12
|
||||
|
||||
mysql:
|
||||
image: mysql:8.0.21 # 如果您是 arm64 架构:如 MacOS 的 M1,请修改镜像为 image: mysql/mysql-server:8.0.21
|
||||
container_name: gva-mysql
|
||||
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci #设置utf8字符集
|
||||
restart: always
|
||||
ports:
|
||||
- "13306:3306" # host物理直接映射端口为13306
|
||||
environment:
|
||||
#MYSQL_ROOT_PASSWORD: 'Aa@6447985' # root管理员用户密码
|
||||
MYSQL_DATABASE: 'qmPlus' # 初始化启动时要创建的数据库的名称
|
||||
MYSQL_USER: 'gva'
|
||||
MYSQL_PASSWORD: 'Aa@6447985'
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "gva", "-pAa@6447985"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
volumes:
|
||||
- mysql:/var/lib/mysql
|
||||
networks:
|
||||
network:
|
||||
ipv4_address: 177.7.0.13
|
||||
|
||||
redis:
|
||||
image: redis:6.0.6
|
||||
container_name: gva-redis # 容器名
|
||||
restart: always
|
||||
ports:
|
||||
- '16379:6379'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
volumes:
|
||||
- redis:/data
|
||||
networks:
|
||||
network:
|
||||
ipv4_address: 177.7.0.14
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM centos:7
|
||||
WORKDIR /opt
|
||||
ENV LANG=en_US.utf8
|
||||
COPY deploy/docker/entrypoint.sh .
|
||||
COPY build/ /usr/share/nginx/html/
|
||||
COPY server/config.yaml /usr/share/nginx/html/config.yaml
|
||||
COPY web/.docker-compose/nginx/conf.d/nginx.conf /etc/nginx/conf.d/nginx.conf
|
||||
RUN set -ex \
|
||||
&& echo "LANG=en_US.utf8" > /etc/locale.conf \
|
||||
&& echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf \
|
||||
&& echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf \
|
||||
&& yum -y install epel-release \
|
||||
&& yum -y localinstall http://mirrors.ustc.edu.cn/mysql-repo/mysql57-community-release-el7.rpm \
|
||||
&& yum -y install mysql-community-server git redis nginx go npm --nogpgcheck && chmod +x ./entrypoint.sh \
|
||||
&& npm install -g yarn && go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct \
|
||||
&& echo "start" > /dev/null
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
if [ ! -d "/var/lib/mysql/gva" ]; then
|
||||
mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql
|
||||
mysqld --daemonize --user=mysql
|
||||
sleep 5s
|
||||
mysql -uroot -e "create database gva default charset 'utf8' collate 'utf8_bin'; grant all on gva.* to 'root'@'127.0.0.1' identified by '123456'; flush privileges;"
|
||||
else
|
||||
mysqld --daemonize --user=mysql
|
||||
fi
|
||||
redis-server &
|
||||
if [ "$1" = "actions" ]; then
|
||||
cd /opt/gva/server && go run main.go &
|
||||
cd /opt/gva/web/ && yarn serve &
|
||||
else
|
||||
/usr/sbin/nginx &
|
||||
cd /usr/share/nginx/html/ && ./server &
|
||||
fi
|
||||
echo "gva ALL start!!!"
|
||||
tail -f /dev/null
|
||||
@@ -0,0 +1,148 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: config.yaml
|
||||
annotations:
|
||||
flipped-aurora/gin-vue-admin: backend
|
||||
github: "https://github.com/flipped-aurora/gin-vue-admin.git"
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
labels:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
data:
|
||||
config.yaml: |
|
||||
# github.com/flipped-aurora/gin-vue-admin/server Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
expires-time: 604800
|
||||
buffer-time: 86400
|
||||
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: 'info'
|
||||
format: 'console'
|
||||
prefix: '[github.com/flipped-aurora/gin-vue-admin/server]'
|
||||
director: 'log'
|
||||
link-name: 'latest_log'
|
||||
show-line: true
|
||||
encode-level: 'LowercaseColorLevelEncoder'
|
||||
stacktrace-key: 'stacktrace'
|
||||
log-in-console: true
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
db: 0
|
||||
addr: '127.0.0.1:6379'
|
||||
password: ''
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: 'xxx@qq.com'
|
||||
port: 465
|
||||
from: 'xxx@163.com'
|
||||
host: 'smtp.163.com'
|
||||
is-ssl: true
|
||||
secret: 'xxx'
|
||||
nickname: 'test'
|
||||
|
||||
# casbin configuration
|
||||
casbin:
|
||||
model-path: './resource/rbac_model.conf'
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
env: 'develop' # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: 'mysql'
|
||||
oss-type: 'local' # 控制oss选择走本期还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-multipoint: false
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
|
||||
# mysql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://www.github.com/flipped-aurora/gin-vue-admin/server.com/docs/first)
|
||||
mysql:
|
||||
path: ''
|
||||
config: ''
|
||||
db-name: ''
|
||||
username: ''
|
||||
password: ''
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: false
|
||||
log-zap: ""
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: 'uploads/file'
|
||||
|
||||
# autocode configuration
|
||||
autocode:
|
||||
transfer-restart: true
|
||||
root: ""
|
||||
server: /server
|
||||
server-api: /api/v1/autocode
|
||||
server-initialize: /initialize
|
||||
server-model: /model/autocode
|
||||
server-request: /model/autocode/request/
|
||||
server-router: /router/autocode
|
||||
server-service: /service/autocode
|
||||
web: /web/src
|
||||
web-api: /api
|
||||
web-flow: /view
|
||||
web-form: /view
|
||||
web-table: /view
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: 'ZoneHuaDong'
|
||||
bucket: ''
|
||||
img-path: ''
|
||||
use-https: false
|
||||
access-key: ''
|
||||
secret-key: ''
|
||||
use-cdn-domains: false
|
||||
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: 'yourEndpoint'
|
||||
access-key-id: 'yourAccessKeyId'
|
||||
access-key-secret: 'yourAccessKeySecret'
|
||||
bucket-name: 'yourBucketName'
|
||||
bucket-url: 'yourBucketUrl'
|
||||
base-path: 'yourBasePath'
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: 'xxxxx-10005608'
|
||||
region: 'ap-shanghai'
|
||||
secret-id: 'xxxxxxxx'
|
||||
secret-key: 'xxxxxxxx'
|
||||
base-url: 'https://gin.vue.admin'
|
||||
path-prefix: 'github.com/flipped-aurora/gin-vue-admin/server'
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: './resource/excel/'
|
||||
|
||||
|
||||
# timer task db clear table
|
||||
Timer:
|
||||
start: true
|
||||
spec: "@daily" # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3
|
||||
detail: [
|
||||
# tableName: 需要清理的表名
|
||||
# compareField: 需要比较时间的字段
|
||||
# interval: 时间间隔, 具体配置详看 time.ParseDuration() 中字符串表示 且不能为负数
|
||||
# 2160h = 24 * 30 * 3 -> 三个月
|
||||
{ tableName: "sys_operation_records" , compareField: "created_at", interval: "2160h" },
|
||||
{ tableName: "jwt_blacklists" , compareField: "created_at", interval: "168h" }
|
||||
#{ tableName: "log2" , compareField: "created_at", interval: "2160h" }
|
||||
]
|
||||
@@ -0,0 +1,74 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gva-server
|
||||
annotations:
|
||||
flipped-aurora/gin-vue-admin: backend
|
||||
github: "https://github.com/flipped-aurora/gin-vue-admin.git"
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
labels:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
spec:
|
||||
containers:
|
||||
- name: gin-vue-admin-container
|
||||
image: registry.cn-hangzhou.aliyuncs.com/gva/server:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8888
|
||||
name: http
|
||||
volumeMounts:
|
||||
- mountPath: /go/src/github.com/flipped-aurora/gin-vue-admin/server/config.docker.yaml
|
||||
name: config
|
||||
subPath: config.yaml
|
||||
- mountPath: /etc/localtime
|
||||
name: localtime
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 2000Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 200Mi
|
||||
livenessProbe:
|
||||
failureThreshold: 1
|
||||
periodSeconds: 5
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 8888
|
||||
timeoutSeconds: 1
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 5
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 8888
|
||||
timeoutSeconds: 1
|
||||
startupProbe:
|
||||
failureThreshold: 40
|
||||
periodSeconds: 5
|
||||
successThreshold: 1
|
||||
tcpSocket:
|
||||
port: 8888
|
||||
timeoutSeconds: 1
|
||||
#imagePullSecrets:
|
||||
# - name: docker-registry
|
||||
volumes:
|
||||
- name: localtime
|
||||
hostPath:
|
||||
path: /etc/localtime
|
||||
- name: config
|
||||
configMap:
|
||||
name: config.yaml
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gva-server
|
||||
annotations:
|
||||
flipped-aurora/gin-vue-admin: backend
|
||||
github: "https://github.com/flipped-aurora/gin-vue-admin.git"
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
labels:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
spec:
|
||||
selector:
|
||||
app: gva-server
|
||||
version: gva-vue3
|
||||
ports:
|
||||
- port: 8888
|
||||
name: http
|
||||
targetPort: 8888
|
||||
type: ClusterIP
|
||||
# type: NodePort
|
||||
@@ -0,0 +1,32 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: my.conf
|
||||
data:
|
||||
my.conf: |
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log logs/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
rewrite ^/api/(.*)$ /$1 break; #重写
|
||||
proxy_pass http://gva-server:8888; # 设置代理服务器的协议和地址
|
||||
}
|
||||
|
||||
location /api/swagger/index.html {
|
||||
proxy_pass http://gva-server:8888/swagger/index.html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: gva-web
|
||||
annotations:
|
||||
flipped-aurora/gin-vue-admin: ui
|
||||
github: "https://github.com/flipped-aurora/gin-vue-admin.git"
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
labels:
|
||||
app: gva-web
|
||||
version: gva-vue3
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: gva-web
|
||||
version: gva-vue3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: gva-web
|
||||
version: gva-vue3
|
||||
spec:
|
||||
containers:
|
||||
- name: gin-vue-admin-nginx-container
|
||||
image: registry.cn-hangzhou.aliyuncs.com/gva/web:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 1000Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 100Mi
|
||||
volumeMounts:
|
||||
- mountPath: /etc/nginx/conf.d/
|
||||
name: nginx-config
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: my.conf
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: gva-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
spec:
|
||||
rules:
|
||||
- host: demo.gin-vue-admin.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: gva-web
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: gva-web
|
||||
annotations:
|
||||
flipped-aurora/gin-vue-admin: ui
|
||||
github: "https://github.com/flipped-aurora/gin-vue-admin.git"
|
||||
app.kubernetes.io/version: 0.0.1
|
||||
labels:
|
||||
app: gva-web
|
||||
version: gva-vue3
|
||||
spec:
|
||||
# type: NodePort
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: gva-web
|
||||
version: gva-vue3
|
||||
@@ -1,31 +0,0 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./dockerfile_server
|
||||
container_name: gva-server # 容器名
|
||||
restart: always
|
||||
ports:
|
||||
- '8888:8888'
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
|
||||
mysql:
|
||||
image: registry.cn-shanghai.aliyuncs.com/gva/gva-mysql:1.1
|
||||
container_name: gva-mysql
|
||||
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci #设置utf8字符集
|
||||
restart: always
|
||||
ports:
|
||||
- "13306:3306" # host物理直接映射端口为6606
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "Aa@6447985" # root管理员用户密码
|
||||
|
||||
redis:
|
||||
image: redis:6.0.6
|
||||
container_name: gva-redis # 容器名
|
||||
restart: always
|
||||
ports:
|
||||
- '6379:6379'
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
envsubst '$API_SERVER' < /etc/nginx/nginx.conf.tpl > /etc/nginx/nginx.conf
|
||||
env nginx
|
||||
./gvadmin
|
||||
@@ -1,56 +0,0 @@
|
||||
daemon on;
|
||||
worker_processes 50;
|
||||
#error_log /dev/stdout warn;
|
||||
error_log /var/log/nginx/error.log error;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
# See http://licson.net/post/optimizing-nginx-for-large-file-delivery/ for more detail
|
||||
# This optimizes the server for HLS fragment delivery
|
||||
sendfile off;
|
||||
#tcp_nopush on;
|
||||
keepalive_timeout 65;
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
#access_log /dev/stdout combined;
|
||||
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
# ssl_session_cache shared:SSL:10m;
|
||||
# ssl_session_timeout 10m;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
# Uncomment these lines to enable SSL.
|
||||
# Update the ssl paths with your own certificate and private key.
|
||||
# listen 443 ssl;
|
||||
# ssl_certificate /opt/certs/example.com.crt;
|
||||
# ssl_certificate_key /opt/certs/example.com.key;
|
||||
location / {
|
||||
root /var/www;
|
||||
try_files $uri $uri/ /index.html;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
location /v1/ {
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_pass ${API_SERVER} ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
rm -f ./core/server.go
|
||||
# 生成server.go文件, 添加Router.Static("/admin", "./resource/dist")这个代码
|
||||
touch ./core/server.go
|
||||
filename="./core/server.go"
|
||||
cat>"${filename}"<<EOF
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/initialize"
|
||||
"time"
|
||||
)
|
||||
|
||||
type server interface {
|
||||
ListenAndServe() error
|
||||
}
|
||||
|
||||
func RunWindowsServer() {
|
||||
if global.GVA_CONFIG.System.UseMultipoint {
|
||||
// 初始化redis服务
|
||||
initialize.Redis()
|
||||
}
|
||||
Router := initialize.Routers()
|
||||
Router.Static("/form-generator", "./resource/page")
|
||||
Router.Static("/admin", "./resource/dist")
|
||||
|
||||
//InstallPlugs(Router)
|
||||
// end 插件描述
|
||||
|
||||
address := fmt.Sprintf(":%d", global.GVA_CONFIG.System.Addr)
|
||||
s := initServer(address, Router)
|
||||
// 保证文本顺序输出
|
||||
// In order to ensure that the text order output can be deleted
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
global.GVA_LOG.Debug("server run success on ", address)
|
||||
|
||||
fmt.Printf("欢迎使用 Gin-Vue-Admin默认自动化文档地址:http://127.0.0.1%s/swagger/index.html\n 默认前端文件运行地址:http://127.0.0.1:8888/admin\n", address)
|
||||
global.GVA_LOG.Error(s.ListenAndServe())
|
||||
}
|
||||
EOF
|
||||
|
||||
rm -f ./config.yaml
|
||||
# 生成config.yaml文件, 用于docker-compose的使用
|
||||
touch ./config.yaml
|
||||
filename="./config.yaml"
|
||||
cat>"${filename}"<<EOF
|
||||
# Gin-Vue-Admin Global Configuration
|
||||
|
||||
# casbin configuration
|
||||
casbin:
|
||||
model-path: './resource/rbac_model.conf'
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
|
||||
# mysql connect configuration
|
||||
mysql:
|
||||
username: root
|
||||
password: 'Aa@6447985'
|
||||
path: mysql
|
||||
db-name: 'qmPlus'
|
||||
config: 'charset=utf8&parseTime=True&loc=Local'
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 10
|
||||
log-mode: true
|
||||
|
||||
#sqlite 配置
|
||||
sqlite:
|
||||
path: db.db
|
||||
log-mode: true
|
||||
config: 'loc=Asia/Shanghai'
|
||||
|
||||
# oss configuration
|
||||
|
||||
# 请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址
|
||||
qiniu:
|
||||
access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
|
||||
secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
|
||||
bucket: 'qm-plus-img'
|
||||
img-path: 'http://qmplusimg.henrongyi.top'
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
addr: redis:6379
|
||||
password: ''
|
||||
db: 0
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
use-multipoint: true
|
||||
env: 'public' # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: "mysql" # support mysql/sqlite
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
|
||||
# logger configuration
|
||||
log:
|
||||
prefix: '[GIN-VUE-ADMIN]'
|
||||
log-file: true
|
||||
stdout: 'DEBUG'
|
||||
file: 'DEBUG'
|
||||
EOF
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
rm -f .env.production
|
||||
touch .env.production
|
||||
filename="./.env.production"
|
||||
cat>"${filename}"<<EOF
|
||||
ENV = 'production'
|
||||
VUE_APP_BASE_API = ''
|
||||
EOF
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
FROM node:12.16.1 as gva-web
|
||||
|
||||
WORKDIR /gva_web/
|
||||
COPY web/ .
|
||||
|
||||
RUN cat .env.production
|
||||
COPY docker/web-handle.sh .
|
||||
RUN sh ./web-handle.sh
|
||||
RUN cat .env.production
|
||||
RUN rm -f web-handle.sh
|
||||
|
||||
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
|
||||
RUN cnpm install || npm install
|
||||
RUN npm run build
|
||||
|
||||
FROM golang:alpine as gva-server
|
||||
|
||||
ENV GO111MODULE=on
|
||||
ENV GOPROXY=https://goproxy.io,direct
|
||||
WORKDIR /go/src/gin-vue-admin
|
||||
COPY server/ ./
|
||||
|
||||
RUN cat ./core/server.go
|
||||
RUN cat ./config.yaml
|
||||
COPY docker/server-handle.sh .
|
||||
RUN sh ./server-handle.sh
|
||||
RUN rm -f server-handle.sh
|
||||
RUN cat ./core/server.go
|
||||
RUN cat ./config.yaml
|
||||
|
||||
RUN go env && go list && go build -o gva-server .
|
||||
|
||||
|
||||
FROM nginx:alpine
|
||||
LABEL MAINTAINER="SliverHorn"
|
||||
|
||||
WORKDIR gva/
|
||||
|
||||
# copy web
|
||||
COPY --from=gva-web /gva_web/dist ./resource/dist
|
||||
# copy server
|
||||
COPY --from=gva-server /go/src/gin-vue-admin/gva-server ./
|
||||
COPY --from=gva-server /go/src/gin-vue-admin/config.yaml ./
|
||||
COPY --from=gva-server /go/src/gin-vue-admin/resource ./resource
|
||||
|
||||
|
||||
EXPOSE 8888
|
||||
|
||||
ENTRYPOINT ./gva-server
|
||||
|
||||
# 根据Dockerfile生成Docker镜像
|
||||
|
||||
# docker build -t gva-server:1.0 .
|
||||
|
||||
#- 根据Docker镜像启动Docker容器
|
||||
# - 后台运行
|
||||
# - ```
|
||||
# docker run -d -p 8888:8888 --name gva-server-v1 gva-server:1.0
|
||||
# ```
|
||||
# - 以可交互模式运行, Ctrl + p + q
|
||||
# - ```
|
||||
# docker run -it -p 8888:8888 --name gva-server-v1 gva-server:1.0
|
||||
# ```
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "server",
|
||||
"name": "backend"
|
||||
},
|
||||
{
|
||||
"path": "web",
|
||||
"name": "frontend"
|
||||
},
|
||||
{
|
||||
"path": ".",
|
||||
"name": "root"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"go.toolsEnvVars": {
|
||||
"GOPROXY": "https://goproxy.cn,direct",
|
||||
"GONOPROXY": "none;"
|
||||
}
|
||||
},
|
||||
"launch": {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"name": "Backend",
|
||||
"cwd": "${workspaceFolder:backend}",
|
||||
"program": "${workspaceFolder:backend}/"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder:frontend}",
|
||||
"name": "Frontend",
|
||||
"runtimeExecutable": "npm",
|
||||
"runtimeArgs": ["run-script", "serve"]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Both (Backend & Frontend)",
|
||||
"configurations": ["Backend", "Frontend"],
|
||||
"stopAll": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Generated
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
+26
-14
@@ -1,19 +1,31 @@
|
||||
FROM golang:alpine as builder
|
||||
|
||||
# 设置go mod proxy 国内代理
|
||||
# 设置golang path
|
||||
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||
GO111MODULE=on \
|
||||
CGO_ENABLED=1
|
||||
WORKDIR /ginvue
|
||||
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
|
||||
WORKDIR /go/src/github.com/flipped-aurora/gin-vue-admin/server
|
||||
COPY . .
|
||||
RUN go env && go list && go build -o app main.go
|
||||
|
||||
RUN go env -w GO111MODULE=on \
|
||||
&& go env -w GOPROXY=https://goproxy.cn,direct \
|
||||
&& go env -w CGO_ENABLED=0 \
|
||||
&& go env \
|
||||
&& go mod tidy \
|
||||
&& go build -o server .
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com"
|
||||
# 设置时区
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN apk update && apk add --no-cache tzdata openntpd \
|
||||
&& ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
WORKDIR /go/src/github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
COPY --from=0 /go/src/github.com/flipped-aurora/gin-vue-admin/server/server ./
|
||||
COPY --from=0 /go/src/github.com/flipped-aurora/gin-vue-admin/server/resource ./resource/
|
||||
COPY --from=0 /go/src/github.com/flipped-aurora/gin-vue-admin/server/config.docker.yaml ./
|
||||
|
||||
# 挂载目录:如果使用了sqlite数据库,容器命令示例:docker run -d -v /宿主机路径/gva.db:/go/src/github.com/flipped-aurora/gin-vue-admin/server/gva.db -p 8888:8888 --name gva-server-v1 gva-server:1.0
|
||||
# VOLUME ["/go/src/github.com/flipped-aurora/gin-vue-admin/server"]
|
||||
|
||||
EXPOSE 8888
|
||||
ENTRYPOINT /ginvue/app
|
||||
|
||||
# 根据Dockerfile生成Docker镜像
|
||||
# docker build -t ginvue .
|
||||
# 根据Docker镜像启动Docker容器
|
||||
# docker run -itd -p 8888:8888 --name ginvue ginvue
|
||||
ENTRYPOINT ./server -c config.docker.yaml
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
## server项目结构
|
||||
|
||||
```shell
|
||||
├── api
|
||||
│ └── v1
|
||||
├── config
|
||||
├── core
|
||||
├── docs
|
||||
├── global
|
||||
├── initialize
|
||||
│ └── internal
|
||||
├── middleware
|
||||
├── model
|
||||
│ ├── request
|
||||
│ └── response
|
||||
├── packfile
|
||||
├── resource
|
||||
│ ├── excel
|
||||
│ ├── page
|
||||
│ └── template
|
||||
├── router
|
||||
├── service
|
||||
├── source
|
||||
└── utils
|
||||
├── timer
|
||||
└── upload
|
||||
```
|
||||
|
||||
| 文件夹 | 说明 | 描述 |
|
||||
| ------------ | ----------------------- | --------------------------- |
|
||||
| `api` | api层 | api层 |
|
||||
| `--v1` | v1版本接口 | v1版本接口 |
|
||||
| `config` | 配置包 | config.yaml对应的配置结构体 |
|
||||
| `core` | 核心文件 | 核心组件(zap, viper, server)的初始化 |
|
||||
| `docs` | swagger文档目录 | swagger文档目录 |
|
||||
| `global` | 全局对象 | 全局对象 |
|
||||
| `initialize` | 初始化 | router,redis,gorm,validator, timer的初始化 |
|
||||
| `--internal` | 初始化内部函数 | gorm 的 longger 自定义,在此文件夹的函数只能由 `initialize` 层进行调用 |
|
||||
| `middleware` | 中间件层 | 用于存放 `gin` 中间件代码 |
|
||||
| `model` | 模型层 | 模型对应数据表 |
|
||||
| `--request` | 入参结构体 | 接收前端发送到后端的数据。 |
|
||||
| `--response` | 出参结构体 | 返回给前端的数据结构体 |
|
||||
| `packfile` | 静态文件打包 | 静态文件打包 |
|
||||
| `resource` | 静态资源文件夹 | 负责存放静态文件 |
|
||||
| `--excel` | excel导入导出默认路径 | excel导入导出默认路径 |
|
||||
| `--page` | 表单生成器 | 表单生成器 打包后的dist |
|
||||
| `--template` | 模板 | 模板文件夹,存放的是代码生成器的模板 |
|
||||
| `router` | 路由层 | 路由层 |
|
||||
| `service` | service层 | 存放业务逻辑问题 |
|
||||
| `source` | source层 | 存放初始化数据的函数 |
|
||||
| `utils` | 工具包 | 工具函数封装 |
|
||||
| `--timer` | timer | 定时器接口封装 |
|
||||
| `--upload` | oss | oss接口封装 |
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/example"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/api/v1/system"
|
||||
)
|
||||
|
||||
var ApiGroupApp = new(ApiGroup)
|
||||
|
||||
type ApiGroup struct {
|
||||
SystemApiGroup system.ApiGroup
|
||||
ExampleApiGroup example.ApiGroup
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 断点续传到服务器
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "an example for breakpoint resume, 断点续传示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /fileUploadAndDownload/breakpointContinue [post]
|
||||
func BreakpointContinue(c *gin.Context) {
|
||||
fileMd5 := c.Request.FormValue("fileMd5")
|
||||
fileName := c.Request.FormValue("fileName")
|
||||
chunkMd5 := c.Request.FormValue("chunkMd5")
|
||||
chunkNumber, _ := strconv.Atoi(c.Request.FormValue("chunkNumber"))
|
||||
chunkTotal, _ := strconv.Atoi(c.Request.FormValue("chunkTotal"))
|
||||
_, FileHeader, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
f, err := FileHeader.Open()
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
cen, _ := ioutil.ReadAll(f)
|
||||
if flag := utils.CheckMd5(cen, chunkMd5); !flag {
|
||||
return
|
||||
}
|
||||
err, file := service.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err, pathc := utils.BreakPointContinue(cen, fileName, chunkNumber, chunkTotal, fileMd5)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err = service.CreateFileChunk(file.ID, pathc, chunkNumber); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("切片创建成功", c)
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "Find the file, 查找文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func FindFile(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
chunkTotal, _ := strconv.Atoi(c.Query("chunkTotal"))
|
||||
err, file := service.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
response.FailWithMessage("查找失败", c)
|
||||
} else {
|
||||
response.OkWithData(resp.FileResponse{File: file}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件完成"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"file uploaded, 文件创建成功"}"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func BreakpointContinueFinish(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
err, filePath := utils.MakeFile(fileName, fileMd5)
|
||||
if err != nil {
|
||||
response.FailWithDetailed(response.ERROR, resp.FilePathResponse{FilePath: filePath}, fmt.Sprintf("文件创建失败:%v", err), c)
|
||||
} else {
|
||||
response.OkDetailed(resp.FilePathResponse{FilePath: filePath}, "文件创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除切片
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "删除缓存切片"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/removeChunk [post]
|
||||
func RemoveChunk(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
filePath := c.Query("filePath")
|
||||
err := utils.RemoveChunk(fileMd5)
|
||||
err = service.DeleteFileChunk(fileMd5, fileName, filePath)
|
||||
if err != nil {
|
||||
response.FailWithDetailed(response.ERROR, resp.FilePathResponse{FilePath: filePath}, fmt.Sprintf("缓存切片删除失败:%v", err), c)
|
||||
} else {
|
||||
response.OkDetailed(resp.FilePathResponse{FilePath: filePath}, "缓存切片删除成功", c)
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.ExaCustomer true "创建客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/customer [post]
|
||||
func CreateExaCustomer(c *gin.Context) {
|
||||
var cu model.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
CustomerVerify := utils.Rules{
|
||||
"CustomerName": {utils.NotEmpty()},
|
||||
"CustomerPhoneData": {utils.NotEmpty()},
|
||||
}
|
||||
CustomerVerifyErr := utils.Verify(cu, CustomerVerify)
|
||||
if CustomerVerifyErr != nil {
|
||||
response.FailWithMessage(CustomerVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
cu.SysUserID = waitUse.ID
|
||||
cu.SysUserAuthorityID = waitUse.AuthorityId
|
||||
err := service.CreateExaCustomer(cu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 删除客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.ExaCustomer true "删除客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/customer [delete]
|
||||
func DeleteExaCustomer(c *gin.Context) {
|
||||
var cu model.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
CustomerVerify := utils.Rules{
|
||||
"ID": {utils.NotEmpty()},
|
||||
}
|
||||
CustomerVerifyErr := utils.Verify(cu.Model, CustomerVerify)
|
||||
if CustomerVerifyErr != nil {
|
||||
response.FailWithMessage(CustomerVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.DeleteExaCustomer(cu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 更新客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.ExaCustomer true "创建客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/customer [put]
|
||||
func UpdateExaCustomer(c *gin.Context) {
|
||||
var cu model.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
IdCustomerVerify := utils.Rules{
|
||||
"ID": {utils.NotEmpty()},
|
||||
}
|
||||
IdCustomerVerifyErr := utils.Verify(cu.Model, IdCustomerVerify)
|
||||
if IdCustomerVerifyErr != nil {
|
||||
response.FailWithMessage(IdCustomerVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
CustomerVerify := utils.Rules{
|
||||
"CustomerName": {utils.NotEmpty()},
|
||||
"CustomerPhoneData": {utils.NotEmpty()},
|
||||
}
|
||||
CustomerVerifyErr := utils.Verify(cu, CustomerVerify)
|
||||
if CustomerVerifyErr != nil {
|
||||
response.FailWithMessage(CustomerVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.UpdateExaCustomer(&cu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取单一客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.ExaCustomer true "获取单一客户信息"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/customer [get]
|
||||
func GetExaCustomer(c *gin.Context) {
|
||||
var cu model.ExaCustomer
|
||||
_ = c.ShouldBindQuery(&cu)
|
||||
IdCustomerVerify := utils.Rules{
|
||||
"ID": {utils.NotEmpty()},
|
||||
}
|
||||
IdCustomerVerifyErr := utils.Verify(cu.Model, IdCustomerVerify)
|
||||
if IdCustomerVerifyErr != nil {
|
||||
response.FailWithMessage(IdCustomerVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, customer := service.GetExaCustomer(cu.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.ExaCustomerResponse{Customer: customer}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取权限客户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "获取权限客户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/customerList [get]
|
||||
func GetExaCustomerList(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindQuery(&pageInfo)
|
||||
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
|
||||
if PageVerifyErr != nil {
|
||||
response.FailWithMessage(PageVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, customerList, total := service.GetCustomerInfoList(waitUse.AuthorityId, pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: customerList,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 上传文件示例
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /fileUploadAndDownload/upload [post]
|
||||
func UploadFile(c *gin.Context) {
|
||||
noSave := c.DefaultQuery("noSave", "0")
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
|
||||
} else {
|
||||
// 文件上传后拿到文件路径
|
||||
err, filePath, key := utils.Upload(header)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
|
||||
} else {
|
||||
// 修改数据库后得到修改后的user并且返回供前端使用
|
||||
var file model.ExaFileUploadAndDownload
|
||||
file.Url = filePath
|
||||
file.Name = header.Filename
|
||||
s := strings.Split(file.Name, ".")
|
||||
file.Tag = s[len(s)-1]
|
||||
file.Key = key
|
||||
if noSave == "0" {
|
||||
err = service.Upload(file)
|
||||
}
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("修改数据库链接失败,%v", err), c)
|
||||
} else {
|
||||
response.OkDetailed(resp.ExaFileResponse{File: file}, "上传成功", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body model.ExaFileUploadAndDownload true "传入文件里面id即可"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /fileUploadAndDownload/deleteFile [post]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
var file model.ExaFileUploadAndDownload
|
||||
_ = c.ShouldBindJSON(&file)
|
||||
err, f := service.FindFile(file.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
err = utils.DeleteFile(f.Key)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
|
||||
} else {
|
||||
err = service.DeleteFile(f)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 分页文件列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "分页获取文件户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /fileUploadAndDownload/getFileList [post]
|
||||
func GetFileList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := service.GetFileRecordInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SimpleUploader
|
||||
// @Summary 断点续传插件版示例
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "断点续传插件版示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /simpleUploader/upload [post]
|
||||
func SimpleUploaderUpload(c *gin.Context) {
|
||||
var chunk model.ExaSimpleUploader
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
chunk.Filename = c.PostForm("filename")
|
||||
chunk.ChunkNumber = c.PostForm("chunkNumber")
|
||||
chunk.CurrentChunkSize = c.PostForm("currentChunkSize")
|
||||
chunk.Identifier = c.PostForm("identifier")
|
||||
chunk.TotalSize = c.PostForm("totalSize")
|
||||
chunk.TotalChunks = c.PostForm("totalChunks")
|
||||
var chunkDir = "./chunk/" + chunk.Identifier + "/"
|
||||
hasDir, _ := utils.PathExists(chunkDir)
|
||||
if !hasDir {
|
||||
utils.CreateDir(chunkDir)
|
||||
}
|
||||
chunkPath := chunkDir + chunk.Filename + chunk.ChunkNumber
|
||||
err = c.SaveUploadedFile(header, chunkPath)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("切片创建失败,%v", err), c)
|
||||
return
|
||||
}
|
||||
chunk.CurrentChunkPath = chunkPath
|
||||
err = service.SaveChunk(chunk)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("切片创建失败,%v", err), c)
|
||||
return
|
||||
} else {
|
||||
response.Ok(c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SimpleUploader
|
||||
// @Summary 断点续传插件版示例
|
||||
// @Security ApiKeyAuth
|
||||
|
||||
// @Produce application/json
|
||||
// @Param md5 query string true "测试文件是否已经存在和判断已经上传过的切片"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /simpleUploader/checkFileMd5 [get]
|
||||
func CheckFileMd5(c *gin.Context) {
|
||||
md5 := c.Query("md5")
|
||||
err, chunks, isDone := service.CheckFileMd5(md5)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("md5读取失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{
|
||||
"chunks": chunks,
|
||||
"isDone": isDone,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SimpleUploader
|
||||
// @Summary 合并文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param md5 query string true "合并文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"合并成功"}"
|
||||
// @Router /simpleUploader/mergeFileMd5 [get]
|
||||
func MergeFileMd5(c *gin.Context) {
|
||||
md5 := c.Query("md5")
|
||||
fileName := c.Query("fileName")
|
||||
err := service.MergeFileMd5(md5, fileName)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("md5读取失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{}, c)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package example
|
||||
|
||||
import "github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
|
||||
type ApiGroup struct {
|
||||
CustomerApi
|
||||
FileUploadAndDownloadApi
|
||||
AttachmentCategoryApi
|
||||
}
|
||||
|
||||
var (
|
||||
customerService = service.ServiceGroupApp.ExampleServiceGroup.CustomerService
|
||||
fileUploadAndDownloadService = service.ServiceGroupApp.ExampleServiceGroup.FileUploadAndDownloadService
|
||||
attachmentCategoryService = service.ServiceGroupApp.ExampleServiceGroup.AttachmentCategoryService
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
common "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AttachmentCategoryApi struct{}
|
||||
|
||||
// GetCategoryList
|
||||
// @Tags GetCategoryList
|
||||
// @Summary 媒体库分类列表
|
||||
// @Security AttachmentCategory
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=example.ExaAttachmentCategory,msg=string} "媒体库分类列表"
|
||||
// @Router /attachmentCategory/getCategoryList [get]
|
||||
func (a *AttachmentCategoryApi) GetCategoryList(c *gin.Context) {
|
||||
res, err := attachmentCategoryService.GetCategoryList()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取分类列表失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取分类列表失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(res, c)
|
||||
}
|
||||
|
||||
// AddCategory
|
||||
// @Tags AddCategory
|
||||
// @Summary 添加媒体库分类
|
||||
// @Security AttachmentCategory
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaAttachmentCategory true "媒体库分类数据"// @Success 200 {object} response.Response{msg=string} "添加媒体库分类"
|
||||
// @Router /attachmentCategory/addCategory [post]
|
||||
func (a *AttachmentCategoryApi) AddCategory(c *gin.Context) {
|
||||
var req example.ExaAttachmentCategory
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
global.GVA_LOG.Error("参数错误!", zap.Error(err))
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := attachmentCategoryService.AddCategory(&req); err != nil {
|
||||
global.GVA_LOG.Error("创建/更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建/更新失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建/更新成功", c)
|
||||
}
|
||||
|
||||
// DeleteCategory
|
||||
// @Tags DeleteCategory
|
||||
// @Summary 删除分类
|
||||
// @Security AttachmentCategory
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body common.GetById true "分类id"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除分类"
|
||||
// @Router /attachmentCategory/deleteCategory [post]
|
||||
func (a *AttachmentCategoryApi) DeleteCategory(c *gin.Context) {
|
||||
var req common.GetById
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if req.ID == 0 {
|
||||
response.FailWithMessage("参数错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err := attachmentCategoryService.DeleteCategory(&req.ID); err != nil {
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
exampleRes "github.com/flipped-aurora/gin-vue-admin/server/model/example/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// BreakpointContinue
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 断点续传到服务器
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "an example for breakpoint resume, 断点续传示例"
|
||||
// @Success 200 {object} response.Response{msg=string} "断点续传到服务器"
|
||||
// @Router /fileUploadAndDownload/breakpointContinue [post]
|
||||
func (b *FileUploadAndDownloadApi) BreakpointContinue(c *gin.Context) {
|
||||
fileMd5 := c.Request.FormValue("fileMd5")
|
||||
fileName := c.Request.FormValue("fileName")
|
||||
chunkMd5 := c.Request.FormValue("chunkMd5")
|
||||
chunkNumber, _ := strconv.Atoi(c.Request.FormValue("chunkNumber"))
|
||||
chunkTotal, _ := strconv.Atoi(c.Request.FormValue("chunkTotal"))
|
||||
_, FileHeader, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("接收文件失败!", zap.Error(err))
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
f, err := FileHeader.Open()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("文件读取失败!", zap.Error(err))
|
||||
response.FailWithMessage("文件读取失败", c)
|
||||
return
|
||||
}
|
||||
defer func(f multipart.File) {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}(f)
|
||||
cen, _ := io.ReadAll(f)
|
||||
if !utils.CheckMd5(cen, chunkMd5) {
|
||||
global.GVA_LOG.Error("检查md5失败!", zap.Error(err))
|
||||
response.FailWithMessage("检查md5失败", c)
|
||||
return
|
||||
}
|
||||
file, err := fileUploadAndDownloadService.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查找或创建记录失败!", zap.Error(err))
|
||||
response.FailWithMessage("查找或创建记录失败", c)
|
||||
return
|
||||
}
|
||||
pathC, err := utils.BreakPointContinue(cen, fileName, chunkNumber, chunkTotal, fileMd5)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("断点续传失败!", zap.Error(err))
|
||||
response.FailWithMessage("断点续传失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
if err = fileUploadAndDownloadService.CreateFileChunk(file.ID, pathC, chunkNumber); err != nil {
|
||||
global.GVA_LOG.Error("创建文件记录失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建文件记录失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("切片创建成功", c)
|
||||
}
|
||||
|
||||
// FindFile
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "Find the file, 查找文件"
|
||||
// @Success 200 {object} response.Response{data=exampleRes.FileResponse,msg=string} "查找文件,返回包括文件详情"
|
||||
// @Router /fileUploadAndDownload/findFile [get]
|
||||
func (b *FileUploadAndDownloadApi) FindFile(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
chunkTotal, _ := strconv.Atoi(c.Query("chunkTotal"))
|
||||
file, err := fileUploadAndDownloadService.FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查找失败!", zap.Error(err))
|
||||
response.FailWithMessage("查找失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(exampleRes.FileResponse{File: file}, "查找成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// BreakpointContinueFinish
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 创建文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件完成"
|
||||
// @Success 200 {object} response.Response{data=exampleRes.FilePathResponse,msg=string} "创建文件,返回包括文件路径"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func (b *FileUploadAndDownloadApi) BreakpointContinueFinish(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
filePath, err := utils.MakeFile(fileName, fileMd5)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("文件创建失败!", zap.Error(err))
|
||||
response.FailWithDetailed(exampleRes.FilePathResponse{FilePath: filePath}, "文件创建失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(exampleRes.FilePathResponse{FilePath: filePath}, "文件创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveChunk
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除切片
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "删除缓存切片"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除切片"
|
||||
// @Router /fileUploadAndDownload/removeChunk [post]
|
||||
func (b *FileUploadAndDownloadApi) RemoveChunk(c *gin.Context) {
|
||||
var file example.ExaFile
|
||||
err := c.ShouldBindJSON(&file)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.RemoveChunk(file.FileMd5)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("缓存切片删除失败!", zap.Error(err))
|
||||
return
|
||||
}
|
||||
err = fileUploadAndDownloadService.DeleteFileChunk(file.FileMd5, file.FilePath)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error(err.Error(), zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("缓存切片删除成功", c)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
|
||||
exampleRes "github.com/flipped-aurora/gin-vue-admin/server/model/example/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CustomerApi struct{}
|
||||
|
||||
// CreateExaCustomer
|
||||
// @Tags ExaCustomer
|
||||
// @Summary 创建客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaCustomer true "客户用户名, 客户手机号码"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建客户"
|
||||
// @Router /customer/customer [post]
|
||||
func (e *CustomerApi) CreateExaCustomer(c *gin.Context) {
|
||||
var customer example.ExaCustomer
|
||||
err := c.ShouldBindJSON(&customer)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(customer, utils.CustomerVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
customer.SysUserID = utils.GetUserID(c)
|
||||
customer.SysUserAuthorityID = utils.GetUserAuthorityId(c)
|
||||
err = customerService.CreateExaCustomer(customer)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteExaCustomer
|
||||
// @Tags ExaCustomer
|
||||
// @Summary 删除客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaCustomer true "客户ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除客户"
|
||||
// @Router /customer/customer [delete]
|
||||
func (e *CustomerApi) DeleteExaCustomer(c *gin.Context) {
|
||||
var customer example.ExaCustomer
|
||||
err := c.ShouldBindJSON(&customer)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(customer.GVA_MODEL, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = customerService.DeleteExaCustomer(customer)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateExaCustomer
|
||||
// @Tags ExaCustomer
|
||||
// @Summary 更新客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaCustomer true "客户ID, 客户信息"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新客户信息"
|
||||
// @Router /customer/customer [put]
|
||||
func (e *CustomerApi) UpdateExaCustomer(c *gin.Context) {
|
||||
var customer example.ExaCustomer
|
||||
err := c.ShouldBindJSON(&customer)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(customer.GVA_MODEL, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(customer, utils.CustomerVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = customerService.UpdateExaCustomer(&customer)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// GetExaCustomer
|
||||
// @Tags ExaCustomer
|
||||
// @Summary 获取单一客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query example.ExaCustomer true "客户ID"
|
||||
// @Success 200 {object} response.Response{data=exampleRes.ExaCustomerResponse,msg=string} "获取单一客户信息,返回包括客户详情"
|
||||
// @Router /customer/customer [get]
|
||||
func (e *CustomerApi) GetExaCustomer(c *gin.Context) {
|
||||
var customer example.ExaCustomer
|
||||
err := c.ShouldBindQuery(&customer)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(customer.GVA_MODEL, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
data, err := customerService.GetExaCustomer(customer.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(exampleRes.ExaCustomerResponse{Customer: data}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetExaCustomerList
|
||||
// @Tags ExaCustomer
|
||||
// @Summary 分页获取权限客户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query request.PageInfo true "页码, 每页大小"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取权限客户列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /customer/customerList [get]
|
||||
func (e *CustomerApi) GetExaCustomerList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(pageInfo, utils.PageInfoVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
customerList, total, err := customerService.GetCustomerInfoList(utils.GetUserAuthorityId(c), pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: customerList,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package example
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/example/request"
|
||||
exampleRes "github.com/flipped-aurora/gin-vue-admin/server/model/example/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type FileUploadAndDownloadApi struct{}
|
||||
|
||||
// UploadFile
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 上传文件示例
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件示例"
|
||||
// @Success 200 {object} response.Response{data=exampleRes.ExaFileResponse,msg=string} "上传文件示例,返回包括文件详情"
|
||||
// @Router /fileUploadAndDownload/upload [post]
|
||||
func (b *FileUploadAndDownloadApi) UploadFile(c *gin.Context) {
|
||||
var file example.ExaFileUploadAndDownload
|
||||
noSave := c.DefaultQuery("noSave", "0")
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
classId, _ := strconv.Atoi(c.DefaultPostForm("classId", "0"))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("接收文件失败!", zap.Error(err))
|
||||
response.FailWithMessage("接收文件失败", c)
|
||||
return
|
||||
}
|
||||
file, err = fileUploadAndDownloadService.UploadFile(header, noSave, classId) // 文件上传后拿到文件路径
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("上传文件失败!", zap.Error(err))
|
||||
response.FailWithMessage("上传文件失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(exampleRes.ExaFileResponse{File: file}, "上传成功", c)
|
||||
}
|
||||
|
||||
// EditFileName 编辑文件名或者备注
|
||||
func (b *FileUploadAndDownloadApi) EditFileName(c *gin.Context) {
|
||||
var file example.ExaFileUploadAndDownload
|
||||
err := c.ShouldBindJSON(&file)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = fileUploadAndDownloadService.EditFileName(file)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("编辑失败!", zap.Error(err))
|
||||
response.FailWithMessage("编辑失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("编辑成功", c)
|
||||
}
|
||||
|
||||
// DeleteFile
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaFileUploadAndDownload true "传入文件里面id即可"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除文件"
|
||||
// @Router /fileUploadAndDownload/deleteFile [post]
|
||||
func (b *FileUploadAndDownloadApi) DeleteFile(c *gin.Context) {
|
||||
var file example.ExaFileUploadAndDownload
|
||||
err := c.ShouldBindJSON(&file)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := fileUploadAndDownloadService.DeleteFile(file); err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// GetFileList
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 分页文件列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.ExaAttachmentCategorySearch true "页码, 每页大小, 分类id"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页文件列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /fileUploadAndDownload/getFileList [post]
|
||||
func (b *FileUploadAndDownloadApi) GetFileList(c *gin.Context) {
|
||||
var pageInfo request.ExaAttachmentCategorySearch
|
||||
err := c.ShouldBindJSON(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := fileUploadAndDownloadService.GetFileRecordInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ImportURL
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 导入URL
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body example.ExaFileUploadAndDownload true "对象"
|
||||
// @Success 200 {object} response.Response{msg=string} "导入URL"
|
||||
// @Router /fileUploadAndDownload/importURL [post]
|
||||
func (b *FileUploadAndDownloadApi) ImportURL(c *gin.Context) {
|
||||
var file []example.ExaFileUploadAndDownload
|
||||
err := c.ShouldBindJSON(&file)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := fileUploadAndDownloadService.ImportURL(&file); err != nil {
|
||||
global.GVA_LOG.Error("导入URL失败!", zap.Error(err))
|
||||
response.FailWithMessage("导入URL失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("导入URL成功", c)
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysApi true "创建api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/createApi [post]
|
||||
func CreateApi(c *gin.Context) {
|
||||
var api model.SysApi
|
||||
_ = c.ShouldBindJSON(&api)
|
||||
ApiVerify := utils.Rules{
|
||||
"Path": {utils.NotEmpty()},
|
||||
"Description": {utils.NotEmpty()},
|
||||
"ApiGroup": {utils.NotEmpty()},
|
||||
"Method": {utils.NotEmpty()},
|
||||
}
|
||||
ApiVerifyErr := utils.Verify(api, ApiVerify)
|
||||
if ApiVerifyErr != nil {
|
||||
response.FailWithMessage(ApiVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.CreateApi(api)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 删除指定api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysApi true "删除api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/deleteApi [post]
|
||||
func DeleteApi(c *gin.Context) {
|
||||
var a model.SysApi
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
ApiVerify := utils.Rules{
|
||||
"ID": {utils.NotEmpty()},
|
||||
}
|
||||
ApiVerifyErr := utils.Verify(a.Model, ApiVerify)
|
||||
if ApiVerifyErr != nil {
|
||||
response.FailWithMessage(ApiVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.DeleteApi(a)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// 条件搜索后端看此api
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 分页获取API列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SearchApiParams true "分页获取API列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getApiList [post]
|
||||
func GetApiList(c *gin.Context) {
|
||||
// 此结构体仅本方法使用
|
||||
var sp request.SearchApiParams
|
||||
_ = c.ShouldBindJSON(&sp)
|
||||
PageVerifyErr := utils.Verify(sp.PageInfo, utils.CustomizeMap["PageVerify"])
|
||||
if PageVerifyErr != nil {
|
||||
response.FailWithMessage(PageVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, list, total := service.GetAPIInfoList(sp.SysApi, sp.PageInfo, sp.OrderKey, sp.Desc)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: sp.PageInfo.Page,
|
||||
PageSize: sp.PageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 根据id获取api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "根据id获取api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getApiById [post]
|
||||
func GetApiById(c *gin.Context) {
|
||||
var idInfo request.GetById
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
IdVerifyErr := utils.Verify(idInfo, utils.CustomizeMap["IdVerify"])
|
||||
if IdVerifyErr != nil {
|
||||
response.FailWithMessage(IdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, api := service.GetApiById(idInfo.Id)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysAPIResponse{Api: api}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysApi true "创建api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/updateApi [post]
|
||||
func UpdateApi(c *gin.Context) {
|
||||
var api model.SysApi
|
||||
_ = c.ShouldBindJSON(&api)
|
||||
ApiVerify := utils.Rules{
|
||||
"Path": {utils.NotEmpty()},
|
||||
"Description": {utils.NotEmpty()},
|
||||
"ApiGroup": {utils.NotEmpty()},
|
||||
"Method": {utils.NotEmpty()},
|
||||
}
|
||||
ApiVerifyErr := utils.Verify(api, ApiVerify)
|
||||
if ApiVerifyErr != nil {
|
||||
response.FailWithMessage(ApiVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.UpdateApi(api)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("修改数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("修改数据成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取所有的Api 不分页
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getAllApis [post]
|
||||
func GetAllApis(c *gin.Context) {
|
||||
err, apis := service.GetAllApis()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysAPIListResponse{Apis: apis}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 创建角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysAuthority true "创建角色"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/createAuthority [post]
|
||||
func CreateAuthority(c *gin.Context) {
|
||||
var auth model.SysAuthority
|
||||
_ = c.ShouldBindJSON(&auth)
|
||||
AuthorityVerify := utils.Rules{
|
||||
"AuthorityId": {utils.NotEmpty()},
|
||||
"AuthorityName": {utils.NotEmpty()},
|
||||
"ParentId": {utils.NotEmpty()},
|
||||
}
|
||||
AuthorityVerifyErr := utils.Verify(auth, AuthorityVerify)
|
||||
if AuthorityVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, authBack := service.CreateAuthority(auth)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysAuthorityResponse{Authority: authBack}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 拷贝角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body response.SysAuthorityCopyResponse true "拷贝角色"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"拷贝成功"}"
|
||||
// @Router /authority/copyAuthority [post]
|
||||
func CopyAuthority(c *gin.Context) {
|
||||
var copyInfo resp.SysAuthorityCopyResponse
|
||||
_ = c.ShouldBindJSON(©Info)
|
||||
OldAuthorityVerify := utils.Rules{
|
||||
"OldAuthorityId": {utils.NotEmpty()},
|
||||
}
|
||||
OldAuthorityVerifyErr := utils.Verify(copyInfo, OldAuthorityVerify)
|
||||
if OldAuthorityVerifyErr != nil {
|
||||
response.FailWithMessage(OldAuthorityVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
AuthorityVerify := utils.Rules{
|
||||
"AuthorityId": {utils.NotEmpty()},
|
||||
"AuthorityName": {utils.NotEmpty()},
|
||||
"ParentId": {utils.NotEmpty()},
|
||||
}
|
||||
AuthorityVerifyErr := utils.Verify(copyInfo.Authority, AuthorityVerify)
|
||||
if AuthorityVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, authBack := service.CopyAuthority(copyInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("拷贝失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysAuthorityResponse{Authority: authBack}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 删除角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysAuthority true "删除角色"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/deleteAuthority [post]
|
||||
func DeleteAuthority(c *gin.Context) {
|
||||
var a model.SysAuthority
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
AuthorityIdVerifyErr := utils.Verify(a, utils.CustomizeMap["AuthorityIdVerify"])
|
||||
if AuthorityIdVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
// 删除角色之前需要判断是否有用户正在使用此角色
|
||||
err := service.DeleteAuthority(&a)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 设置角色资源权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysAuthority true "设置角色资源权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
|
||||
// @Router /authority/updateAuthority [post]
|
||||
func UpdateAuthority(c *gin.Context) {
|
||||
var auth model.SysAuthority
|
||||
_ = c.ShouldBindJSON(&auth)
|
||||
AuthorityVerify := utils.Rules{
|
||||
"AuthorityId": {utils.NotEmpty()},
|
||||
"AuthorityName": {utils.NotEmpty()},
|
||||
"ParentId": {utils.NotEmpty()},
|
||||
}
|
||||
AuthorityVerifyErr := utils.Verify(auth, AuthorityVerify)
|
||||
if AuthorityVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, authority := service.UpdateAuthority(auth)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysAuthorityResponse{Authority: authority}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 分页获取角色列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/getAuthorityList [post]
|
||||
func GetAuthorityList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
|
||||
if PageVerifyErr != nil {
|
||||
response.FailWithMessage(PageVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, list, total := service.GetAuthorityInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 设置角色资源权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysAuthority true "设置角色资源权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
|
||||
// @Router /authority/setDataAuthority [post]
|
||||
func SetDataAuthority(c *gin.Context) {
|
||||
var auth model.SysAuthority
|
||||
_ = c.ShouldBindJSON(&auth)
|
||||
AuthorityIdVerifyErr := utils.Verify(auth, utils.CustomizeMap["AuthorityIdVerify"])
|
||||
if AuthorityIdVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.SetDataAuthority(auth)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("设置关联失败,%v", err), c)
|
||||
} else {
|
||||
response.Ok(c)
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 自动代码模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.AutoCodeStruct true "创建自动代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/createTemp [post]
|
||||
func CreateTemp(c *gin.Context) {
|
||||
var a model.AutoCodeStruct
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
AutoCodeVerify := utils.Rules{
|
||||
"Abbreviation": {utils.NotEmpty()},
|
||||
"StructName": {utils.NotEmpty()},
|
||||
"PackageName": {utils.NotEmpty()},
|
||||
"Fields": {utils.NotEmpty()},
|
||||
}
|
||||
WKVerifyErr := utils.Verify(a, AutoCodeVerify)
|
||||
if WKVerifyErr != nil {
|
||||
response.FailWithMessage(WKVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
if a.AutoCreateApiToSql {
|
||||
apiList := [6]model.SysApi{
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "create" + a.StructName,
|
||||
Description: "新增" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "POST",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "delete" + a.StructName,
|
||||
Description: "删除" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "DELETE",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "delete" + a.StructName+"ByIds",
|
||||
Description: "批量删除" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "DELETE",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "update" + a.StructName,
|
||||
Description: "更新" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "PUT",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "find" + a.StructName,
|
||||
Description: "根据ID获取" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "GET",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "get" + a.StructName + "List",
|
||||
Description: "获取" + a.Description + "列表",
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "GET",
|
||||
},
|
||||
}
|
||||
for _, v := range apiList {
|
||||
errC := service.CreateApi(v)
|
||||
if errC != nil {
|
||||
c.Writer.Header().Add("success", "false")
|
||||
c.Writer.Header().Add("msg", url.QueryEscape(fmt.Sprintf("自动化创建失败,%v,请自行清空垃圾数据", errC)))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
err := service.CreateTemp(a)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
os.Remove("./ginvueadmin.zip")
|
||||
} else {
|
||||
c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", "ginvueadmin.zip")) // fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名
|
||||
c.Writer.Header().Add("Content-Type", "application/json")
|
||||
c.Writer.Header().Add("success", "true")
|
||||
c.File("./ginvueadmin.zip")
|
||||
os.Remove("./ginvueadmin.zip")
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取当前数据库所有表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/getTables [get]
|
||||
|
||||
func GetTables(c *gin.Context) {
|
||||
dbName := c.DefaultQuery("dbName", global.GVA_CONFIG.Mysql.Dbname)
|
||||
err, tables := service.GetTables(dbName)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{
|
||||
"tables": tables,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取当前所有数据库
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/getDatabase [get]
|
||||
func GetDB(c *gin.Context) {
|
||||
err, dbs := service.GetDB()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{
|
||||
"dbs": dbs,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取当前表所有字段
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/getDatabase [get]
|
||||
func GetColume(c *gin.Context) {
|
||||
dbName := c.DefaultQuery("dbName", global.GVA_CONFIG.Mysql.Dbname)
|
||||
tableName := c.Query("tableName")
|
||||
err, columes := service.GetColume(tableName, dbName)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{
|
||||
"columes": columes,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/global/response"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
)
|
||||
|
||||
var store = base64Captcha.DefaultMemStore
|
||||
|
||||
// @Tags base
|
||||
// @Summary 生成验证码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /base/captcha [post]
|
||||
func Captcha(c *gin.Context) {
|
||||
//字符,公式,验证码配置
|
||||
// 生成默认数字的driver
|
||||
driver := base64Captcha.NewDriverDigit(global.GVA_CONFIG.Captcha.ImgHeight, global.GVA_CONFIG.Captcha.ImgWidth, global.GVA_CONFIG.Captcha.KeyLong, 0.7, 80)
|
||||
cp := base64Captcha.NewCaptcha(driver, store)
|
||||
id, b64s, err := cp.Generate()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkDetailed(resp.SysCaptchaResponse{
|
||||
CaptchaId: id,
|
||||
PicPath: b64s,
|
||||
}, "验证码获取成功", c)
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary 更改角色api权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.CasbinInReceive true "更改角色api权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/UpdateCasbin [post]
|
||||
func UpdateCasbin(c *gin.Context) {
|
||||
var cmr request.CasbinInReceive
|
||||
_ = c.ShouldBindJSON(&cmr)
|
||||
AuthorityIdVerifyErr := utils.Verify(cmr, utils.CustomizeMap["AuthorityIdVerify"])
|
||||
if AuthorityIdVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.UpdateCasbin(cmr.AuthorityId, cmr.CasbinInfos)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("添加规则失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("添加规则成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary 获取权限列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.CasbinInReceive true "获取权限列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/getPolicyPathByAuthorityId [post]
|
||||
func GetPolicyPathByAuthorityId(c *gin.Context) {
|
||||
var cmr request.CasbinInReceive
|
||||
_ = c.ShouldBindJSON(&cmr)
|
||||
AuthorityIdVerifyErr := utils.Verify(cmr, utils.CustomizeMap["AuthorityIdVerify"])
|
||||
if AuthorityIdVerifyErr != nil {
|
||||
response.FailWithMessage(AuthorityIdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
paths := service.GetPolicyPathByAuthorityId(cmr.AuthorityId)
|
||||
response.OkWithData(resp.PolicyPathResponse{Paths: paths}, c)
|
||||
}
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary casb RBAC RESTFUL测试路由
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.CasbinInReceive true "获取权限列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/CasbinTest [get]
|
||||
func CasbinTest(c *gin.Context) {
|
||||
// 测试restful以及占位符代码 随意书写
|
||||
pathParam := c.Param("pathParam")
|
||||
query := c.Query("query")
|
||||
response.OkDetailed(gin.H{"pathParam": pathParam, "query": query}, "获取规则成功", c)
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysDictionary
|
||||
// @Summary 创建SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionary true "创建SysDictionary"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysDictionary/createSysDictionary [post]
|
||||
func CreateSysDictionary(c *gin.Context) {
|
||||
var sysDictionary model.SysDictionary
|
||||
_ = c.ShouldBindJSON(&sysDictionary)
|
||||
err := service.CreateSysDictionary(sysDictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionary
|
||||
// @Summary 删除SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionary true "删除SysDictionary"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysDictionary/deleteSysDictionary [delete]
|
||||
func DeleteSysDictionary(c *gin.Context) {
|
||||
var sysDictionary model.SysDictionary
|
||||
_ = c.ShouldBindJSON(&sysDictionary)
|
||||
err := service.DeleteSysDictionary(sysDictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionary
|
||||
// @Summary 更新SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionary true "更新SysDictionary"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /sysDictionary/updateSysDictionary [put]
|
||||
func UpdateSysDictionary(c *gin.Context) {
|
||||
var sysDictionary model.SysDictionary
|
||||
_ = c.ShouldBindJSON(&sysDictionary)
|
||||
err := service.UpdateSysDictionary(&sysDictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionary
|
||||
// @Summary 用id查询SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionary true "用id查询SysDictionary"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /sysDictionary/findSysDictionary [get]
|
||||
func FindSysDictionary(c *gin.Context) {
|
||||
var sysDictionary model.SysDictionary
|
||||
_ = c.ShouldBindQuery(&sysDictionary)
|
||||
err, resysDictionary := service.GetSysDictionary(sysDictionary.Type, sysDictionary.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"resysDictionary": resysDictionary}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionary
|
||||
// @Summary 分页获取SysDictionary列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysDictionarySearch true "分页获取SysDictionary列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysDictionary/getSysDictionaryList [get]
|
||||
func GetSysDictionaryList(c *gin.Context) {
|
||||
var pageInfo request.SysDictionarySearch
|
||||
_ = c.ShouldBindQuery(&pageInfo)
|
||||
err, list, total := service.GetSysDictionaryInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 创建SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionaryDetail true "创建SysDictionaryDetail"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysDictionaryDetail/createSysDictionaryDetail [post]
|
||||
func CreateSysDictionaryDetail(c *gin.Context) {
|
||||
var sysDictionaryDetail model.SysDictionaryDetail
|
||||
_ = c.ShouldBindJSON(&sysDictionaryDetail)
|
||||
err := service.CreateSysDictionaryDetail(sysDictionaryDetail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 删除SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionaryDetail true "删除SysDictionaryDetail"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysDictionaryDetail/deleteSysDictionaryDetail [delete]
|
||||
func DeleteSysDictionaryDetail(c *gin.Context) {
|
||||
var sysDictionaryDetail model.SysDictionaryDetail
|
||||
_ = c.ShouldBindJSON(&sysDictionaryDetail)
|
||||
err := service.DeleteSysDictionaryDetail(sysDictionaryDetail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 更新SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionaryDetail true "更新SysDictionaryDetail"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /sysDictionaryDetail/updateSysDictionaryDetail [put]
|
||||
func UpdateSysDictionaryDetail(c *gin.Context) {
|
||||
var sysDictionaryDetail model.SysDictionaryDetail
|
||||
_ = c.ShouldBindJSON(&sysDictionaryDetail)
|
||||
err := service.UpdateSysDictionaryDetail(&sysDictionaryDetail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 用id查询SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysDictionaryDetail true "用id查询SysDictionaryDetail"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /sysDictionaryDetail/findSysDictionaryDetail [get]
|
||||
func FindSysDictionaryDetail(c *gin.Context) {
|
||||
var sysDictionaryDetail model.SysDictionaryDetail
|
||||
_ = c.ShouldBindQuery(&sysDictionaryDetail)
|
||||
err, resysDictionaryDetail := service.GetSysDictionaryDetail(sysDictionaryDetail.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"resysDictionaryDetail": resysDictionaryDetail}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 分页获取SysDictionaryDetail列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysDictionaryDetailSearch true "分页获取SysDictionaryDetail列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysDictionaryDetail/getSysDictionaryDetailList [get]
|
||||
func GetSysDictionaryDetailList(c *gin.Context) {
|
||||
var pageInfo request.SysDictionaryDetailSearch
|
||||
_ = c.ShouldBindQuery(&pageInfo)
|
||||
err, list, total := service.GetSysDictionaryDetailInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags jwt
|
||||
// @Summary jwt加入黑名单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"拉黑成功"}"
|
||||
// @Router /jwt/jsonInBlacklist [post]
|
||||
func JsonInBlacklist(c *gin.Context) {
|
||||
token := c.Request.Header.Get("x-token")
|
||||
modelJwt := model.JwtBlacklist{
|
||||
Jwt: token,
|
||||
}
|
||||
err := service.JsonInBlacklist(modelJwt)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("jwt作废失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("jwt作废成功", c)
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body request.RegisterAndLoginStruct true "可以什么都不填"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /menu/getMenu [post]
|
||||
func GetMenu(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
err, menus := service.GetMenuTree(waitUse.AuthorityId)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysMenusResponse{Menus: menus}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 分页获取基础menu列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "分页获取基础menu列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/getMenuList [post]
|
||||
func GetMenuList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
|
||||
if PageVerifyErr != nil {
|
||||
response.FailWithMessage(PageVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, menuList, total := service.GetInfoList()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: menuList,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 新增菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysBaseMenu true "新增菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/addBaseMenu [post]
|
||||
func AddBaseMenu(c *gin.Context) {
|
||||
var menu model.SysBaseMenu
|
||||
_ = c.ShouldBindJSON(&menu)
|
||||
MenuVerify := utils.Rules{
|
||||
"Path": {utils.NotEmpty()},
|
||||
"ParentId": {utils.NotEmpty()},
|
||||
"Name": {utils.NotEmpty()},
|
||||
"Component": {utils.NotEmpty()},
|
||||
"Sort": {utils.Ge("0")},
|
||||
}
|
||||
MenuVerifyErr := utils.Verify(menu, MenuVerify)
|
||||
if MenuVerifyErr != nil {
|
||||
response.FailWithMessage(MenuVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
MetaVerify := utils.Rules{
|
||||
"Title": {utils.NotEmpty()},
|
||||
}
|
||||
MetaVerifyErr := utils.Verify(menu.Meta, MetaVerify)
|
||||
if MetaVerifyErr != nil {
|
||||
response.FailWithMessage(MetaVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.AddBaseMenu(menu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("添加失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("添加成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body request.RegisterAndLoginStruct true "可以什么都不填"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /menu/getBaseMenuTree [post]
|
||||
func GetBaseMenuTree(c *gin.Context) {
|
||||
err, menus := service.GetBaseMenuTree()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysBaseMenusResponse{Menus: menus}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 增加menu和角色关联关系
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AddMenuAuthorityInfo true "增加menu和角色关联关系"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/addMenuAuthority [post]
|
||||
func AddMenuAuthority(c *gin.Context) {
|
||||
var addMenuAuthorityInfo request.AddMenuAuthorityInfo
|
||||
_ = c.ShouldBindJSON(&addMenuAuthorityInfo)
|
||||
MenuVerify := utils.Rules{
|
||||
"AuthorityId": {"notEmpty"},
|
||||
}
|
||||
MenuVerifyErr := utils.Verify(addMenuAuthorityInfo, MenuVerify)
|
||||
if MenuVerifyErr != nil {
|
||||
response.FailWithMessage(MenuVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.AddMenuAuthority(addMenuAuthorityInfo.Menus, addMenuAuthorityInfo.AuthorityId)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("添加失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("添加成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取指定角色menu
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AuthorityIdInfo true "增加menu和角色关联关系"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/GetMenuAuthority [post]
|
||||
func GetMenuAuthority(c *gin.Context) {
|
||||
var authorityIdInfo request.AuthorityIdInfo
|
||||
_ = c.ShouldBindJSON(&authorityIdInfo)
|
||||
MenuVerify := utils.Rules{
|
||||
"AuthorityId": {"notEmpty"},
|
||||
}
|
||||
MenuVerifyErr := utils.Verify(authorityIdInfo, MenuVerify)
|
||||
if MenuVerifyErr != nil {
|
||||
response.FailWithMessage(MenuVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, menus := service.GetMenuAuthority(authorityIdInfo.AuthorityId)
|
||||
if err != nil {
|
||||
response.FailWithDetailed(response.ERROR, resp.SysMenusResponse{Menus: menus}, fmt.Sprintf("添加失败,%v", err), c)
|
||||
} else {
|
||||
response.Result(response.SUCCESS, gin.H{"menus": menus}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 删除菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "删除菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/deleteBaseMenu [post]
|
||||
func DeleteBaseMenu(c *gin.Context) {
|
||||
var idInfo request.GetById
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
IdVerifyErr := utils.Verify(idInfo, utils.CustomizeMap["IdVerify"])
|
||||
if IdVerifyErr != nil {
|
||||
response.FailWithMessage(IdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.DeleteBaseMenu(idInfo.Id)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 更新菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysBaseMenu true "更新菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/updateBaseMenu [post]
|
||||
func UpdateBaseMenu(c *gin.Context) {
|
||||
var menu model.SysBaseMenu
|
||||
_ = c.ShouldBindJSON(&menu)
|
||||
MenuVerify := utils.Rules{
|
||||
"Path": {"notEmpty"},
|
||||
"ParentId": {utils.NotEmpty()},
|
||||
"Name": {utils.NotEmpty()},
|
||||
"Component": {utils.NotEmpty()},
|
||||
"Sort": {utils.Ge("0")},
|
||||
}
|
||||
MenuVerifyErr := utils.Verify(menu, MenuVerify)
|
||||
if MenuVerifyErr != nil {
|
||||
response.FailWithMessage(MenuVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
MetaVerify := utils.Rules{
|
||||
"Title": {utils.NotEmpty()},
|
||||
}
|
||||
MetaVerifyErr := utils.Verify(menu.Meta, MetaVerify)
|
||||
if MetaVerifyErr != nil {
|
||||
response.FailWithMessage(MetaVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.UpdateBaseMenu(menu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("修改失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 根据id获取菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "根据id获取菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/getBaseMenuById [post]
|
||||
func GetBaseMenuById(c *gin.Context) {
|
||||
var idInfo request.GetById
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
MenuVerify := utils.Rules{
|
||||
"Id": {"notEmpty"},
|
||||
}
|
||||
MenuVerifyErr := utils.Verify(idInfo, MenuVerify)
|
||||
if MenuVerifyErr != nil {
|
||||
response.FailWithMessage(MenuVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, menu := service.GetBaseMenuById(idInfo.Id)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysBaseMenuResponse{Menu: menu}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 创建SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysOperationRecord true "创建SysOperationRecord"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysOperationRecord/createSysOperationRecord [post]
|
||||
func CreateSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord model.SysOperationRecord
|
||||
_ = c.ShouldBindJSON(&sysOperationRecord)
|
||||
err := service.CreateSysOperationRecord(sysOperationRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 删除SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysOperationRecord true "删除SysOperationRecord"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysOperationRecord/deleteSysOperationRecord [delete]
|
||||
func DeleteSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord model.SysOperationRecord
|
||||
_ = c.ShouldBindJSON(&sysOperationRecord)
|
||||
err := service.DeleteSysOperationRecord(sysOperationRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 批量删除SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "批量删除SysOperationRecord"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysOperationRecord/deleteSysOperationRecordByIds [delete]
|
||||
func DeleteSysOperationRecordByIds(c *gin.Context) {
|
||||
var IDS request.IdsReq
|
||||
_ = c.ShouldBindJSON(&IDS)
|
||||
err := service.DeleteSysOperationRecordByIds(IDS)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 更新SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysOperationRecord true "更新SysOperationRecord"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /sysOperationRecord/updateSysOperationRecord [put]
|
||||
func UpdateSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord model.SysOperationRecord
|
||||
_ = c.ShouldBindJSON(&sysOperationRecord)
|
||||
err := service.UpdateSysOperationRecord(&sysOperationRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 用id查询SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysOperationRecord true "用id查询SysOperationRecord"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /sysOperationRecord/findSysOperationRecord [get]
|
||||
func FindSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord model.SysOperationRecord
|
||||
_ = c.ShouldBindQuery(&sysOperationRecord)
|
||||
err, resysOperationRecord := service.GetSysOperationRecord(sysOperationRecord.ID)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"resysOperationRecord": resysOperationRecord}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 分页获取SysOperationRecord列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysOperationRecordSearch true "分页获取SysOperationRecord列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysOperationRecord/getSysOperationRecordList [get]
|
||||
func GetSysOperationRecordList(c *gin.Context) {
|
||||
var pageInfo request.SysOperationRecordSearch
|
||||
_ = c.ShouldBindQuery(&pageInfo)
|
||||
err, list, total := service.GetSysOperationRecordInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags system
|
||||
// @Summary 获取配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/getSystemConfig [post]
|
||||
func GetSystemConfig(c *gin.Context) {
|
||||
err, config := service.GetSystemConfig()
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysConfigResponse{Config: config}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags system
|
||||
// @Summary 设置配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body model.System true "设置配置文件内容"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/setSystemConfig [post]
|
||||
func SetSystemConfig(c *gin.Context) {
|
||||
var sys model.System
|
||||
_ = c.ShouldBindJSON(&sys)
|
||||
err := service.SetSystemConfig(sys)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("设置失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData("设置成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// 本方法开发中 开发者windows系统 缺少linux系统所需的包 因此搁置
|
||||
// @Tags system
|
||||
// @Summary 设置配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body model.System true "设置配置文件内容"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/ReloadSystem [post]
|
||||
func ReloadSystem(c *gin.Context) {
|
||||
var sys model.System
|
||||
_ = c.ShouldBindJSON(&sys)
|
||||
err := service.SetSystemConfig(sys)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("设置失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/middleware"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/model/request"
|
||||
resp "gin-vue-admin/model/response"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
)
|
||||
|
||||
// @Tags Base
|
||||
// @Summary 用户注册账号
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysUser true "用户注册接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
|
||||
// @Router /base/register [post]
|
||||
func Register(c *gin.Context) {
|
||||
var R request.RegisterStruct
|
||||
_ = c.ShouldBindJSON(&R)
|
||||
UserVerify := utils.Rules{
|
||||
"Username": {utils.NotEmpty()},
|
||||
"NickName": {utils.NotEmpty()},
|
||||
"Password": {utils.NotEmpty()},
|
||||
"AuthorityId": {utils.NotEmpty()},
|
||||
}
|
||||
UserVerifyErr := utils.Verify(R, UserVerify)
|
||||
if UserVerifyErr != nil {
|
||||
response.FailWithMessage(UserVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
user := &model.SysUser{Username: R.Username, NickName: R.NickName, Password: R.Password, HeaderImg: R.HeaderImg, AuthorityId: R.AuthorityId}
|
||||
err, userReturn := service.Register(*user)
|
||||
if err != nil {
|
||||
response.FailWithDetailed(response.ERROR, resp.SysUserResponse{User: userReturn}, fmt.Sprintf("%v", err), c)
|
||||
} else {
|
||||
response.OkDetailed(resp.SysUserResponse{User: userReturn}, "注册成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags Base
|
||||
// @Summary 用户登录
|
||||
// @Produce application/json
|
||||
// @Param data body request.RegisterAndLoginStruct true "用户登录接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"登陆成功"}"
|
||||
// @Router /base/login [post]
|
||||
func Login(c *gin.Context) {
|
||||
var L request.RegisterAndLoginStruct
|
||||
_ = c.ShouldBindJSON(&L)
|
||||
UserVerify := utils.Rules{
|
||||
"CaptchaId": {utils.NotEmpty()},
|
||||
"Captcha": {utils.NotEmpty()},
|
||||
"Username": {utils.NotEmpty()},
|
||||
"Password": {utils.NotEmpty()},
|
||||
}
|
||||
UserVerifyErr := utils.Verify(L, UserVerify)
|
||||
if UserVerifyErr != nil {
|
||||
response.FailWithMessage(UserVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
if store.Verify(L.CaptchaId, L.Captcha, true) {
|
||||
U := &model.SysUser{Username: L.Username, Password: L.Password}
|
||||
if err, user := service.Login(U); err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("用户名密码错误或%v", err), c)
|
||||
} else {
|
||||
tokenNext(c, *user)
|
||||
}
|
||||
} else {
|
||||
response.FailWithMessage("验证码错误", c)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 登录以后签发jwt
|
||||
func tokenNext(c *gin.Context, user model.SysUser) {
|
||||
j := &middleware.JWT{
|
||||
SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey), // 唯一签名
|
||||
}
|
||||
clams := request.CustomClaims{
|
||||
UUID: user.UUID,
|
||||
ID: user.ID,
|
||||
NickName: user.NickName,
|
||||
Username: user.Username,
|
||||
AuthorityId: user.AuthorityId,
|
||||
BufferTime: 60*60*24, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
NotBefore: time.Now().Unix() - 1000, // 签名生效时间
|
||||
ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 7天
|
||||
Issuer: "qmPlus", // 签名的发行者
|
||||
},
|
||||
}
|
||||
token, err := j.CreateToken(clams)
|
||||
if err != nil {
|
||||
response.FailWithMessage("获取token失败", c)
|
||||
return
|
||||
}
|
||||
if !global.GVA_CONFIG.System.UseMultipoint {
|
||||
response.OkWithData(resp.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: clams.StandardClaims.ExpiresAt * 1000,
|
||||
}, c)
|
||||
return
|
||||
}
|
||||
err, jwtStr := service.GetRedisJWT(user.Username)
|
||||
if err == redis.Nil {
|
||||
if err := service.SetRedisJWT(token, user.Username); err != nil {
|
||||
response.FailWithMessage("设置登录状态失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resp.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: clams.StandardClaims.ExpiresAt * 1000,
|
||||
}, c)
|
||||
} else if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("%v", err), c)
|
||||
} else {
|
||||
var blackJWT model.JwtBlacklist
|
||||
blackJWT.Jwt = jwtStr
|
||||
if err := service.JsonInBlacklist(blackJWT); err != nil {
|
||||
response.FailWithMessage("jwt作废失败", c)
|
||||
return
|
||||
}
|
||||
if err := service.SetRedisJWT(jwtStr, user.Username); err != nil {
|
||||
response.FailWithMessage("设置登录状态失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resp.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: clams.StandardClaims.ExpiresAt * 1000,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 用户修改密码
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body request.ChangePasswordStruct true "用户修改密码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
|
||||
// @Router /user/changePassword [put]
|
||||
func ChangePassword(c *gin.Context) {
|
||||
var params request.ChangePasswordStruct
|
||||
_ = c.ShouldBindJSON(¶ms)
|
||||
UserVerify := utils.Rules{
|
||||
"Username": {utils.NotEmpty()},
|
||||
"Password": {utils.NotEmpty()},
|
||||
"NewPassword": {utils.NotEmpty()},
|
||||
}
|
||||
UserVerifyErr := utils.Verify(params, UserVerify)
|
||||
if UserVerifyErr != nil {
|
||||
response.FailWithMessage(UserVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
U := &model.SysUser{Username: params.Username, Password: params.Password}
|
||||
if err, _ := service.ChangePassword(U, params.NewPassword); err != nil {
|
||||
response.FailWithMessage("修改失败,请检查用户名密码", c)
|
||||
} else {
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
type UserHeaderImg struct {
|
||||
HeaderImg multipart.File `json:"headerImg"`
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 用户上传头像
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param headerImg formData file true "用户上传头像"
|
||||
// @Param username formData string true "用户上传头像"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /user/uploadHeaderImg [post]
|
||||
func UploadHeaderImg(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
// 获取头像文件
|
||||
// 这里我们通过断言获取 claims内的所有内容
|
||||
waitUse := claims.(*request.CustomClaims)
|
||||
uuid := waitUse.UUID
|
||||
_, header, err := c.Request.FormFile("headerImg")
|
||||
// 便于找到用户 以后从jwt中取
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
|
||||
} else {
|
||||
// 文件上传后拿到文件路径
|
||||
err, filePath, _ := utils.Upload(header)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
|
||||
} else {
|
||||
// 修改数据库后得到修改后的user并且返回供前端使用
|
||||
err, user := service.UploadHeaderImg(uuid, filePath)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("修改数据库链接失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.SysUserResponse{User: *user}, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 分页获取用户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /user/getUserList [post]
|
||||
func GetUserList(c *gin.Context) {
|
||||
var pageInfo request.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
PageVerifyErr := utils.Verify(pageInfo, utils.CustomizeMap["PageVerify"])
|
||||
if PageVerifyErr != nil {
|
||||
response.FailWithMessage(PageVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err, list, total := service.GetUserInfoList(pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithData(resp.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SetUserAuth true "设置用户权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
|
||||
// @Router /user/setUserAuthority [post]
|
||||
func SetUserAuthority(c *gin.Context) {
|
||||
var sua request.SetUserAuth
|
||||
_ = c.ShouldBindJSON(&sua)
|
||||
UserVerify := utils.Rules{
|
||||
"UUID": {utils.NotEmpty()},
|
||||
"AuthorityId": {utils.NotEmpty()},
|
||||
}
|
||||
UserVerifyErr := utils.Verify(sua, UserVerify)
|
||||
if UserVerifyErr != nil {
|
||||
response.FailWithMessage(UserVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.SetUserAuthority(sua.UUID, sua.AuthorityId)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("修改失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 删除用户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "删除用户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
|
||||
// @Router /user/deleteUser [delete]
|
||||
func DeleteUser(c *gin.Context) {
|
||||
var reqId request.GetById
|
||||
_ = c.ShouldBindJSON(&reqId)
|
||||
IdVerifyErr := utils.Verify(reqId, utils.CustomizeMap["IdVerify"])
|
||||
if IdVerifyErr != nil {
|
||||
response.FailWithMessage(IdVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.DeleteUser(reqId.Id)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/global/response"
|
||||
"gin-vue-admin/model"
|
||||
"gin-vue-admin/service"
|
||||
"gin-vue-admin/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags workflow
|
||||
// @Summary 注册工作流
|
||||
// @Produce application/json
|
||||
// @Param data body model.SysWorkflow true "注册工作流接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
|
||||
// @Router /workflow/createWorkFlow [post]
|
||||
func CreateWorkFlow(c *gin.Context) {
|
||||
var wk model.SysWorkflow
|
||||
_ = c.ShouldBindJSON(&wk)
|
||||
WKVerify := utils.Rules{
|
||||
"WorkflowNickName": {utils.NotEmpty()},
|
||||
"WorkflowName": {utils.NotEmpty()},
|
||||
"WorkflowDescription": {utils.NotEmpty()},
|
||||
"WorkflowStepInfo": {utils.NotEmpty()},
|
||||
}
|
||||
WKVerifyErr := utils.Verify(wk, WKVerify)
|
||||
if WKVerifyErr != nil {
|
||||
response.FailWithMessage(WKVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
err := service.Create(wk)
|
||||
if err != nil {
|
||||
response.FailWithMessage(fmt.Sprintf("获取失败:%v", err), c)
|
||||
} else {
|
||||
response.OkWithMessage("获取成功", c)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
common "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
request "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AutoCodeHistoryApi struct{}
|
||||
|
||||
// First
|
||||
// @Tags AutoCode
|
||||
// @Summary 获取meta信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "请求参数"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取meta信息"
|
||||
// @Router /autoCode/getMeta [post]
|
||||
func (a *AutoCodeHistoryApi) First(c *gin.Context) {
|
||||
var info common.GetById
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
data, err := autoCodeHistoryService.First(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"meta": data}, "获取成功", c)
|
||||
}
|
||||
|
||||
// Delete
|
||||
// @Tags AutoCode
|
||||
// @Summary 删除回滚记录
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "请求参数"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除回滚记录"
|
||||
// @Router /autoCode/delSysHistory [post]
|
||||
func (a *AutoCodeHistoryApi) Delete(c *gin.Context) {
|
||||
var info common.GetById
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = autoCodeHistoryService.Delete(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// RollBack
|
||||
// @Tags AutoCode
|
||||
// @Summary 回滚自动生成代码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysAutoHistoryRollBack true "请求参数"
|
||||
// @Success 200 {object} response.Response{msg=string} "回滚自动生成代码"
|
||||
// @Router /autoCode/rollback [post]
|
||||
func (a *AutoCodeHistoryApi) RollBack(c *gin.Context) {
|
||||
var info request.SysAutoHistoryRollBack
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = autoCodeHistoryService.RollBack(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("回滚成功", c)
|
||||
}
|
||||
|
||||
// GetList
|
||||
// @Tags AutoCode
|
||||
// @Summary 查询回滚记录
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body common.PageInfo true "请求参数"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "查询回滚记录,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /autoCode/getSysHistory [post]
|
||||
func (a *AutoCodeHistoryApi) GetList(c *gin.Context) {
|
||||
var info common.PageInfo
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := autoCodeHistoryService.GetList(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: info.Page,
|
||||
PageSize: info.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/mcp/client"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
)
|
||||
|
||||
// Create
|
||||
// @Tags mcp
|
||||
// @Summary 自动McpTool
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AutoMcpTool true "创建自动代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/mcp [post]
|
||||
func (a *AutoCodeTemplateApi) MCP(c *gin.Context) {
|
||||
var info request.AutoMcpTool
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
toolFilePath, err := autoCodeTemplateService.CreateMcp(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
response.FailWithMessage("创建失败", c)
|
||||
global.GVA_LOG.Error(err.Error())
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功,MCP Tool路径:"+toolFilePath, c)
|
||||
}
|
||||
|
||||
// Create
|
||||
// @Tags mcp
|
||||
// @Summary 自动McpTool
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AutoMcpTool true "创建自动代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/mcpList [post]
|
||||
func (a *AutoCodeTemplateApi) MCPList(c *gin.Context) {
|
||||
|
||||
baseUrl := fmt.Sprintf("http://127.0.0.1:%d%s", global.GVA_CONFIG.System.Addr, global.GVA_CONFIG.MCP.SSEPath)
|
||||
|
||||
testClient, err := client.NewClient(baseUrl, "testClient", "v1.0.0", global.GVA_CONFIG.MCP.Name)
|
||||
defer testClient.Close()
|
||||
toolsRequest := mcp.ListToolsRequest{}
|
||||
|
||||
list, err := testClient.ListTools(c.Request.Context(), toolsRequest)
|
||||
|
||||
if err != nil {
|
||||
response.FailWithMessage("创建失败", c)
|
||||
global.GVA_LOG.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
mcpServerConfig := map[string]interface{}{
|
||||
"mcpServers": map[string]interface{}{
|
||||
global.GVA_CONFIG.MCP.Name: map[string]string{
|
||||
"url": baseUrl,
|
||||
},
|
||||
},
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"mcpServerConfig": mcpServerConfig,
|
||||
"list": list,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// Create
|
||||
// @Tags mcp
|
||||
// @Summary 测试McpTool
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body object true "调用MCP Tool的参数"
|
||||
// @Success 200 {object} response.Response "{"success":true,"data":{},"msg":"测试成功"}"
|
||||
// @Router /autoCode/mcpTest [post]
|
||||
func (a *AutoCodeTemplateApi) MCPTest(c *gin.Context) {
|
||||
// 定义接口请求结构
|
||||
var testRequest struct {
|
||||
Name string `json:"name" binding:"required"` // 工具名称
|
||||
Arguments map[string]interface{} `json:"arguments" binding:"required"` // 工具参数
|
||||
}
|
||||
|
||||
// 绑定JSON请求体
|
||||
if err := c.ShouldBindJSON(&testRequest); err != nil {
|
||||
response.FailWithMessage("参数解析失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建MCP客户端
|
||||
baseUrl := fmt.Sprintf("http://127.0.0.1:%d%s", global.GVA_CONFIG.System.Addr, global.GVA_CONFIG.MCP.SSEPath)
|
||||
testClient, err := client.NewClient(baseUrl, "testClient", "v1.0.0", global.GVA_CONFIG.MCP.Name)
|
||||
if err != nil {
|
||||
response.FailWithMessage("创建MCP客户端失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
defer testClient.Close()
|
||||
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// 初始化MCP连接
|
||||
initRequest := mcp.InitializeRequest{}
|
||||
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
|
||||
initRequest.Params.ClientInfo = mcp.Implementation{
|
||||
Name: "testClient",
|
||||
Version: "v1.0.0",
|
||||
}
|
||||
|
||||
_, err = testClient.Initialize(ctx, initRequest)
|
||||
if err != nil {
|
||||
response.FailWithMessage("初始化MCP连接失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建工具调用请求
|
||||
request := mcp.CallToolRequest{}
|
||||
request.Params.Name = testRequest.Name
|
||||
request.Params.Arguments = testRequest.Arguments
|
||||
|
||||
// 调用工具
|
||||
result, err := testClient.CallTool(ctx, request)
|
||||
if err != nil {
|
||||
response.FailWithMessage("工具调用失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 处理响应结果
|
||||
if len(result.Content) == 0 {
|
||||
response.FailWithMessage("工具未返回任何内容", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
response.OkWithData(result.Content, c)
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
common "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AutoCodePackageApi struct{}
|
||||
|
||||
// Create
|
||||
// @Tags AutoCodePackage
|
||||
// @Summary 创建package
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysAutoCodePackageCreate true "创建package"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "创建package成功"
|
||||
// @Router /autoCode/createPackage [post]
|
||||
func (a *AutoCodePackageApi) Create(c *gin.Context) {
|
||||
var info request.SysAutoCodePackageCreate
|
||||
_ = c.ShouldBindJSON(&info)
|
||||
if err := utils.Verify(info, utils.AutoPackageVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if strings.Contains(info.PackageName, "\\") || strings.Contains(info.PackageName, "/") || strings.Contains(info.PackageName, "..") {
|
||||
response.FailWithMessage("包名不合法", c)
|
||||
return
|
||||
} // PackageName可能导致路径穿越的问题 / 和 \ 都要防止
|
||||
err := autoCodePackageService.Create(c.Request.Context(), &info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// Delete
|
||||
// @Tags AutoCode
|
||||
// @Summary 删除package
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body common.GetById true "创建package"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "删除package成功"
|
||||
// @Router /autoCode/delPackage [post]
|
||||
func (a *AutoCodePackageApi) Delete(c *gin.Context) {
|
||||
var info common.GetById
|
||||
_ = c.ShouldBindJSON(&info)
|
||||
err := autoCodePackageService.Delete(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// All
|
||||
// @Tags AutoCodePackage
|
||||
// @Summary 获取package
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "创建package成功"
|
||||
// @Router /autoCode/getPackage [post]
|
||||
func (a *AutoCodePackageApi) All(c *gin.Context) {
|
||||
data, err := autoCodePackageService.All(c.Request.Context())
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"pkgs": data}, "获取成功", c)
|
||||
}
|
||||
|
||||
// Templates
|
||||
// @Tags AutoCodePackage
|
||||
// @Summary 获取package
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "创建package成功"
|
||||
// @Router /autoCode/getTemplates [get]
|
||||
func (a *AutoCodePackageApi) Templates(c *gin.Context) {
|
||||
data, err := autoCodePackageService.Templates(c.Request.Context())
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(data, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AutoCodePluginApi struct{}
|
||||
|
||||
// Install
|
||||
// @Tags AutoCodePlugin
|
||||
// @Summary 安装插件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param plug formData file true "this is a test file"
|
||||
// @Success 200 {object} response.Response{data=[]interface{},msg=string} "安装插件成功"
|
||||
// @Router /autoCode/installPlugin [post]
|
||||
func (a *AutoCodePluginApi) Install(c *gin.Context) {
|
||||
header, err := c.FormFile("plug")
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
web, server, err := autoCodePluginService.Install(header)
|
||||
webStr := "web插件安装成功"
|
||||
serverStr := "server插件安装成功"
|
||||
if web == -1 {
|
||||
webStr = "web端插件未成功安装,请按照文档自行解压安装,如果为纯后端插件请忽略此条提示"
|
||||
}
|
||||
if server == -1 {
|
||||
serverStr = "server端插件未成功安装,请按照文档自行解压安装,如果为纯前端插件请忽略此条提示"
|
||||
}
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData([]interface{}{
|
||||
gin.H{
|
||||
"code": web,
|
||||
"msg": webStr,
|
||||
},
|
||||
gin.H{
|
||||
"code": server,
|
||||
"msg": serverStr,
|
||||
}}, c)
|
||||
}
|
||||
|
||||
// Packaged
|
||||
// @Tags AutoCodePlugin
|
||||
// @Summary 打包插件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param plugName query string true "插件名称"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "打包插件成功"
|
||||
// @Router /autoCode/pubPlug [post]
|
||||
func (a *AutoCodePluginApi) Packaged(c *gin.Context) {
|
||||
plugName := c.Query("plugName")
|
||||
zipPath, err := autoCodePluginService.PubPlug(plugName)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("打包失败!", zap.Error(err))
|
||||
response.FailWithMessage("打包失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage(fmt.Sprintf("打包成功,文件路径为:%s", zipPath), c)
|
||||
}
|
||||
|
||||
// InitMenu
|
||||
// @Tags AutoCodePlugin
|
||||
// @Summary 打包插件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "打包插件成功"
|
||||
// @Router /autoCode/initMenu [post]
|
||||
func (a *AutoCodePluginApi) InitMenu(c *gin.Context) {
|
||||
var menuInfo request.InitMenu
|
||||
err := c.ShouldBindJSON(&menuInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = autoCodePluginService.InitMenu(menuInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建初始化Menu失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建初始化Menu失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("文件变更成功", c)
|
||||
}
|
||||
|
||||
// InitAPI
|
||||
// @Tags AutoCodePlugin
|
||||
// @Summary 打包插件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "打包插件成功"
|
||||
// @Router /autoCode/initAPI [post]
|
||||
func (a *AutoCodePluginApi) InitAPI(c *gin.Context) {
|
||||
var apiInfo request.InitApi
|
||||
err := c.ShouldBindJSON(&apiInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = autoCodePluginService.InitAPI(apiInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建初始化API失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建初始化API失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("文件变更成功", c)
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AutoCodeTemplateApi struct{}
|
||||
|
||||
// Preview
|
||||
// @Tags AutoCodeTemplate
|
||||
// @Summary 预览创建后的代码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AutoCode true "预览创建代码"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "预览创建后的代码"
|
||||
// @Router /autoCode/preview [post]
|
||||
func (a *AutoCodeTemplateApi) Preview(c *gin.Context) {
|
||||
var info request.AutoCode
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(info, utils.AutoCodeVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = info.Pretreatment()
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
info.PackageT = utils.FirstUpper(info.Package)
|
||||
autoCode, err := autoCodeTemplateService.Preview(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error(err.Error(), zap.Error(err))
|
||||
response.FailWithMessage("预览失败:"+err.Error(), c)
|
||||
} else {
|
||||
response.OkWithDetailed(gin.H{"autoCode": autoCode}, "预览成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// Create
|
||||
// @Tags AutoCodeTemplate
|
||||
// @Summary 自动代码模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AutoCode true "创建自动代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/createTemp [post]
|
||||
func (a *AutoCodeTemplateApi) Create(c *gin.Context) {
|
||||
var info request.AutoCode
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(info, utils.AutoCodeVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = info.Pretreatment()
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = autoCodeTemplateService.Create(c.Request.Context(), info)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// AddFunc
|
||||
// @Tags AddFunc
|
||||
// @Summary 增加方法
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.AutoCode true "增加方法"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/addFunc [post]
|
||||
func (a *AutoCodeTemplateApi) AddFunc(c *gin.Context) {
|
||||
var info request.AutoFunc
|
||||
err := c.ShouldBindJSON(&info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
var tempMap map[string]string
|
||||
if info.IsPreview {
|
||||
info.Router = "填充router"
|
||||
info.FuncName = "填充funcName"
|
||||
info.Method = "填充method"
|
||||
info.Description = "填充description"
|
||||
tempMap, err = autoCodeTemplateService.GetApiAndServer(info)
|
||||
} else {
|
||||
err = autoCodeTemplateService.AddFunc(info)
|
||||
}
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("注入失败!", zap.Error(err))
|
||||
response.FailWithMessage("注入失败", c)
|
||||
} else {
|
||||
if info.IsPreview {
|
||||
response.OkWithDetailed(tempMap, "注入成功", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("注入成功", c)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package system
|
||||
|
||||
import "github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
|
||||
type ApiGroup struct {
|
||||
DBApi
|
||||
JwtApi
|
||||
BaseApi
|
||||
SystemApi
|
||||
CasbinApi
|
||||
AutoCodeApi
|
||||
SystemApiApi
|
||||
AuthorityApi
|
||||
DictionaryApi
|
||||
AuthorityMenuApi
|
||||
OperationRecordApi
|
||||
DictionaryDetailApi
|
||||
AuthorityBtnApi
|
||||
SysExportTemplateApi
|
||||
AutoCodePluginApi
|
||||
AutoCodePackageApi
|
||||
AutoCodeHistoryApi
|
||||
AutoCodeTemplateApi
|
||||
SysParamsApi
|
||||
SysVersionApi
|
||||
}
|
||||
|
||||
var (
|
||||
apiService = service.ServiceGroupApp.SystemServiceGroup.ApiService
|
||||
jwtService = service.ServiceGroupApp.SystemServiceGroup.JwtService
|
||||
menuService = service.ServiceGroupApp.SystemServiceGroup.MenuService
|
||||
userService = service.ServiceGroupApp.SystemServiceGroup.UserService
|
||||
initDBService = service.ServiceGroupApp.SystemServiceGroup.InitDBService
|
||||
casbinService = service.ServiceGroupApp.SystemServiceGroup.CasbinService
|
||||
baseMenuService = service.ServiceGroupApp.SystemServiceGroup.BaseMenuService
|
||||
authorityService = service.ServiceGroupApp.SystemServiceGroup.AuthorityService
|
||||
dictionaryService = service.ServiceGroupApp.SystemServiceGroup.DictionaryService
|
||||
authorityBtnService = service.ServiceGroupApp.SystemServiceGroup.AuthorityBtnService
|
||||
systemConfigService = service.ServiceGroupApp.SystemServiceGroup.SystemConfigService
|
||||
sysParamsService = service.ServiceGroupApp.SystemServiceGroup.SysParamsService
|
||||
operationRecordService = service.ServiceGroupApp.SystemServiceGroup.OperationRecordService
|
||||
dictionaryDetailService = service.ServiceGroupApp.SystemServiceGroup.DictionaryDetailService
|
||||
autoCodeService = service.ServiceGroupApp.SystemServiceGroup.AutoCodeService
|
||||
autoCodePluginService = service.ServiceGroupApp.SystemServiceGroup.AutoCodePlugin
|
||||
autoCodePackageService = service.ServiceGroupApp.SystemServiceGroup.AutoCodePackage
|
||||
autoCodeHistoryService = service.ServiceGroupApp.SystemServiceGroup.AutoCodeHistory
|
||||
autoCodeTemplateService = service.ServiceGroupApp.SystemServiceGroup.AutoCodeTemplate
|
||||
sysVersionService = service.ServiceGroupApp.SystemServiceGroup.SysVersionService
|
||||
)
|
||||
@@ -0,0 +1,323 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SystemApiApi struct{}
|
||||
|
||||
// CreateApi
|
||||
// @Tags SysApi
|
||||
// @Summary 创建基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysApi true "api路径, api中文描述, api组, 方法"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建基础api"
|
||||
// @Router /api/createApi [post]
|
||||
func (s *SystemApiApi) CreateApi(c *gin.Context) {
|
||||
var api system.SysApi
|
||||
err := c.ShouldBindJSON(&api)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(api, utils.ApiVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.CreateApi(api)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// SyncApi
|
||||
// @Tags SysApi
|
||||
// @Summary 同步API
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "同步API"
|
||||
// @Router /api/syncApi [get]
|
||||
func (s *SystemApiApi) SyncApi(c *gin.Context) {
|
||||
newApis, deleteApis, ignoreApis, err := apiService.SyncApi()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("同步失败!", zap.Error(err))
|
||||
response.FailWithMessage("同步失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"newApis": newApis,
|
||||
"deleteApis": deleteApis,
|
||||
"ignoreApis": ignoreApis,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// GetApiGroups
|
||||
// @Tags SysApi
|
||||
// @Summary 获取API分组
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "获取API分组"
|
||||
// @Router /api/getApiGroups [get]
|
||||
func (s *SystemApiApi) GetApiGroups(c *gin.Context) {
|
||||
groups, apiGroupMap, err := apiService.GetApiGroups()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"groups": groups,
|
||||
"apiGroupMap": apiGroupMap,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// IgnoreApi
|
||||
// @Tags IgnoreApi
|
||||
// @Summary 忽略API
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "同步API"
|
||||
// @Router /api/ignoreApi [post]
|
||||
func (s *SystemApiApi) IgnoreApi(c *gin.Context) {
|
||||
var ignoreApi system.SysIgnoreApi
|
||||
err := c.ShouldBindJSON(&ignoreApi)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.IgnoreApi(ignoreApi)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("忽略失败!", zap.Error(err))
|
||||
response.FailWithMessage("忽略失败", c)
|
||||
return
|
||||
}
|
||||
response.Ok(c)
|
||||
}
|
||||
|
||||
// EnterSyncApi
|
||||
// @Tags SysApi
|
||||
// @Summary 确认同步API
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "确认同步API"
|
||||
// @Router /api/enterSyncApi [post]
|
||||
func (s *SystemApiApi) EnterSyncApi(c *gin.Context) {
|
||||
var syncApi systemRes.SysSyncApis
|
||||
err := c.ShouldBindJSON(&syncApi)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.EnterSyncApi(syncApi)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("忽略失败!", zap.Error(err))
|
||||
response.FailWithMessage("忽略失败", c)
|
||||
return
|
||||
}
|
||||
response.Ok(c)
|
||||
}
|
||||
|
||||
// DeleteApi
|
||||
// @Tags SysApi
|
||||
// @Summary 删除api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysApi true "ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除api"
|
||||
// @Router /api/deleteApi [post]
|
||||
func (s *SystemApiApi) DeleteApi(c *gin.Context) {
|
||||
var api system.SysApi
|
||||
err := c.ShouldBindJSON(&api)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(api.GVA_MODEL, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.DeleteApi(api)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// GetApiList
|
||||
// @Tags SysApi
|
||||
// @Summary 分页获取API列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.SearchApiParams true "分页获取API列表"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取API列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /api/getApiList [post]
|
||||
func (s *SystemApiApi) GetApiList(c *gin.Context) {
|
||||
var pageInfo systemReq.SearchApiParams
|
||||
err := c.ShouldBindJSON(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(pageInfo.PageInfo, utils.PageInfoVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := apiService.GetAPIInfoList(pageInfo.SysApi, pageInfo.PageInfo, pageInfo.OrderKey, pageInfo.Desc)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetApiById
|
||||
// @Tags SysApi
|
||||
// @Summary 根据id获取api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "根据id获取api"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysAPIResponse} "根据id获取api,返回包括api详情"
|
||||
// @Router /api/getApiById [post]
|
||||
func (s *SystemApiApi) GetApiById(c *gin.Context) {
|
||||
var idInfo request.GetById
|
||||
err := c.ShouldBindJSON(&idInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(idInfo, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
api, err := apiService.GetApiById(idInfo.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysAPIResponse{Api: api}, "获取成功", c)
|
||||
}
|
||||
|
||||
// UpdateApi
|
||||
// @Tags SysApi
|
||||
// @Summary 修改基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysApi true "api路径, api中文描述, api组, 方法"
|
||||
// @Success 200 {object} response.Response{msg=string} "修改基础api"
|
||||
// @Router /api/updateApi [post]
|
||||
func (s *SystemApiApi) UpdateApi(c *gin.Context) {
|
||||
var api system.SysApi
|
||||
err := c.ShouldBindJSON(&api)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(api, utils.ApiVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.UpdateApi(api)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改失败!", zap.Error(err))
|
||||
response.FailWithMessage("修改失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
|
||||
// GetAllApis
|
||||
// @Tags SysApi
|
||||
// @Summary 获取所有的Api 不分页
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysAPIListResponse,msg=string} "获取所有的Api 不分页,返回包括api列表"
|
||||
// @Router /api/getAllApis [post]
|
||||
func (s *SystemApiApi) GetAllApis(c *gin.Context) {
|
||||
authorityID := utils.GetUserAuthorityId(c)
|
||||
apis, err := apiService.GetAllApis(authorityID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysAPIListResponse{Apis: apis}, "获取成功", c)
|
||||
}
|
||||
|
||||
// DeleteApisByIds
|
||||
// @Tags SysApi
|
||||
// @Summary 删除选中Api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除选中Api"
|
||||
// @Router /api/deleteApisByIds [delete]
|
||||
func (s *SystemApiApi) DeleteApisByIds(c *gin.Context) {
|
||||
var ids request.IdsReq
|
||||
err := c.ShouldBindJSON(&ids)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = apiService.DeleteApisByIds(ids)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// FreshCasbin
|
||||
// @Tags SysApi
|
||||
// @Summary 刷新casbin缓存
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "刷新成功"
|
||||
// @Router /api/freshCasbin [get]
|
||||
func (s *SystemApiApi) FreshCasbin(c *gin.Context) {
|
||||
err := casbinService.FreshCasbin()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("刷新失败!", zap.Error(err))
|
||||
response.FailWithMessage("刷新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("刷新成功", c)
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AuthorityApi struct{}
|
||||
|
||||
// CreateAuthority
|
||||
// @Tags Authority
|
||||
// @Summary 创建角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysAuthority true "权限id, 权限名, 父角色id"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysAuthorityResponse,msg=string} "创建角色,返回包括系统角色详情"
|
||||
// @Router /authority/createAuthority [post]
|
||||
func (a *AuthorityApi) CreateAuthority(c *gin.Context) {
|
||||
var authority, authBack system.SysAuthority
|
||||
var err error
|
||||
|
||||
if err = c.ShouldBindJSON(&authority); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if err = utils.Verify(authority, utils.AuthorityVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if *authority.ParentId == 0 && global.GVA_CONFIG.System.UseStrictAuth {
|
||||
authority.ParentId = utils.Pointer(utils.GetUserAuthorityId(c))
|
||||
}
|
||||
|
||||
if authBack, err = authorityService.CreateAuthority(authority); err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = casbinService.FreshCasbin()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建成功,权限刷新失败。", zap.Error(err))
|
||||
response.FailWithMessage("创建成功,权限刷新失败。"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysAuthorityResponse{Authority: authBack}, "创建成功", c)
|
||||
}
|
||||
|
||||
// CopyAuthority
|
||||
// @Tags Authority
|
||||
// @Summary 拷贝角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body response.SysAuthorityCopyResponse true "旧角色id, 新权限id, 新权限名, 新父角色id"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysAuthorityResponse,msg=string} "拷贝角色,返回包括系统角色详情"
|
||||
// @Router /authority/copyAuthority [post]
|
||||
func (a *AuthorityApi) CopyAuthority(c *gin.Context) {
|
||||
var copyInfo systemRes.SysAuthorityCopyResponse
|
||||
err := c.ShouldBindJSON(©Info)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(copyInfo, utils.OldAuthorityVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(copyInfo.Authority, utils.AuthorityVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
adminAuthorityID := utils.GetUserAuthorityId(c)
|
||||
authBack, err := authorityService.CopyAuthority(adminAuthorityID, copyInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("拷贝失败!", zap.Error(err))
|
||||
response.FailWithMessage("拷贝失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysAuthorityResponse{Authority: authBack}, "拷贝成功", c)
|
||||
}
|
||||
|
||||
// DeleteAuthority
|
||||
// @Tags Authority
|
||||
// @Summary 删除角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysAuthority true "删除角色"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除角色"
|
||||
// @Router /authority/deleteAuthority [post]
|
||||
func (a *AuthorityApi) DeleteAuthority(c *gin.Context) {
|
||||
var authority system.SysAuthority
|
||||
var err error
|
||||
if err = c.ShouldBindJSON(&authority); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err = utils.Verify(authority, utils.AuthorityIdVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
// 删除角色之前需要判断是否有用户正在使用此角色
|
||||
if err = authorityService.DeleteAuthority(&authority); err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
_ = casbinService.FreshCasbin()
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateAuthority
|
||||
// @Tags Authority
|
||||
// @Summary 更新角色信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysAuthority true "权限id, 权限名, 父角色id"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysAuthorityResponse,msg=string} "更新角色信息,返回包括系统角色详情"
|
||||
// @Router /authority/updateAuthority [put]
|
||||
func (a *AuthorityApi) UpdateAuthority(c *gin.Context) {
|
||||
var auth system.SysAuthority
|
||||
err := c.ShouldBindJSON(&auth)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(auth, utils.AuthorityVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
authority, err := authorityService.UpdateAuthority(auth)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysAuthorityResponse{Authority: authority}, "更新成功", c)
|
||||
}
|
||||
|
||||
// GetAuthorityList
|
||||
// @Tags Authority
|
||||
// @Summary 分页获取角色列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "页码, 每页大小"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取角色列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /authority/getAuthorityList [post]
|
||||
func (a *AuthorityApi) GetAuthorityList(c *gin.Context) {
|
||||
authorityID := utils.GetUserAuthorityId(c)
|
||||
list, err := authorityService.GetAuthorityInfoList(authorityID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(list, "获取成功", c)
|
||||
}
|
||||
|
||||
// SetDataAuthority
|
||||
// @Tags Authority
|
||||
// @Summary 设置角色资源权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysAuthority true "设置角色资源权限"
|
||||
// @Success 200 {object} response.Response{msg=string} "设置角色资源权限"
|
||||
// @Router /authority/setDataAuthority [post]
|
||||
func (a *AuthorityApi) SetDataAuthority(c *gin.Context) {
|
||||
var auth system.SysAuthority
|
||||
err := c.ShouldBindJSON(&auth)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(auth, utils.AuthorityIdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
adminAuthorityID := utils.GetUserAuthorityId(c)
|
||||
err = authorityService.SetDataAuthority(adminAuthorityID, auth)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AuthorityBtnApi struct{}
|
||||
|
||||
// GetAuthorityBtn
|
||||
// @Tags AuthorityBtn
|
||||
// @Summary 获取权限按钮
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysAuthorityBtnReq true "菜单id, 角色id, 选中的按钮id"
|
||||
// @Success 200 {object} response.Response{data=response.SysAuthorityBtnRes,msg=string} "返回列表成功"
|
||||
// @Router /authorityBtn/getAuthorityBtn [post]
|
||||
func (a *AuthorityBtnApi) GetAuthorityBtn(c *gin.Context) {
|
||||
var req request.SysAuthorityBtnReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
res, err := authorityBtnService.GetAuthorityBtn(req)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(res, "查询成功", c)
|
||||
}
|
||||
|
||||
// SetAuthorityBtn
|
||||
// @Tags AuthorityBtn
|
||||
// @Summary 设置权限按钮
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.SysAuthorityBtnReq true "菜单id, 角色id, 选中的按钮id"
|
||||
// @Success 200 {object} response.Response{msg=string} "返回列表成功"
|
||||
// @Router /authorityBtn/setAuthorityBtn [post]
|
||||
func (a *AuthorityBtnApi) SetAuthorityBtn(c *gin.Context) {
|
||||
var req request.SysAuthorityBtnReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = authorityBtnService.SetAuthorityBtn(req)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("分配失败!", zap.Error(err))
|
||||
response.FailWithMessage("分配失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("分配成功", c)
|
||||
}
|
||||
|
||||
// CanRemoveAuthorityBtn
|
||||
// @Tags AuthorityBtn
|
||||
// @Summary 设置权限按钮
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "删除成功"
|
||||
// @Router /authorityBtn/canRemoveAuthorityBtn [post]
|
||||
func (a *AuthorityBtnApi) CanRemoveAuthorityBtn(c *gin.Context) {
|
||||
id := c.Query("id")
|
||||
err := authorityBtnService.CanRemoveAuthorityBtn(id)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common"
|
||||
"github.com/goccy/go-json"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AutoCodeApi struct{}
|
||||
|
||||
// GetDB
|
||||
// @Tags AutoCode
|
||||
// @Summary 获取当前所有数据库
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取当前所有数据库"
|
||||
// @Router /autoCode/getDB [get]
|
||||
func (autoApi *AutoCodeApi) GetDB(c *gin.Context) {
|
||||
businessDB := c.Query("businessDB")
|
||||
dbs, err := autoCodeService.Database(businessDB).GetDB(businessDB)
|
||||
var dbList []map[string]interface{}
|
||||
for _, db := range global.GVA_CONFIG.DBList {
|
||||
var item = make(map[string]interface{})
|
||||
item["aliasName"] = db.AliasName
|
||||
item["dbName"] = db.Dbname
|
||||
item["disable"] = db.Disable
|
||||
item["dbtype"] = db.Type
|
||||
dbList = append(dbList, item)
|
||||
}
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(gin.H{"dbs": dbs, "dbList": dbList}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTables
|
||||
// @Tags AutoCode
|
||||
// @Summary 获取当前数据库所有表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取当前数据库所有表"
|
||||
// @Router /autoCode/getTables [get]
|
||||
func (autoApi *AutoCodeApi) GetTables(c *gin.Context) {
|
||||
dbName := c.Query("dbName")
|
||||
businessDB := c.Query("businessDB")
|
||||
if dbName == "" {
|
||||
dbName = *global.GVA_ACTIVE_DBNAME
|
||||
if businessDB != "" {
|
||||
for _, db := range global.GVA_CONFIG.DBList {
|
||||
if db.AliasName == businessDB {
|
||||
dbName = db.Dbname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tables, err := autoCodeService.Database(businessDB).GetTables(businessDB, dbName)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询table失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询table失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(gin.H{"tables": tables}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetColumn
|
||||
// @Tags AutoCode
|
||||
// @Summary 获取当前表所有字段
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取当前表所有字段"
|
||||
// @Router /autoCode/getColumn [get]
|
||||
func (autoApi *AutoCodeApi) GetColumn(c *gin.Context) {
|
||||
businessDB := c.Query("businessDB")
|
||||
dbName := c.Query("dbName")
|
||||
if dbName == "" {
|
||||
dbName = *global.GVA_ACTIVE_DBNAME
|
||||
if businessDB != "" {
|
||||
for _, db := range global.GVA_CONFIG.DBList {
|
||||
if db.AliasName == businessDB {
|
||||
dbName = db.Dbname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tableName := c.Query("tableName")
|
||||
columns, err := autoCodeService.Database(businessDB).GetColumn(businessDB, tableName, dbName)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(gin.H{"columns": columns}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (autoApi *AutoCodeApi) LLMAuto(c *gin.Context) {
|
||||
var llm common.JSONMap
|
||||
err := c.ShouldBindJSON(&llm)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if global.GVA_CONFIG.AutoCode.AiPath == "" {
|
||||
response.FailWithMessage("请先前往插件市场个人中心获取AiPath并填入config.yaml中", c)
|
||||
return
|
||||
}
|
||||
|
||||
path := strings.ReplaceAll(global.GVA_CONFIG.AutoCode.AiPath, "{FUNC}", fmt.Sprintf("api/chat/%s", llm["mode"]))
|
||||
res, err := request.HttpRequest(
|
||||
path,
|
||||
"POST",
|
||||
nil,
|
||||
nil,
|
||||
llm,
|
||||
)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("大模型生成失败!", zap.Error(err))
|
||||
response.FailWithMessage("大模型生成失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
var resStruct response.Response
|
||||
b, err := io.ReadAll(res.Body)
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("大模型生成失败!", zap.Error(err))
|
||||
response.FailWithMessage("大模型生成失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(b, &resStruct)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("大模型生成失败!", zap.Error(err))
|
||||
response.FailWithMessage("大模型生成失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
if resStruct.Code == 7 {
|
||||
global.GVA_LOG.Error("大模型生成失败!"+resStruct.Msg, zap.Error(err))
|
||||
response.FailWithMessage("大模型生成失败"+resStruct.Msg, c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resStruct.Data, c)
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// 当开启多服务器部署时,替换下面的配置,使用redis共享存储验证码
|
||||
// var store = captcha.NewDefaultRedisStore()
|
||||
var store = base64Captcha.DefaultMemStore
|
||||
|
||||
type BaseApi struct{}
|
||||
|
||||
// Captcha
|
||||
// @Tags Base
|
||||
// @Summary 生成验证码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysCaptchaResponse,msg=string} "生成验证码,返回包括随机数id,base64,验证码长度,是否开启验证码"
|
||||
// @Router /base/captcha [post]
|
||||
func (b *BaseApi) Captcha(c *gin.Context) {
|
||||
// 判断验证码是否开启
|
||||
openCaptcha := global.GVA_CONFIG.Captcha.OpenCaptcha // 是否开启防爆次数
|
||||
openCaptchaTimeOut := global.GVA_CONFIG.Captcha.OpenCaptchaTimeOut // 缓存超时时间
|
||||
key := c.ClientIP()
|
||||
v, ok := global.BlackCache.Get(key)
|
||||
if !ok {
|
||||
global.BlackCache.Set(key, 1, time.Second*time.Duration(openCaptchaTimeOut))
|
||||
}
|
||||
|
||||
var oc bool
|
||||
if openCaptcha == 0 || openCaptcha < interfaceToInt(v) {
|
||||
oc = true
|
||||
}
|
||||
// 字符,公式,验证码配置
|
||||
// 生成默认数字的driver
|
||||
driver := base64Captcha.NewDriverDigit(global.GVA_CONFIG.Captcha.ImgHeight, global.GVA_CONFIG.Captcha.ImgWidth, global.GVA_CONFIG.Captcha.KeyLong, 0.7, 80)
|
||||
// cp := base64Captcha.NewCaptcha(driver, store.UseWithCtx(c)) // v8下使用redis
|
||||
cp := base64Captcha.NewCaptcha(driver, store)
|
||||
id, b64s, _, err := cp.Generate()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("验证码获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("验证码获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysCaptchaResponse{
|
||||
CaptchaId: id,
|
||||
PicPath: b64s,
|
||||
CaptchaLength: global.GVA_CONFIG.Captcha.KeyLong,
|
||||
OpenCaptcha: oc,
|
||||
}, "验证码获取成功", c)
|
||||
}
|
||||
|
||||
// 类型转换
|
||||
func interfaceToInt(v interface{}) (i int) {
|
||||
switch v := v.(type) {
|
||||
case int:
|
||||
i = v
|
||||
default:
|
||||
i = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CasbinApi struct{}
|
||||
|
||||
// UpdateCasbin
|
||||
// @Tags Casbin
|
||||
// @Summary 更新角色api权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.CasbinInReceive true "权限id, 权限模型列表"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新角色api权限"
|
||||
// @Router /casbin/UpdateCasbin [post]
|
||||
func (cas *CasbinApi) UpdateCasbin(c *gin.Context) {
|
||||
var cmr request.CasbinInReceive
|
||||
err := c.ShouldBindJSON(&cmr)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(cmr, utils.AuthorityIdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
adminAuthorityID := utils.GetUserAuthorityId(c)
|
||||
err = casbinService.UpdateCasbin(adminAuthorityID, cmr.AuthorityId, cmr.CasbinInfos)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// GetPolicyPathByAuthorityId
|
||||
// @Tags Casbin
|
||||
// @Summary 获取权限列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.CasbinInReceive true "权限id, 权限模型列表"
|
||||
// @Success 200 {object} response.Response{data=systemRes.PolicyPathResponse,msg=string} "获取权限列表,返回包括casbin详情列表"
|
||||
// @Router /casbin/getPolicyPathByAuthorityId [post]
|
||||
func (cas *CasbinApi) GetPolicyPathByAuthorityId(c *gin.Context) {
|
||||
var casbin request.CasbinInReceive
|
||||
err := c.ShouldBindJSON(&casbin)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(casbin, utils.AuthorityIdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
paths := casbinService.GetPolicyPathByAuthorityId(casbin.AuthorityId)
|
||||
response.OkWithDetailed(systemRes.PolicyPathResponse{Paths: paths}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DictionaryApi struct{}
|
||||
|
||||
// CreateSysDictionary
|
||||
// @Tags SysDictionary
|
||||
// @Summary 创建SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionary true "SysDictionary模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建SysDictionary"
|
||||
// @Router /sysDictionary/createSysDictionary [post]
|
||||
func (s *DictionaryApi) CreateSysDictionary(c *gin.Context) {
|
||||
var dictionary system.SysDictionary
|
||||
err := c.ShouldBindJSON(&dictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryService.CreateSysDictionary(dictionary)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysDictionary
|
||||
// @Tags SysDictionary
|
||||
// @Summary 删除SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionary true "SysDictionary模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除SysDictionary"
|
||||
// @Router /sysDictionary/deleteSysDictionary [delete]
|
||||
func (s *DictionaryApi) DeleteSysDictionary(c *gin.Context) {
|
||||
var dictionary system.SysDictionary
|
||||
err := c.ShouldBindJSON(&dictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryService.DeleteSysDictionary(dictionary)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysDictionary
|
||||
// @Tags SysDictionary
|
||||
// @Summary 更新SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionary true "SysDictionary模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新SysDictionary"
|
||||
// @Router /sysDictionary/updateSysDictionary [put]
|
||||
func (s *DictionaryApi) UpdateSysDictionary(c *gin.Context) {
|
||||
var dictionary system.SysDictionary
|
||||
err := c.ShouldBindJSON(&dictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryService.UpdateSysDictionary(&dictionary)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysDictionary
|
||||
// @Tags SysDictionary
|
||||
// @Summary 用id查询SysDictionary
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query system.SysDictionary true "ID或字典英名"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "用id查询SysDictionary"
|
||||
// @Router /sysDictionary/findSysDictionary [get]
|
||||
func (s *DictionaryApi) FindSysDictionary(c *gin.Context) {
|
||||
var dictionary system.SysDictionary
|
||||
err := c.ShouldBindQuery(&dictionary)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
sysDictionary, err := dictionaryService.GetSysDictionary(dictionary.Type, dictionary.ID, dictionary.Status)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("字典未创建或未开启!", zap.Error(err))
|
||||
response.FailWithMessage("字典未创建或未开启", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"resysDictionary": sysDictionary}, "查询成功", c)
|
||||
}
|
||||
|
||||
// GetSysDictionaryList
|
||||
// @Tags SysDictionary
|
||||
// @Summary 分页获取SysDictionary列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取SysDictionary列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /sysDictionary/getSysDictionaryList [get]
|
||||
func (s *DictionaryApi) GetSysDictionaryList(c *gin.Context) {
|
||||
list, err := dictionaryService.GetSysDictionaryInfoList()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(list, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type DictionaryDetailApi struct{}
|
||||
|
||||
// CreateSysDictionaryDetail
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 创建SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionaryDetail true "SysDictionaryDetail模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建SysDictionaryDetail"
|
||||
// @Router /sysDictionaryDetail/createSysDictionaryDetail [post]
|
||||
func (s *DictionaryDetailApi) CreateSysDictionaryDetail(c *gin.Context) {
|
||||
var detail system.SysDictionaryDetail
|
||||
err := c.ShouldBindJSON(&detail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryDetailService.CreateSysDictionaryDetail(detail)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysDictionaryDetail
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 删除SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionaryDetail true "SysDictionaryDetail模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除SysDictionaryDetail"
|
||||
// @Router /sysDictionaryDetail/deleteSysDictionaryDetail [delete]
|
||||
func (s *DictionaryDetailApi) DeleteSysDictionaryDetail(c *gin.Context) {
|
||||
var detail system.SysDictionaryDetail
|
||||
err := c.ShouldBindJSON(&detail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryDetailService.DeleteSysDictionaryDetail(detail)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysDictionaryDetail
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 更新SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysDictionaryDetail true "更新SysDictionaryDetail"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新SysDictionaryDetail"
|
||||
// @Router /sysDictionaryDetail/updateSysDictionaryDetail [put]
|
||||
func (s *DictionaryDetailApi) UpdateSysDictionaryDetail(c *gin.Context) {
|
||||
var detail system.SysDictionaryDetail
|
||||
err := c.ShouldBindJSON(&detail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = dictionaryDetailService.UpdateSysDictionaryDetail(&detail)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysDictionaryDetail
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 用id查询SysDictionaryDetail
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query system.SysDictionaryDetail true "用id查询SysDictionaryDetail"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "用id查询SysDictionaryDetail"
|
||||
// @Router /sysDictionaryDetail/findSysDictionaryDetail [get]
|
||||
func (s *DictionaryDetailApi) FindSysDictionaryDetail(c *gin.Context) {
|
||||
var detail system.SysDictionaryDetail
|
||||
err := c.ShouldBindQuery(&detail)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(detail, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
reSysDictionaryDetail, err := dictionaryDetailService.GetSysDictionaryDetail(detail.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"reSysDictionaryDetail": reSysDictionaryDetail}, "查询成功", c)
|
||||
}
|
||||
|
||||
// GetSysDictionaryDetailList
|
||||
// @Tags SysDictionaryDetail
|
||||
// @Summary 分页获取SysDictionaryDetail列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query request.SysDictionaryDetailSearch true "页码, 每页大小, 搜索条件"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取SysDictionaryDetail列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /sysDictionaryDetail/getSysDictionaryDetailList [get]
|
||||
func (s *DictionaryDetailApi) GetSysDictionaryDetailList(c *gin.Context) {
|
||||
var pageInfo request.SysDictionaryDetailSearch
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := dictionaryDetailService.GetSysDictionaryDetailInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/service"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// 用于token一次性存储
|
||||
var (
|
||||
exportTokenCache = make(map[string]interface{})
|
||||
exportTokenExpiration = make(map[string]time.Time)
|
||||
tokenMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// 五分钟检测窗口过期
|
||||
func cleanupExpiredTokens() {
|
||||
for {
|
||||
time.Sleep(5 * time.Minute)
|
||||
tokenMutex.Lock()
|
||||
now := time.Now()
|
||||
for token, expiry := range exportTokenExpiration {
|
||||
if now.After(expiry) {
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
}
|
||||
}
|
||||
tokenMutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
go cleanupExpiredTokens()
|
||||
}
|
||||
|
||||
type SysExportTemplateApi struct {
|
||||
}
|
||||
|
||||
var sysExportTemplateService = service.ServiceGroupApp.SystemServiceGroup.SysExportTemplateService
|
||||
|
||||
// CreateSysExportTemplate 创建导出模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 创建导出模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysExportTemplate true "创建导出模板"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /sysExportTemplate/createSysExportTemplate [post]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) CreateSysExportTemplate(c *gin.Context) {
|
||||
var sysExportTemplate system.SysExportTemplate
|
||||
err := c.ShouldBindJSON(&sysExportTemplate)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
verify := utils.Rules{
|
||||
"Name": {utils.NotEmpty()},
|
||||
}
|
||||
if err := utils.Verify(sysExportTemplate, verify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := sysExportTemplateService.CreateSysExportTemplate(&sysExportTemplate); err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplate 删除导出模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 删除导出模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysExportTemplate true "删除导出模板"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /sysExportTemplate/deleteSysExportTemplate [delete]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) DeleteSysExportTemplate(c *gin.Context) {
|
||||
var sysExportTemplate system.SysExportTemplate
|
||||
err := c.ShouldBindJSON(&sysExportTemplate)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := sysExportTemplateService.DeleteSysExportTemplate(sysExportTemplate); err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSysExportTemplateByIds 批量删除导出模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 批量删除导出模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "批量删除导出模板"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
|
||||
// @Router /sysExportTemplate/deleteSysExportTemplateByIds [delete]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) DeleteSysExportTemplateByIds(c *gin.Context) {
|
||||
var IDS request.IdsReq
|
||||
err := c.ShouldBindJSON(&IDS)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := sysExportTemplateService.DeleteSysExportTemplateByIds(IDS); err != nil {
|
||||
global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("批量删除失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSysExportTemplate 更新导出模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 更新导出模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysExportTemplate true "更新导出模板"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /sysExportTemplate/updateSysExportTemplate [put]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) UpdateSysExportTemplate(c *gin.Context) {
|
||||
var sysExportTemplate system.SysExportTemplate
|
||||
err := c.ShouldBindJSON(&sysExportTemplate)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
verify := utils.Rules{
|
||||
"Name": {utils.NotEmpty()},
|
||||
}
|
||||
if err := utils.Verify(sysExportTemplate, verify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := sysExportTemplateService.UpdateSysExportTemplate(sysExportTemplate); err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// FindSysExportTemplate 用id查询导出模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 用id查询导出模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query system.SysExportTemplate true "用id查询导出模板"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /sysExportTemplate/findSysExportTemplate [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) FindSysExportTemplate(c *gin.Context) {
|
||||
var sysExportTemplate system.SysExportTemplate
|
||||
err := c.ShouldBindQuery(&sysExportTemplate)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if resysExportTemplate, err := sysExportTemplateService.GetSysExportTemplate(sysExportTemplate.ID); err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败", c)
|
||||
} else {
|
||||
response.OkWithData(gin.H{"resysExportTemplate": resysExportTemplate}, c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetSysExportTemplateList 分页获取导出模板列表
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 分页获取导出模板列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query systemReq.SysExportTemplateSearch true "分页获取导出模板列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /sysExportTemplate/getSysExportTemplateList [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) GetSysExportTemplateList(c *gin.Context) {
|
||||
var pageInfo systemReq.SysExportTemplateSearch
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if list, total, err := sysExportTemplateService.GetSysExportTemplateInfoList(pageInfo); err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// ExportExcel 导出表格token
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 导出表格
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /sysExportTemplate/exportExcel [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) ExportExcel(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
queryParams := c.Request.URL.Query()
|
||||
|
||||
//创造一次性token
|
||||
token := utils.RandomString(32) // 随机32位
|
||||
|
||||
// 记录本次请求参数
|
||||
exportParams := map[string]interface{}{
|
||||
"templateID": templateID,
|
||||
"queryParams": queryParams,
|
||||
}
|
||||
|
||||
// 参数保留记录完成鉴权
|
||||
tokenMutex.Lock()
|
||||
exportTokenCache[token] = exportParams
|
||||
exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 生成一次性链接
|
||||
exportUrl := fmt.Sprintf("/sysExportTemplate/exportExcelByToken?token=%s", token)
|
||||
response.OkWithData(exportUrl, c)
|
||||
}
|
||||
|
||||
// ExportExcelByToken 导出表格
|
||||
// @Tags ExportExcelByToken
|
||||
// @Summary 导出表格
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /sysExportTemplate/exportExcelByToken [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) ExportExcelByToken(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
response.FailWithMessage("导出token不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取token并且从缓存中剔除
|
||||
tokenMutex.RLock()
|
||||
exportParamsRaw, exists := exportTokenCache[token]
|
||||
expiry, _ := exportTokenExpiration[token]
|
||||
tokenMutex.RUnlock()
|
||||
|
||||
if !exists || time.Now().After(expiry) {
|
||||
global.GVA_LOG.Error("导出token无效或已过期!")
|
||||
response.FailWithMessage("导出token无效或已过期", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 从token获取参数
|
||||
exportParams, ok := exportParamsRaw.(map[string]interface{})
|
||||
if !ok {
|
||||
global.GVA_LOG.Error("解析导出参数失败!")
|
||||
response.FailWithMessage("解析导出参数失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取导出参数
|
||||
templateID := exportParams["templateID"].(string)
|
||||
queryParams := exportParams["queryParams"].(url.Values)
|
||||
|
||||
// 清理一次性token
|
||||
tokenMutex.Lock()
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 导出
|
||||
if file, name, err := sysExportTemplateService.ExportExcel(templateID, queryParams); err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+utils.RandomString(6)+".xlsx"))
|
||||
c.Header("success", "true")
|
||||
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", file.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// ExportTemplate 导出表格模板
|
||||
// @Tags SysExportTemplate
|
||||
// @Summary 导出表格模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /sysExportTemplate/exportTemplate [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) ExportTemplate(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 创造一次性token
|
||||
token := utils.RandomString(32) // 随机32位
|
||||
|
||||
// 记录本次请求参数
|
||||
exportParams := map[string]interface{}{
|
||||
"templateID": templateID,
|
||||
"isTemplate": true,
|
||||
}
|
||||
|
||||
// 参数保留记录完成鉴权
|
||||
tokenMutex.Lock()
|
||||
exportTokenCache[token] = exportParams
|
||||
exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 生成一次性链接
|
||||
exportUrl := fmt.Sprintf("/sysExportTemplate/exportTemplateByToken?token=%s", token)
|
||||
response.OkWithData(exportUrl, c)
|
||||
}
|
||||
|
||||
// ExportTemplateByToken 通过token导出表格模板
|
||||
// @Tags ExportTemplateByToken
|
||||
// @Summary 通过token导出表格模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /sysExportTemplate/exportTemplateByToken [get]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) ExportTemplateByToken(c *gin.Context) {
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
response.FailWithMessage("导出token不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取token并且从缓存中剔除
|
||||
tokenMutex.RLock()
|
||||
exportParamsRaw, exists := exportTokenCache[token]
|
||||
expiry, _ := exportTokenExpiration[token]
|
||||
tokenMutex.RUnlock()
|
||||
|
||||
if !exists || time.Now().After(expiry) {
|
||||
global.GVA_LOG.Error("导出token无效或已过期!")
|
||||
response.FailWithMessage("导出token无效或已过期", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 从token获取参数
|
||||
exportParams, ok := exportParamsRaw.(map[string]interface{})
|
||||
if !ok {
|
||||
global.GVA_LOG.Error("解析导出参数失败!")
|
||||
response.FailWithMessage("解析导出参数失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为模板导出
|
||||
isTemplate, _ := exportParams["isTemplate"].(bool)
|
||||
if !isTemplate {
|
||||
global.GVA_LOG.Error("token类型错误!")
|
||||
response.FailWithMessage("token类型错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取导出参数
|
||||
templateID := exportParams["templateID"].(string)
|
||||
|
||||
// 清理一次性token
|
||||
tokenMutex.Lock()
|
||||
delete(exportTokenCache, token)
|
||||
delete(exportTokenExpiration, token)
|
||||
tokenMutex.Unlock()
|
||||
|
||||
// 导出模板
|
||||
if file, name, err := sysExportTemplateService.ExportTemplate(templateID); err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
} else {
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+"模板.xlsx"))
|
||||
c.Header("success", "true")
|
||||
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", file.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// ImportExcel 导入表格
|
||||
// @Tags SysImportTemplate
|
||||
// @Summary 导入表格
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Router /sysExportTemplate/importExcel [post]
|
||||
func (sysExportTemplateApi *SysExportTemplateApi) ImportExcel(c *gin.Context) {
|
||||
templateID := c.Query("templateID")
|
||||
if templateID == "" {
|
||||
response.FailWithMessage("模板ID不能为空", c)
|
||||
return
|
||||
}
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("文件获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("文件获取失败", c)
|
||||
return
|
||||
}
|
||||
if err := sysExportTemplateService.ImportExcel(templateID, file); err != nil {
|
||||
global.GVA_LOG.Error(err.Error(), zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
} else {
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type DBApi struct{}
|
||||
|
||||
// InitDB
|
||||
// @Tags InitDB
|
||||
// @Summary 初始化用户数据库
|
||||
// @Produce application/json
|
||||
// @Param data body request.InitDB true "初始化数据库参数"
|
||||
// @Success 200 {object} response.Response{data=string} "初始化用户数据库"
|
||||
// @Router /init/initdb [post]
|
||||
func (i *DBApi) InitDB(c *gin.Context) {
|
||||
if global.GVA_DB != nil {
|
||||
global.GVA_LOG.Error("已存在数据库配置!")
|
||||
response.FailWithMessage("已存在数据库配置", c)
|
||||
return
|
||||
}
|
||||
var dbInfo request.InitDB
|
||||
if err := c.ShouldBindJSON(&dbInfo); err != nil {
|
||||
global.GVA_LOG.Error("参数校验不通过!", zap.Error(err))
|
||||
response.FailWithMessage("参数校验不通过", c)
|
||||
return
|
||||
}
|
||||
if err := initDBService.InitDB(dbInfo); err != nil {
|
||||
global.GVA_LOG.Error("自动创建数据库失败!", zap.Error(err))
|
||||
response.FailWithMessage("自动创建数据库失败,请查看后台日志,检查后在进行初始化", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("自动创建数据库成功", c)
|
||||
}
|
||||
|
||||
// CheckDB
|
||||
// @Tags CheckDB
|
||||
// @Summary 初始化用户数据库
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "初始化用户数据库"
|
||||
// @Router /init/checkdb [post]
|
||||
func (i *DBApi) CheckDB(c *gin.Context) {
|
||||
var (
|
||||
message = "前往初始化数据库"
|
||||
needInit = true
|
||||
)
|
||||
|
||||
if global.GVA_DB != nil {
|
||||
message = "数据库无需初始化"
|
||||
needInit = false
|
||||
}
|
||||
global.GVA_LOG.Info(message)
|
||||
response.OkWithDetailed(gin.H{"needInit": needInit}, message, c)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type JwtApi struct{}
|
||||
|
||||
// JsonInBlacklist
|
||||
// @Tags Jwt
|
||||
// @Summary jwt加入黑名单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "jwt加入黑名单"
|
||||
// @Router /jwt/jsonInBlacklist [post]
|
||||
func (j *JwtApi) JsonInBlacklist(c *gin.Context) {
|
||||
token := utils.GetToken(c)
|
||||
jwt := system.JwtBlacklist{Jwt: token}
|
||||
err := jwtService.JsonInBlacklist(jwt)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("jwt作废失败!", zap.Error(err))
|
||||
response.FailWithMessage("jwt作废失败", c)
|
||||
return
|
||||
}
|
||||
utils.ClearToken(c)
|
||||
response.OkWithMessage("jwt作废成功", c)
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AuthorityMenuApi struct{}
|
||||
|
||||
// GetMenu
|
||||
// @Tags AuthorityMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body request.Empty true "空"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysMenusResponse,msg=string} "获取用户动态路由,返回包括系统菜单详情列表"
|
||||
// @Router /menu/getMenu [post]
|
||||
func (a *AuthorityMenuApi) GetMenu(c *gin.Context) {
|
||||
menus, err := menuService.GetMenuTree(utils.GetUserAuthorityId(c))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
if menus == nil {
|
||||
menus = []system.SysMenu{}
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysMenusResponse{Menus: menus}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetBaseMenuTree
|
||||
// @Tags AuthorityMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body request.Empty true "空"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysBaseMenusResponse,msg=string} "获取用户动态路由,返回包括系统菜单列表"
|
||||
// @Router /menu/getBaseMenuTree [post]
|
||||
func (a *AuthorityMenuApi) GetBaseMenuTree(c *gin.Context) {
|
||||
authority := utils.GetUserAuthorityId(c)
|
||||
menus, err := menuService.GetBaseMenuTree(authority)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysBaseMenusResponse{Menus: menus}, "获取成功", c)
|
||||
}
|
||||
|
||||
// AddMenuAuthority
|
||||
// @Tags AuthorityMenu
|
||||
// @Summary 增加menu和角色关联关系
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.AddMenuAuthorityInfo true "角色ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "增加menu和角色关联关系"
|
||||
// @Router /menu/addMenuAuthority [post]
|
||||
func (a *AuthorityMenuApi) AddMenuAuthority(c *gin.Context) {
|
||||
var authorityMenu systemReq.AddMenuAuthorityInfo
|
||||
err := c.ShouldBindJSON(&authorityMenu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if err := utils.Verify(authorityMenu, utils.AuthorityIdVerify); err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
adminAuthorityID := utils.GetUserAuthorityId(c)
|
||||
if err := menuService.AddMenuAuthority(authorityMenu.Menus, adminAuthorityID, authorityMenu.AuthorityId); err != nil {
|
||||
global.GVA_LOG.Error("添加失败!", zap.Error(err))
|
||||
response.FailWithMessage("添加失败", c)
|
||||
} else {
|
||||
response.OkWithMessage("添加成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetMenuAuthority
|
||||
// @Tags AuthorityMenu
|
||||
// @Summary 获取指定角色menu
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetAuthorityId true "角色ID"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取指定角色menu"
|
||||
// @Router /menu/getMenuAuthority [post]
|
||||
func (a *AuthorityMenuApi) GetMenuAuthority(c *gin.Context) {
|
||||
var param request.GetAuthorityId
|
||||
err := c.ShouldBindJSON(¶m)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(param, utils.AuthorityIdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
menus, err := menuService.GetMenuAuthority(¶m)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithDetailed(systemRes.SysMenusResponse{Menus: menus}, "获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"menus": menus}, "获取成功", c)
|
||||
}
|
||||
|
||||
// AddBaseMenu
|
||||
// @Tags Menu
|
||||
// @Summary 新增菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysBaseMenu true "路由path, 父菜单ID, 路由name, 对应前端文件路径, 排序标记"
|
||||
// @Success 200 {object} response.Response{msg=string} "新增菜单"
|
||||
// @Router /menu/addBaseMenu [post]
|
||||
func (a *AuthorityMenuApi) AddBaseMenu(c *gin.Context) {
|
||||
var menu system.SysBaseMenu
|
||||
err := c.ShouldBindJSON(&menu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(menu, utils.MenuVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(menu.Meta, utils.MenuMetaVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = menuService.AddBaseMenu(menu)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("添加失败!", zap.Error(err))
|
||||
response.FailWithMessage("添加失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("添加成功", c)
|
||||
}
|
||||
|
||||
// DeleteBaseMenu
|
||||
// @Tags Menu
|
||||
// @Summary 删除菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "菜单id"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除菜单"
|
||||
// @Router /menu/deleteBaseMenu [post]
|
||||
func (a *AuthorityMenuApi) DeleteBaseMenu(c *gin.Context) {
|
||||
var menu request.GetById
|
||||
err := c.ShouldBindJSON(&menu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(menu, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = baseMenuService.DeleteBaseMenu(menu.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateBaseMenu
|
||||
// @Tags Menu
|
||||
// @Summary 更新菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysBaseMenu true "路由path, 父菜单ID, 路由name, 对应前端文件路径, 排序标记"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新菜单"
|
||||
// @Router /menu/updateBaseMenu [post]
|
||||
func (a *AuthorityMenuApi) UpdateBaseMenu(c *gin.Context) {
|
||||
var menu system.SysBaseMenu
|
||||
err := c.ShouldBindJSON(&menu)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(menu, utils.MenuVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(menu.Meta, utils.MenuMetaVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = baseMenuService.UpdateBaseMenu(menu)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// GetBaseMenuById
|
||||
// @Tags Menu
|
||||
// @Summary 根据id获取菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "菜单id"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysBaseMenuResponse,msg=string} "根据id获取菜单,返回包括系统菜单列表"
|
||||
// @Router /menu/getBaseMenuById [post]
|
||||
func (a *AuthorityMenuApi) GetBaseMenuById(c *gin.Context) {
|
||||
var idInfo request.GetById
|
||||
err := c.ShouldBindJSON(&idInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(idInfo, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
menu, err := baseMenuService.GetBaseMenuById(idInfo.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysBaseMenuResponse{Menu: menu}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetMenuList
|
||||
// @Tags Menu
|
||||
// @Summary 分页获取基础menu列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.PageInfo true "页码, 每页大小"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取基础menu列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /menu/getMenuList [post]
|
||||
func (a *AuthorityMenuApi) GetMenuList(c *gin.Context) {
|
||||
authorityID := utils.GetUserAuthorityId(c)
|
||||
menuList, err := menuService.GetInfoList(authorityID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(menuList, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type OperationRecordApi struct{}
|
||||
|
||||
// DeleteSysOperationRecord
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 删除SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysOperationRecord true "SysOperationRecord模型"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除SysOperationRecord"
|
||||
// @Router /sysOperationRecord/deleteSysOperationRecord [delete]
|
||||
func (s *OperationRecordApi) DeleteSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord system.SysOperationRecord
|
||||
err := c.ShouldBindJSON(&sysOperationRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = operationRecordService.DeleteSysOperationRecord(sysOperationRecord)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysOperationRecordByIds
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 批量删除SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.IdsReq true "批量删除SysOperationRecord"
|
||||
// @Success 200 {object} response.Response{msg=string} "批量删除SysOperationRecord"
|
||||
// @Router /sysOperationRecord/deleteSysOperationRecordByIds [delete]
|
||||
func (s *OperationRecordApi) DeleteSysOperationRecordByIds(c *gin.Context) {
|
||||
var IDS request.IdsReq
|
||||
err := c.ShouldBindJSON(&IDS)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = operationRecordService.DeleteSysOperationRecordByIds(IDS)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("批量删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// FindSysOperationRecord
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 用id查询SysOperationRecord
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query system.SysOperationRecord true "Id"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "用id查询SysOperationRecord"
|
||||
// @Router /sysOperationRecord/findSysOperationRecord [get]
|
||||
func (s *OperationRecordApi) FindSysOperationRecord(c *gin.Context) {
|
||||
var sysOperationRecord system.SysOperationRecord
|
||||
err := c.ShouldBindQuery(&sysOperationRecord)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(sysOperationRecord, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
reSysOperationRecord, err := operationRecordService.GetSysOperationRecord(sysOperationRecord.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"reSysOperationRecord": reSysOperationRecord}, "查询成功", c)
|
||||
}
|
||||
|
||||
// GetSysOperationRecordList
|
||||
// @Tags SysOperationRecord
|
||||
// @Summary 分页获取SysOperationRecord列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query request.SysOperationRecordSearch true "页码, 每页大小, 搜索条件"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取SysOperationRecord列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /sysOperationRecord/getSysOperationRecordList [get]
|
||||
func (s *OperationRecordApi) GetSysOperationRecordList(c *gin.Context) {
|
||||
var pageInfo systemReq.SysOperationRecordSearch
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := operationRecordService.GetSysOperationRecordInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SysParamsApi struct{}
|
||||
|
||||
// CreateSysParams 创建参数
|
||||
// @Tags SysParams
|
||||
// @Summary 创建参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysParams true "创建参数"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建成功"
|
||||
// @Router /sysParams/createSysParams [post]
|
||||
func (sysParamsApi *SysParamsApi) CreateSysParams(c *gin.Context) {
|
||||
var sysParams system.SysParams
|
||||
err := c.ShouldBindJSON(&sysParams)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = sysParamsService.CreateSysParams(&sysParams)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("创建失败!", zap.Error(err))
|
||||
response.FailWithMessage("创建失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("创建成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysParams 删除参数
|
||||
// @Tags SysParams
|
||||
// @Summary 删除参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysParams true "删除参数"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除成功"
|
||||
// @Router /sysParams/deleteSysParams [delete]
|
||||
func (sysParamsApi *SysParamsApi) DeleteSysParams(c *gin.Context) {
|
||||
ID := c.Query("ID")
|
||||
err := sysParamsService.DeleteSysParams(ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysParamsByIds 批量删除参数
|
||||
// @Tags SysParams
|
||||
// @Summary 批量删除参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "批量删除成功"
|
||||
// @Router /sysParams/deleteSysParamsByIds [delete]
|
||||
func (sysParamsApi *SysParamsApi) DeleteSysParamsByIds(c *gin.Context) {
|
||||
IDs := c.QueryArray("IDs[]")
|
||||
err := sysParamsService.DeleteSysParamsByIds(IDs)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("批量删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// UpdateSysParams 更新参数
|
||||
// @Tags SysParams
|
||||
// @Summary 更新参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysParams true "更新参数"
|
||||
// @Success 200 {object} response.Response{msg=string} "更新成功"
|
||||
// @Router /sysParams/updateSysParams [put]
|
||||
func (sysParamsApi *SysParamsApi) UpdateSysParams(c *gin.Context) {
|
||||
var sysParams system.SysParams
|
||||
err := c.ShouldBindJSON(&sysParams)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = sysParamsService.UpdateSysParams(sysParams)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("更新失败!", zap.Error(err))
|
||||
response.FailWithMessage("更新失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("更新成功", c)
|
||||
}
|
||||
|
||||
// FindSysParams 用id查询参数
|
||||
// @Tags SysParams
|
||||
// @Summary 用id查询参数
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query system.SysParams true "用id查询参数"
|
||||
// @Success 200 {object} response.Response{data=system.SysParams,msg=string} "查询成功"
|
||||
// @Router /sysParams/findSysParams [get]
|
||||
func (sysParamsApi *SysParamsApi) FindSysParams(c *gin.Context) {
|
||||
ID := c.Query("ID")
|
||||
resysParams, err := sysParamsService.GetSysParams(ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resysParams, c)
|
||||
}
|
||||
|
||||
// GetSysParamsList 分页获取参数列表
|
||||
// @Tags SysParams
|
||||
// @Summary 分页获取参数列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query systemReq.SysParamsSearch true "分页获取参数列表"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功"
|
||||
// @Router /sysParams/getSysParamsList [get]
|
||||
func (sysParamsApi *SysParamsApi) GetSysParamsList(c *gin.Context) {
|
||||
var pageInfo systemReq.SysParamsSearch
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := sysParamsService.GetSysParamsInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetSysParam 根据key获取参数value
|
||||
// @Tags SysParams
|
||||
// @Summary 根据key获取参数value
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param key query string true "key"
|
||||
// @Success 200 {object} response.Response{data=system.SysParams,msg=string} "获取成功"
|
||||
// @Router /sysParams/getSysParam [get]
|
||||
func (sysParamsApi *SysParamsApi) GetSysParam(c *gin.Context) {
|
||||
k := c.Query("key")
|
||||
params, err := sysParamsService.GetSysParam(k)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(params, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SystemApi struct{}
|
||||
|
||||
// GetSystemConfig
|
||||
// @Tags System
|
||||
// @Summary 获取配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysConfigResponse,msg=string} "获取配置文件内容,返回包括系统配置"
|
||||
// @Router /system/getSystemConfig [post]
|
||||
func (s *SystemApi) GetSystemConfig(c *gin.Context) {
|
||||
config, err := systemConfigService.GetSystemConfig()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysConfigResponse{Config: config}, "获取成功", c)
|
||||
}
|
||||
|
||||
// SetSystemConfig
|
||||
// @Tags System
|
||||
// @Summary 设置配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body system.System true "设置配置文件内容"
|
||||
// @Success 200 {object} response.Response{data=string} "设置配置文件内容"
|
||||
// @Router /system/setSystemConfig [post]
|
||||
func (s *SystemApi) SetSystemConfig(c *gin.Context) {
|
||||
var sys system.System
|
||||
err := c.ShouldBindJSON(&sys)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = systemConfigService.SetSystemConfig(sys)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
|
||||
// ReloadSystem
|
||||
// @Tags System
|
||||
// @Summary 重载系统
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "重载系统"
|
||||
// @Router /system/reloadSystem [post]
|
||||
func (s *SystemApi) ReloadSystem(c *gin.Context) {
|
||||
// 触发系统重载事件
|
||||
err := utils.GlobalSystemEvents.TriggerReload()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("重载系统失败!", zap.Error(err))
|
||||
response.FailWithMessage("重载系统失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("重载系统成功", c)
|
||||
}
|
||||
|
||||
// GetServerInfo
|
||||
// @Tags System
|
||||
// @Summary 获取服务器信息
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取服务器信息"
|
||||
// @Router /system/getServerInfo [post]
|
||||
func (s *SystemApi) GetServerInfo(c *gin.Context) {
|
||||
server, err := systemConfigService.GetServerInfo()
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"server": server}, "获取成功", c)
|
||||
}
|
||||
@@ -0,0 +1,483 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Login
|
||||
// @Tags Base
|
||||
// @Summary 用户登录
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.Login true "用户名, 密码, 验证码"
|
||||
// @Success 200 {object} response.Response{data=systemRes.LoginResponse,msg=string} "返回包括用户信息,token,过期时间"
|
||||
// @Router /base/login [post]
|
||||
func (b *BaseApi) Login(c *gin.Context) {
|
||||
var l systemReq.Login
|
||||
err := c.ShouldBindJSON(&l)
|
||||
key := c.ClientIP()
|
||||
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(l, utils.LoginVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 判断验证码是否开启
|
||||
openCaptcha := global.GVA_CONFIG.Captcha.OpenCaptcha // 是否开启防爆次数
|
||||
openCaptchaTimeOut := global.GVA_CONFIG.Captcha.OpenCaptchaTimeOut // 缓存超时时间
|
||||
v, ok := global.BlackCache.Get(key)
|
||||
if !ok {
|
||||
global.BlackCache.Set(key, 1, time.Second*time.Duration(openCaptchaTimeOut))
|
||||
}
|
||||
|
||||
var oc bool = openCaptcha == 0 || openCaptcha < interfaceToInt(v)
|
||||
|
||||
if !oc || (l.CaptchaId != "" && l.Captcha != "" && store.Verify(l.CaptchaId, l.Captcha, true)) {
|
||||
u := &system.SysUser{Username: l.Username, Password: l.Password}
|
||||
user, err := userService.Login(u)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("登陆失败! 用户名不存在或者密码错误!", zap.Error(err))
|
||||
// 验证码次数+1
|
||||
global.BlackCache.Increment(key, 1)
|
||||
response.FailWithMessage("用户名不存在或者密码错误", c)
|
||||
return
|
||||
}
|
||||
if user.Enable != 1 {
|
||||
global.GVA_LOG.Error("登陆失败! 用户被禁止登录!")
|
||||
// 验证码次数+1
|
||||
global.BlackCache.Increment(key, 1)
|
||||
response.FailWithMessage("用户被禁止登录", c)
|
||||
return
|
||||
}
|
||||
b.TokenNext(c, *user)
|
||||
return
|
||||
}
|
||||
// 验证码次数+1
|
||||
global.BlackCache.Increment(key, 1)
|
||||
response.FailWithMessage("验证码错误", c)
|
||||
}
|
||||
|
||||
// TokenNext 登录以后签发jwt
|
||||
func (b *BaseApi) TokenNext(c *gin.Context, user system.SysUser) {
|
||||
token, claims, err := utils.LoginToken(&user)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取token失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取token失败", c)
|
||||
return
|
||||
}
|
||||
if !global.GVA_CONFIG.System.UseMultipoint {
|
||||
utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
response.OkWithDetailed(systemRes.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", c)
|
||||
return
|
||||
}
|
||||
|
||||
if jwtStr, err := jwtService.GetRedisJWT(user.Username); err == redis.Nil {
|
||||
if err := utils.SetRedisJWT(token, user.Username); err != nil {
|
||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置登录状态失败", c)
|
||||
return
|
||||
}
|
||||
utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
response.OkWithDetailed(systemRes.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", c)
|
||||
} else if err != nil {
|
||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置登录状态失败", c)
|
||||
} else {
|
||||
var blackJWT system.JwtBlacklist
|
||||
blackJWT.Jwt = jwtStr
|
||||
if err := jwtService.JsonInBlacklist(blackJWT); err != nil {
|
||||
response.FailWithMessage("jwt作废失败", c)
|
||||
return
|
||||
}
|
||||
if err := utils.SetRedisJWT(token, user.GetUsername()); err != nil {
|
||||
response.FailWithMessage("设置登录状态失败", c)
|
||||
return
|
||||
}
|
||||
utils.SetToken(c, token, int(claims.RegisteredClaims.ExpiresAt.Unix()-time.Now().Unix()))
|
||||
response.OkWithDetailed(systemRes.LoginResponse{
|
||||
User: user,
|
||||
Token: token,
|
||||
ExpiresAt: claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||
}, "登录成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// Register
|
||||
// @Tags SysUser
|
||||
// @Summary 用户注册账号
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.Register true "用户名, 昵称, 密码, 角色ID"
|
||||
// @Success 200 {object} response.Response{data=systemRes.SysUserResponse,msg=string} "用户注册账号,返回包括用户信息"
|
||||
// @Router /user/admin_register [post]
|
||||
func (b *BaseApi) Register(c *gin.Context) {
|
||||
var r systemReq.Register
|
||||
err := c.ShouldBindJSON(&r)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(r, utils.RegisterVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
var authorities []system.SysAuthority
|
||||
for _, v := range r.AuthorityIds {
|
||||
authorities = append(authorities, system.SysAuthority{
|
||||
AuthorityId: v,
|
||||
})
|
||||
}
|
||||
user := &system.SysUser{Username: r.Username, NickName: r.NickName, Password: r.Password, HeaderImg: r.HeaderImg, AuthorityId: r.AuthorityId, Authorities: authorities, Enable: r.Enable, Phone: r.Phone, Email: r.Email}
|
||||
userReturn, err := userService.Register(*user)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("注册失败!", zap.Error(err))
|
||||
response.FailWithDetailed(systemRes.SysUserResponse{User: userReturn}, "注册失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(systemRes.SysUserResponse{User: userReturn}, "注册成功", c)
|
||||
}
|
||||
|
||||
// ChangePassword
|
||||
// @Tags SysUser
|
||||
// @Summary 用户修改密码
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.ChangePasswordReq true "用户名, 原密码, 新密码"
|
||||
// @Success 200 {object} response.Response{msg=string} "用户修改密码"
|
||||
// @Router /user/changePassword [post]
|
||||
func (b *BaseApi) ChangePassword(c *gin.Context) {
|
||||
var req systemReq.ChangePasswordReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(req, utils.ChangePasswordVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
uid := utils.GetUserID(c)
|
||||
u := &system.SysUser{GVA_MODEL: global.GVA_MODEL{ID: uid}, Password: req.Password}
|
||||
err = userService.ChangePassword(u, req.NewPassword)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改失败!", zap.Error(err))
|
||||
response.FailWithMessage("修改失败,原密码与当前账户不符", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
|
||||
// GetUserList
|
||||
// @Tags SysUser
|
||||
// @Summary 分页获取用户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.GetUserList true "页码, 每页大小"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "分页获取用户列表,返回包括列表,总数,页码,每页数量"
|
||||
// @Router /user/getUserList [post]
|
||||
func (b *BaseApi) GetUserList(c *gin.Context) {
|
||||
var pageInfo systemReq.GetUserList
|
||||
err := c.ShouldBindJSON(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(pageInfo, utils.PageInfoVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := userService.GetUserInfoList(pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// SetUserAuthority
|
||||
// @Tags SysUser
|
||||
// @Summary 更改用户权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.SetUserAuth true "用户UUID, 角色ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "设置用户权限"
|
||||
// @Router /user/setUserAuthority [post]
|
||||
func (b *BaseApi) SetUserAuthority(c *gin.Context) {
|
||||
var sua systemReq.SetUserAuth
|
||||
err := c.ShouldBindJSON(&sua)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if UserVerifyErr := utils.Verify(sua, utils.SetUserAuthorityVerify); UserVerifyErr != nil {
|
||||
response.FailWithMessage(UserVerifyErr.Error(), c)
|
||||
return
|
||||
}
|
||||
userID := utils.GetUserID(c)
|
||||
err = userService.SetUserAuthority(userID, sua.AuthorityId)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改失败!", zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
claims := utils.GetUserInfo(c)
|
||||
claims.AuthorityId = sua.AuthorityId
|
||||
token, err := utils.NewJWT().CreateToken(*claims)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改失败!", zap.Error(err))
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
c.Header("new-token", token)
|
||||
c.Header("new-expires-at", strconv.FormatInt(claims.ExpiresAt.Unix(), 10))
|
||||
utils.SetToken(c, token, int((claims.ExpiresAt.Unix()-time.Now().Unix())/60))
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
|
||||
// SetUserAuthorities
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.SetUserAuthorities true "用户UUID, 角色ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "设置用户权限"
|
||||
// @Router /user/setUserAuthorities [post]
|
||||
func (b *BaseApi) SetUserAuthorities(c *gin.Context) {
|
||||
var sua systemReq.SetUserAuthorities
|
||||
err := c.ShouldBindJSON(&sua)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
authorityID := utils.GetUserAuthorityId(c)
|
||||
err = userService.SetUserAuthorities(authorityID, sua.ID, sua.AuthorityIds)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("修改失败!", zap.Error(err))
|
||||
response.FailWithMessage("修改失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("修改成功", c)
|
||||
}
|
||||
|
||||
// DeleteUser
|
||||
// @Tags SysUser
|
||||
// @Summary 删除用户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body request.GetById true "用户ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除用户"
|
||||
// @Router /user/deleteUser [delete]
|
||||
func (b *BaseApi) DeleteUser(c *gin.Context) {
|
||||
var reqId request.GetById
|
||||
err := c.ShouldBindJSON(&reqId)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(reqId, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
jwtId := utils.GetUserID(c)
|
||||
if jwtId == uint(reqId.ID) {
|
||||
response.FailWithMessage("删除失败, 无法删除自己。", c)
|
||||
return
|
||||
}
|
||||
err = userService.DeleteUser(reqId.ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// SetUserInfo
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysUser true "ID, 用户名, 昵称, 头像链接"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "设置用户信息"
|
||||
// @Router /user/setUserInfo [put]
|
||||
func (b *BaseApi) SetUserInfo(c *gin.Context) {
|
||||
var user systemReq.ChangeUserInfo
|
||||
err := c.ShouldBindJSON(&user)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = utils.Verify(user, utils.IdVerify)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if len(user.AuthorityIds) != 0 {
|
||||
authorityID := utils.GetUserAuthorityId(c)
|
||||
err = userService.SetUserAuthorities(authorityID, user.ID, user.AuthorityIds)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = userService.SetUserInfo(system.SysUser{
|
||||
GVA_MODEL: global.GVA_MODEL{
|
||||
ID: user.ID,
|
||||
},
|
||||
NickName: user.NickName,
|
||||
HeaderImg: user.HeaderImg,
|
||||
Phone: user.Phone,
|
||||
Email: user.Email,
|
||||
Enable: user.Enable,
|
||||
})
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
|
||||
// SetSelfInfo
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysUser true "ID, 用户名, 昵称, 头像链接"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "设置用户信息"
|
||||
// @Router /user/SetSelfInfo [put]
|
||||
func (b *BaseApi) SetSelfInfo(c *gin.Context) {
|
||||
var user systemReq.ChangeUserInfo
|
||||
err := c.ShouldBindJSON(&user)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
user.ID = utils.GetUserID(c)
|
||||
err = userService.SetSelfInfo(system.SysUser{
|
||||
GVA_MODEL: global.GVA_MODEL{
|
||||
ID: user.ID,
|
||||
},
|
||||
NickName: user.NickName,
|
||||
HeaderImg: user.HeaderImg,
|
||||
Phone: user.Phone,
|
||||
Email: user.Email,
|
||||
Enable: user.Enable,
|
||||
})
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
|
||||
// SetSelfSetting
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户配置
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body map[string]interface{} true "用户配置数据"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "设置用户配置"
|
||||
// @Router /user/SetSelfSetting [put]
|
||||
func (b *BaseApi) SetSelfSetting(c *gin.Context) {
|
||||
var req common.JSONMap
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
err = userService.SetSelfSetting(req, utils.GetUserID(c))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("设置失败!", zap.Error(err))
|
||||
response.FailWithMessage("设置失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("设置成功", c)
|
||||
}
|
||||
|
||||
// GetUserInfo
|
||||
// @Tags SysUser
|
||||
// @Summary 获取用户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "获取用户信息"
|
||||
// @Router /user/getUserInfo [get]
|
||||
func (b *BaseApi) GetUserInfo(c *gin.Context) {
|
||||
uuid := utils.GetUserUuid(c)
|
||||
ReqUser, err := userService.GetUserInfo(uuid)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败", c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(gin.H{"userInfo": ReqUser}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ResetPassword
|
||||
// @Tags SysUser
|
||||
// @Summary 重置用户密码
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysUser true "ID"
|
||||
// @Success 200 {object} response.Response{msg=string} "重置用户密码"
|
||||
// @Router /user/resetPassword [post]
|
||||
func (b *BaseApi) ResetPassword(c *gin.Context) {
|
||||
var rps systemReq.ResetPassword
|
||||
err := c.ShouldBindJSON(&rps)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
err = userService.ResetPassword(rps.ID, rps.Password)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("重置失败!", zap.Error(err))
|
||||
response.FailWithMessage("重置失败"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("重置成功", c)
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/global"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/model/system"
|
||||
systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
|
||||
systemRes "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
|
||||
"github.com/flipped-aurora/gin-vue-admin/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SysVersionApi struct{}
|
||||
|
||||
// buildMenuTree 构建菜单树结构
|
||||
func buildMenuTree(menus []system.SysBaseMenu) []system.SysBaseMenu {
|
||||
// 创建菜单映射
|
||||
menuMap := make(map[uint]*system.SysBaseMenu)
|
||||
for i := range menus {
|
||||
menuMap[menus[i].ID] = &menus[i]
|
||||
}
|
||||
|
||||
// 构建树结构
|
||||
var rootMenus []system.SysBaseMenu
|
||||
for _, menu := range menus {
|
||||
if menu.ParentId == 0 {
|
||||
// 根菜单
|
||||
menuData := convertMenuToStruct(menu, menuMap)
|
||||
rootMenus = append(rootMenus, menuData)
|
||||
}
|
||||
}
|
||||
|
||||
// 按sort排序根菜单
|
||||
sort.Slice(rootMenus, func(i, j int) bool {
|
||||
return rootMenus[i].Sort < rootMenus[j].Sort
|
||||
})
|
||||
|
||||
return rootMenus
|
||||
}
|
||||
|
||||
// convertMenuToStruct 将菜单转换为结构体并递归处理子菜单
|
||||
func convertMenuToStruct(menu system.SysBaseMenu, menuMap map[uint]*system.SysBaseMenu) system.SysBaseMenu {
|
||||
result := system.SysBaseMenu{
|
||||
Path: menu.Path,
|
||||
Name: menu.Name,
|
||||
Hidden: menu.Hidden,
|
||||
Component: menu.Component,
|
||||
Sort: menu.Sort,
|
||||
Meta: menu.Meta,
|
||||
}
|
||||
|
||||
// 清理并复制参数数据
|
||||
if len(menu.Parameters) > 0 {
|
||||
cleanParameters := make([]system.SysBaseMenuParameter, 0, len(menu.Parameters))
|
||||
for _, param := range menu.Parameters {
|
||||
cleanParam := system.SysBaseMenuParameter{
|
||||
Type: param.Type,
|
||||
Key: param.Key,
|
||||
Value: param.Value,
|
||||
// 不复制 ID, CreatedAt, UpdatedAt, SysBaseMenuID
|
||||
}
|
||||
cleanParameters = append(cleanParameters, cleanParam)
|
||||
}
|
||||
result.Parameters = cleanParameters
|
||||
}
|
||||
|
||||
// 清理并复制菜单按钮数据
|
||||
if len(menu.MenuBtn) > 0 {
|
||||
cleanMenuBtns := make([]system.SysBaseMenuBtn, 0, len(menu.MenuBtn))
|
||||
for _, btn := range menu.MenuBtn {
|
||||
cleanBtn := system.SysBaseMenuBtn{
|
||||
Name: btn.Name,
|
||||
Desc: btn.Desc,
|
||||
// 不复制 ID, CreatedAt, UpdatedAt, SysBaseMenuID
|
||||
}
|
||||
cleanMenuBtns = append(cleanMenuBtns, cleanBtn)
|
||||
}
|
||||
result.MenuBtn = cleanMenuBtns
|
||||
}
|
||||
|
||||
// 查找并处理子菜单
|
||||
var children []system.SysBaseMenu
|
||||
for _, childMenu := range menuMap {
|
||||
if childMenu.ParentId == menu.ID {
|
||||
childData := convertMenuToStruct(*childMenu, menuMap)
|
||||
children = append(children, childData)
|
||||
}
|
||||
}
|
||||
|
||||
// 按sort排序子菜单
|
||||
if len(children) > 0 {
|
||||
sort.Slice(children, func(i, j int) bool {
|
||||
return children[i].Sort < children[j].Sort
|
||||
})
|
||||
result.Children = children
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// DeleteSysVersion 删除版本管理
|
||||
// @Tags SysVersion
|
||||
// @Summary 删除版本管理
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body system.SysVersion true "删除版本管理"
|
||||
// @Success 200 {object} response.Response{msg=string} "删除成功"
|
||||
// @Router /sysVersion/deleteSysVersion [delete]
|
||||
func (sysVersionApi *SysVersionApi) DeleteSysVersion(c *gin.Context) {
|
||||
// 创建业务用Context
|
||||
ctx := c.Request.Context()
|
||||
|
||||
ID := c.Query("ID")
|
||||
err := sysVersionService.DeleteSysVersion(ctx, ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
|
||||
// DeleteSysVersionByIds 批量删除版本管理
|
||||
// @Tags SysVersion
|
||||
// @Summary 批量删除版本管理
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{msg=string} "批量删除成功"
|
||||
// @Router /sysVersion/deleteSysVersionByIds [delete]
|
||||
func (sysVersionApi *SysVersionApi) DeleteSysVersionByIds(c *gin.Context) {
|
||||
// 创建业务用Context
|
||||
ctx := c.Request.Context()
|
||||
|
||||
IDs := c.QueryArray("IDs[]")
|
||||
err := sysVersionService.DeleteSysVersionByIds(ctx, IDs)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
|
||||
response.FailWithMessage("批量删除失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithMessage("批量删除成功", c)
|
||||
}
|
||||
|
||||
// FindSysVersion 用id查询版本管理
|
||||
// @Tags SysVersion
|
||||
// @Summary 用id查询版本管理
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param ID query uint true "用id查询版本管理"
|
||||
// @Success 200 {object} response.Response{data=system.SysVersion,msg=string} "查询成功"
|
||||
// @Router /sysVersion/findSysVersion [get]
|
||||
func (sysVersionApi *SysVersionApi) FindSysVersion(c *gin.Context) {
|
||||
// 创建业务用Context
|
||||
ctx := c.Request.Context()
|
||||
|
||||
ID := c.Query("ID")
|
||||
resysVersion, err := sysVersionService.GetSysVersion(ctx, ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("查询失败!", zap.Error(err))
|
||||
response.FailWithMessage("查询失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(resysVersion, c)
|
||||
}
|
||||
|
||||
// GetSysVersionList 分页获取版本管理列表
|
||||
// @Tags SysVersion
|
||||
// @Summary 分页获取版本管理列表
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data query systemReq.SysVersionSearch true "分页获取版本管理列表"
|
||||
// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功"
|
||||
// @Router /sysVersion/getSysVersionList [get]
|
||||
func (sysVersionApi *SysVersionApi) GetSysVersionList(c *gin.Context) {
|
||||
// 创建业务用Context
|
||||
ctx := c.Request.Context()
|
||||
|
||||
var pageInfo systemReq.SysVersionSearch
|
||||
err := c.ShouldBindQuery(&pageInfo)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
list, total, err := sysVersionService.GetSysVersionInfoList(ctx, pageInfo)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: pageInfo.Page,
|
||||
PageSize: pageInfo.PageSize,
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// GetSysVersionPublic 不需要鉴权的版本管理接口
|
||||
// @Tags SysVersion
|
||||
// @Summary 不需要鉴权的版本管理接口
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {object} response.Response{data=object,msg=string} "获取成功"
|
||||
// @Router /sysVersion/getSysVersionPublic [get]
|
||||
func (sysVersionApi *SysVersionApi) GetSysVersionPublic(c *gin.Context) {
|
||||
// 创建业务用Context
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// 此接口不需要鉴权
|
||||
// 示例为返回了一个固定的消息接口,一般本接口用于C端服务,需要自己实现业务逻辑
|
||||
sysVersionService.GetSysVersionPublic(ctx)
|
||||
response.OkWithDetailed(gin.H{
|
||||
"info": "不需要鉴权的版本管理接口信息",
|
||||
}, "获取成功", c)
|
||||
}
|
||||
|
||||
// ExportVersion 创建发版数据
|
||||
// @Tags SysVersion
|
||||
// @Summary 创建发版数据
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.ExportVersionRequest true "创建发版数据"
|
||||
// @Success 200 {object} response.Response{msg=string} "创建成功"
|
||||
// @Router /sysVersion/exportVersion [post]
|
||||
func (sysVersionApi *SysVersionApi) ExportVersion(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
var req systemReq.ExportVersionRequest
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取选中的菜单数据
|
||||
var menuData []system.SysBaseMenu
|
||||
if len(req.MenuIds) > 0 {
|
||||
menuData, err = sysVersionService.GetMenusByIds(ctx, req.MenuIds)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取菜单数据失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取菜单数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 获取选中的API数据
|
||||
var apiData []system.SysApi
|
||||
if len(req.ApiIds) > 0 {
|
||||
apiData, err = sysVersionService.GetApisByIds(ctx, req.ApiIds)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取API数据失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取API数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 处理菜单数据,构建递归的children结构
|
||||
processedMenus := buildMenuTree(menuData)
|
||||
|
||||
// 处理API数据,清除ID和时间戳字段
|
||||
processedApis := make([]system.SysApi, 0, len(apiData))
|
||||
for _, api := range apiData {
|
||||
cleanApi := system.SysApi{
|
||||
Path: api.Path,
|
||||
Description: api.Description,
|
||||
ApiGroup: api.ApiGroup,
|
||||
Method: api.Method,
|
||||
}
|
||||
processedApis = append(processedApis, cleanApi)
|
||||
}
|
||||
|
||||
// 构建导出数据
|
||||
exportData := systemRes.ExportVersionResponse{
|
||||
Version: systemReq.VersionInfo{
|
||||
Name: req.VersionName,
|
||||
Code: req.VersionCode,
|
||||
Description: req.Description,
|
||||
ExportTime: time.Now().Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
Menus: processedMenus,
|
||||
Apis: processedApis,
|
||||
}
|
||||
|
||||
// 转换为JSON
|
||||
jsonData, err := json.MarshalIndent(exportData, "", " ")
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("JSON序列化失败!", zap.Error(err))
|
||||
response.FailWithMessage("JSON序列化失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存版本记录
|
||||
version := system.SysVersion{
|
||||
VersionName: utils.Pointer(req.VersionName),
|
||||
VersionCode: utils.Pointer(req.VersionCode),
|
||||
Description: utils.Pointer(req.Description),
|
||||
VersionData: utils.Pointer(string(jsonData)),
|
||||
}
|
||||
|
||||
err = sysVersionService.CreateSysVersion(ctx, &version)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("保存版本记录失败!", zap.Error(err))
|
||||
response.FailWithMessage("保存版本记录失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
response.OkWithMessage("创建发版成功", c)
|
||||
}
|
||||
|
||||
// DownloadVersionJson 下载版本JSON数据
|
||||
// @Tags SysVersion
|
||||
// @Summary 下载版本JSON数据
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param ID query string true "版本ID"
|
||||
// @Success 200 {object} response.Response{data=object,msg=string} "下载成功"
|
||||
// @Router /sysVersion/downloadVersionJson [get]
|
||||
func (sysVersionApi *SysVersionApi) DownloadVersionJson(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
ID := c.Query("ID")
|
||||
if ID == "" {
|
||||
response.FailWithMessage("版本ID不能为空", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取版本记录
|
||||
version, err := sysVersionService.GetSysVersion(ctx, ID)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("获取版本记录失败!", zap.Error(err))
|
||||
response.FailWithMessage("获取版本记录失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 构建JSON数据
|
||||
var jsonData []byte
|
||||
if version.VersionData != nil && *version.VersionData != "" {
|
||||
jsonData = []byte(*version.VersionData)
|
||||
} else {
|
||||
// 如果没有存储的JSON数据,构建一个基本的结构
|
||||
basicData := systemRes.ExportVersionResponse{
|
||||
Version: systemReq.VersionInfo{
|
||||
Name: *version.VersionName,
|
||||
Code: *version.VersionCode,
|
||||
Description: *version.Description,
|
||||
ExportTime: version.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
},
|
||||
Menus: []system.SysBaseMenu{},
|
||||
Apis: []system.SysApi{},
|
||||
}
|
||||
jsonData, _ = json.MarshalIndent(basicData, "", " ")
|
||||
}
|
||||
|
||||
// 设置下载响应头
|
||||
filename := fmt.Sprintf("version_%s_%s.json", *version.VersionCode, time.Now().Format("20060102150405"))
|
||||
c.Header("Content-Type", "application/json")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
|
||||
c.Header("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
|
||||
c.Data(http.StatusOK, "application/json", jsonData)
|
||||
}
|
||||
|
||||
// ImportVersion 导入版本数据
|
||||
// @Tags SysVersion
|
||||
// @Summary 导入版本数据
|
||||
// @Security ApiKeyAuth
|
||||
// @Accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body systemReq.ImportVersionRequest true "版本JSON数据"
|
||||
// @Success 200 {object} response.Response{msg=string} "导入成功"
|
||||
// @Router /sysVersion/importVersion [post]
|
||||
func (sysVersionApi *SysVersionApi) ImportVersion(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// 获取JSON数据
|
||||
var importData systemReq.ImportVersionRequest
|
||||
err := c.ShouldBindJSON(&importData)
|
||||
if err != nil {
|
||||
response.FailWithMessage("解析JSON数据失败:"+err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证数据格式
|
||||
if importData.VersionInfo.Name == "" || importData.VersionInfo.Code == "" {
|
||||
response.FailWithMessage("版本信息格式错误", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 导入菜单数据
|
||||
if len(importData.ExportMenu) > 0 {
|
||||
if err := sysVersionService.ImportMenus(ctx, importData.ExportMenu); err != nil {
|
||||
global.GVA_LOG.Error("导入菜单失败!", zap.Error(err))
|
||||
response.FailWithMessage("导入菜单失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 导入API数据
|
||||
if len(importData.ExportApi) > 0 {
|
||||
if err := sysVersionService.ImportApis(importData.ExportApi); err != nil {
|
||||
global.GVA_LOG.Error("导入API失败!", zap.Error(err))
|
||||
response.FailWithMessage("导入API失败: "+err.Error(), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 创建导入记录
|
||||
jsonData, _ := json.Marshal(importData)
|
||||
version := system.SysVersion{
|
||||
VersionName: utils.Pointer(importData.VersionInfo.Name),
|
||||
VersionCode: utils.Pointer(fmt.Sprintf("%s_imported_%s", importData.VersionInfo.Code, time.Now().Format("20060102150405"))),
|
||||
Description: utils.Pointer(fmt.Sprintf("导入版本: %s", importData.VersionInfo.Description)),
|
||||
VersionData: utils.Pointer(string(jsonData)),
|
||||
}
|
||||
|
||||
err = sysVersionService.CreateSysVersion(ctx, &version)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("保存导入记录失败!", zap.Error(err))
|
||||
// 这里不返回错误,因为数据已经导入成功
|
||||
}
|
||||
|
||||
response.OkWithMessage("导入成功", c)
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
# github.com/flipped-aurora/gin-vue-admin/server Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: qmPlus
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: info
|
||||
format: console
|
||||
prefix: "[github.com/flipped-aurora/gin-vue-admin/server]"
|
||||
director: log
|
||||
show-line: true
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
log-in-console: true
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
db: 0
|
||||
addr: 177.7.0.14:6379
|
||||
password: ""
|
||||
|
||||
# mongo configuration
|
||||
mongo:
|
||||
coll: ''
|
||||
options: ''
|
||||
database: ''
|
||||
username: ''
|
||||
password: ''
|
||||
min-pool-size: 0
|
||||
max-pool-size: 100
|
||||
socket-timeout-ms: 0
|
||||
connect-timeout-ms: 0
|
||||
is-zap: false
|
||||
hosts:
|
||||
- host: ''
|
||||
port: ''
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
port: 465
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
is-ssl: true
|
||||
secret: xxx
|
||||
nickname: test
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
env: public # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: mysql
|
||||
oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-redis: false # 使用redis
|
||||
use-mongo: false # 使用mongo
|
||||
use-multipoint: false
|
||||
# IP限制次数 一个小时15000次
|
||||
iplimit-count: 15000
|
||||
# IP限制一个小时
|
||||
iplimit-time: 3600
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0 # 0代表一直开启,大于0代表限制次数
|
||||
open-captcha-timeout: 3600 # open-captcha大于0时才生效
|
||||
|
||||
# mysql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
mysql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# pgsql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
pgsql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
db-list:
|
||||
- disable: true # 是否禁用
|
||||
type: "" # 数据库的类型,目前支持mysql、pgsql
|
||||
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
|
||||
# autocode configuration
|
||||
autocode:
|
||||
transfer-restart: true
|
||||
# root 自动适配项目根目录
|
||||
# 请不要手动配置,他会在项目加载的时候识别出根路径
|
||||
root: ""
|
||||
server: /server
|
||||
server-plug: /plugin/%s
|
||||
server-api: /api/v1/%s
|
||||
server-initialize: /initialize
|
||||
server-model: /model/%s
|
||||
server-request: /model/%s/request/
|
||||
server-router: /router/%s
|
||||
server-service: /service/%s
|
||||
web: /web/src
|
||||
web-api: /api
|
||||
web-form: /view
|
||||
web-table: /view
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: ZoneHuaDong
|
||||
bucket: ""
|
||||
img-path: ""
|
||||
use-https: false
|
||||
access-key: ""
|
||||
secret-key: ""
|
||||
use-cdn-domains: false
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
bucket-url: yourBucketUrl
|
||||
base-path: yourBasePath
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# aws s3 configuration (minio compatible)
|
||||
aws-s3:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
endpoint: ""
|
||||
s3-force-path-style: false
|
||||
disable-ssl: false
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# huawei obs configuration
|
||||
hua-wei-obs:
|
||||
path: you-path
|
||||
bucket: you-bucket
|
||||
endpoint: you-endpoint
|
||||
access-key: you-access-key
|
||||
secret-key: you-secret-key
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
|
||||
# timer task db clear table
|
||||
Timer:
|
||||
start: true
|
||||
spec: "@daily" # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron/v3
|
||||
detail:
|
||||
- tableName: sys_operation_records
|
||||
compareField: created_at
|
||||
interval: 2160h
|
||||
- tableName: jwt_blacklists
|
||||
compareField: created_at
|
||||
interval: 168h
|
||||
|
||||
# 跨域配置
|
||||
# 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用
|
||||
cors:
|
||||
mode: whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
- allow-origin: example2.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
+265
-43
@@ -1,61 +1,283 @@
|
||||
# Gin-Vue-Admin Global Configuration
|
||||
|
||||
# casbin configuration
|
||||
casbin:
|
||||
model-path: './resource/rbac_model.conf'
|
||||
# github.com/flipped-aurora/gin-vue-admin/server Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
|
||||
# mysql connect configuration
|
||||
mysql:
|
||||
username: root
|
||||
password: 'Aa@6447985'
|
||||
path: '127.0.0.1:3306'
|
||||
db-name: 'qmPlus'
|
||||
config: 'charset=utf8&parseTime=True&loc=Local'
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 10
|
||||
log-mode: false
|
||||
|
||||
#sqlite 配置
|
||||
sqlite:
|
||||
path: db.db
|
||||
log-mode: true
|
||||
config: 'loc=Asia/Shanghai'
|
||||
|
||||
# oss configuration
|
||||
|
||||
# 请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址
|
||||
qiniu:
|
||||
access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
|
||||
secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
|
||||
bucket: 'qm-plus-img'
|
||||
img-path: 'http://qmplusimg.henrongyi.top'
|
||||
signing-key: qmPlus
|
||||
expires-time: 7d
|
||||
buffer-time: 1d
|
||||
issuer: qmPlus
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: info
|
||||
format: console
|
||||
prefix: "[github.com/flipped-aurora/gin-vue-admin/server]"
|
||||
director: log
|
||||
show-line: true
|
||||
encode-level: LowercaseColorLevelEncoder
|
||||
stacktrace-key: stacktrace
|
||||
log-in-console: true
|
||||
retention-day: -1
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
addr: '127.0.0.1:6379'
|
||||
password: ''
|
||||
#是否使用redis集群模式
|
||||
useCluster: false
|
||||
#使用集群模式addr和db默认无效
|
||||
addr: 127.0.0.1:6379
|
||||
password: ""
|
||||
db: 0
|
||||
clusterAddrs:
|
||||
- "172.21.0.3:7000"
|
||||
- "172.21.0.4:7001"
|
||||
- "172.21.0.2:7002"
|
||||
|
||||
# redis-list configuration
|
||||
redis-list:
|
||||
- name: cache # 数据库的名称,注意: name 需要在 redis-list 中唯一
|
||||
useCluster: false # 是否使用redis集群模式
|
||||
addr: 127.0.0.1:6379 # 使用集群模式addr和db默认无效
|
||||
password: ""
|
||||
db: 0
|
||||
clusterAddrs:
|
||||
- "172.21.0.3:7000"
|
||||
- "172.21.0.4:7001"
|
||||
- "172.21.0.2:7002"
|
||||
|
||||
# mongo configuration
|
||||
mongo:
|
||||
coll: ''
|
||||
options: ''
|
||||
database: ''
|
||||
username: ''
|
||||
password: ''
|
||||
auth-source: ''
|
||||
min-pool-size: 0
|
||||
max-pool-size: 100
|
||||
socket-timeout-ms: 0
|
||||
connect-timeout-ms: 0
|
||||
is-zap: false
|
||||
hosts:
|
||||
- host: ''
|
||||
port: ''
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: xxx@qq.com
|
||||
port: 465
|
||||
from: xxx@163.com
|
||||
host: smtp.163.com
|
||||
is-ssl: true
|
||||
secret: xxx
|
||||
nickname: test
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
use-multipoint: false
|
||||
env: 'public' # Change to "develop" to skip authentication for development mode
|
||||
env: local # 修改为public可以关闭路由日志输出
|
||||
addr: 8888
|
||||
db-type: "mysql" # support mysql/sqlite
|
||||
db-type: mysql
|
||||
oss-type: local # 控制oss选择走本地还是 七牛等其他仓 自行增加其他oss仓可以在 server/utils/upload/upload.go 中 NewOss函数配置
|
||||
use-redis: false # 使用redis
|
||||
use-mongo: false # 使用mongo
|
||||
use-multipoint: false
|
||||
# IP限制次数 一个小时15000次
|
||||
iplimit-count: 15000
|
||||
# IP限制一个小时
|
||||
iplimit-time: 3600
|
||||
# 路由全局前缀
|
||||
router-prefix: ""
|
||||
# 严格角色模式 打开后权限将会存在上下级关系
|
||||
use-strict-auth: false
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
open-captcha: 0 # 0代表一直开启,大于0代表限制次数
|
||||
open-captcha-timeout: 3600 # open-captcha大于0时才生效
|
||||
|
||||
# logger configuration
|
||||
log:
|
||||
prefix: '[GIN-VUE-ADMIN]'
|
||||
log-file: true
|
||||
stdout: 'DEBUG'
|
||||
file: 'DEBUG'
|
||||
# mysql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
mysql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# pgsql connect configuration
|
||||
# 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://gin-vue-admin.com/docs/first_master)
|
||||
pgsql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
oracle:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
mssql:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
sqlite:
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
db-list:
|
||||
- disable: true # 是否禁用
|
||||
type: "" # 数据库的类型,目前支持mysql、pgsql、mssql、oracle
|
||||
alias-name: "" # 数据库的名称,注意: alias-name 需要在db-list中唯一
|
||||
path: ""
|
||||
port: ""
|
||||
config: ""
|
||||
db-name: ""
|
||||
username: ""
|
||||
password: ""
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 100
|
||||
log-mode: ""
|
||||
log-zap: false
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: uploads/file
|
||||
store-path: uploads/file
|
||||
|
||||
# autocode configuration
|
||||
autocode:
|
||||
web: web/src
|
||||
root: "" # root 自动适配项目根目录, 请不要手动配置,他会在项目加载的时候识别出根路径
|
||||
server: server
|
||||
module: 'github.com/flipped-aurora/gin-vue-admin/server'
|
||||
ai-path: "" # AI服务路径
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: ZoneHuaDong
|
||||
bucket: ""
|
||||
img-path: ""
|
||||
use-https: false
|
||||
access-key: ""
|
||||
secret-key: ""
|
||||
use-cdn-domains: false
|
||||
|
||||
# minio oss configuration
|
||||
minio:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
use-ssl: false
|
||||
base-path: ""
|
||||
bucket-url: "http://host:9000/yourBucketName"
|
||||
|
||||
# aliyun oss configuration
|
||||
aliyun-oss:
|
||||
endpoint: yourEndpoint
|
||||
access-key-id: yourAccessKeyId
|
||||
access-key-secret: yourAccessKeySecret
|
||||
bucket-name: yourBucketName
|
||||
bucket-url: yourBucketUrl
|
||||
base-path: yourBasePath
|
||||
|
||||
# tencent cos configuration
|
||||
tencent-cos:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# aws s3 configuration (minio compatible)
|
||||
aws-s3:
|
||||
bucket: xxxxx-10005608
|
||||
region: ap-shanghai
|
||||
endpoint: ""
|
||||
s3-force-path-style: false
|
||||
disable-ssl: false
|
||||
secret-id: your-secret-id
|
||||
secret-key: your-secret-key
|
||||
base-url: https://gin.vue.admin
|
||||
path-prefix: github.com/flipped-aurora/gin-vue-admin/server
|
||||
|
||||
# cloudflare r2 configuration
|
||||
cloudflare-r2:
|
||||
bucket: xxxx0bucket
|
||||
base-url: https://gin.vue.admin.com
|
||||
path: uploads
|
||||
account-id: xxx_account_id
|
||||
access-key-id: xxx_key_id
|
||||
secret-access-key: xxx_secret_key
|
||||
|
||||
# huawei obs configuration
|
||||
hua-wei-obs:
|
||||
path: you-path
|
||||
bucket: you-bucket
|
||||
endpoint: you-endpoint
|
||||
access-key: you-access-key
|
||||
secret-key: you-secret-key
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
|
||||
# disk usage configuration
|
||||
disk-list:
|
||||
- mount-point: "/"
|
||||
|
||||
# 跨域配置
|
||||
# 需要配合 server/initialize/router.go -> `Router.Use(middleware.CorsByRules())` 使用
|
||||
cors:
|
||||
mode: strict-whitelist # 放行模式: allow-all, 放行全部; whitelist, 白名单模式, 来自白名单内域名的请求添加 cors 头; strict-whitelist 严格白名单模式, 白名单外的请求一律拒绝
|
||||
whitelist:
|
||||
- allow-origin: example1.com
|
||||
allow-headers: Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id
|
||||
allow-methods: POST, GET
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
|
||||
allow-credentials: true # 布尔值
|
||||
- allow-origin: example2.com
|
||||
allow-headers: content-type
|
||||
allow-methods: GET, POST
|
||||
expose-headers: Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type
|
||||
allow-credentials: true # 布尔值
|
||||
mcp:
|
||||
name: GVA_MCP
|
||||
version: v1.0.0
|
||||
sse_path: /sse
|
||||
message_path: /message
|
||||
url_prefix: ''
|
||||
@@ -0,0 +1,22 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Autocode struct {
|
||||
Web string `mapstructure:"web" json:"web" yaml:"web"`
|
||||
Root string `mapstructure:"root" json:"root" yaml:"root"`
|
||||
Server string `mapstructure:"server" json:"server" yaml:"server"`
|
||||
Module string `mapstructure:"module" json:"module" yaml:"module"`
|
||||
AiPath string `mapstructure:"ai-path" json:"ai-path" yaml:"ai-path"`
|
||||
}
|
||||
|
||||
func (a *Autocode) WebRoot() string {
|
||||
webs := strings.Split(a.Web, "/")
|
||||
if len(webs) == 0 {
|
||||
webs = strings.Split(a.Web, "\\")
|
||||
}
|
||||
return filepath.Join(webs...)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
type Captcha struct {
|
||||
KeyLong int `mapstructure:"key-long" json:"key-long" yaml:"key-long"` // 验证码长度
|
||||
ImgWidth int `mapstructure:"img-width" json:"img-width" yaml:"img-width"` // 验证码宽度
|
||||
ImgHeight int `mapstructure:"img-height" json:"img-height" yaml:"img-height"` // 验证码高度
|
||||
OpenCaptcha int `mapstructure:"open-captcha" json:"open-captcha" yaml:"open-captcha"` // 防爆破验证码开启此数,0代表每次登录都需要验证码,其他数字代表错误密码次数,如3代表错误三次后出现验证码
|
||||
OpenCaptchaTimeOut int `mapstructure:"open-captcha-timeout" json:"open-captcha-timeout" yaml:"open-captcha-timeout"` // 防爆破验证码超时时间,单位:s(秒)
|
||||
}
|
||||
+32
-64
@@ -1,72 +1,40 @@
|
||||
package config
|
||||
|
||||
type Server struct {
|
||||
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
|
||||
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite" yaml:"sqlite"`
|
||||
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
|
||||
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`
|
||||
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
|
||||
System System `mapstructure:"system" json:"system" yaml:"system"`
|
||||
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
|
||||
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
|
||||
Log Log `mapstructure:"log" json:"log" yaml:"log"`
|
||||
}
|
||||
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
|
||||
Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"`
|
||||
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
|
||||
RedisList []Redis `mapstructure:"redis-list" json:"redis-list" yaml:"redis-list"`
|
||||
Mongo Mongo `mapstructure:"mongo" json:"mongo" yaml:"mongo"`
|
||||
Email Email `mapstructure:"email" json:"email" yaml:"email"`
|
||||
System System `mapstructure:"system" json:"system" yaml:"system"`
|
||||
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
|
||||
// auto
|
||||
AutoCode Autocode `mapstructure:"autocode" json:"autocode" yaml:"autocode"`
|
||||
// gorm
|
||||
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
|
||||
Mssql Mssql `mapstructure:"mssql" json:"mssql" yaml:"mssql"`
|
||||
Pgsql Pgsql `mapstructure:"pgsql" json:"pgsql" yaml:"pgsql"`
|
||||
Oracle Oracle `mapstructure:"oracle" json:"oracle" yaml:"oracle"`
|
||||
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite" yaml:"sqlite"`
|
||||
DBList []SpecializedDB `mapstructure:"db-list" json:"db-list" yaml:"db-list"`
|
||||
// oss
|
||||
Local Local `mapstructure:"local" json:"local" yaml:"local"`
|
||||
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
|
||||
AliyunOSS AliyunOSS `mapstructure:"aliyun-oss" json:"aliyun-oss" yaml:"aliyun-oss"`
|
||||
HuaWeiObs HuaWeiObs `mapstructure:"hua-wei-obs" json:"hua-wei-obs" yaml:"hua-wei-obs"`
|
||||
TencentCOS TencentCOS `mapstructure:"tencent-cos" json:"tencent-cos" yaml:"tencent-cos"`
|
||||
AwsS3 AwsS3 `mapstructure:"aws-s3" json:"aws-s3" yaml:"aws-s3"`
|
||||
CloudflareR2 CloudflareR2 `mapstructure:"cloudflare-r2" json:"cloudflare-r2" yaml:"cloudflare-r2"`
|
||||
Minio Minio `mapstructure:"minio" json:"minio" yaml:"minio"`
|
||||
|
||||
type System struct {
|
||||
UseMultipoint bool `mapstructure:"use-multipoint" json:"useMultipoint" yaml:"use-multipoint"`
|
||||
Env string `mapstructure:"env" json:"env" yaml:"env"`
|
||||
Addr int `mapstructure:"addr" json:"addr" yaml:"addr"`
|
||||
DbType string `mapstructure:"db-type" json:"dbType" yaml:"db-type"`
|
||||
}
|
||||
Excel Excel `mapstructure:"excel" json:"excel" yaml:"excel"`
|
||||
|
||||
type JWT struct {
|
||||
SigningKey string `mapstructure:"signing-key" json:"signingKey" yaml:"signing-key"`
|
||||
}
|
||||
DiskList []DiskList `mapstructure:"disk-list" json:"disk-list" yaml:"disk-list"`
|
||||
|
||||
type Casbin struct {
|
||||
ModelPath string `mapstructure:"model-path" json:"modelPath" yaml:"model-path"`
|
||||
}
|
||||
// 跨域配置
|
||||
Cors CORS `mapstructure:"cors" json:"cors" yaml:"cors"`
|
||||
|
||||
type Mysql struct {
|
||||
Username string `mapstructure:"username" json:"username" yaml:"username"`
|
||||
Password string `mapstructure:"password" json:"password" yaml:"password"`
|
||||
Path string `mapstructure:"path" json:"path" yaml:"path"`
|
||||
Dbname string `mapstructure:"db-name" json:"dbname" yaml:"db-name"`
|
||||
Config string `mapstructure:"config" json:"config" yaml:"config"`
|
||||
MaxIdleConns int `mapstructure:"max-idle-conns" json:"maxIdleConns" yaml:"max-idle-conns"`
|
||||
MaxOpenConns int `mapstructure:"max-open-conns" json:"maxOpenConns" yaml:"max-open-conns"`
|
||||
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
|
||||
}
|
||||
|
||||
type Redis struct {
|
||||
Addr string `mapstructure:"addr" json:"addr" yaml:"addr"`
|
||||
Password string `mapstructure:"password" json:"password" yaml:"password"`
|
||||
DB int `mapstructure:"db" json:"db" yaml:"db"`
|
||||
}
|
||||
type Qiniu struct {
|
||||
AccessKey string `mapstructure:"access-key" json:"accessKey" yaml:"access-key"`
|
||||
SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`
|
||||
Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket"`
|
||||
ImgPath string `mapstructure:"img-path" json:"imgPath" yaml:"img-path"`
|
||||
}
|
||||
|
||||
type Captcha struct {
|
||||
KeyLong int `mapstructure:"key-long" json:"keyLong" yaml:"key-long"`
|
||||
ImgWidth int `mapstructure:"img-width" json:"imgWidth" yaml:"img-width"`
|
||||
ImgHeight int `mapstructure:"img-height" json:"imgHeight" yaml:"img-height"`
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
|
||||
LogFile bool `mapstructure:"log-file" json:"logFile" yaml:"log-file"`
|
||||
Stdout string `mapstructure:"stdout" json:"stdout" yaml:"stdout"`
|
||||
File string `mapstructure:"file" json:"file" yaml:"file"`
|
||||
}
|
||||
|
||||
type Sqlite struct {
|
||||
Username string `mapstructure:"username" json:"username" yaml:"username"`
|
||||
Password string `mapstructure:"password" json:"password" yaml:"password"`
|
||||
Path string `mapstructure:"path" json:"path" yaml:"path"`
|
||||
Config string `mapstructure:"config" json:"config" yaml:"config"`
|
||||
LogMode bool `mapstructure:"log-mode" json:"logMode" yaml:"log-mode"`
|
||||
// MCP配置
|
||||
MCP MCP `mapstructure:"mcp" json:"mcp" yaml:"mcp"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package config
|
||||
|
||||
type CORS struct {
|
||||
Mode string `mapstructure:"mode" json:"mode" yaml:"mode"`
|
||||
Whitelist []CORSWhitelist `mapstructure:"whitelist" json:"whitelist" yaml:"whitelist"`
|
||||
}
|
||||
|
||||
type CORSWhitelist struct {
|
||||
AllowOrigin string `mapstructure:"allow-origin" json:"allow-origin" yaml:"allow-origin"`
|
||||
AllowMethods string `mapstructure:"allow-methods" json:"allow-methods" yaml:"allow-methods"`
|
||||
AllowHeaders string `mapstructure:"allow-headers" json:"allow-headers" yaml:"allow-headers"`
|
||||
ExposeHeaders string `mapstructure:"expose-headers" json:"expose-headers" yaml:"expose-headers"`
|
||||
AllowCredentials bool `mapstructure:"allow-credentials" json:"allow-credentials" yaml:"allow-credentials"`
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
type DsnProvider interface {
|
||||
Dsn() string
|
||||
}
|
||||
|
||||
// Embeded 结构体可以压平到上一层,从而保持 config 文件的结构和原来一样
|
||||
// 见 playground: https://go.dev/play/p/KIcuhqEoxmY
|
||||
|
||||
// GeneralDB 也被 Pgsql 和 Mysql 原样使用
|
||||
type GeneralDB struct {
|
||||
Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"` // 数据库前缀
|
||||
Port string `mapstructure:"port" json:"port" yaml:"port"` // 数据库端口
|
||||
Config string `mapstructure:"config" json:"config" yaml:"config"` // 高级配置
|
||||
Dbname string `mapstructure:"db-name" json:"db-name" yaml:"db-name"` // 数据库名
|
||||
Username string `mapstructure:"username" json:"username" yaml:"username"` // 数据库账号
|
||||
Password string `mapstructure:"password" json:"password" yaml:"password"` // 数据库密码
|
||||
Path string `mapstructure:"path" json:"path" yaml:"path"` // 数据库地址
|
||||
Engine string `mapstructure:"engine" json:"engine" yaml:"engine" default:"InnoDB"` // 数据库引擎,默认InnoDB
|
||||
LogMode string `mapstructure:"log-mode" json:"log-mode" yaml:"log-mode"` // 是否开启Gorm全局日志
|
||||
MaxIdleConns int `mapstructure:"max-idle-conns" json:"max-idle-conns" yaml:"max-idle-conns"` // 空闲中的最大连接数
|
||||
MaxOpenConns int `mapstructure:"max-open-conns" json:"max-open-conns" yaml:"max-open-conns"` // 打开到数据库的最大连接数
|
||||
Singular bool `mapstructure:"singular" json:"singular" yaml:"singular"` // 是否开启全局禁用复数,true表示开启
|
||||
LogZap bool `mapstructure:"log-zap" json:"log-zap" yaml:"log-zap"` // 是否通过zap写入日志文件
|
||||
}
|
||||
|
||||
func (c GeneralDB) LogLevel() logger.LogLevel {
|
||||
switch strings.ToLower(c.LogMode) {
|
||||
case "silent":
|
||||
return logger.Silent
|
||||
case "error":
|
||||
return logger.Error
|
||||
case "warn":
|
||||
return logger.Warn
|
||||
case "info":
|
||||
return logger.Info
|
||||
default:
|
||||
return logger.Info
|
||||
}
|
||||
}
|
||||
|
||||
type SpecializedDB struct {
|
||||
Type string `mapstructure:"type" json:"type" yaml:"type"`
|
||||
AliasName string `mapstructure:"alias-name" json:"alias-name" yaml:"alias-name"`
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
Disable bool `mapstructure:"disable" json:"disable" yaml:"disable"`
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
type Disk struct {
|
||||
MountPoint string `mapstructure:"mount-point" json:"mount-point" yaml:"mount-point"`
|
||||
}
|
||||
|
||||
type DiskList struct {
|
||||
Disk `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package config
|
||||
|
||||
type Email struct {
|
||||
To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 例:a@qq.com b@qq.com 正式开发中请把此项目作为参数使用
|
||||
From string `mapstructure:"from" json:"from" yaml:"from"` // 发件人 你自己要发邮件的邮箱
|
||||
Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议
|
||||
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥
|
||||
Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 发件人昵称 通常为自己的邮箱
|
||||
Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465
|
||||
IsSSL bool `mapstructure:"is-ssl" json:"is-ssl" yaml:"is-ssl"` // 是否SSL 是否开启SSL
|
||||
IsLoginAuth bool `mapstructure:"is-loginauth" json:"is-loginauth" yaml:"is-loginauth"` // 是否LoginAuth 是否使用LoginAuth认证方式(适用于IBM、微软邮箱服务器等)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
type Excel struct {
|
||||
Dir string `mapstructure:"dir" json:"dir" yaml:"dir"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
type Mssql struct {
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
// Dsn "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
|
||||
func (m *Mssql) Dsn() string {
|
||||
return "sqlserver://" + m.Username + ":" + m.Password + "@" + m.Path + ":" + m.Port + "?database=" + m.Dbname + "&encrypt=disable"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
type Mysql struct {
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func (m *Mysql) Dsn() string {
|
||||
return m.Username + ":" + m.Password + "@tcp(" + m.Path + ":" + m.Port + ")/" + m.Dbname + "?" + m.Config
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
type Oracle struct {
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func (m *Oracle) Dsn() string {
|
||||
return "oracle://" + m.Username + ":" + m.Password + "@" + m.Path + ":" + m.Port + "/" + m.Dbname + "?" + m.Config
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package config
|
||||
|
||||
type Pgsql struct {
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
// Dsn 基于配置文件获取 dsn
|
||||
// Author [SliverHorn](https://github.com/SliverHorn)
|
||||
func (p *Pgsql) Dsn() string {
|
||||
return "host=" + p.Path + " user=" + p.Username + " password=" + p.Password + " dbname=" + p.Dbname + " port=" + p.Port + " " + p.Config
|
||||
}
|
||||
|
||||
// LinkDsn 根据 dbname 生成 dsn
|
||||
// Author [SliverHorn](https://github.com/SliverHorn)
|
||||
func (p *Pgsql) LinkDsn(dbname string) string {
|
||||
return "host=" + p.Path + " user=" + p.Username + " password=" + p.Password + " dbname=" + dbname + " port=" + p.Port + " " + p.Config
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Sqlite struct {
|
||||
GeneralDB `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func (s *Sqlite) Dsn() string {
|
||||
return filepath.Join(s.Path, s.Dbname+".db")
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package config
|
||||
|
||||
type JWT struct {
|
||||
SigningKey string `mapstructure:"signing-key" json:"signing-key" yaml:"signing-key"` // jwt签名
|
||||
ExpiresTime string `mapstructure:"expires-time" json:"expires-time" yaml:"expires-time"` // 过期时间
|
||||
BufferTime string `mapstructure:"buffer-time" json:"buffer-time" yaml:"buffer-time"` // 缓冲时间
|
||||
Issuer string `mapstructure:"issuer" json:"issuer" yaml:"issuer"` // 签发者
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package config
|
||||
|
||||
type MCP struct {
|
||||
Name string `mapstructure:"name" json:"name" yaml:"name"` // MCP名称
|
||||
Version string `mapstructure:"version" json:"version" yaml:"version"` // MCP版本
|
||||
SSEPath string `mapstructure:"sse_path" json:"sse_path" yaml:"sse_path"` // SSE路径
|
||||
MessagePath string `mapstructure:"message_path" json:"message_path" yaml:"message_path"` // 消息路径
|
||||
UrlPrefix string `mapstructure:"url_prefix" json:"url_prefix" yaml:"url_prefix"` // URL前缀
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Mongo struct {
|
||||
Coll string `json:"coll" yaml:"coll" mapstructure:"coll"` // collection name
|
||||
Options string `json:"options" yaml:"options" mapstructure:"options"` // mongodb options
|
||||
Database string `json:"database" yaml:"database" mapstructure:"database"` // database name
|
||||
Username string `json:"username" yaml:"username" mapstructure:"username"` // 用户名
|
||||
Password string `json:"password" yaml:"password" mapstructure:"password"` // 密码
|
||||
AuthSource string `json:"auth-source" yaml:"auth-source" mapstructure:"auth-source"` // 验证数据库
|
||||
MinPoolSize uint64 `json:"min-pool-size" yaml:"min-pool-size" mapstructure:"min-pool-size"` // 最小连接池
|
||||
MaxPoolSize uint64 `json:"max-pool-size" yaml:"max-pool-size" mapstructure:"max-pool-size"` // 最大连接池
|
||||
SocketTimeoutMs int64 `json:"socket-timeout-ms" yaml:"socket-timeout-ms" mapstructure:"socket-timeout-ms"` // socket超时时间
|
||||
ConnectTimeoutMs int64 `json:"connect-timeout-ms" yaml:"connect-timeout-ms" mapstructure:"connect-timeout-ms"` // 连接超时时间
|
||||
IsZap bool `json:"is-zap" yaml:"is-zap" mapstructure:"is-zap"` // 是否开启zap日志
|
||||
Hosts []*MongoHost `json:"hosts" yaml:"hosts" mapstructure:"hosts"` // 主机列表
|
||||
}
|
||||
|
||||
type MongoHost struct {
|
||||
Host string `json:"host" yaml:"host" mapstructure:"host"` // ip地址
|
||||
Port string `json:"port" yaml:"port" mapstructure:"port"` // 端口
|
||||
}
|
||||
|
||||
// Uri .
|
||||
func (x *Mongo) Uri() string {
|
||||
length := len(x.Hosts)
|
||||
hosts := make([]string, 0, length)
|
||||
for i := 0; i < length; i++ {
|
||||
if x.Hosts[i].Host != "" && x.Hosts[i].Port != "" {
|
||||
hosts = append(hosts, x.Hosts[i].Host+":"+x.Hosts[i].Port)
|
||||
}
|
||||
}
|
||||
if x.Options != "" {
|
||||
return fmt.Sprintf("mongodb://%s/%s?%s", strings.Join(hosts, ","), x.Database, x.Options)
|
||||
}
|
||||
return fmt.Sprintf("mongodb://%s/%s", strings.Join(hosts, ","), x.Database)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user