mirror of
https://github.com/go-admin-team/go-admin.git
synced 2026-09-23 10:51:09 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec10917272 | ||
|
|
b8af16baf0 | ||
|
|
92987cdee3 | ||
|
|
df98ffb5c5 | ||
|
|
acc9378283 | ||
|
|
b4b5bc5b3a | ||
|
|
27ad988fd7 | ||
|
|
effc3a3e69 | ||
|
|
08f789737f | ||
|
|
f57bf5d61d | ||
|
|
143dbf19a2 | ||
|
|
f6bd306d6d | ||
|
|
3beb00143a | ||
|
|
7a52a50964 | ||
|
|
630e13686c | ||
|
|
05661e2f3e | ||
|
|
3625ce851b | ||
|
|
8b312bed1d | ||
|
|
30bcb57f41 | ||
|
|
5bb211afcd | ||
|
|
d102c4b7c1 | ||
|
|
545453c93e | ||
|
|
c3d2a5952b | ||
|
|
d65b21baf6 | ||
|
|
0f31feae6f | ||
|
|
0494a27d6c | ||
|
|
e2b6ddb290 | ||
|
|
28eba92077 | ||
|
|
aa7a92664d | ||
|
|
68ecc5f9a8 | ||
|
|
8341044251 | ||
|
|
8b03400ecc | ||
|
|
8115c3a737 | ||
|
|
c01307202d | ||
|
|
5ecb1e6e4c | ||
|
|
9c299805c1 | ||
|
|
2a900c9876 | ||
|
|
0008b943a3 | ||
|
|
50c74b1f96 | ||
|
|
ae1eef6d4f | ||
|
|
d01cdc040f | ||
|
|
92b9af17b7 | ||
|
|
898e1b023a | ||
|
|
1cd39b80b3 | ||
|
|
a90c67473e | ||
|
|
1a84b8a892 | ||
|
|
656d14cd54 | ||
|
|
9dd271ecab | ||
|
|
4973ee030d | ||
|
|
137bb3ad33 | ||
|
|
03d587db6a | ||
|
|
1f56b956d2 | ||
|
|
37aece9791 | ||
|
|
309b400bc0 | ||
|
|
1b9868b72b | ||
|
|
25344aa572 | ||
|
|
ea9d27cf6d | ||
|
|
0bee8ec46c | ||
|
|
3a5afeb518 | ||
|
|
fc8ba4d615 | ||
|
|
dc20062e5b | ||
|
|
ff430c509b | ||
|
|
d43d7a46dd | ||
|
|
72c496ab93 | ||
|
|
b228152308 | ||
|
|
006756ea40 | ||
|
|
aa539c061f | ||
|
|
74b0ee8776 | ||
|
|
412413c12f | ||
|
|
35d213f339 | ||
|
|
9c68bc25a5 | ||
|
|
9c5d9d16a7 | ||
|
|
46c10f999a | ||
|
|
d12f40c9a0 | ||
|
|
cd363fce3d | ||
|
|
709cebd4a7 | ||
|
|
ba5ef9f79c | ||
|
|
2c50317a98 | ||
|
|
28350a15bb | ||
|
|
c6d3ea5f81 | ||
|
|
7fadb4b585 | ||
|
|
691df82016 | ||
|
|
ea348fa9d1 | ||
|
|
925c6772a6 | ||
|
|
0c60e44aee | ||
|
|
a716086295 | ||
|
|
f8a5066a40 | ||
|
|
f978967ef1 | ||
|
|
d6e2c02fda | ||
|
|
e98b65cf90 | ||
|
|
bc5411c30c | ||
|
|
27f23121f0 | ||
|
|
047b23872c | ||
|
|
84bd87dcc9 | ||
|
|
0e7a13aeba | ||
|
|
85d50da494 | ||
|
|
1d9def4314 | ||
|
|
ed9bbd01e2 | ||
|
|
523d6a3649 | ||
|
|
6326962862 | ||
|
|
cd7c8375c0 | ||
|
|
63bcc912ef | ||
|
|
adcdd2edcd | ||
|
|
29406f839e | ||
|
|
a43133ab7b | ||
|
|
7002cd4065 | ||
|
|
8faa8d2aed | ||
|
|
705427178d | ||
|
|
8f10d202e6 | ||
|
|
5648bd1dcf | ||
|
|
a442eadb96 | ||
|
|
f3b67e9abc | ||
|
|
4e51f56623 | ||
|
|
7e4e17bbcf | ||
|
|
799e892a68 | ||
|
|
0e2adb3165 | ||
|
|
249e044ded | ||
|
|
d6309c75be | ||
|
|
211ae85a4e | ||
|
|
3c3d94ca76 | ||
|
|
6138d2d74c | ||
|
|
d5de79f75b | ||
|
|
46e793972c | ||
|
|
46f4092b43 | ||
|
|
196195357b | ||
|
|
c579c5f84c | ||
|
|
241c27358b | ||
|
|
aa3c9866cb | ||
|
|
2ac01ea584 | ||
|
|
7f9cc1e435 | ||
|
|
4fb0529d2d | ||
|
|
8ee4141af6 | ||
|
|
36f2549172 | ||
|
|
dff0e64f51 | ||
|
|
0b78bc1e2e | ||
|
|
94163f9afb | ||
|
|
4510b06959 | ||
|
|
750c7c744e | ||
|
|
d52dca1cb6 | ||
|
|
71413a4248 | ||
|
|
4fede43254 | ||
|
|
0a629e2f3f | ||
|
|
37065fb089 | ||
|
|
6966f14dd4 | ||
|
|
22716e90c1 | ||
|
|
73cce7fc2f | ||
|
|
b59c7f0d46 | ||
|
|
d3a44a2a6b | ||
|
|
5c3c3907d5 | ||
|
|
f2215e132e | ||
|
|
a69afab34f | ||
|
|
e0132db1b9 | ||
|
|
7c3f55a873 | ||
|
|
f7c0247394 | ||
|
|
ac23556029 | ||
|
|
f64115e03a | ||
|
|
a2524c31bf | ||
|
|
71d6211c61 | ||
|
|
c67760bc39 | ||
|
|
d3e7f46a46 | ||
|
|
55866682ae | ||
|
|
550e95ff43 | ||
|
|
060b6cfd64 | ||
|
|
89a4738394 | ||
|
|
d8529289cf | ||
|
|
4a8f97b1ee | ||
|
|
d54ac844ef | ||
|
|
379fba515f | ||
|
|
58105cb478 | ||
|
|
47af6f4306 | ||
|
|
7d29c9953a | ||
|
|
0729624c2f | ||
|
|
b3a740ab2a | ||
|
|
adf617f5d0 | ||
|
|
049a20cd04 | ||
|
|
be3c4452e3 | ||
|
|
5b01c9ada8 | ||
|
|
ffd82a6a10 | ||
|
|
dd8d89a990 | ||
|
|
2e5b23565e | ||
|
|
f4e3f04d30 | ||
|
|
954ebdc9eb | ||
|
|
2840010dfd | ||
|
|
b147d9b833 | ||
|
|
b3ecb81614 | ||
|
|
ce4581bb99 | ||
|
|
f406ca0160 | ||
|
|
39ea1f6aef | ||
|
|
b2053f507a | ||
|
|
9520117914 | ||
|
|
7a5fc7d440 | ||
|
|
bd5e83d464 | ||
|
|
63dd40a8d7 | ||
|
|
32bd88504d | ||
|
|
d70818a9db | ||
|
|
9d4a425fc0 | ||
|
|
4d6456a588 | ||
|
|
07ff92aa55 | ||
|
|
4156387eb9 | ||
|
|
34773a0a81 | ||
|
|
36a018400b | ||
|
|
7bb02c5f1d | ||
|
|
15fb128236 | ||
|
|
3581e060ec | ||
|
|
0604a29596 | ||
|
|
d8a2958797 | ||
|
|
ab28fa7bed | ||
|
|
e88d751039 | ||
|
|
b836945eea | ||
|
|
d7a8e66753 | ||
|
|
68780a845c | ||
|
|
487dc94a2e | ||
|
|
016e977776 | ||
|
|
dcfe512204 | ||
|
|
fe6ebfd47c | ||
|
|
eba5fba3da | ||
|
|
b7e9a79225 | ||
|
|
deffb19fd8 | ||
|
|
c858b322bd | ||
|
|
1b5b52f0f1 | ||
|
|
ecb31a158b | ||
|
|
1aecc140dc | ||
|
|
e464a4aedd | ||
|
|
595c4a6be5 | ||
|
|
d115c5299c | ||
|
|
9bd542bb59 | ||
|
|
0fa015b6d0 | ||
|
|
ec7d838ebd | ||
|
|
26e116c16c | ||
|
|
90d98893f5 | ||
|
|
10f162bf5d | ||
|
|
19909746f5 | ||
|
|
205febdb8a | ||
|
|
5aec4ba32b | ||
|
|
8f1ea50dfe | ||
|
|
1483ca401d | ||
|
|
ed74623a73 | ||
|
|
1bc2e22833 | ||
|
|
cd8edfa5d4 | ||
|
|
dcc2c8e175 | ||
|
|
d991a285ba | ||
|
|
76c9d1211e | ||
|
|
f5273f5a58 | ||
|
|
54ffaac9c5 | ||
|
|
484de2e698 | ||
|
|
d72ff76aad | ||
|
|
4a523bed92 | ||
|
|
55dc33b865 | ||
|
|
3d13f5856a | ||
|
|
aa2976ba17 | ||
|
|
8e141ff8a0 | ||
|
|
2628ab8e3e | ||
|
|
1b7dcd843c | ||
|
|
f0d91fb763 | ||
|
|
7238c6a26d | ||
|
|
0964cf98e2 | ||
|
|
04c6a081ae | ||
|
|
fcbd9ae02e | ||
|
|
d34d30a197 | ||
|
|
ecfea845c2 | ||
|
|
e05ff7c809 | ||
|
|
28a9626661 | ||
|
|
96b2cb3acf | ||
|
|
87fe6b7d9b | ||
|
|
722de8ea65 | ||
|
|
8ffde94433 | ||
|
|
08eef12bca | ||
|
|
ab0e8e6056 | ||
|
|
2cef52d906 | ||
|
|
95077b116b | ||
|
|
d4cf11d313 | ||
|
|
f201792d8f | ||
|
|
d16f5e7180 | ||
|
|
f8f697af2b | ||
|
|
eb8da38a46 | ||
|
|
f19568c69a | ||
|
|
91bf25e5fe | ||
|
|
85666f160f | ||
|
|
b2baf48dc6 | ||
|
|
c906e1d503 | ||
|
|
3b93ac19f8 | ||
|
|
9914373d45 | ||
|
|
4911730012 | ||
|
|
88bab51056 | ||
|
|
0fd4f68b6c | ||
|
|
c66cb5c6a8 | ||
|
|
b16ec0af77 | ||
|
|
82ea8539eb | ||
|
|
d17d5c1206 | ||
|
|
041d22d0d2 | ||
|
|
5864058a81 | ||
|
|
45035a16e4 | ||
|
|
f4d0108d49 | ||
|
|
b81611ba72 | ||
|
|
bb34108831 | ||
|
|
b7fd92f39b | ||
|
|
63b800a3ba | ||
|
|
ed9450a2d5 | ||
|
|
1d551a10ab | ||
|
|
4d7c9e5a12 | ||
|
|
d1f5fe5681 | ||
|
|
e8c2e0a966 | ||
|
|
cef0a19a9c | ||
|
|
c0e81363dc | ||
|
|
df2e4a2b48 | ||
|
|
9088ebc2e1 | ||
|
|
9f2dec3036 | ||
|
|
ea049f9b06 | ||
|
|
1f1349a685 | ||
|
|
dcef2df38e | ||
|
|
92834d6e39 | ||
|
|
f06540883b | ||
|
|
3c9ce5b6b0 | ||
|
|
ff8a59550a | ||
|
|
7cddef33a2 | ||
|
|
7013c2fa4a | ||
|
|
65bacacb38 | ||
|
|
45587028c3 | ||
|
|
887c9cca4b | ||
|
|
a6ddb113fc | ||
|
|
b83eef8670 | ||
|
|
43dcd61c51 | ||
|
|
1bd64d4562 | ||
|
|
44e81bc72f | ||
|
|
3312f8b7b9 | ||
|
|
d6a2272f9d | ||
|
|
a5cc0a9e29 | ||
|
|
3f995735e9 | ||
|
|
b65b74dee5 | ||
|
|
98cf3ad95a | ||
|
|
8649d8d791 | ||
|
|
817e34c6aa | ||
|
|
952cd92648 | ||
|
|
6b1e961a7f | ||
|
|
762eba5af7 | ||
|
|
e82128f679 | ||
|
|
8f8a197db1 | ||
|
|
364854eda0 | ||
|
|
b259e91f4d | ||
|
|
76411f80bc | ||
|
|
5494353229 | ||
|
|
afe5efbe36 | ||
|
|
db422785fc | ||
|
|
4ac68323da | ||
|
|
44002fcb11 | ||
|
|
5bbd919745 | ||
|
|
54dd3de5b6 | ||
|
|
9540fdfc30 | ||
|
|
937775e2a7 | ||
|
|
84721265dd | ||
|
|
3ab67dfa7d | ||
|
|
6a1941a820 | ||
|
|
3ae7c44585 | ||
|
|
9d809f6392 | ||
|
|
4b477b3103 | ||
|
|
e7ae2fe019 | ||
|
|
d5ba3d9770 | ||
|
|
f3d744f6f5 | ||
|
|
0315631b53 | ||
|
|
48e7ce88ff | ||
|
|
357db6b1c9 | ||
|
|
83e0531f43 | ||
|
|
898ba7d8eb | ||
|
|
8751f34539 | ||
|
|
4aa0068d2d | ||
|
|
b954a2f092 | ||
|
|
9227bd2be1 | ||
|
|
e70a0b1314 | ||
|
|
21c262a31e | ||
|
|
f30889bd19 | ||
|
|
23e519999e | ||
|
|
bedf064ace | ||
|
|
9a8e0cddde | ||
|
|
c0c16036d3 | ||
|
|
dd905a2bed | ||
|
|
2d76430f89 | ||
|
|
5dde1d2a00 | ||
|
|
93f25c6cdf | ||
|
|
d366df372d | ||
|
|
7281d05efc | ||
|
|
e6d6a65267 | ||
|
|
9ff094b6f5 | ||
|
|
fc9c253a9f | ||
|
|
9d735ed5aa | ||
|
|
d782b00117 | ||
|
|
239159dd2a | ||
|
|
0c1e91c3b5 | ||
|
|
c09347b387 | ||
|
|
e49e47c7a1 | ||
|
|
98b46535aa | ||
|
|
014a23aac3 | ||
|
|
f1dfba79e0 | ||
|
|
a282e44b1d | ||
|
|
d1279e67fb | ||
|
|
37a5963cd6 | ||
|
|
69df1b3d34 | ||
|
|
eae97f7a15 | ||
|
|
ce0b5ff7bf | ||
|
|
73118e49b9 | ||
|
|
7b43982595 | ||
|
|
31cd1ee768 | ||
|
|
8df7551946 | ||
|
|
79c1295a70 | ||
|
|
26d9a2e9e4 | ||
|
|
b09b7b6ccc | ||
|
|
ef6fdaa221 | ||
|
|
23c80f0217 | ||
|
|
95dc699e2e | ||
|
|
74b7d62c75 | ||
|
|
68accd5448 | ||
|
|
3edbef8696 | ||
|
|
5527f6386a | ||
|
|
c48f70a7c6 | ||
|
|
a078e31664 | ||
|
|
04d2d7dde1 | ||
|
|
b846053bea | ||
|
|
a1a5634c4e | ||
|
|
6036c6e4e3 | ||
|
|
7d74e6f325 | ||
|
|
1bf9f74bdf | ||
|
|
f61de5beeb | ||
|
|
79fb2d0bee | ||
|
|
c973d6819c | ||
|
|
3d8b879e64 | ||
|
|
ac971bda4b | ||
|
|
44f62abbca | ||
|
|
7d7d8484d4 | ||
|
|
c8b27492eb | ||
|
|
783f79dcb6 | ||
|
|
ddd97d5a9e | ||
|
|
fa73c3d6b1 | ||
|
|
5b2f3e9316 | ||
|
|
42f3025217 | ||
|
|
5df43b4d11 | ||
|
|
eac1bf197e | ||
|
|
5c834939af | ||
|
|
642e86951b | ||
|
|
bc42412e92 | ||
|
|
d9122d29cb | ||
|
|
b532ad994c | ||
|
|
b62fbc803c | ||
|
|
ed8bac8a1b | ||
|
|
d56142463a | ||
|
|
f795a356e7 | ||
|
|
a359c25e36 | ||
|
|
0ef422d309 | ||
|
|
e0519a4d7e | ||
|
|
5043ce5411 | ||
|
|
cc0cdc7d0e | ||
|
|
c004b3d333 | ||
|
|
453dd65cb1 | ||
|
|
b55cbe1992 | ||
|
|
b6e1b7b210 | ||
|
|
3685510d25 | ||
|
|
d7e685536c | ||
|
|
4df859a0ea | ||
|
|
7d1b84e837 | ||
|
|
be1f0be9b2 | ||
|
|
0f742900f5 | ||
|
|
e6f4fac859 | ||
|
|
d39faa1aca | ||
|
|
c3fe13d9dd | ||
|
|
90db381b5a | ||
|
|
508137da4b | ||
|
|
695ac7b29b | ||
|
|
c06df13a75 | ||
|
|
e663de3697 | ||
|
|
10b4f03ff5 | ||
|
|
c7a4434a0e | ||
|
|
1f8babd9e7 | ||
|
|
8e8fe906fd | ||
|
|
386d08a03f | ||
|
|
af38e1694b | ||
|
|
5609e004cc | ||
|
|
5be468308a | ||
|
|
39702abfba | ||
|
|
a97d86e801 | ||
|
|
75582539fe | ||
|
|
466723c55e | ||
|
|
6b3b2125df | ||
|
|
8c8d268708 | ||
|
|
73ac7273a0 | ||
|
|
dcafcdc6ce | ||
|
|
5b1405391e | ||
|
|
0993173b1f | ||
|
|
483ec2bf3e | ||
|
|
60fe272ba0 | ||
|
|
8df2e8190e | ||
|
|
66c8eb5ee8 | ||
|
|
bb65e76219 | ||
|
|
a585e29073 | ||
|
|
7655d0fd38 | ||
|
|
5bec640f20 | ||
|
|
62d9084ee8 | ||
|
|
df8ab39aa0 | ||
|
|
a7d3666811 | ||
|
|
ea9e3d2fe1 | ||
|
|
f14085f3ee | ||
|
|
e8b9db1df5 | ||
|
|
dc625997c4 | ||
|
|
4f458591e8 | ||
|
|
7a074d93cd | ||
|
|
9d1e1f6482 | ||
|
|
19153170bb | ||
|
|
6bf774c463 | ||
|
|
0de5ba77aa | ||
|
|
f4c0134d9c | ||
|
|
2c5c1b69b4 | ||
|
|
d34a33b691 | ||
|
|
869394c898 | ||
|
|
b97bde11b2 | ||
|
|
852cfa66e8 | ||
|
|
289fbba8e0 | ||
|
|
a6ffac657e | ||
|
|
096663ac91 | ||
|
|
d40a0c0837 | ||
|
|
f94b437852 | ||
|
|
7e571b038f | ||
|
|
56968c0bd2 | ||
|
|
ef6b85faec | ||
|
|
0d47fb4e68 | ||
|
|
8bfee8af16 | ||
|
|
0fc7276ccd | ||
|
|
9a596397ca | ||
|
|
1bea64bb6d | ||
|
|
09bfdc3d39 | ||
|
|
fe8b39691b | ||
|
|
1465bfdf15 | ||
|
|
bccbd67450 | ||
|
|
50a3b39666 | ||
|
|
087ba38c24 | ||
|
|
8a3c50ea1a | ||
|
|
86187e4c79 | ||
|
|
98c495abb1 | ||
|
|
c53c4fd9f8 | ||
|
|
b231705a67 | ||
|
|
86f94a2cb9 | ||
|
|
ef41e07550 | ||
|
|
255c72d3f1 | ||
|
|
260eedfcc6 | ||
|
|
f43cd117e3 | ||
|
|
83b219458f | ||
|
|
0f1b9369df | ||
|
|
b31e1c0d58 | ||
|
|
0122024789 | ||
|
|
f469536174 | ||
|
|
70bd8b26ad | ||
|
|
dabc4d88b3 | ||
|
|
214f90b366 | ||
|
|
3c4cc054df | ||
|
|
4d329287ce | ||
|
|
866714d75e | ||
|
|
b268d03e30 | ||
|
|
953d3b4135 | ||
|
|
0d6b347d7e | ||
|
|
a19622f6ac | ||
|
|
45c8737601 | ||
|
|
4925383f5e | ||
|
|
62ab985050 | ||
|
|
50f14f7658 | ||
|
|
1cd31079d7 | ||
|
|
46b62a9809 | ||
|
|
8f70a1dca4 | ||
|
|
937b62e641 | ||
|
|
3873342f6c | ||
|
|
717903a2b6 | ||
|
|
88030e301a | ||
|
|
cd0792e3d2 | ||
|
|
6ed2fcbf6c | ||
|
|
eb33515e29 | ||
|
|
bf93b86bd0 | ||
|
|
c41672c21a | ||
|
|
8716b073df | ||
|
|
638bab3c9d | ||
|
|
c5d7a8c740 | ||
|
|
b030be8f80 | ||
|
|
1fe19d1c3b | ||
|
|
1508e850fe | ||
|
|
81bc15d77c | ||
|
|
24adca55e4 | ||
|
|
9c8974a26e | ||
|
|
01e8984b79 | ||
|
|
7f1aa89539 | ||
|
|
4876fc0aa1 | ||
|
|
f998d20a86 | ||
|
|
cdb5faf043 | ||
|
|
dfaa2ff51e | ||
|
|
8754ff8147 | ||
|
|
cca84c3c21 | ||
|
|
72391f0201 | ||
|
|
39e26d738c | ||
|
|
f114424079 | ||
|
|
98b60f0564 | ||
|
|
d02b52f383 | ||
|
|
b52da434bb | ||
|
|
3cfa7a2767 | ||
|
|
054199d1e4 | ||
|
|
02b62a288d | ||
|
|
24908a8732 | ||
|
|
26ee7b7985 | ||
|
|
b76db48112 | ||
|
|
e2c5075319 | ||
|
|
e9f36e74ca | ||
|
|
0b73bd7b25 | ||
|
|
ccccab3104 | ||
|
|
ae8e32d806 | ||
|
|
fd2709affa | ||
|
|
34b3395d15 | ||
|
|
abdc80b756 | ||
|
|
492ac31973 | ||
|
|
3ac1878c3c | ||
|
|
0cc27355f7 | ||
|
|
562f761807 | ||
|
|
88e4b37c03 | ||
|
|
b73d88d6cf | ||
|
|
443c30d48c | ||
|
|
64cbf31184 | ||
|
|
ce9d9bd3ec | ||
|
|
57330784ac | ||
|
|
85e1c6fe54 | ||
|
|
7ca776bfab | ||
|
|
082c369d41 | ||
|
|
0ac9f41e1a | ||
|
|
16701d38a6 | ||
|
|
30eb280698 | ||
|
|
974a8096ca | ||
|
|
bb83a97613 | ||
|
|
8baae5e712 | ||
|
|
49e4c19cbb | ||
|
|
6f67628012 | ||
|
|
8a1573cc14 | ||
|
|
03b916ef8a | ||
|
|
9d25648c1f | ||
|
|
aa6c3df892 | ||
|
|
bdaa6e0db0 | ||
|
|
4740a39808 | ||
|
|
386c620b48 | ||
|
|
2441412714 | ||
|
|
9db940150a | ||
|
|
8c5639af53 | ||
|
|
b4a6f82f5f | ||
|
|
7dd62a4cf8 | ||
|
|
095ed7c2fd | ||
|
|
76567eea84 | ||
|
|
5a65fcd477 | ||
|
|
27b0e1a07a | ||
|
|
3e20e93797 | ||
|
|
5d3b1c3d0f | ||
|
|
b5a57e6dd9 | ||
|
|
2decf43b4c | ||
|
|
7dd3e2b27e | ||
|
|
325c91989c | ||
|
|
96250bafb1 | ||
|
|
fff795ce5a | ||
|
|
9887250407 | ||
|
|
e42191c6af | ||
|
|
adce44dc1f | ||
|
|
a70ee44466 | ||
|
|
fd0fa49f1c | ||
|
|
10491f9745 | ||
|
|
981313c0e2 | ||
|
|
6b88c9a004 | ||
|
|
25395b5006 | ||
|
|
2f516b49cf | ||
|
|
41ff26edc8 | ||
|
|
a1c6f586cf | ||
|
|
8b01126e0f | ||
|
|
e59d40af21 | ||
|
|
6b476bfab7 | ||
|
|
12429d4585 | ||
|
|
6fe2edbe89 | ||
|
|
cee6bd6abd | ||
|
|
4ac3350920 | ||
|
|
a45113258c | ||
|
|
4a2659573b | ||
|
|
c74080664f | ||
|
|
84e06395a5 | ||
|
|
411b85afcd | ||
|
|
57d128144d | ||
|
|
a7fa7e079b | ||
|
|
2781e413dc | ||
|
|
41d8daac97 | ||
|
|
dd22d55ee7 | ||
|
|
32a1bd2511 | ||
|
|
1130d20f14 | ||
|
|
90b17e995a | ||
|
|
1c41b0ec72 | ||
|
|
3f90605589 | ||
|
|
c1347fbb5d | ||
|
|
0d1cb2ee33 | ||
|
|
b6be297a1e | ||
|
|
b9b3cbee93 | ||
|
|
37d318b4d9 | ||
|
|
5368cfbcb8 | ||
|
|
72a4ba077c | ||
|
|
fba03625d0 | ||
|
|
007807e776 | ||
|
|
f2ae95d932 | ||
|
|
25d7323ed1 | ||
|
|
f7e737534d | ||
|
|
760c6b2814 | ||
|
|
d0f49ef8c7 | ||
|
|
1295b1fd35 | ||
|
|
eb8062d19b | ||
|
|
d82129d364 | ||
|
|
16923017b2 | ||
|
|
f4396e7e83 | ||
|
|
acee466fc8 | ||
|
|
862f24d8a7 | ||
|
|
e2cb033670 | ||
|
|
029c505501 | ||
|
|
dd5f0c52fb | ||
|
|
f80e64688e | ||
|
|
3fd34db3c1 | ||
|
|
0607d462d0 | ||
|
|
7f8c302405 | ||
|
|
c82c58443c | ||
|
|
9591be883f | ||
|
|
acdcd0c867 | ||
|
|
0f623521c4 | ||
|
|
91b93a3f48 | ||
|
|
32d123eb89 | ||
|
|
2025809d91 | ||
|
|
d552875e8a | ||
|
|
6994857f4b | ||
|
|
7ac941c1d0 | ||
|
|
af68778436 | ||
|
|
1ab11c46ba | ||
|
|
add355637d | ||
|
|
65380695f2 | ||
|
|
a6116ede02 | ||
|
|
dafa627e31 | ||
|
|
993115c8ae | ||
|
|
b97b3bc6d8 | ||
|
|
636294b6f5 | ||
|
|
37fe63126c | ||
|
|
9ace1d8201 | ||
|
|
25472887c9 | ||
|
|
5e7d2614b3 | ||
|
|
484246e146 | ||
|
|
65fb965f66 | ||
|
|
493d714723 | ||
|
|
a911e73238 | ||
|
|
dff133bbbc | ||
|
|
60d9c59544 | ||
|
|
185df737c8 | ||
|
|
a0b7d9969a | ||
|
|
3358eeb54c | ||
|
|
d32751ea5d | ||
|
|
8f637e02d0 | ||
|
|
e4ffd1df14 | ||
|
|
869bea2163 | ||
|
|
7e9919e3ae | ||
|
|
5afe67bd1b | ||
|
|
13f09d6059 | ||
|
|
1c9d2075d7 | ||
|
|
3a688c06a1 | ||
|
|
2d4b4d617d | ||
|
|
9fb23b45cd | ||
|
|
af7a3e99a8 | ||
|
|
992d892523 | ||
|
|
7699d8cf42 | ||
|
|
f81c9c2ca0 | ||
|
|
76351fe685 | ||
|
|
f0e8f18c6d | ||
|
|
880a3700d1 | ||
|
|
273f2ba8b0 | ||
|
|
a3507998f7 | ||
|
|
67d393a222 | ||
|
|
372248c819 | ||
|
|
b837489af0 | ||
|
|
e7223be040 | ||
|
|
e37743733d | ||
|
|
58a9b00120 | ||
|
|
d8a627f880 | ||
|
|
df46f86130 | ||
|
|
c98dd649eb | ||
|
|
da15a2d3bb | ||
|
|
00c87d7c80 | ||
|
|
7c8c285fb8 | ||
|
|
e0cf7af7a9 | ||
|
|
ed52efaa44 | ||
|
|
4a2aa02210 | ||
|
|
cc0dab3cd0 | ||
|
|
7b6e57b8dd | ||
|
|
325b2cc0a2 | ||
|
|
52f45e362b | ||
|
|
1391366ece | ||
|
|
40668581b8 | ||
|
|
261e448577 | ||
|
|
7c7cd7ef7e | ||
|
|
860226ab41 | ||
|
|
898b1ea1e6 | ||
|
|
f4d63c57e9 | ||
|
|
3aa64d107b | ||
|
|
0e3e733745 | ||
|
|
e6384de265 | ||
|
|
b9e8759ef1 | ||
|
|
ff5d498c53 | ||
|
|
a8820a0aac | ||
|
|
24c78519ed | ||
|
|
49c6febdf0 | ||
|
|
3d620d0149 | ||
|
|
352224b994 | ||
|
|
897b9e6919 | ||
|
|
1b579fb814 | ||
|
|
ab9020e7c7 | ||
|
|
54e116818b | ||
|
|
6a31ac916a | ||
|
|
f35a808975 | ||
|
|
b8ab38308d | ||
|
|
91d902389a | ||
|
|
5948c5c9a6 | ||
|
|
9a2c0729f6 | ||
|
|
c96d9c35a7 | ||
|
|
65e0b58be9 | ||
|
|
dad4b4cca8 | ||
|
|
3be02f1364 | ||
|
|
190dcfedc0 | ||
|
|
6e01c13e1c | ||
|
|
bb77450f2c | ||
|
|
4dfd4e4647 | ||
|
|
9a49700d09 | ||
|
|
107a8d8f90 | ||
|
|
b70b853016 | ||
|
|
dd2ed9f9a5 | ||
|
|
1a645f8521 | ||
|
|
c05cb63bc7 | ||
|
|
602ff26988 | ||
|
|
b7d6b6786c | ||
|
|
95c794c80d | ||
|
|
e59dd88f97 | ||
|
|
f31d1a137f | ||
|
|
b1d3924294 | ||
|
|
526a993698 | ||
|
|
f5d9a22f83 | ||
|
|
5ae3ef3a15 | ||
|
|
0773de2fc5 | ||
|
|
48a57c4244 | ||
|
|
9b1cba311e | ||
|
|
06000a6dac | ||
|
|
a54d4ba0c1 | ||
|
|
a7cc943b8e | ||
|
|
0314991f9e | ||
|
|
32d8f4384a | ||
|
|
d69b7807c1 | ||
|
|
dc32d92755 | ||
|
|
ca8fd2178d | ||
|
|
b565b72cd3 | ||
|
|
8d272e8862 | ||
|
|
dd7b50e0fa | ||
|
|
623e796c92 | ||
|
|
126f62ce59 | ||
|
|
77c149af04 | ||
|
|
b21f665760 | ||
|
|
be36c595c3 | ||
|
|
1ac6568f67 | ||
|
|
b902ab2a5f | ||
|
|
5069c3074b | ||
|
|
e0bd26d837 | ||
|
|
cc74686108 | ||
|
|
7880151ef2 | ||
|
|
cfa88b5ecf | ||
|
|
452a561309 | ||
|
|
2ac8f925c9 | ||
|
|
6cbded6241 | ||
|
|
f40b300c16 | ||
|
|
e473f158e8 | ||
|
|
408dcc5057 | ||
|
|
765775c54d | ||
|
|
44545f3d5b | ||
|
|
e23a1f615f | ||
|
|
d3fa3ecf6c | ||
|
|
6b1c3d9226 | ||
|
|
70d4976595 | ||
|
|
b2345039e4 | ||
|
|
33275573f9 | ||
|
|
9fdde1a13b | ||
|
|
09cc51e5de | ||
|
|
20e7f79f4f | ||
|
|
b82c3d9f99 | ||
|
|
dfd460c50b | ||
|
|
8adc79a5f7 | ||
|
|
2580be08ab | ||
|
|
fd9df69d1f | ||
|
|
d0b2e8d03f | ||
|
|
70998c424d | ||
|
|
abcdf880fd | ||
|
|
fac18b28f0 | ||
|
|
ee15329bd2 | ||
|
|
98e0ee92a7 | ||
|
|
54158b8824 | ||
|
|
75cd2f374a | ||
|
|
a78cc33cd1 | ||
|
|
fea425c36c | ||
|
|
61c89bca8d | ||
|
|
76e83de8cd | ||
|
|
c9d9350476 | ||
|
|
34a1eea45e | ||
|
|
c505884cf2 | ||
|
|
b95f517a4c | ||
|
|
50da7825bb | ||
|
|
0a3e3be12c | ||
|
|
c13d13ccf4 | ||
|
|
0317c3aaf5 | ||
|
|
03eaad5b8b | ||
|
|
e091603bc8 | ||
|
|
cd29c1728d | ||
|
|
65b86353e3 | ||
|
|
5f594d6bae | ||
|
|
bde8148eb1 | ||
|
|
ae34ff8f82 | ||
|
|
ef33508e2b | ||
|
|
a8c5f19075 | ||
|
|
1c046d9ddd | ||
|
|
6222765e20 | ||
|
|
f56839926e | ||
|
|
c6a52134b3 | ||
|
|
7fffcffcdd | ||
|
|
b0225d9bab |
@@ -0,0 +1,100 @@
|
|||||||
|
---
|
||||||
|
name: new-business-module
|
||||||
|
description: Scaffold a new single-table CRUD business module end to end — migration, Actions-mode model/dto/router, and the sys_menu/sys_api/casbin seed data that makes it show up in the UI with working permissions. Use when the user wants to add a new business table/module to go-admin, not for cross-table or non-CRUD business logic.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 新增业务模块
|
||||||
|
|
||||||
|
给一张新的业务表配齐"能跑、能看见、能授权"的完整闭环:迁移 → 后端代码 → 菜单与权限种子数据。
|
||||||
|
只适用于单表增删改查;跨表事务、外部调用、复杂校验等超出这个范围(见下方"何时不适用")。
|
||||||
|
|
||||||
|
开始前先读 `AGENTS.md`(分层边界、通用 Action 使用前提、命名规则)和 `app/demo/` 下的全部文件——
|
||||||
|
这是可编译、有测试、CI 会跑的参照物,本文与它冲突时以它为准。
|
||||||
|
|
||||||
|
## 何时不适用
|
||||||
|
|
||||||
|
业务超出单表 CRUD(跨表事务、外部服务调用、复杂校验)时,不要用这个 skill 硬套——
|
||||||
|
改成手写 Handler + Service,参照 `app/admin/apis/sys_post.go` 及其 Service,遵守
|
||||||
|
`AGENTS.md` 的分层约束(Api 不碰 Orm,Service 不碰 `gin.Context`,一律用 `e.Orm`)。
|
||||||
|
|
||||||
|
## 步骤
|
||||||
|
|
||||||
|
### 1. 确认表结构
|
||||||
|
|
||||||
|
表结构需符合命名规范:`sys_`/业务前缀 + 下划线(如 `tb_article`)。核对字段是否已有
|
||||||
|
`created_at`/`updated_at`/`deleted_at` 这类约定字段。
|
||||||
|
|
||||||
|
### 2. 写数据库迁移
|
||||||
|
|
||||||
|
放在 `cmd/migrate/migration/version/` 目录(**不是** `version-local/` —— 后者在
|
||||||
|
`.gitignore` 中,提交时会被忽略,`git status` 也看不到)。
|
||||||
|
|
||||||
|
- 文件名前 13 位是时间戳版本号
|
||||||
|
- 已执行过的迁移文件不可修改;需要修正时新增一个迁移
|
||||||
|
- 包名为 `version`
|
||||||
|
|
||||||
|
### 3. 生成 model / dto / router 三个文件(Actions 模式)
|
||||||
|
|
||||||
|
不要手写 Api 与 Service。使用 `common/actions` 的通用 Action,一个模块只需
|
||||||
|
model、dto、router 三个文件,完整写法照抄 `app/demo/` 的结构。
|
||||||
|
|
||||||
|
**关键正确性要求**(这三条是实际出问题最多的地方):
|
||||||
|
|
||||||
|
- Model 实现 `models.ActiveRecord`(`Generate` / `GetId` / `TableName`),
|
||||||
|
`TableName()` 必须显式声明——GORM 配置了 `SingularTable`,不会自动推导
|
||||||
|
- **`Generate()` 必须返回副本,不要就地返回**——Action 在并发请求间复用实例,
|
||||||
|
就地返回会导致请求之间串数据;这个问题单人测试时几乎不出现,上线后才暴露
|
||||||
|
- 完成后确认 `cmd/api/` 中已用 `_` 导入新包,否则路由不会被注册
|
||||||
|
|
||||||
|
### 4. 写菜单、接口与权限种子数据
|
||||||
|
|
||||||
|
这一步最容易被漏掉——代码能编译、接口能测通,但界面上看不到菜单、点了按钮说
|
||||||
|
没权限,往往就是漏了这一步。结构参照 `cmd/migrate/migration/version/1786700001000_demo_menu.go`
|
||||||
|
——它是可运行、幂等(用 `upsert`,重复跑不会报错)的真实例子。
|
||||||
|
|
||||||
|
:::danger
|
||||||
|
**但不要照抄它的 import。** 那个文件用的是 `cmd/migrate/migration/models`,
|
||||||
|
只因为它的版本号排在软删除转换(`1786700003000`)之前才是安全的。
|
||||||
|
|
||||||
|
**你新写的迁移版本号在转换之后,必须改用 `app/` 下的运行时模型**
|
||||||
|
(`app/admin/models.SysApi`、`SysMenu`),否则第一条 insert 就会
|
||||||
|
`NOT NULL constraint failed: sys_api.deleted_at`。
|
||||||
|
`TestPostConversionMigrationsAvoidFrozenSeedModels` 会拦住这个错误。
|
||||||
|
:::
|
||||||
|
|
||||||
|
一个模块要在界面上可用,需要四类数据,缺一样都不行:
|
||||||
|
|
||||||
|
| 表 | 作用 |
|
||||||
|
|---|---|
|
||||||
|
| `sys_api` | 后端路由登记,Casbin 据此判定权限 |
|
||||||
|
| `sys_menu` | 侧边栏菜单(目录用 `M`、菜单用 `C`、按钮用 `F`) |
|
||||||
|
| `sys_menu_api_rule` | 菜单与接口的多对多关联,角色保存时据此生成策略 |
|
||||||
|
| `casbin_rule` | 实际生效的权限策略(**不是** `sys_casbin_rule`,那张表的唯一索引在 MySQL 下会超长,不要迁移它) |
|
||||||
|
|
||||||
|
必须核对的两处一致性——**错了不会报错,只会在界面上表现为"看不到/点不动"**:
|
||||||
|
|
||||||
|
- `sys_menu.menu_name` 必须与前端组件的 `defineOptions({ name: 'XxxManage' })` 一致,
|
||||||
|
否则 `keep-alive` 缓存静默失效
|
||||||
|
- 按钮级 `sys_menu.permission`(格式 `模块:资源:操作`)必须与前端
|
||||||
|
`v-permisaction="['模块:资源:操作']"` 完全一致,否则按钮权限判断静默失效
|
||||||
|
|
||||||
|
### 5. 收尾检查
|
||||||
|
|
||||||
|
| 检查项 | 出错后果 |
|
||||||
|
| --- | --- |
|
||||||
|
| `Generate()` 是否返回副本 | 并发请求之间串数据 |
|
||||||
|
| 是否使用 `e.Orm` 而非全局 DB | 多租户下拿到错误的数据库连接 |
|
||||||
|
| `TableName()` 是否显式声明 | GORM 不会自动推导 |
|
||||||
|
| 迁移文件是否放在 `version/` | 放进 `version-local/` 会被忽略,别人拉代码看不到 |
|
||||||
|
| `sys_menu.menu_name` 是否与前端组件 `name` 一致 | keep-alive 缓存静默失效 |
|
||||||
|
| `sys_menu.permission` 是否与前端 `v-permisaction` 一致 | 按钮权限静默失效 |
|
||||||
|
|
||||||
|
跑一遍 `go run -tags sqlite3 . migrate -c config/settings.sqlite.yml` 验证迁移可执行,
|
||||||
|
再 `go run -tags sqlite3 . server -c config/settings.sqlite.yml` 启动服务,用 admin
|
||||||
|
账号登录确认新菜单和按钮权限都出现了。
|
||||||
|
|
||||||
|
如果前端页面还没生成,下一步用 go-admin-ui 仓库里的 `new-list-page` skill——两边靠
|
||||||
|
`sys_menu.permission` / `v-permisaction` 这个字符串对齐。
|
||||||
|
|
||||||
|
> 不要把 `config/settings.yml` 的真实内容贴给 AI 工具——`database.source` 含数据库
|
||||||
|
> 账号密码,`jwt.secret` 泄露后可被用来伪造任意用户的 token。
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: true
|
||||||
|
contact_links:
|
||||||
|
- name: 🆕 Create new issue
|
||||||
|
url: http://new-issue.go-admin.dev
|
||||||
|
about: The issue which is not created via http://new-issue.go-admin.dev will be closed immediately.
|
||||||
|
- name: 🆕 创建一个新 Issue
|
||||||
|
url: http://new-issue.go-admin.dev
|
||||||
|
about: 不是用 http://new-issue.go-admin.dev 创建的 issue 会被机器人自动关闭。
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<!--
|
||||||
|
First of all, thank you for your contribution! 😄
|
||||||
|
|
||||||
|
For requesting to pull a new feature or bugfix, please send it from a feature/bugfix branch based on the `master` branch.
|
||||||
|
|
||||||
|
Before submitting your pull request, please make sure the checklist below is confirmed.
|
||||||
|
|
||||||
|
Your pull requests will be merged after one of the collaborators approve.
|
||||||
|
|
||||||
|
Thank you!
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
[[中文版模板 / Chinese template](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE/pr_cn.md)]
|
||||||
|
|
||||||
|
### 🤔 This is a ...
|
||||||
|
|
||||||
|
- [ ] New feature
|
||||||
|
- [ ] Bug fix
|
||||||
|
- [ ] Site / documentation update
|
||||||
|
- [ ] Demo update
|
||||||
|
- [ ] Component style update
|
||||||
|
- [ ] TypeScript definition update
|
||||||
|
- [ ] Bundle size optimization
|
||||||
|
- [ ] Performance optimization
|
||||||
|
- [ ] Enhancement feature
|
||||||
|
- [ ] Internationalization
|
||||||
|
- [ ] Refactoring
|
||||||
|
- [ ] Code style optimization
|
||||||
|
- [ ] Test Case
|
||||||
|
- [ ] Branch merge
|
||||||
|
- [ ] Other (about what?)
|
||||||
|
|
||||||
|
### 🔗 Related issue link
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. Put the related issue or discussion links here.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### 💡 Background and solution
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. Describe the problem and the scenario.
|
||||||
|
2. GIF or snapshot should be provided if includes UI/interactive modification.
|
||||||
|
3. How to fix the problem, and list the final API implementation and usage sample if that is a new feature.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### 📝 Changelog
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Describe changes from the user side, and list all potential break changes or other risks.
|
||||||
|
--->
|
||||||
|
|
||||||
|
| Language | Changelog |
|
||||||
|
| ---------- | --------- |
|
||||||
|
| 🇺🇸 English | |
|
||||||
|
| 🇨🇳 Chinese | |
|
||||||
|
|
||||||
|
### ☑️ Self-Check before Merge
|
||||||
|
|
||||||
|
⚠️ Please check all items below before review. ⚠️
|
||||||
|
|
||||||
|
- [ ] Doc is updated/provided or not needed
|
||||||
|
- [ ] Demo is updated/provided or not needed
|
||||||
|
- [ ] TypeScript's definition is updated/provided or not needed
|
||||||
|
- [ ] Changelog is provided or not needed
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<!--
|
||||||
|
首先,感谢你的贡献!😄
|
||||||
|
|
||||||
|
新特性请提交至 feature 分支,其余可提交至 master 分支。
|
||||||
|
在维护者审核通过后会合并。
|
||||||
|
请确保填写以下 pull request 的信息,谢谢!~
|
||||||
|
-->
|
||||||
|
|
||||||
|
[[English Template / 英文模板](https://github.com/go-admin-team/go-admin/blob/master/.github/PULL_REQUEST_TEMPLATE.md)]
|
||||||
|
|
||||||
|
### 🤔 这个变动的性质是?
|
||||||
|
|
||||||
|
- [ ] 新特性提交
|
||||||
|
- [ ] 日常 bug 修复
|
||||||
|
- [ ] 站点、文档改进
|
||||||
|
- [ ] 演示代码改进
|
||||||
|
- [ ] 组件样式/交互改进
|
||||||
|
- [ ] TypeScript 定义更新
|
||||||
|
- [ ] 包体积优化
|
||||||
|
- [ ] 性能优化
|
||||||
|
- [ ] 功能增强
|
||||||
|
- [ ] 国际化改进
|
||||||
|
- [ ] 重构
|
||||||
|
- [ ] 代码风格优化
|
||||||
|
- [ ] 测试用例
|
||||||
|
- [ ] 分支合并
|
||||||
|
- [ ] 其他改动(是关于什么的改动?)
|
||||||
|
|
||||||
|
### 🔗 相关 Issue
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. 描述相关需求的来源,如相关的 issue 讨论链接。
|
||||||
|
-->
|
||||||
|
|
||||||
|
### 💡 需求背景和解决方案
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. 要解决的具体问题。
|
||||||
|
2. 列出最终的 API 实现和用法。
|
||||||
|
3. 涉及UI/交互变动需要有截图或 GIF。
|
||||||
|
-->
|
||||||
|
|
||||||
|
### 📝 更新日志
|
||||||
|
|
||||||
|
<!--
|
||||||
|
从用户角度描述具体变化,以及可能的 breaking change 和其他风险。
|
||||||
|
-->
|
||||||
|
|
||||||
|
| 语言 | 更新描述 |
|
||||||
|
| ------- | -------- |
|
||||||
|
| 🇺🇸 英文 | |
|
||||||
|
| 🇨🇳 中文 | |
|
||||||
|
|
||||||
|
### ☑️ 请求合并前的自查清单
|
||||||
|
|
||||||
|
⚠️ 请自检并全部**勾选全部选项**。⚠️
|
||||||
|
|
||||||
|
- [ ] 文档已补充或无须补充
|
||||||
|
- [ ] 代码演示已提供或无须提供
|
||||||
|
- [ ] TypeScript 定义已补充或无须补充
|
||||||
|
- [ ] Changelog 已提供或无须提供
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
# Documentation-only changes, and changes confined to the Kubernetes
|
||||||
|
# manifests, skip this workflow entirely.
|
||||||
|
#
|
||||||
|
# A push to master here does not just build - it pushes an image, runs the
|
||||||
|
# migrations and restarts the demo container, so the site takes a short outage.
|
||||||
|
# Paying that for a README edit is waste at best; at worst a deploy fails for a
|
||||||
|
# reason unrelated to anything in the change. Code coverage is unaffected,
|
||||||
|
# because go.yml still builds every push and pull request.
|
||||||
|
#
|
||||||
|
# scripts/k8s holds deploy.yml, storage.yml and prerun.sh, and the deploy below
|
||||||
|
# reads none of them - it is an ssh into one host that runs docker, building the
|
||||||
|
# Dockerfile at the repository root. Those manifests are for people deploying to
|
||||||
|
# a cluster of their own. The pattern is scripts/k8s/** rather than scripts/**
|
||||||
|
# because scripts/Dockerfile is a build input: go.yml builds the release image
|
||||||
|
# from it on a tag.
|
||||||
|
#
|
||||||
|
# A file outside these patterns still runs the workflow even when the rest of
|
||||||
|
# the change is ignorable: paths-ignore skips only when every changed path
|
||||||
|
# matches. Editing this file is one such case, on purpose - a deploy script
|
||||||
|
# that is never exercised by the change that broke it is worse than an outage.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'docs/**'
|
||||||
|
- 'LICENSE*'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
|
- 'scripts/k8s/**'
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'docs/**'
|
||||||
|
- 'LICENSE*'
|
||||||
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
|
- 'scripts/k8s/**'
|
||||||
|
|
||||||
|
# One deploy at a time. Two merges seconds apart raced here: both runs did
|
||||||
|
# docker rm -f then docker run, the second removed the container the first had
|
||||||
|
# just created, and the first's docker run then failed on a name conflict -
|
||||||
|
# leaving the demo on the older image with a red deploy.
|
||||||
|
concurrency:
|
||||||
|
group: deploy-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api # 镜像名称
|
||||||
|
TAG: ${{ github.sha }}
|
||||||
|
IMAGE_NAME_TAG: registry.ap-northeast-1.aliyuncs.com/go-admin/go-admin-api:${{ github.sha }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
||||||
|
with:
|
||||||
|
go-version: 1.26.5
|
||||||
|
|
||||||
|
- name: Tidy
|
||||||
|
run: go mod tidy
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags "sqlite3,json1" --ldflags "-extldflags -static" -o main .
|
||||||
|
|
||||||
|
# 以下推镜像与重启步骤仅在 master 收到 push 时执行。
|
||||||
|
# pull_request 事件同样会触发本工作流,若不加限制,任何指向 master 的
|
||||||
|
# PR 一经创建就会把 PR 分支的镜像推上仓库,并直接重启线上 API 服务,
|
||||||
|
# 且发生在合并之前。构建与编译校验不受影响,PR 仍会执行。
|
||||||
|
- name: Build the Docker image and push
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
echo "************ docker login end"
|
||||||
|
docker build -t go-admin-api:latest .
|
||||||
|
echo "************ docker build end"
|
||||||
|
docker tag go-admin-api ${{ env.IMAGE_NAME_TAG }}
|
||||||
|
echo "************ docker tag end"
|
||||||
|
docker images
|
||||||
|
echo "************ docker images end"
|
||||||
|
docker push ${{ env.IMAGE_NAME_TAG }} # 推送
|
||||||
|
echo "************ docker push end"
|
||||||
|
|
||||||
|
- name: Restart server # 第五步,重启服务
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||||
|
uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5
|
||||||
|
env:
|
||||||
|
GITHUB_SHA_X: ${GITHUB_SHA}
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }} # 下面三个配置与上一步类似
|
||||||
|
username: ${{ secrets.SSH_USERNAME }}
|
||||||
|
key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
# 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
|
||||||
|
#
|
||||||
|
# 配置从宿主机挂载,不使用镜像里的那份:演示站连的是托管数据库,
|
||||||
|
# 而 config/settings.demo.yml 会随仓库公开、也会打进镜像,凭据不能写在那里。
|
||||||
|
# 镜像里那份保持 sqlite,供 clone 仓库的人开箱即用。
|
||||||
|
#
|
||||||
|
# 路径本身走 secret:它不是凭据,但本仓库公开,没有理由把服务器的
|
||||||
|
# 目录结构一并公布。DEMO_CONFIG_PATH 指向宿主机上那份配置。
|
||||||
|
#
|
||||||
|
# 顺序是有意的:迁移先跑,跑不过就保持现有版本不动;
|
||||||
|
# 旧容器改名保留而不是删除,新容器不健康时能原样恢复。
|
||||||
|
# 健康检查两条都要过——HTTP 活着不代表数据库通了。
|
||||||
|
script: |
|
||||||
|
set -u
|
||||||
|
CFG="${{ secrets.DEMO_CONFIG_PATH }}"
|
||||||
|
IMG="${{ env.IMAGE_NAME_TAG }}"
|
||||||
|
NAME=go-admin-api
|
||||||
|
PREV="$NAME-prev"
|
||||||
|
|
||||||
|
test -f "$CFG" || { echo "宿主机配置缺失,中止部署"; exit 1; }
|
||||||
|
|
||||||
|
# Old images of this repository are removed here and nowhere else.
|
||||||
|
# Every deployment pulls one tagged with its commit and nothing ever
|
||||||
|
# removed the previous one, so they only accumulated: 68 of them
|
||||||
|
# filled the disk and the next deployment could not pull.
|
||||||
|
#
|
||||||
|
# Three are kept so a release can be re-run by tag by hand.
|
||||||
|
#
|
||||||
|
# Only this repository's images are listed, because the host runs
|
||||||
|
# other services whose images are not this script's business. The
|
||||||
|
# image the live container is on is excluded by id rather than by
|
||||||
|
# position, so it survives even if the listing order is not what
|
||||||
|
# it looks like. With no container to ask, the function returns
|
||||||
|
# rather than running the pipeline on an empty id - which would
|
||||||
|
# also delete nothing, but by way of grep -v matching every line,
|
||||||
|
# which reads like the opposite of what it does. No -f, so an image
|
||||||
|
# any container still holds - including the one kept for rollback -
|
||||||
|
# is refused rather than taken away from it.
|
||||||
|
prune_old_images() {
|
||||||
|
REPO="${IMG%:*}"
|
||||||
|
LIVE=$(sudo docker inspect -f '{{.Image}}' "$NAME" 2>/dev/null | sed 's/^sha256://' | cut -c1-12)
|
||||||
|
[ -n "$LIVE" ] || return 0
|
||||||
|
sudo docker images "$REPO" --format '{{.ID}} {{.Repository}}:{{.Tag}}' \
|
||||||
|
| grep -v "^$LIVE" \
|
||||||
|
| tail -n +3 \
|
||||||
|
| awk '{print $2}' \
|
||||||
|
| xargs -r -n1 sudo docker rmi >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
sudo docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
# Before the pull, not only after a successful deploy. The pull
|
||||||
|
# is the first thing here that needs space and it is where a full
|
||||||
|
# disk stops this script, so a cleanup that only runs afterwards
|
||||||
|
# never runs on the host that needs it: rerunning the workflow
|
||||||
|
# fails at the same pull, and the disk has to be cleared by hand.
|
||||||
|
prune_old_images
|
||||||
|
sudo docker pull "$IMG" || { echo "拉取镜像失败,中止部署"; exit 1; }
|
||||||
|
|
||||||
|
# 迁移用新镜像跑。失败时线上仍是旧版本配旧 schema,是自洽的;
|
||||||
|
# 硬切过去才会得到代码与表对不上的服务。
|
||||||
|
if ! sudo docker run --rm -v "$CFG":/config/settings.yml:ro "$IMG" \
|
||||||
|
/main migrate -c /config/settings.yml; then
|
||||||
|
echo "迁移失败,保持现有版本"; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if sudo docker ps -a --format '{{.Names}}' | grep -qx "$NAME"; then
|
||||||
|
sudo docker rm -f "$PREV" >/dev/null 2>&1 || true
|
||||||
|
sudo docker rename "$NAME" "$PREV"
|
||||||
|
# --timeout, because the default is 10 seconds and the process
|
||||||
|
# spends drain + server + cleanup from extend.shutdown before it
|
||||||
|
# exits - 8 seconds out of the box, and more for anyone who
|
||||||
|
# configures a drain window. Past the deadline docker sends
|
||||||
|
# SIGKILL and the cleanup callbacks are cut off part-way through.
|
||||||
|
# checksilent's docker-stop-cuts-shutdown-short check compares
|
||||||
|
# this number against config/settings.yml.
|
||||||
|
sudo docker stop --timeout 30 "$PREV" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo docker run -d -p 8000:8000 \
|
||||||
|
-v "$CFG":/config/settings.yml:ro \
|
||||||
|
--name "$NAME" "$IMG"
|
||||||
|
|
||||||
|
ok=0
|
||||||
|
for i in $(seq 1 20); do
|
||||||
|
sleep 3
|
||||||
|
code=$(curl -s -o /dev/null -w '%{http_code}' -m 5 http://127.0.0.1:8000/api/v1/captcha 2>/dev/null || true)
|
||||||
|
if [ "$code" = "200" ] && sudo docker logs "$NAME" 2>&1 | grep -q 'connect success'; then
|
||||||
|
ok=1; echo "健康检查通过(第 $i 次探测)"; break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$ok" = "1" ]; then
|
||||||
|
sudo docker rm -f "$PREV" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Again, so the image this deployment replaced falls out of the
|
||||||
|
# window rather than waiting for the next deployment to notice.
|
||||||
|
prune_old_images
|
||||||
|
else
|
||||||
|
echo "健康检查失败,回滚到上一版本"
|
||||||
|
sudo docker logs --tail 40 "$NAME" 2>&1 || true
|
||||||
|
sudo docker rm -f "$NAME" >/dev/null 2>&1 || true
|
||||||
|
if sudo docker ps -a --format '{{.Names}}' | grep -qx "$PREV"; then
|
||||||
|
sudo docker rename "$PREV" "$NAME"
|
||||||
|
sudo docker start "$NAME" >/dev/null
|
||||||
|
echo "已恢复"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -19,11 +19,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v1
|
uses: github/codeql-action/init@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v1
|
uses: github/codeql-action/autobuild@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -48,4 +48,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v1
|
uses: github/codeql-action/analyze@24c7eb380a2dc368f2d129e4c65e51d172983a1e # v4
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
name: build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ dev-lwx ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ dev-lwx ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Set up Go 1.15
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.15
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Get 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
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin .
|
|
||||||
mv go-admin ./scripts
|
|
||||||
|
|
||||||
- uses: Azure/docker-login@v1
|
|
||||||
with:
|
|
||||||
login-server: registry.cn-shanghai.aliyuncs.com
|
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
||||||
- run: |
|
|
||||||
docker build ./scripts -t registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}
|
|
||||||
docker push registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}
|
|
||||||
- uses: Azure/k8s-set-context@v1
|
|
||||||
with:
|
|
||||||
kubeconfig: ${{ secrets.KUBE_CONFIG }}
|
|
||||||
|
|
||||||
- uses: Azure/k8s-create-secret@v1
|
|
||||||
with:
|
|
||||||
namespace: 'go-admin'
|
|
||||||
container-registry-url: registry.cn-shanghai.aliyuncs.com
|
|
||||||
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
|
|
||||||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
|
|
||||||
secret-name: aliyuncs-k8s-secret
|
|
||||||
|
|
||||||
- uses: Azure/k8s-deploy@v1
|
|
||||||
with:
|
|
||||||
namespace: 'go-admin'
|
|
||||||
manifests: 'scripts/k8s/deploy.yml'
|
|
||||||
images: 'registry.cn-shanghai.aliyuncs.com/go-admin-team/go-admin:${{ github.sha }}'
|
|
||||||
imagepullsecrets: 'aliyuncs-k8s-secret'
|
|
||||||
kubectl-version: 'latest'
|
|
||||||
+172
-12
@@ -2,33 +2,193 @@ name: build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master, dev ]
|
||||||
|
tags: [ 'v*', '[0-9]*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# The queue's ordering rule - consumers registered before the queue is
|
||||||
|
# started - is invisible on the memory backend, which is the default and
|
||||||
|
# therefore what every other test runs on: queue.Memory's Register starts a
|
||||||
|
# consumer goroutine whatever the state. Only redis refuses a late
|
||||||
|
# registration, so without a server here the tests that cover it would skip
|
||||||
|
# and the suite would report success for a queue that accepts no consumers.
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
options: >-
|
||||||
|
--health-cmd "redis-cli ping"
|
||||||
|
--health-interval 5s
|
||||||
|
--health-timeout 3s
|
||||||
|
--health-retries 10
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: goadmin_test
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U postgres"
|
||||||
|
--health-interval 5s
|
||||||
|
--health-timeout 3s
|
||||||
|
--health-retries 10
|
||||||
|
|
||||||
|
# The fourth registered driver, and the one that disagrees with the
|
||||||
|
# other three about NULL: its unique index treats two NULLs as equal and
|
||||||
|
# permits one. A migration that builds a unique index over a nullable
|
||||||
|
# column therefore fails here and nowhere else, which is how one shipped
|
||||||
|
# that no SQL Server database could apply at all - not even an empty
|
||||||
|
# one. The password is this container's only credential and the
|
||||||
|
# container lives for the length of one job.
|
||||||
|
sqlserver:
|
||||||
|
image: mcr.microsoft.com/mssql/server:2022-latest
|
||||||
|
env:
|
||||||
|
ACCEPT_EULA: "Y"
|
||||||
|
MSSQL_SA_PASSWORD: GoAdmin_Test1
|
||||||
|
MSSQL_PID: Developer
|
||||||
|
ports:
|
||||||
|
- 1433:1433
|
||||||
|
options: >-
|
||||||
|
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P GoAdmin_Test1 -C -Q 'SELECT 1'"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 20
|
||||||
|
--health-start-period 20s
|
||||||
|
|
||||||
|
# The dialect most installations actually run, and until the
|
||||||
|
# scheduler lease (#915) the only one with no service here. The lease
|
||||||
|
# reads the database's clock, and the first implementation read it as
|
||||||
|
# a timestamp: over go-admin's own `parseTime=True&loc=Local` DSN,
|
||||||
|
# MySQL's UTC_TIMESTAMP comes back relabelled as local time, so on any
|
||||||
|
# host that is not UTC every lease was one zone offset out - and every
|
||||||
|
# assertion that compared the lease only against itself still passed.
|
||||||
|
# The three dialects that were here could not see it.
|
||||||
|
mysql:
|
||||||
|
image: mysql:8
|
||||||
|
env:
|
||||||
|
MYSQL_ROOT_PASSWORD: GoAdmin_Test1
|
||||||
|
MYSQL_DATABASE: goadmin_test
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
options: >-
|
||||||
|
--health-cmd "mysqladmin ping -h 127.0.0.1 -uroot -pGoAdmin_Test1"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 20
|
||||||
|
--health-start-period 20s
|
||||||
|
|
||||||
|
env:
|
||||||
|
GO_ADMIN_TEST_REDIS_ADDR: 127.0.0.1:6379
|
||||||
|
# The soft-delete conversion drops an index, and gorm's PostgreSQL driver
|
||||||
|
# produced unparseable SQL for that - on SQLite, where the rest of these
|
||||||
|
# tests run, the same code works. The suite reported success for a
|
||||||
|
# migration that failed on every PostgreSQL database it was pointed at.
|
||||||
|
# See go-admin#919.
|
||||||
|
GO_ADMIN_TEST_POSTGRES_DSN: "host=127.0.0.1 port=5432 user=postgres password=postgres dbname=goadmin_test sslmode=disable"
|
||||||
|
GO_ADMIN_TEST_SQLSERVER_DSN: "sqlserver://sa:GoAdmin_Test1@127.0.0.1:1433?database=goadmin_test"
|
||||||
|
# loc=Local on purpose: it is what config/settings.yml ships and what
|
||||||
|
# made the timezone defect above reachable. A DSN here that quietly
|
||||||
|
# differed from the one installations use would test a configuration
|
||||||
|
# nobody runs.
|
||||||
|
GO_ADMIN_TEST_MYSQL_DSN: "root:GoAdmin_Test1@tcp(127.0.0.1:3306)/goadmin_test?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Set up Go 1.14
|
- name: Set up Go 1.26
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
||||||
with:
|
with:
|
||||||
go-version: 1.14
|
go-version: 1.26.5
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
|
# SQL Server has no equivalent of POSTGRES_DB, so the database the DSN
|
||||||
|
# names has to be created before the tests run.
|
||||||
|
- name: Create the SQL Server test database
|
||||||
|
run: |
|
||||||
|
docker exec ${{ job.services.sqlserver.id }} /opt/mssql-tools18/bin/sqlcmd \
|
||||||
|
-S localhost -U sa -P GoAdmin_Test1 -C \
|
||||||
|
-Q "IF DB_ID('goadmin_test') IS NULL CREATE DATABASE goadmin_test"
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: |
|
run: go mod tidy
|
||||||
go get -v -t -d ./...
|
|
||||||
if [ -f Gopkg.toml ]; then
|
# Before the tests rather than beside checksilent at the end: a formatting
|
||||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
# miss is a one-command fix, and finding out about it after five minutes of
|
||||||
dep ensure
|
# tests and an end-to-end install is five minutes nobody gets back.
|
||||||
fi
|
- name: Formatting
|
||||||
|
run: make fmt-check
|
||||||
|
|
||||||
|
# go build does not compile _test.go, so building alone never ran a single
|
||||||
|
# test. This is the only workflow that fires on every push and pull request,
|
||||||
|
# which makes it the one place a test gate belongs.
|
||||||
|
- name: Test
|
||||||
|
run: make test
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: go build -v .
|
run: make build
|
||||||
|
|
||||||
|
# A separate module, so none of the steps above see it: the main module's
|
||||||
|
# go.mod, its build and its tests are all unaware of the example
|
||||||
|
# application. This is the only thing that exercises an application being
|
||||||
|
# installed at all - everything below it runs against an injected engine
|
||||||
|
# and a hand-built schema, and none of that can catch an application's
|
||||||
|
# init() reaching one registry and not the other.
|
||||||
|
- name: End-to-end install and uninstall
|
||||||
|
run: make test-e2e
|
||||||
|
|
||||||
|
# Fails the build on the silent-failure classes listed in
|
||||||
|
# tools/checksilent, one of which is the contract boundary: nothing under
|
||||||
|
# common/ may import app/. A boundary that is only written down erodes; this
|
||||||
|
# is what keeps it true.
|
||||||
|
- name: Silent-failure checks
|
||||||
|
run: make checksilent
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
tags: |
|
||||||
|
type=schedule
|
||||||
|
type=ref,event=tag
|
||||||
|
type=sha,prefix=,format=long,enable=true,priority=100
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: scripts/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|||||||
+24
-6
@@ -1,15 +1,19 @@
|
|||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
*/.DS_Store
|
.DS_Store
|
||||||
static/uploadfile
|
static/uploadfile
|
||||||
main.exe
|
main.exe
|
||||||
|
*.exe
|
||||||
go-admin
|
go-admin
|
||||||
|
go-admin.exe
|
||||||
|
# `go build ./tools/checksilent` drops the binary here, next to the one for the
|
||||||
|
# server. Anchored with a leading slash: unanchored, the same pattern matches
|
||||||
|
# tools/checksilent/ as well and the tool's own source never gets committed.
|
||||||
|
/checksilent
|
||||||
temp/
|
temp/
|
||||||
!temp
|
!temp
|
||||||
vendor
|
vendor
|
||||||
config/settings.dev.yml
|
config/settings.dev.yml
|
||||||
go-admin
|
|
||||||
common/middleware/demo.go
|
|
||||||
config/settings.dev.*.yml
|
config/settings.dev.*.yml
|
||||||
config/settings.dev.*.yml.log
|
config/settings.dev.*.yml.log
|
||||||
temp/logs
|
temp/logs
|
||||||
@@ -17,8 +21,22 @@ config/settings.dev.yml.log
|
|||||||
config/settings.b.dev.yml
|
config/settings.b.dev.yml
|
||||||
cmd/migrate/migration/version-local/*
|
cmd/migrate/migration/version-local/*
|
||||||
!cmd/migrate/migration/version-local/doc.go
|
!cmd/migrate/migration/version-local/doc.go
|
||||||
*/.DS_Store
|
|
||||||
|
|
||||||
# go sum
|
|
||||||
go.sum
|
|
||||||
config/settings.deva.yml
|
config/settings.deva.yml
|
||||||
|
go-admin-server
|
||||||
|
CLAUDE.md
|
||||||
|
# Everything under .claude is private by default. Skills meant for people using
|
||||||
|
# go-admin are re-included one directory at a time, so a personal one dropped in
|
||||||
|
# here is never committed by accident.
|
||||||
|
.claude/*
|
||||||
|
!.claude/skills/
|
||||||
|
.claude/skills/*
|
||||||
|
!.claude/skills/new-business-module/
|
||||||
|
config/settings.local.dev.yml
|
||||||
|
|
||||||
|
# Go workspace files. They exist to point this module at a local checkout of
|
||||||
|
# go-admin-core while the two are developed together, which is a private
|
||||||
|
# arrangement between one machine's directories - committing one would break
|
||||||
|
# the build for everyone else.
|
||||||
|
go.work
|
||||||
|
go.work.sum
|
||||||
|
|||||||
@@ -0,0 +1,273 @@
|
|||||||
|
# AGENTS.md — go-admin 后端
|
||||||
|
|
||||||
|
> 给 AI 编码工具与新贡献者的约定。**只写"不遵守就会出错"的规则**;技术栈版本以
|
||||||
|
> `go.mod` 为准,命令以 `Makefile` 为准,此处不复述,避免与代码脱节。
|
||||||
|
>
|
||||||
|
> 标准 CRUD 模块的完整写法见 **`app/demo/`** —— 那是可编译、有测试、CI 会跑的参照物。
|
||||||
|
> 本文与它冲突时,以 `app/demo/` 为准。
|
||||||
|
|
||||||
|
## 分层
|
||||||
|
|
||||||
|
```
|
||||||
|
Router → Api → Service → Model
|
||||||
|
路由注册 参数绑定 业务逻辑 GORM 结构体
|
||||||
|
中间件链 调用 Service 操作数据库 TableName()
|
||||||
|
```
|
||||||
|
|
||||||
|
对应目录:`app/{模块}/router|apis|service|models`,DTO 位于 `service/dto`。
|
||||||
|
|
||||||
|
**不可跨层**:Api 不直接操作 `Orm`,Service 不接触 `gin.Context`。
|
||||||
|
|
||||||
|
## 优先使用通用 Action
|
||||||
|
|
||||||
|
单表 CRUD **不要手写 Api 与 Service**。`common/actions` 提供的五个
|
||||||
|
Action 已覆盖参数绑定、数据权限过滤、操作人注入、分页与错误响应:
|
||||||
|
|
||||||
|
```go
|
||||||
|
r := v1.Group("/demo-product").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
|
{
|
||||||
|
m := &models.DemoProduct{}
|
||||||
|
r.GET("", actions.PermissionAction(), actions.IndexAction(m, new(dto.DemoProductSearch), func() interface{} {
|
||||||
|
list := make([]models.DemoProduct, 0); return &list
|
||||||
|
}))
|
||||||
|
r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.DemoProductById), func() interface{} {
|
||||||
|
return &models.DemoProduct{}
|
||||||
|
}))
|
||||||
|
r.POST("", actions.CreateAction(new(dto.DemoProductControl)))
|
||||||
|
r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.DemoProductControl)))
|
||||||
|
r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.DemoProductById)))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这样一个模块只需 **model + dto + router** 三个文件,完整示例见 `app/demo/`。
|
||||||
|
|
||||||
|
使用通用 Action 的前提:
|
||||||
|
|
||||||
|
- Model 实现 `models.ActiveRecord`(`Generate` / `GetId` / `TableName`)
|
||||||
|
- 列表 DTO 实现 `dto.Index`,增改删 DTO 实现 `dto.Control`
|
||||||
|
- **所有 `Generate()` 必须返回副本** —— Action 在并发请求间复用实例,
|
||||||
|
就地返回会串数据(`app/demo` 的测试锁定了这一点)
|
||||||
|
- 详情/删除 DTO 内嵌 `dto.ObjectById` 即可继承 `Bind` 与 `GetId`,无需重写
|
||||||
|
|
||||||
|
仅当业务超出单表 CRUD(跨表事务、外部调用、复杂校验)时才自行编写 Api
|
||||||
|
与 Service,写法见下。
|
||||||
|
|
||||||
|
## Api 层(仅在通用 Action 不适用时)
|
||||||
|
|
||||||
|
结构体嵌入 `api.Api`,链式初始化后**必须检查 `Errors`**:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (e SysPost) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostPageReq{}
|
||||||
|
err := e.MakeContext(c).MakeOrm().Bind(&req, binding.Form).MakeService(&s.Service).Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// ... 调用 s.GetPage(...)
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应一律走 `e.OK` / `e.PageOK` / `e.Error`,不要自行 `c.JSON`。
|
||||||
|
|
||||||
|
## Service 层(仅在通用 Action 不适用时)
|
||||||
|
|
||||||
|
结构体嵌入 `service.Service`(持有 `Orm` 与 `Log`)。查询通过 Scopes 组合:
|
||||||
|
|
||||||
|
```go
|
||||||
|
err = e.Orm.Model(&data).Scopes(
|
||||||
|
cDto.MakeCondition(c.GetNeedSearch()), // 由 search tag 生成 WHERE
|
||||||
|
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
|
||||||
|
actions.Permission(data.TableName(), p), // 数据权限,列表/详情必须带
|
||||||
|
).Find(list).Limit(-1).Offset(-1).Count(count).Error
|
||||||
|
```
|
||||||
|
|
||||||
|
**遗漏 `actions.Permission` 会使数据权限配置静默失效** —— 这是最容易出的错。
|
||||||
|
|
||||||
|
错误一律 `return err` 向上传递,日志用 `e.Log.Errorf`,不使用 `panic`。
|
||||||
|
|
||||||
|
## DTO
|
||||||
|
|
||||||
|
搜索条件由 tag 声明,`MakeCondition` 据此拼 SQL:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type SysPostPageReq struct {
|
||||||
|
dto.Pagination `search:"-"`
|
||||||
|
PostName string `form:"postName" search:"type:contains;column:post_name;table:sys_post"`
|
||||||
|
}
|
||||||
|
func (m *SysPostPageReq) GetNeedSearch() interface{} { return *m }
|
||||||
|
```
|
||||||
|
|
||||||
|
`type` 可选:`exact` `iexact` `contains` `gt` `gte` `lt` `lte` `order` `left`(联表)。
|
||||||
|
|
||||||
|
## Model
|
||||||
|
|
||||||
|
```go
|
||||||
|
type SysPost struct {
|
||||||
|
PostId int `gorm:"primaryKey;autoIncrement" json:"postId"`
|
||||||
|
// ... 业务字段
|
||||||
|
models.ControlBy // CreateBy / UpdateBy
|
||||||
|
models.ModelTime // CreatedAt / UpdatedAt / DeletedAt
|
||||||
|
}
|
||||||
|
func (SysPost) TableName() string { return "sys_post" }
|
||||||
|
```
|
||||||
|
|
||||||
|
`TableName()` 必须显式声明(GORM 配置了 `SingularTable`,不会自动推导复数)。
|
||||||
|
|
||||||
|
## 公共契约面
|
||||||
|
|
||||||
|
第三方应用(`app/` 下的业务模块)可以稳定依赖哪些包、路由与迁移怎么注册、
|
||||||
|
哪些约束是硬的,见 `docs/contract.md`。
|
||||||
|
|
||||||
|
两条与主仓贡献者直接相关的:
|
||||||
|
|
||||||
|
- **`common/`、`core/` 不得 import `app/`** —— `make checksilent` 在 CI 里守着,违反即红。
|
||||||
|
- **从 core 契约包声明出来的类型必须写成别名**(`type X = pkg.Y`,不是 `type X pkg.Y`)
|
||||||
|
—— `contract-shim-alias` 检查守着。defined type 会丢掉整个方法集,
|
||||||
|
而且**不一定在本仓编译失败**,理由见 `docs/contract.md` 末节。
|
||||||
|
- **注册类 API(`AppRouters` / `sdk.Runtime.SetAppRouters` / `migration.ForApp`)
|
||||||
|
必须在 `runStartupHooks()` 之前调用完** —— `init()` 是最省事的位置,
|
||||||
|
但约束的是**顺序**,不是写在哪个函数里;晚到的注册会被丢弃并只记一条 ERROR。
|
||||||
|
|
||||||
|
## 路由注册
|
||||||
|
|
||||||
|
通过 `init()` 自注册,不在中心文件手工添加:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func init() { routerCheckRole = append(routerCheckRole, registerSysPostRouter) }
|
||||||
|
|
||||||
|
func registerSysPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
|
api := apis.SysPost{}
|
||||||
|
r := v1.Group("/post").
|
||||||
|
Use(authMiddleware.MiddlewareFunc()).
|
||||||
|
Use(middleware.AuthCheckRole()). // Casbin 鉴权
|
||||||
|
Use(actions.PermissionAction()) // 注入数据权限
|
||||||
|
{ r.GET("", api.GetPage); r.POST("", api.Insert); /* ... */ }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
新增路由文件后,需确认 `cmd/api/` 中已用 `_` 导入该包。
|
||||||
|
|
||||||
|
## 命名
|
||||||
|
|
||||||
|
| 对象 | 规则 | 示例 |
|
||||||
|
|---|---|---|
|
||||||
|
| 数据表 | `sys_` 前缀 + 下划线 | `sys_post` |
|
||||||
|
| API 路径 | `/api/v1/` + kebab-case | `/api/v1/sys-user` |
|
||||||
|
| DTO | `{Model}{Action}Req` | `SysPostPageReq` |
|
||||||
|
| 权限标识 | `模块:资源:操作` | `admin:sysPost:add` |
|
||||||
|
|
||||||
|
权限标识需与前端 `v-permisaction` 一致,并写入 `sys_menu` 种子数据——完整可运行的
|
||||||
|
参照见 `cmd/migrate/migration/version/1786700001000_demo_menu.go`(sys_api /
|
||||||
|
sys_menu / sys_menu_api_rule / casbin_rule 四张表如何配齐,用的是幂等 upsert,
|
||||||
|
可以直接照抄结构)。
|
||||||
|
|
||||||
|
## Swagger
|
||||||
|
|
||||||
|
Api 必须带完整注解,`go generate` 会据此生成文档:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// @Summary 岗位列表
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Router /api/v1/post [get]
|
||||||
|
// @Security Bearer
|
||||||
|
```
|
||||||
|
|
||||||
|
## 本地运行
|
||||||
|
|
||||||
|
**配置 `driver: sqlite3` 时必须带构建标签**,否则启动即 panic:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run -tags sqlite3 . migrate -c config/settings.sqlite.yml
|
||||||
|
go run -tags sqlite3 . server -c config/settings.sqlite.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
原因:`common/database/open.go` 带 `//go:build !sqlite3`,不加标签时编进的是
|
||||||
|
不含 sqlite3 的版本,`opens["sqlite3"]` 为 nil,调用时在 nil 函数上崩溃。
|
||||||
|
报错信息不会提到构建标签,容易误判成环境损坏。MySQL / PostgreSQL 无此问题。
|
||||||
|
|
||||||
|
对应 `Makefile` 的 `build-sqlite` 目标。
|
||||||
|
|
||||||
|
## 数据库迁移
|
||||||
|
|
||||||
|
文件名前 13 位为毫秒时间戳版本号,不合规的名字会在启动时 panic 并报出该文件名。
|
||||||
|
**已执行过的迁移文件不可修改** ——
|
||||||
|
`sys_migration` 表按版本号去重,改动不会重跑,只能新增一个迁移来修正。
|
||||||
|
|
||||||
|
放哪个目录取决于身份:
|
||||||
|
|
||||||
|
| 目录 | 用途 | 是否入库 |
|
||||||
|
|---|---|---|
|
||||||
|
| `version/` | 框架自带迁移,随仓库分发给所有使用者 | 是 |
|
||||||
|
| `version-local/` | 使用者自己项目的迁移 | 否(已在 `.gitignore`) |
|
||||||
|
|
||||||
|
**向本仓库提交迁移必须放 `version/`** —— 放进 `version-local/` 会被忽略掉,
|
||||||
|
`git status` 看不到,PR 里也不会出现。两个目录的包名分别是 `version` 与
|
||||||
|
`version_local`(后者与目录名不一致,因为标识符不能含连字符)。
|
||||||
|
|
||||||
|
### 写种子数据用哪个 models 包
|
||||||
|
|
||||||
|
`1786700003000` 之后新增的迁移,**种子数据要用 `app/` 下的运行时模型**
|
||||||
|
(如 `app/admin/models.SysApi`、`SysMenu`),**不要用 `cmd/migrate/migration/models`**。
|
||||||
|
|
||||||
|
后者的 `ModelTime` 声明的是可空的 `gorm.DeletedAt`,这对它之前的迁移是对的(那正是
|
||||||
|
当时列的形状),转换之后就不再成立,两个方向都会出问题:
|
||||||
|
|
||||||
|
- **写**:往 NOT NULL 列里塞 NULL,第一条 insert 就 `NOT NULL constraint failed`
|
||||||
|
- **读**:GORM 拼 `WHERE deleted_at IS NULL`,而活跃行存的是 `0`,静默查不到——
|
||||||
|
照抄 `demo_menu.go` 的授权段落会因此跳过授权,菜单建好、权限没授、迁移仍记为成功
|
||||||
|
|
||||||
|
干净库跑不出这个问题,今天所有用该包的迁移都排在转换之前。完整推导见
|
||||||
|
`schema_coverage_test.go` 里 `TestPostConversionMigrationsAvoidFrozenSeedModels`
|
||||||
|
的注释,那个测试也守着这条边界。
|
||||||
|
|
||||||
|
## 静默失败校验
|
||||||
|
|
||||||
|
`make checksilent` 逐条检查那些**不报错、不记日志、行为悄悄变得不对**的问题,
|
||||||
|
CI 会跑,命中 ERROR 即失败。这里不写条数——写死的数字会悄悄过时,
|
||||||
|
真正的清单是 `tools/checksilent/checks.go` 里 `runChecks` 跑的那几个:
|
||||||
|
|
||||||
|
| 检查 | 级别 | 静默后果 |
|
||||||
|
|---|---|---|
|
||||||
|
| `modeltime-mix` | ERROR | 两个 `ModelTime` 混用,整张表查不到数据 |
|
||||||
|
| `menu-sort-overflow` | ERROR | 菜单 `sort` 超 127,MySQL tinyint 拒绝写入,迁移中断 |
|
||||||
|
| `config-value-truncation` | ERROR | `sys_config.config_value` 超 255 字符被静默截断 |
|
||||||
|
| `menu-id-collision` | ERROR | 两个模块硬编码同一菜单 ID,互相覆盖 |
|
||||||
|
| `contract-import-boundary` | ERROR | 契约包 import `app/`,应用无法独立编译 |
|
||||||
|
| `contract-shim-alias` | ERROR | 契约薄壳写成 defined type 而非别名,方法集丢失,本仓可能照常编译、第三方应用编译不过 |
|
||||||
|
| `datascope-route-unguarded` | ERROR | handler 读调用方的数据权限,而注册它的路由组没装提供权限的中间件。取不到时拿到零值、走 fail-closed 分支,查询被塞进 `1 = 0`:接口对确实存在的行返回「查不到」,且只在 `enabledp: true` 的部署上出现 |
|
||||||
|
| `shutdown-budget-overruns-grace` | ERROR / WARN | `settings.yml` 的 `extend.shutdown` 预算(含清单里的 `preStop`)放不进自带 k8s 清单的 `terminationGracePeriodSeconds`,SIGKILL 在清理回调跑到一半时到达 |
|
||||||
|
| `docker-stop-cuts-shutdown-short` | ERROR / WARN | 停止容器的两条路径——脚本/工作流里的 `docker stop`,和 `docker-compose.yml` 的 `stop_grace_period`——没写或写得不够关闭预算用。两边默认都是 10 秒,而这个数字离命令很远,调大预算的人不会想起它 |
|
||||||
|
| `menu-name-mismatch` | WARN | 菜单名与前端组件 `name` 不一致,keep-alive 缓存静默失效 |
|
||||||
|
|
||||||
|
两条关闭预算检查分两级,用的是同一条算术和同一个 5 秒边际:真的超限报 ERROR,
|
||||||
|
放得进但余量不足 5 秒报 WARN。余量不足做 WARN 不做 ERROR,是因为那是个技术上
|
||||||
|
跑得通的配置——**一条在正确配置下也会响的 ERROR,训练的是忽略它**。
|
||||||
|
|
||||||
|
最后一条要跨仓库比对,只能做正则启发式,因此是 WARN,**不影响退出码**,
|
||||||
|
且默认跳过;要跑它得指定前端目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make checksilent UI_DIR=../go-admin-ui/src
|
||||||
|
```
|
||||||
|
|
||||||
|
升级门槛:连续 2 个发版周期零误报后转为 ERROR。
|
||||||
|
|
||||||
|
## 提交规范
|
||||||
|
|
||||||
|
格式 `type+emoji: 描述`:
|
||||||
|
|
||||||
|
`feat✨` `fix🐛` `style💄` `docs📝` `perf👌` `test✅` `refactor🎨` `chore🔧`
|
||||||
|
|
||||||
|
一个提交只做一件事。改动跨越多个语义时拆分提交,不要混在一起。
|
||||||
|
|
||||||
|
## 红线
|
||||||
|
|
||||||
|
- 不使用全局 DB 变量,一律用 `e.Orm`(来自请求上下文,多租户依赖它)
|
||||||
|
- 不在 Service 中引用 `gin.Context`
|
||||||
|
- 生产部署前确认 `mode: prod` 且已修改 `jwt.secret`(dev 模式下 token 几乎不过期)
|
||||||
|
- 不提交 `config/settings.yml` 中的真实凭据
|
||||||
+29
-21
@@ -1,26 +1,34 @@
|
|||||||
FROM golang:alpine as builder
|
|
||||||
|
|
||||||
MAINTAINER lwnmengjing
|
|
||||||
|
|
||||||
ENV GOPROXY https://goproxy.cn/
|
|
||||||
|
|
||||||
WORKDIR /go/release
|
|
||||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
|
||||||
RUN apk update && apk add tzdata
|
|
||||||
|
|
||||||
COPY go.mod ./go.mod
|
|
||||||
RUN go mod download
|
|
||||||
COPY . .
|
|
||||||
RUN pwd && ls
|
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o go-admin .
|
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
COPY --from=builder /go/release/go-admin /
|
# ENV GOPROXY https://goproxy.cn/
|
||||||
|
|
||||||
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
||||||
|
|
||||||
|
# Runtime packages only.
|
||||||
|
#
|
||||||
|
# gcc and g++ used to be installed here and were 273MB of a 381MB image. The
|
||||||
|
# binary this image runs is compiled and linked before the image is built and
|
||||||
|
# arrives as a COPY, so nothing in the container ever invokes a compiler -
|
||||||
|
# there is no toolchain to drive it with either, since Go itself is not
|
||||||
|
# installed.
|
||||||
|
#
|
||||||
|
# That layer was also why a host could not share storage between images. apk
|
||||||
|
# resolves against an index that moves, so the layer digest differed on every
|
||||||
|
# build and no two images shared it: a host keeping one image per deployed
|
||||||
|
# commit stored a private 273MB copy each time. 68 of them filled the disk
|
||||||
|
# and the next deployment could not pull.
|
||||||
|
#
|
||||||
|
# libc6-compat stays. Nothing measured needs it - the binary CI produces is
|
||||||
|
# statically linked, and a container built without libc6-compat resolves a
|
||||||
|
# hostname and opens a database connection exactly as one built with it - but
|
||||||
|
# it is half a megabyte and it covers a ./main that was linked dynamically,
|
||||||
|
# which this Dockerfile has no way to check.
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata libc6-compat
|
||||||
|
ENV TZ Asia/Shanghai
|
||||||
|
|
||||||
|
COPY ./main /main
|
||||||
|
COPY ./config/settings.demo.yml /config/settings.yml
|
||||||
|
COPY ./go-admin-db.db /go-admin-db.db
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
RUN chmod +x /main
|
||||||
CMD ["/go-admin","server","-c", "/config/settings.yml"]
|
CMD ["/main","server","-c", "/config/settings.yml"]
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 wenjianzhang
|
Copyright (c) 2026 go-admin-team
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,13 +2,109 @@ PROJECT:=go-admin
|
|||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build:
|
build:
|
||||||
CGO_ENABLED=0 go build -o go-admin main.go
|
CGO_ENABLED=0 go build -ldflags="-w -s" -a -installsuffix "" -o go-admin .
|
||||||
|
|
||||||
|
# make build-linux
|
||||||
|
build-linux:
|
||||||
|
@docker build -t go-admin:latest .
|
||||||
|
@echo "build successful"
|
||||||
|
|
||||||
build-sqlite:
|
build-sqlite:
|
||||||
go build -tags sqlite3 -o go-admin main.go
|
go build -tags sqlite3 -ldflags="-w -s" -a -installsuffix -o go-admin .
|
||||||
#.PHONY: test
|
|
||||||
#test:
|
# make run
|
||||||
# go test -v ./... -cover
|
run:
|
||||||
|
# delete go-admin-api container
|
||||||
|
#
|
||||||
|
# stop then rm, rather than `rm -f`. The force flag kills a running
|
||||||
|
# container with SIGKILL and no grace at all, so restarting locally cut
|
||||||
|
# short every shutdown this application does - the drain window was never
|
||||||
|
# once reached on a developer's machine. --timeout has to cover
|
||||||
|
# extend.shutdown's drain + server + cleanup; checksilent's
|
||||||
|
# docker-stop-cuts-shutdown-short check compares it against
|
||||||
|
# config/settings.yml. On a container that has already stopped, stop is a
|
||||||
|
# no-op and the removal is unchanged.
|
||||||
|
@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker stop --timeout 30 go-admin && docker rm go-admin; fi
|
||||||
|
|
||||||
|
# 启动方法一 run go-admin-api container docker-compose 启动方式
|
||||||
|
# 进入到项目根目录 执行 make run 命令
|
||||||
|
@docker-compose up -d
|
||||||
|
|
||||||
|
# 启动方式二 docker run 这里注意-v挂载的宿主机的地址改为部署时的实际绝对路径
|
||||||
|
#@docker run --name=go-admin -p 8000:8000 -v /home/code/go/src/go-admin/go-admin/config:/go-admin-api/config -v /home/code/go/src/go-admin/go-admin-api/static:/go-admin/static -v /home/code/go/src/go-admin/go-admin/temp:/go-admin-api/temp -d --restart=always go-admin:latest
|
||||||
|
|
||||||
|
@echo "go-admin service is running..."
|
||||||
|
|
||||||
|
# delete Tag=<none> 的镜像
|
||||||
|
@docker image prune -f
|
||||||
|
@docker ps -a | grep "go-admin"
|
||||||
|
|
||||||
|
stop:
|
||||||
|
# delete go-admin-api container
|
||||||
|
@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker-compose down; fi
|
||||||
|
#@if [ $(shell docker ps -aq --filter name=go-admin --filter publish=8000) ]; then docker rm -f go-admin; fi
|
||||||
|
#@echo "go-admin stop success"
|
||||||
|
|
||||||
|
|
||||||
|
# -race is worth the extra minute here: common/actions reuses model instances
|
||||||
|
# across concurrent requests, so a Generate() that returns in place instead of
|
||||||
|
# a copy leaks data between them - and that is invisible to a single-threaded
|
||||||
|
# test run.
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -race -cover ./...
|
||||||
|
|
||||||
|
# The end-to-end install, which `test` above cannot reach: test/e2e-apporder
|
||||||
|
# is its own module, so `./...` in this one does not include it. It builds a
|
||||||
|
# go-admin binary with the example application linked in and drives
|
||||||
|
# `migrate install` / `migrate uninstall` against a real database.
|
||||||
|
#
|
||||||
|
# Its own target rather than a line in the CI workflow, so the one thing in
|
||||||
|
# the build that exercises installing an application is also the one thing
|
||||||
|
# somebody can run before pushing.
|
||||||
|
.PHONY: test-e2e
|
||||||
|
test-e2e:
|
||||||
|
cd test/e2e-apporder && go test ./... -count=1
|
||||||
|
|
||||||
|
# Reports the failures that do not announce themselves - see
|
||||||
|
# tools/checksilent. Exits non-zero on an ERROR; the one WARN-level check
|
||||||
|
# prints and does not fail the build.
|
||||||
|
#
|
||||||
|
# Pass UI_DIR to enable the cross-repository menu-name check, which is skipped
|
||||||
|
# without it: make checksilent UI_DIR=../go-admin-ui/src
|
||||||
|
.PHONY: checksilent
|
||||||
|
checksilent:
|
||||||
|
ifdef UI_DIR
|
||||||
|
go run ./tools/checksilent -ui-dir $(UI_DIR)
|
||||||
|
else
|
||||||
|
go run ./tools/checksilent
|
||||||
|
endif
|
||||||
|
|
||||||
|
# gofmt as a gate, not a rewrite. CI cannot commit, and a target that quietly
|
||||||
|
# reformats hides what it touched, so this reports and fails instead. `gofmt -l`
|
||||||
|
# prints the files it would rewrite and nothing at all when there are none, so
|
||||||
|
# that list is both the failure message and the instructions for fixing it.
|
||||||
|
#
|
||||||
|
# The tree reached zero unformatted files once; without something holding it
|
||||||
|
# there it drifts back, which is how the previous batch grew to 26 files -
|
||||||
|
# mostly a missing newline at the end of the file, which no reviewer notices.
|
||||||
|
.PHONY: fmt-check
|
||||||
|
fmt-check:
|
||||||
|
@unformatted=$$(gofmt -l .); \
|
||||||
|
if [ -n "$$unformatted" ]; then \
|
||||||
|
echo "gofmt would rewrite these files. Run 'gofmt -w .' and commit the result:"; \
|
||||||
|
echo "$$unformatted"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
#.PHONY: docker
|
#.PHONY: docker
|
||||||
#docker:
|
#docker:
|
||||||
# docker build . -t go-admin:latest
|
# docker build . -t go-admin:latest
|
||||||
|
|
||||||
|
# make deploy
|
||||||
|
deploy:
|
||||||
|
|
||||||
|
#@git checkout master
|
||||||
|
#@git pull origin master
|
||||||
|
make build-linux
|
||||||
|
make run
|
||||||
|
|||||||
+116
-59
@@ -1,27 +1,30 @@
|
|||||||
# go-admin
|
# go-admin
|
||||||
|
|
||||||
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
|
<img align="right" width="320" src="https://doc-image.zhangwj.com/img/go-admin.svg">
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/go-admin-team/go-admin)
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
[](https://github.com/go-admin-team/go-admin/releases)
|
[](https://github.com/go-admin-team/go-admin/releases)
|
||||||
[](https://github.com/go-admin-team/go-admin)
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
|
||||||
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | 简体中文
|
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | 简体中文 | [繁體中文](https://github.com/go-admin-team/go-admin/blob/master/README.zh-TW.md) | [日本語](https://github.com/go-admin-team/go-admin/blob/master/README.ja-JP.md)
|
||||||
|
|
||||||
|
基于Gin + Vue + Element UI OR Arco Design OR Ant Design的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务
|
||||||
|
|
||||||
基于Gin + Vue + Element UI的前后端分离权限管理系统,系统初始化极度简单,只需要配置文件中,修改数据库连接,系统支持多指令操作,迁移指令可以让初始化数据库信息变得更简单,服务指令可以很简单的启动api服务
|
[在线文档](https://www.go-admin.pro)
|
||||||
|
|
||||||
[在线文档](https://doc.go-admin.dev)
|
|
||||||
|
|
||||||
[github在线文档](https://wenjianzhang.github.io)
|
|
||||||
|
|
||||||
[gitee在线文档](http://mydearzwj.gitee.io/go-admin-doc/)
|
|
||||||
|
|
||||||
[前端项目](https://github.com/go-admin-team/go-admin-ui)
|
[前端项目](https://github.com/go-admin-team/go-admin-ui)
|
||||||
|
|
||||||
[视频教程](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
[视频教程](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||||
|
|
||||||
|
## 🎬 在线体验
|
||||||
|
|
||||||
|
Element Plus vue3 体验:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
|
||||||
|
> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456
|
||||||
|
|
||||||
|
antd 体验(go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
|
||||||
|
> ⚠️⚠️⚠️ 账号 / 密码: admin / 123456
|
||||||
|
|
||||||
## ✨ 特性
|
## ✨ 特性
|
||||||
|
|
||||||
- 遵循 RESTful API 设计规范
|
- 遵循 RESTful API 设计规范
|
||||||
@@ -34,7 +37,7 @@
|
|||||||
|
|
||||||
- 支持 Swagger 文档(基于swaggo)
|
- 支持 Swagger 文档(基于swaggo)
|
||||||
|
|
||||||
- 基于 GORM 的数据库存储,可扩展多种类型数据库
|
- 基于 GORM 的数据库存储,可扩展多种类型数据库
|
||||||
|
|
||||||
- 配置文件简单的模型映射,快速能够得到想要的配置
|
- 配置文件简单的模型映射,快速能够得到想要的配置
|
||||||
|
|
||||||
@@ -44,11 +47,13 @@
|
|||||||
|
|
||||||
- 多指令模式
|
- 多指令模式
|
||||||
|
|
||||||
- TODO: 单元测试
|
- 多租户的支持
|
||||||
|
|
||||||
|
- TODO: 单元测试
|
||||||
|
|
||||||
## 🎁 内置
|
## 🎁 内置
|
||||||
|
|
||||||
|
1. 多租户:系统默认支持多租户,按库分离,一个库一个租户。
|
||||||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||||
3. 岗位管理:配置系统用户所属担任职务。
|
3. 岗位管理:配置系统用户所属担任职务。
|
||||||
@@ -63,6 +68,7 @@
|
|||||||
1. 表单构建:自定义页面样式,拖拉拽实现页面布局。
|
1. 表单构建:自定义页面样式,拖拉拽实现页面布局。
|
||||||
1. 服务监控:查看一些服务器的基本信息。
|
1. 服务监控:查看一些服务器的基本信息。
|
||||||
1. 内容管理:demo功能,下设分类管理、内容管理。可以参考使用方便快速入门。
|
1. 内容管理:demo功能,下设分类管理、内容管理。可以参考使用方便快速入门。
|
||||||
|
1. 定时任务:自动化任务,目前支持接口调用和函数调用。
|
||||||
|
|
||||||
## 准备工作
|
## 准备工作
|
||||||
|
|
||||||
@@ -72,11 +78,11 @@
|
|||||||
|
|
||||||
### 轻松实现go-admin写出第一个应用 - 文档教程
|
### 轻松实现go-admin写出第一个应用 - 文档教程
|
||||||
|
|
||||||
[步骤一 - 基础内容介绍](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
|
[步骤一 - 基础内容介绍](https://www.go-admin.pro/guide/intro/tutorial01.html)
|
||||||
|
|
||||||
[步骤二 - 实际应用 - 编写增删改查](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
|
[步骤二 - 实际应用 - 编写增删改查](https://www.go-admin.pro/guide/intro/tutorial02.html)
|
||||||
|
|
||||||
### 手把手教你从入门到放弃 - 视频教程
|
### 手把手教你从入门到放弃 - 视频教程
|
||||||
|
|
||||||
[如何启动go-admin](https://www.bilibili.com/video/BV1z5411x7JG)
|
[如何启动go-admin](https://www.bilibili.com/video/BV1z5411x7JG)
|
||||||
|
|
||||||
@@ -94,11 +100,18 @@
|
|||||||
|
|
||||||
[go-admin数据权限使用说明](https://www.bilibili.com/video/BV1LK4y1s71e) [必看]
|
[go-admin数据权限使用说明](https://www.bilibili.com/video/BV1LK4y1s71e) [必看]
|
||||||
|
|
||||||
|
|
||||||
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr ,视频教程和文档持续更新中**
|
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr ,视频教程和文档持续更新中**
|
||||||
|
|
||||||
## 📦 本地开发
|
## 📦 本地开发
|
||||||
|
|
||||||
|
### 环境要求
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
|
|
||||||
|
node版本: v22+(推荐 v24 LTS)
|
||||||
|
|
||||||
|
包管理器: pnpm v9+(UI 项目使用 pnpm)
|
||||||
|
|
||||||
### 开发目录创建
|
### 开发目录创建
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -121,7 +134,6 @@ git clone https://github.com/go-admin-team/go-admin-ui.git
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### 启动说明
|
### 启动说明
|
||||||
|
|
||||||
#### 服务端启动说明
|
#### 服务端启动说明
|
||||||
@@ -130,19 +142,22 @@ git clone https://github.com/go-admin-team/go-admin-ui.git
|
|||||||
# 进入 go-admin 后端项目
|
# 进入 go-admin 后端项目
|
||||||
cd ./go-admin
|
cd ./go-admin
|
||||||
|
|
||||||
|
# 更新整理依赖
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
# 编译项目
|
# 编译项目
|
||||||
go build
|
go build
|
||||||
|
|
||||||
# 修改配置
|
# 修改配置
|
||||||
# 文件路径 go-admin/config/settings.yml
|
# 文件路径 go-admin/config/settings.yml
|
||||||
vi ./config/setting.yml
|
vi ./config/settings.yml
|
||||||
|
|
||||||
# 1. 配置文件中修改数据库信息
|
# 1. 配置文件中修改数据库信息
|
||||||
# 注意: settings.database 下对应的配置数据
|
# 注意: settings.database 下对应的配置数据
|
||||||
# 2. 确认log路径
|
# 2. 确认log路径
|
||||||
```
|
```
|
||||||
|
|
||||||
:::tip ⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题;
|
⚠️注意 在windows环境如果没有安装中CGO,会出现这个问题;
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
E:\go-admin>go build
|
E:\go-admin>go build
|
||||||
@@ -158,19 +173,18 @@ D:\Code\go-admin>go build
|
|||||||
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||||
```
|
```
|
||||||
|
|
||||||
[解决cgo问题进入](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
|
[解决cgo问题进入](https://www.go-admin.pro/zh-CN/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### 初始化数据库,以及服务启动
|
#### 初始化数据库,以及服务启动
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# 首次配置需要初始化数据库资源信息
|
# 首次配置需要初始化数据库资源信息
|
||||||
# macOS or linux 下使用
|
# macOS or linux 下使用
|
||||||
$ ./go-admin migrate -c=config/settings.dev.yml
|
$ ./go-admin migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
# ⚠️注意:windows 下使用
|
# ⚠️注意:windows 下使用
|
||||||
$ go-admin.exe migrate -c=config/settings.dev.yml
|
$ go-admin.exe migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
|
|
||||||
# 启动项目,也可以用IDE进行调试
|
# 启动项目,也可以用IDE进行调试
|
||||||
@@ -182,6 +196,13 @@ $ ./go-admin server -c config/settings.yml
|
|||||||
$ go-admin.exe server -c config/settings.yml
|
$ go-admin.exe server -c config/settings.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### sys_api 表的数据如何添加
|
||||||
|
|
||||||
|
在项目启动时,使用`-a true` 系统会自动添加缺少的接口数据
|
||||||
|
```bash
|
||||||
|
./go-admin server -c config/settings.yml -a true
|
||||||
|
```
|
||||||
|
|
||||||
#### 使用docker 编译启动
|
#### 使用docker 编译启动
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -193,8 +214,6 @@ docker build -t go-admin .
|
|||||||
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 文档生成
|
#### 文档生成
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -202,6 +221,7 @@ go generate
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 交叉编译
|
#### 交叉编译
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# windows
|
# windows
|
||||||
env GOOS=windows GOARCH=amd64 go build main.go
|
env GOOS=windows GOARCH=amd64 go build main.go
|
||||||
@@ -214,45 +234,77 @@ env GOOS=linux GOARCH=amd64 go build main.go
|
|||||||
### UI交互端启动说明
|
### UI交互端启动说明
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 安装依赖
|
# 安装 pnpm(若未安装)
|
||||||
npm install
|
npm install -g pnpm
|
||||||
|
|
||||||
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
|
# 安装依赖
|
||||||
npm install --registry=https://registry.npm.taobao.org
|
pnpm install
|
||||||
|
|
||||||
|
# 国内网络可指定镜像源加速
|
||||||
|
pnpm install --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
# 启动服务
|
# 启动服务
|
||||||
npm run dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🎬 在线体验
|
|
||||||
> admin / 123456
|
|
||||||
|
|
||||||
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
|
|
||||||
|
|
||||||
|
|
||||||
## 📨 互动
|
## 📨 互动
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq.png" width="200px"></td>
|
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
|
||||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||||
|
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>微信</td>
|
<td>微信</td>
|
||||||
<td>此群已满</td>
|
<td>公众号🔥🔥🔥</td>
|
||||||
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||||
|
<td>哔哩哔哩🔥🔥🔥</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
## 💎 主要成员
|
## 💎 贡献者
|
||||||
|
|
||||||
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
|
|
||||||
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
|
|
||||||
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
|
|
||||||
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
|
||||||
## JetBrains 开源证书支持
|
## JetBrains 开源证书支持
|
||||||
|
|
||||||
@@ -260,18 +312,22 @@ npm run dev
|
|||||||
|
|
||||||
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||||
|
|
||||||
|
|
||||||
## 🤝 特别感谢
|
## 🤝 特别感谢
|
||||||
1. [chengxiao](https://github.com/chengxiao)
|
|
||||||
2. [gin](https://github.com/gin-gonic/gin)
|
1. [ant-design](https://github.com/ant-design/ant-design)
|
||||||
2. [casbin](https://github.com/casbin/casbin)
|
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
|
||||||
2. [spf13/viper](https://github.com/spf13/viper)
|
2. [arco-design](https://github.com/arco-design/arco-design)
|
||||||
2. [gorm](https://github.com/jinzhu/gorm)
|
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
|
||||||
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
4. [gin](https://github.com/gin-gonic/gin)
|
||||||
2. [jwt-go](https://github.com/dgrijalva/jwt-go)
|
5. [casbin](https://github.com/casbin/casbin)
|
||||||
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
6. [spf13/viper](https://github.com/spf13/viper)
|
||||||
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
7. [gorm](https://github.com/go-gorm/gorm)
|
||||||
2. [form-generator](https://github.com/JakHuang/form-generator)
|
8. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||||
|
9. [golang-jwt](https://github.com/golang-jwt/jwt)
|
||||||
|
10. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||||
|
11. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||||
|
12. [form-generator](https://github.com/JakHuang/form-generator)
|
||||||
|
|
||||||
|
|
||||||
## 🤟 打赏
|
## 🤟 打赏
|
||||||
|
|
||||||
@@ -280,10 +336,11 @@ npm run dev
|
|||||||
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||||
|
|
||||||
## 🤝 链接
|
## 🤝 链接
|
||||||
[Go开发者成长线路图](http://www.golangroadmap.com/)
|
|
||||||
|
- [mss-boot-io](https://docs.mss-boot-io.top/)
|
||||||
|
|
||||||
## 🔑 License
|
## 🔑 License
|
||||||
|
|
||||||
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||||
|
|
||||||
Copyright (c) 2020 wenjianzhang
|
Copyright (c) 2026 wenjianzhang
|
||||||
|
|||||||
+344
@@ -0,0 +1,344 @@
|
|||||||
|
# go-admin
|
||||||
|
|
||||||
|
<img align="right" width="320" src="https://doc-image.zhangwj.com/img/go-admin.svg">
|
||||||
|
|
||||||
|
|
||||||
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
[](https://github.com/go-admin-team/go-admin/releases)
|
||||||
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
|
||||||
|
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md) | [繁體中文](https://github.com/go-admin-team/go-admin/blob/master/README.zh-TW.md) | 日本語
|
||||||
|
|
||||||
|
Gin + Vue + Element UI / Arco Design / Ant Design による、フロントエンドとバックエンドを分離した権限管理システムです。初期化は非常に簡単で、設定ファイルのデータベース接続情報を変更するだけで動作します。複数のコマンドに対応しており、マイグレーションコマンドでデータベースの初期化が容易になり、サーバーコマンドで API を手軽に起動できます。
|
||||||
|
|
||||||
|
[オンラインドキュメント](https://www.go-admin.pro)
|
||||||
|
|
||||||
|
[フロントエンドプロジェクト](https://github.com/go-admin-team/go-admin-ui)
|
||||||
|
|
||||||
|
[動画チュートリアル](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||||
|
|
||||||
|
## 🎬 オンラインデモ
|
||||||
|
|
||||||
|
Element Plus vue3 デモ:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
|
||||||
|
> ⚠️⚠️⚠️ アカウント / パスワード: admin / 123456
|
||||||
|
|
||||||
|
antd デモ(go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
|
||||||
|
> ⚠️⚠️⚠️ アカウント / パスワード: admin / 123456
|
||||||
|
|
||||||
|
## ✨ 特徴
|
||||||
|
|
||||||
|
- RESTful API の設計規約に準拠
|
||||||
|
|
||||||
|
- GIN WEB API フレームワークをベースに、豊富なミドルウェアを提供(ユーザー認証、CORS、アクセスログ、トレース ID など)
|
||||||
|
|
||||||
|
- Casbin による RBAC アクセス制御モデル
|
||||||
|
|
||||||
|
- JWT 認証
|
||||||
|
|
||||||
|
- Swagger ドキュメントに対応(swaggo ベース)
|
||||||
|
|
||||||
|
- GORM によるデータベース永続化、複数種類のデータベースに拡張可能
|
||||||
|
|
||||||
|
- 設定ファイルからモデルへの単純なマッピングで、必要な設定をすぐに取得
|
||||||
|
|
||||||
|
- コード生成ツール
|
||||||
|
|
||||||
|
- フォームビルダー
|
||||||
|
|
||||||
|
- マルチコマンド方式
|
||||||
|
|
||||||
|
- マルチテナント対応
|
||||||
|
|
||||||
|
- TODO: ユニットテスト
|
||||||
|
|
||||||
|
## 🎁 標準機能
|
||||||
|
|
||||||
|
1. マルチテナント:デフォルトで対応。データベース単位で分離し、1 データベースにつき 1 テナント。
|
||||||
|
1. ユーザー管理:システムの操作者であるユーザーの設定を行います。
|
||||||
|
2. 部門管理:組織構造(会社・部門・グループ)を設定します。ツリー構造で表示し、データ権限に対応します。
|
||||||
|
3. 役職管理:ユーザーが担当する職務を設定します。
|
||||||
|
4. メニュー管理:メニュー、操作権限、ボタン権限識別子、API 権限などを設定します。
|
||||||
|
5. ロール管理:ロールへのメニュー権限の割り当て、および組織単位でのデータ範囲権限の設定を行います。
|
||||||
|
6. 辞書管理:システム内で頻繁に使う固定的なデータを管理します。
|
||||||
|
7. パラメータ管理:よく使うパラメータを動的に設定します。
|
||||||
|
8. 操作ログ:正常系の操作ログと異常情報のログを記録・検索します。
|
||||||
|
9. ログインログ:ログイン履歴を記録・検索します。ログイン異常も含みます。
|
||||||
|
1. API ドキュメント:業務コードから API ドキュメントを自動生成します。
|
||||||
|
1. コード生成:テーブル定義から CRUD 業務を生成します。すべて画面上で操作でき、基本的な業務をコードなしで実現できます。
|
||||||
|
1. フォームビルダー:ページのスタイルをカスタマイズし、ドラッグ&ドロップでレイアウトを作成します。
|
||||||
|
1. サービス監視:サーバーの基本情報を確認します。
|
||||||
|
1. コンテンツ管理:デモ機能。カテゴリ管理とコンテンツ管理を含み、入門用の参考実装として利用できます。
|
||||||
|
1. スケジュールタスク:自動実行タスク。現在は API 呼び出しと関数呼び出しに対応しています。
|
||||||
|
|
||||||
|
## 事前準備
|
||||||
|
|
||||||
|
ローカルに [go] [gin] [node](http://nodejs.org/) と [git](https://git-scm.com/) をインストールしてください。
|
||||||
|
|
||||||
|
ダウンロードから使いこなすまでを解説した動画とドキュメントのチュートリアルを用意しています。本プロジェクトを試す前に、まずこれらに目を通すことを強くおすすめします。
|
||||||
|
|
||||||
|
### go-admin で最初のアプリケーションを作る - ドキュメント
|
||||||
|
|
||||||
|
[ステップ 1 - 基礎の紹介](https://www.go-admin.pro/guide/intro/tutorial01.html)
|
||||||
|
|
||||||
|
[ステップ 2 - 実践 - CRUD を書く](https://www.go-admin.pro/guide/intro/tutorial02.html)
|
||||||
|
|
||||||
|
### 動画チュートリアル
|
||||||
|
|
||||||
|
[go-admin の起動方法](https://www.bilibili.com/video/BV1z5411x7JG)
|
||||||
|
|
||||||
|
[生成ツールで業務を手軽に実装する](https://www.bilibili.com/video/BV1Dg4y1i79D)
|
||||||
|
|
||||||
|
[v1.1.0 のコード生成ツール](https://www.bilibili.com/video/BV1N54y1i71P) [応用]
|
||||||
|
|
||||||
|
[マルチコマンドでの起動方法と IDE 設定](https://www.bilibili.com/video/BV1Fg4y1q7ph)
|
||||||
|
|
||||||
|
[go-admin のメニュー設定](https://www.bilibili.com/video/BV1Wp4y1D715) [必見]
|
||||||
|
|
||||||
|
[メニュー情報と API 情報の設定方法](https://www.bilibili.com/video/BV1zv411B7nG) [必見]
|
||||||
|
|
||||||
|
[go-admin の権限設定](https://www.bilibili.com/video/BV1rt4y197d3) [必見]
|
||||||
|
|
||||||
|
[go-admin のデータ権限](https://www.bilibili.com/video/BV1LK4y1s71e) [必見]
|
||||||
|
|
||||||
|
**不明点はまず上記のドキュメントと記事をご確認ください。解決しない場合は issue や pr をお寄せください。動画とドキュメントは継続的に更新しています**
|
||||||
|
|
||||||
|
## 📦 ローカル開発
|
||||||
|
|
||||||
|
### 動作要件
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
|
|
||||||
|
node バージョン: v22 以上(v24 LTS 推奨)
|
||||||
|
|
||||||
|
パッケージマネージャー: pnpm v9 以上(UI プロジェクトは pnpm を使用)
|
||||||
|
|
||||||
|
### 開発ディレクトリの作成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
# 開発ディレクトリを作成
|
||||||
|
mkdir goadmin
|
||||||
|
cd goadmin
|
||||||
|
```
|
||||||
|
|
||||||
|
### コードの取得
|
||||||
|
|
||||||
|
> 重要:2 つのプロジェクトは同じディレクトリに配置してください。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# バックエンドのコードを取得
|
||||||
|
git clone https://github.com/go-admin-team/go-admin.git
|
||||||
|
|
||||||
|
# フロントエンドのコードを取得
|
||||||
|
git clone https://github.com/go-admin-team/go-admin-ui.git
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 起動方法
|
||||||
|
|
||||||
|
#### サーバーの起動
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# go-admin バックエンドプロジェクトへ移動
|
||||||
|
cd ./go-admin
|
||||||
|
|
||||||
|
# 依存関係を整理
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
# ビルド
|
||||||
|
go build
|
||||||
|
|
||||||
|
# 設定を変更
|
||||||
|
# ファイルパス go-admin/config/settings.yml
|
||||||
|
vi ./config/settings.yml
|
||||||
|
|
||||||
|
# 1. 設定ファイル内のデータベース情報を変更
|
||||||
|
# 注意: settings.database 配下の設定項目
|
||||||
|
# 2. log のパスを確認
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️注意 Windows 環境で CGO が未導入の場合、次のエラーが発生します。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
E:\go-admin>go build
|
||||||
|
# github.com/mattn/go-sqlite3
|
||||||
|
cgo: exec /missing-cc: exec: "/missing-cc": file does not exist
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
D:\Code\go-admin>go build
|
||||||
|
# github.com/mattn/go-sqlite3
|
||||||
|
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||||
|
```
|
||||||
|
|
||||||
|
[cgo の問題の解決方法はこちら](https://www.go-admin.pro/zh-CN/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
|
||||||
|
|
||||||
|
|
||||||
|
#### データベースの初期化とサービス起動
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# 初回はデータベースのリソース情報を初期化する必要があります
|
||||||
|
# macOS または linux の場合
|
||||||
|
$ ./go-admin migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
|
# ⚠️注意: windows の場合
|
||||||
|
$ go-admin.exe migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
|
|
||||||
|
# プロジェクトを起動します。IDE からデバッグ実行することもできます
|
||||||
|
# macOS または linux の場合
|
||||||
|
$ ./go-admin server -c config/settings.yml
|
||||||
|
|
||||||
|
|
||||||
|
# ⚠️注意: windows の場合
|
||||||
|
$ go-admin.exe server -c config/settings.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
#### sys_api テーブルへのデータ追加方法
|
||||||
|
|
||||||
|
起動時に `-a true` を付けると、不足している API データが自動的に追加されます。
|
||||||
|
```bash
|
||||||
|
./go-admin server -c config/settings.yml -a true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### docker でのビルドと起動
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# イメージをビルド
|
||||||
|
docker build -t go-admin .
|
||||||
|
|
||||||
|
# コンテナを起動します。1 つ目の go-admin はコンテナ名、2 つ目はイメージ名です
|
||||||
|
# -v は設定ファイルのマウント ローカルパス:コンテナ内パス
|
||||||
|
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ドキュメント生成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### クロスコンパイル
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# windows
|
||||||
|
env GOOS=windows GOARCH=amd64 go build main.go
|
||||||
|
|
||||||
|
# or
|
||||||
|
# linux
|
||||||
|
env GOOS=linux GOARCH=amd64 go build main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI 側の起動方法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# pnpm をインストール(未導入の場合)
|
||||||
|
npm install -g pnpm
|
||||||
|
|
||||||
|
# 依存関係をインストール
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# 中国本土のネットワークではミラーを指定すると高速化できます
|
||||||
|
pnpm install --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
|
# 開発サーバーを起動
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📨 コミュニティ
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||||
|
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
|
||||||
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||||
|
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>微信</td>
|
||||||
|
<td>公众号🔥🔥🔥</td>
|
||||||
|
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||||
|
<td>哔哩哔哩🔥🔥🔥</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## 💎 コントリビューター
|
||||||
|
|
||||||
|
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
## JetBrains のオープンソースライセンス支援
|
||||||
|
|
||||||
|
`go-admin` は一貫して JetBrains 社の GoLand 統合開発環境で開発されています。**free JetBrains Open Source license(s)** による正規の無償ライセンス提供に、この場を借りて感謝を申し上げます。
|
||||||
|
|
||||||
|
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||||
|
|
||||||
|
## 🤝 謝辞
|
||||||
|
|
||||||
|
1. [ant-design](https://github.com/ant-design/ant-design)
|
||||||
|
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
|
||||||
|
2. [arco-design](https://github.com/arco-design/arco-design)
|
||||||
|
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
|
||||||
|
4. [gin](https://github.com/gin-gonic/gin)
|
||||||
|
5. [casbin](https://github.com/casbin/casbin)
|
||||||
|
6. [spf13/viper](https://github.com/spf13/viper)
|
||||||
|
7. [gorm](https://github.com/go-gorm/gorm)
|
||||||
|
8. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||||
|
9. [golang-jwt](https://github.com/golang-jwt/jwt)
|
||||||
|
10. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||||
|
11. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||||
|
12. [form-generator](https://github.com/JakHuang/form-generator)
|
||||||
|
|
||||||
|
## 🤟 支援
|
||||||
|
|
||||||
|
> このプロジェクトがお役に立ちましたら、作者にジュースを一杯おごる形で応援いただけます :tropical_drink:
|
||||||
|
|
||||||
|
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||||
|
|
||||||
|
## 🤝 関連リンク
|
||||||
|
|
||||||
|
- [mss-boot-io](https://docs.mss-boot-io.top/)
|
||||||
|
|
||||||
|
## 🔑 License
|
||||||
|
|
||||||
|
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||||
|
|
||||||
|
Copyright (c) 2026 wenjianzhang
|
||||||
@@ -1,23 +1,31 @@
|
|||||||
|
|
||||||
# go-admin
|
# go-admin
|
||||||
|
|
||||||
<img align="right" width="320" src="https://gitee.com/mydearzwj/image/raw/master/img/go-admin.svg">
|
<img align="right" width="320" src="https://raw.githubusercontent.com/wenjianzhang/image/203c5930b9ed08d5cf2fcb4516b85e412f8e0e60/img/go-admin.svg">
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/go-admin-team/go-admin)
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
[](https://github.com/go-admin-team/go-admin/releases)
|
[](https://github.com/go-admin-team/go-admin/releases)
|
||||||
[](https://github.com/go-admin-team/go-admin)
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
|
||||||
English | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md)
|
English | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md) | [繁體中文](https://github.com/go-admin-team/go-admin/blob/master/README.zh-TW.md) | [日本語](https://github.com/go-admin-team/go-admin/blob/master/README.ja-JP.md)
|
||||||
|
|
||||||
The front-end and back-end separation authority management system based on Gin + Vue + Element UI is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service.
|
The front-end and back-end separation authority management system based on Gin + Vue + Element UI OR Arco Design OR Ant Design is extremely simple to initialize the system. You only need to modify the database connection in the configuration file. The system supports multi-instruction operations. Migration instructions can make it easier to initialize database information. Service instructions It's easy to start the api service.
|
||||||
|
|
||||||
[documentation](https://doc.go-admin.dev)
|
[documentation](https://www.go-admin.pro)
|
||||||
|
|
||||||
[Front-end project](https://github.com/go-admin-team/go-admin-ui)
|
[Front-end project](https://github.com/go-admin-team/go-admin-ui)
|
||||||
|
|
||||||
[Video tutorial](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
[Video tutorial](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||||
|
|
||||||
|
## 🎬 Online Demo
|
||||||
|
|
||||||
|
Element Plus vue3 demo:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
|
||||||
|
> Account / Password: admin / 123456
|
||||||
|
|
||||||
|
antd demo (go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
|
||||||
|
> Account / Password: admin / 123456
|
||||||
|
>
|
||||||
## ✨ Feature
|
## ✨ Feature
|
||||||
|
|
||||||
- Follow RESTful API design specifications
|
- Follow RESTful API design specifications
|
||||||
@@ -68,9 +76,9 @@ At the same time, a series of tutorials including videos and documents are provi
|
|||||||
|
|
||||||
### Easily implement go-admin to write the first application-documentation tutorial
|
### Easily implement go-admin to write the first application-documentation tutorial
|
||||||
|
|
||||||
[Step 1 - basic content introduction](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial01.html)
|
[Step 1 - basic content introduction](https://www.go-admin.pro/guide/intro/tutorial01.html)
|
||||||
|
|
||||||
[Step 2 - Practical application - writing database operations](http://doc.zhangwj.com/go-admin-site/guide/intro/tutorial02.html)
|
[Step 2 - Practical application - writing database operations](https://www.go-admin.pro/guide/intro/tutorial02.html)
|
||||||
|
|
||||||
### Teach you from getting started to giving up-video tutorial
|
### Teach you from getting started to giving up-video tutorial
|
||||||
|
|
||||||
@@ -94,6 +102,14 @@ At the same time, a series of tutorials including videos and documents are provi
|
|||||||
|
|
||||||
## 📦 Local development
|
## 📦 Local development
|
||||||
|
|
||||||
|
### Environmental requirements
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
|
|
||||||
|
nodejs: v22+ (v24 LTS recommended)
|
||||||
|
|
||||||
|
package manager: pnpm v9+ (the UI project uses pnpm)
|
||||||
|
|
||||||
### Development directory creation
|
### Development directory creation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -124,19 +140,22 @@ git clone https://github.com/go-admin-team/go-admin-ui.git
|
|||||||
# Enter the go-admin backend project
|
# Enter the go-admin backend project
|
||||||
cd ./go-admin
|
cd ./go-admin
|
||||||
|
|
||||||
|
# Update dependencies
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
# Compile the project
|
# Compile the project
|
||||||
go build
|
go build
|
||||||
|
|
||||||
# Change setting
|
# Change setting
|
||||||
# File path go-admin/config/settings.yml
|
# File path go-admin/config/settings.yml
|
||||||
vi ./config/setting.yml
|
vi ./config/settings.yml
|
||||||
|
|
||||||
# 1. Modify the database information in the configuration file
|
# 1. Modify the database information in the configuration file
|
||||||
# Note: The corresponding configuration data under settings.database
|
# Note: The corresponding configuration data under settings.database
|
||||||
# 2. Confirm the log path
|
# 2. Confirm the log path
|
||||||
```
|
```
|
||||||
|
|
||||||
:::tip ⚠️Note that this problem will occur if CGO is not installed in the windows environment;
|
⚠️ Note that this problem will occur if CGO is not installed in the windows10+ environment;
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
E:\go-admin>go build
|
E:\go-admin>go build
|
||||||
@@ -152,19 +171,17 @@ D:\Code\go-admin>go build
|
|||||||
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||||
```
|
```
|
||||||
|
|
||||||
[Solve the cgo problem and enter](https://doc.go-admin.dev/guide/other/faq.html#_5-cgo-exec-missing-cc-exec-missing-cc-file-does-not-exist)
|
[Solve the cgo problem and enter](https://www.go-admin.pro/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Initialize the database, and start the service
|
#### Initialize the database, and start the service
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# The first configuration needs to initialize the database resource information
|
# The first configuration needs to initialize the database resource information
|
||||||
# Use under macOS or linux
|
# Use under macOS or linux
|
||||||
$ ./go-admin migrate -c=config/settings.dev.yml
|
$ ./go-admin migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
# ⚠️Note: Use under windows
|
# ⚠️Note: Use under windows
|
||||||
$ go-admin.exe migrate -c=config/settings.dev.yml
|
$ go-admin.exe migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
# Start the project, you can also use the IDE for debugging
|
# Start the project, you can also use the IDE for debugging
|
||||||
# Use under macOS or linux
|
# Use under macOS or linux
|
||||||
@@ -207,38 +224,73 @@ env GOOS=linux GOARCH=amd64 go build main.go
|
|||||||
### UI interactive terminal startup instructions
|
### UI interactive terminal startup instructions
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Install pnpm if you don't have it
|
||||||
|
npm install -g pnpm
|
||||||
|
|
||||||
# Installation dependencies
|
# Installation dependencies
|
||||||
npm install # or cnpm install
|
pnpm install
|
||||||
|
|
||||||
# Start service
|
# Start service
|
||||||
npm run dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🎬 Online Demo
|
|
||||||
> admin / 123456
|
|
||||||
|
|
||||||
演示地址:[http://www.go-admin.dev](http://www.go-admin.dev/#/login)
|
|
||||||
|
|
||||||
|
|
||||||
## 📨 Interactive
|
## 📨 Interactive
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||||
|
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
|
||||||
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||||
|
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Wechat</td>
|
<td>Wechat</td>
|
||||||
|
<td>Wechat公众号🔥🔥🔥</td>
|
||||||
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||||
|
<td>bilibili🔥🔥🔥</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
## 💎 Members
|
## 💎 Contributors
|
||||||
|
|
||||||
<a href="https://github.com/wenjianzhang"> <img src="https://avatars.githubusercontent.com/u/3890175?s=460&u=20eac63daef81588fbac611da676b99859319251&v=4" width="80px"></a>
|
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
<a href="https://github.com/lwnmengjing"> <img src="https://avatars.githubusercontent.com/u/12806223?s=400&u=a89272dce50100b77b4c0d5c81c718bf78ebb580&v=4" width="80px"></a>
|
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
<a href="https://github.com/chengxiao"> <img src="https://avatars.githubusercontent.com/u/1379545?s=460&u=557da5503d0ac4a8628df6b4075b17853d5edcd9&v=4" width="80px"></a>
|
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
<a href="https://github.com/bing127"> <img src="https://avatars.githubusercontent.com/u/31166183?s=460&u=c085bff88df10bb7676c8c0351ba9dcd031d1fb3&v=4" width="80px"></a>
|
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -250,13 +302,17 @@ The `go-admin` project has always been developed in the GoLand integrated develo
|
|||||||
|
|
||||||
|
|
||||||
## 🤝 Thanks
|
## 🤝 Thanks
|
||||||
1. [chengxiao](https://github.com/chengxiao)
|
|
||||||
|
1. [ant-design](https://github.com/ant-design/ant-design)
|
||||||
|
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
|
||||||
|
2. [arco-design](https://github.com/arco-design/arco-design)
|
||||||
|
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
|
||||||
2. [gin](https://github.com/gin-gonic/gin)
|
2. [gin](https://github.com/gin-gonic/gin)
|
||||||
2. [casbin](https://github.com/casbin/casbin)
|
2. [casbin](https://github.com/casbin/casbin)
|
||||||
2. [spf13/viper](https://github.com/spf13/viper)
|
2. [spf13/viper](https://github.com/spf13/viper)
|
||||||
2. [gorm](https://github.com/jinzhu/gorm)
|
2. [gorm](https://github.com/go-gorm/gorm)
|
||||||
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
2. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||||
2. [jwt-go](https://github.com/dgrijalva/jwt-go)
|
2. [golang-jwt](https://github.com/golang-jwt/jwt)
|
||||||
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
2. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||||
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
2. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||||
2. [form-generator](https://github.com/JakHuang/form-generator)
|
2. [form-generator](https://github.com/JakHuang/form-generator)
|
||||||
@@ -268,10 +324,10 @@ The `go-admin` project has always been developed in the GoLand integrated develo
|
|||||||
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||||
|
|
||||||
## 🤝 Link
|
## 🤝 Link
|
||||||
[Go developer growth roadmap](http://www.golangroadmap.com/)
|
- [mss-boot-io](https://docs.mss-boot-io.top/)
|
||||||
|
|
||||||
## 🔑 License
|
## 🔑 License
|
||||||
|
|
||||||
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||||
|
|
||||||
Copyright (c) 2020 wenjianzhang
|
Copyright (c) 2026 wenjianzhang
|
||||||
|
|||||||
+344
@@ -0,0 +1,344 @@
|
|||||||
|
# go-admin
|
||||||
|
|
||||||
|
<img align="right" width="320" src="https://doc-image.zhangwj.com/img/go-admin.svg">
|
||||||
|
|
||||||
|
|
||||||
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
[](https://github.com/go-admin-team/go-admin/releases)
|
||||||
|
[](https://github.com/go-admin-team/go-admin)
|
||||||
|
|
||||||
|
[English](https://github.com/go-admin-team/go-admin/blob/master/README.md) | [简体中文](https://github.com/go-admin-team/go-admin/blob/master/README.Zh-cn.md) | 繁體中文 | [日本語](https://github.com/go-admin-team/go-admin/blob/master/README.ja-JP.md)
|
||||||
|
|
||||||
|
基於 Gin + Vue + Element UI OR Arco Design OR Ant Design 的前後端分離權限管理系統。系統初始化極為簡單,只需在設定檔中修改資料庫連線資訊即可。系統支援多指令操作:遷移指令讓資料庫初始化變得更簡單,服務指令則能輕鬆啟動 API 服務。
|
||||||
|
|
||||||
|
[線上文件](https://www.go-admin.pro)
|
||||||
|
|
||||||
|
[前端專案](https://github.com/go-admin-team/go-admin-ui)
|
||||||
|
|
||||||
|
[影片教學](https://space.bilibili.com/565616721/channel/detail?cid=125737)
|
||||||
|
|
||||||
|
## 🎬 線上體驗
|
||||||
|
|
||||||
|
Element Plus vue3 體驗:[https://vue.go-admin.pro](https://vue.go-admin.pro/#/login)
|
||||||
|
> ⚠️⚠️⚠️ 帳號 / 密碼: admin / 123456
|
||||||
|
|
||||||
|
antd 體驗(go-admin-pro):[https://antd.go-admin.pro](https://antd.go-admin.pro/)
|
||||||
|
> ⚠️⚠️⚠️ 帳號 / 密碼: admin / 123456
|
||||||
|
|
||||||
|
## ✨ 特性
|
||||||
|
|
||||||
|
- 遵循 RESTful API 設計規範
|
||||||
|
|
||||||
|
- 基於 GIN WEB API 框架,提供豐富的中介軟體支援(使用者認證、跨域、存取日誌、追蹤 ID 等)
|
||||||
|
|
||||||
|
- 基於 Casbin 的 RBAC 存取控制模型
|
||||||
|
|
||||||
|
- JWT 認證
|
||||||
|
|
||||||
|
- 支援 Swagger 文件(基於 swaggo)
|
||||||
|
|
||||||
|
- 基於 GORM 的資料庫儲存,可擴充多種類型資料庫
|
||||||
|
|
||||||
|
- 設定檔簡單的模型映射,快速取得所需設定
|
||||||
|
|
||||||
|
- 程式碼產生工具
|
||||||
|
|
||||||
|
- 表單建構工具
|
||||||
|
|
||||||
|
- 多指令模式
|
||||||
|
|
||||||
|
- 多租戶的支援
|
||||||
|
|
||||||
|
- TODO: 單元測試
|
||||||
|
|
||||||
|
## 🎁 內建
|
||||||
|
|
||||||
|
1. 多租戶:系統預設支援多租戶,按資料庫分離,一個資料庫一個租戶。
|
||||||
|
1. 使用者管理:使用者是系統操作者,該功能主要完成系統使用者設定。
|
||||||
|
2. 部門管理:設定系統組織架構(公司、部門、小組),以樹狀結構呈現並支援資料權限。
|
||||||
|
3. 職位管理:設定系統使用者所擔任的職務。
|
||||||
|
4. 選單管理:設定系統選單、操作權限、按鈕權限標識、介面權限等。
|
||||||
|
5. 角色管理:角色選單權限分配、設定角色按機構進行資料範圍權限劃分。
|
||||||
|
6. 字典管理:對系統中經常使用且較為固定的資料進行維護。
|
||||||
|
7. 參數管理:對系統動態設定常用參數。
|
||||||
|
8. 操作日誌:系統正常操作的日誌記錄與查詢;系統異常資訊的日誌記錄與查詢。
|
||||||
|
9. 登入日誌:系統登入日誌記錄查詢,包含登入異常。
|
||||||
|
1. 介面文件:根據業務程式碼自動產生相關的 API 介面文件。
|
||||||
|
1. 程式碼產生:根據資料表結構產生對應的增刪改查業務,全程視覺化操作,讓基本業務可以零程式碼實現。
|
||||||
|
1. 表單建構:自訂頁面樣式,拖拉放實現頁面佈局。
|
||||||
|
1. 服務監控:檢視伺服器的基本資訊。
|
||||||
|
1. 內容管理:demo 功能,下設分類管理、內容管理,可參考使用以快速入門。
|
||||||
|
1. 排程任務:自動化任務,目前支援介面呼叫與函式呼叫。
|
||||||
|
|
||||||
|
## 準備工作
|
||||||
|
|
||||||
|
你需要在本機安裝 [go] [gin] [node](http://nodejs.org/) 和 [git](https://git-scm.com/)
|
||||||
|
|
||||||
|
同時配套了系列教學(含影片與文件),說明如何從下載到熟練使用。強烈建議先看完這些教學再來實作本專案!!!
|
||||||
|
|
||||||
|
### 輕鬆用 go-admin 寫出第一個應用 - 文件教學
|
||||||
|
|
||||||
|
[步驟一 - 基礎內容介紹](https://www.go-admin.pro/guide/intro/tutorial01.html)
|
||||||
|
|
||||||
|
[步驟二 - 實際應用 - 撰寫增刪改查](https://www.go-admin.pro/guide/intro/tutorial02.html)
|
||||||
|
|
||||||
|
### 手把手教你從入門到放棄 - 影片教學
|
||||||
|
|
||||||
|
[如何啟動 go-admin](https://www.bilibili.com/video/BV1z5411x7JG)
|
||||||
|
|
||||||
|
[使用產生工具輕鬆實現業務](https://www.bilibili.com/video/BV1Dg4y1i79D)
|
||||||
|
|
||||||
|
[v1.1.0 版本程式碼產生工具 - 釋放雙手](https://www.bilibili.com/video/BV1N54y1i71P) [進階]
|
||||||
|
|
||||||
|
[多指令啟動方式講解以及 IDE 設定](https://www.bilibili.com/video/BV1Fg4y1q7ph)
|
||||||
|
|
||||||
|
[go-admin 選單的設定說明](https://www.bilibili.com/video/BV1Wp4y1D715) [必看]
|
||||||
|
|
||||||
|
[如何設定選單資訊以及介面資訊](https://www.bilibili.com/video/BV1zv411B7nG) [必看]
|
||||||
|
|
||||||
|
[go-admin 權限設定使用說明](https://www.bilibili.com/video/BV1rt4y197d3) [必看]
|
||||||
|
|
||||||
|
[go-admin 資料權限使用說明](https://www.bilibili.com/video/BV1LK4y1s71e) [必看]
|
||||||
|
|
||||||
|
**如有問題請先參閱上述文件與文章,若仍無法解決,歡迎提出 issue 與 pr。影片教學與文件持續更新中**
|
||||||
|
|
||||||
|
## 📦 本機開發
|
||||||
|
|
||||||
|
### 環境需求
|
||||||
|
|
||||||
|
go 1.26.5
|
||||||
|
|
||||||
|
node 版本: v22+(建議 v24 LTS)
|
||||||
|
|
||||||
|
套件管理器: pnpm v9+(UI 專案使用 pnpm)
|
||||||
|
|
||||||
|
### 建立開發目錄
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
# 建立開發目錄
|
||||||
|
mkdir goadmin
|
||||||
|
cd goadmin
|
||||||
|
```
|
||||||
|
|
||||||
|
### 取得程式碼
|
||||||
|
|
||||||
|
> 重點注意:兩個專案必須放在同一資料夾下;
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 取得後端程式碼
|
||||||
|
git clone https://github.com/go-admin-team/go-admin.git
|
||||||
|
|
||||||
|
# 取得前端程式碼
|
||||||
|
git clone https://github.com/go-admin-team/go-admin-ui.git
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 啟動說明
|
||||||
|
|
||||||
|
#### 伺服器端啟動說明
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 進入 go-admin 後端專案
|
||||||
|
cd ./go-admin
|
||||||
|
|
||||||
|
# 更新整理相依套件
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
# 編譯專案
|
||||||
|
go build
|
||||||
|
|
||||||
|
# 修改設定
|
||||||
|
# 檔案路徑 go-admin/config/settings.yml
|
||||||
|
vi ./config/settings.yml
|
||||||
|
|
||||||
|
# 1. 在設定檔中修改資料庫資訊
|
||||||
|
# 注意: settings.database 下對應的設定資料
|
||||||
|
# 2. 確認 log 路徑
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️注意 在 Windows 環境若未安裝 CGO,會出現這個問題;
|
||||||
|
|
||||||
|
```bash
|
||||||
|
E:\go-admin>go build
|
||||||
|
# github.com/mattn/go-sqlite3
|
||||||
|
cgo: exec /missing-cc: exec: "/missing-cc": file does not exist
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
D:\Code\go-admin>go build
|
||||||
|
# github.com/mattn/go-sqlite3
|
||||||
|
cgo: exec gcc: exec: "gcc": executable file not found in %PATH%
|
||||||
|
```
|
||||||
|
|
||||||
|
[解決 cgo 問題請進入](https://www.go-admin.pro/zh-CN/guide/faq#cgo-%E7%9A%84%E9%97%AE%E9%A2%98)
|
||||||
|
|
||||||
|
|
||||||
|
#### 初始化資料庫,以及服務啟動
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# 首次設定需要初始化資料庫資源資訊
|
||||||
|
# macOS or linux 下使用
|
||||||
|
$ ./go-admin migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
|
# ⚠️注意:windows 下使用
|
||||||
|
$ go-admin.exe migrate -c config/settings.dev.yml
|
||||||
|
|
||||||
|
|
||||||
|
# 啟動專案,也可以用 IDE 進行除錯
|
||||||
|
# macOS or linux 下使用
|
||||||
|
$ ./go-admin server -c config/settings.yml
|
||||||
|
|
||||||
|
|
||||||
|
# ⚠️注意:windows 下使用
|
||||||
|
$ go-admin.exe server -c config/settings.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
#### sys_api 表的資料如何新增
|
||||||
|
|
||||||
|
在專案啟動時,使用 `-a true` 系統會自動新增缺少的介面資料
|
||||||
|
```bash
|
||||||
|
./go-admin server -c config/settings.yml -a true
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 使用 docker 編譯啟動
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# 編譯映像檔
|
||||||
|
docker build -t go-admin .
|
||||||
|
|
||||||
|
# 啟動容器,第一個 go-admin 是容器名稱,第二個 go-admin 是映像檔名稱
|
||||||
|
# -v 映射設定檔 本機路徑:容器路徑
|
||||||
|
docker run --name go-admin -p 8000:8000 -v /config/settings.yml:/config/settings.yml -d go-admin-server
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 文件產生
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go generate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 交叉編譯
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# windows
|
||||||
|
env GOOS=windows GOARCH=amd64 go build main.go
|
||||||
|
|
||||||
|
# or
|
||||||
|
# linux
|
||||||
|
env GOOS=linux GOARCH=amd64 go build main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI 互動端啟動說明
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 安裝 pnpm(若未安裝)
|
||||||
|
npm install -g pnpm
|
||||||
|
|
||||||
|
# 安裝相依套件
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# 中國大陸網路可指定鏡像來源加速
|
||||||
|
pnpm install --registry=https://registry.npmmirror.com
|
||||||
|
|
||||||
|
# 啟動服務
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📨 互動
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/wx.png" width="180px"></td>
|
||||||
|
<td><img src="https://doc-image.zhangwj.com/img/qrcode_for_gh_b798dc7db30c_258.jpg" width="180px"></td>
|
||||||
|
<td><img src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/qq2.png" width="200px"></td>
|
||||||
|
<td><a href="https://space.bilibili.com/565616721">wenjianzhang</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>微信</td>
|
||||||
|
<td>公众号🔥🔥🔥</td>
|
||||||
|
<td><a target="_blank" href="https://shang.qq.com/wpa/qunwpa?idkey=0f2bf59f5f2edec6a4550c364242c0641f870aa328e468c4ee4b7dbfb392627b"><img border="0" src="https://pub.idqqimg.com/wpa/images/group.png" alt="go-admin技术交流乙号" title="go-admin技术交流乙号"></a></td>
|
||||||
|
<td>哔哩哔哩🔥🔥🔥</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## 💎 貢獻者
|
||||||
|
|
||||||
|
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wenjianzhang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3890175?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/G-Akiraka" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45746659?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/lwnmengjing" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/12806223?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bing127" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31166183?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/chengxiao" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1379545?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NightFire0307" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19854086?v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/appleboy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/21979?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/ninstein" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/580303?v=4&h=60&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/kikiyou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/17959053?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/horizonzy" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/22524871?s=64&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/nodece" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16235121?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stephenzhang0713" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/18169290?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhouxixi-dev" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/100399679?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Jalins" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/31172582?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxxiong6" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/6983441?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/GizmoOAO" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20385106?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/bestgopher" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/36840497?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/wxb1207" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/20775558?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/misakichan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/16569274?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zhuxuyang" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/19301024?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/mss-boot" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/109259065?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/AuroraV" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/37330199?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Vingurzhou" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/57127283?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/haimait" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/40926384?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/zyd" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/3446278?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/infnan" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/38274826?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/d1y" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/45585937?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/qlijin" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/515900?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/stepway
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/9927079?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/NaturalGao
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/43291304?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/DemoLiang
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/23476007?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/jfcg
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/1410597?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
<span style="margin: 0 5px;" ><a href="https://github.com/Nicole0724
|
||||||
|
" ><img src="https://images.weserv.nl/?url=avatars.githubusercontent.com/u/10487328?s=60&v=4&w=60&fit=cover&mask=circle&maxage=7d" /></a></span>
|
||||||
|
## JetBrains 開源證書支援
|
||||||
|
|
||||||
|
`go-admin` 專案一直以來都是在 JetBrains 公司旗下的 GoLand 整合開發環境中進行開發,基於 **free JetBrains Open Source license(s)** 正版免費授權,在此表達我的謝意。
|
||||||
|
|
||||||
|
<a href="https://www.jetbrains.com/?from=kubeadm-ha" target="_blank"><img src="https://raw.githubusercontent.com/panjf2000/illustrations/master/jetbrains/jetbrains-variant-4.png" width="250" align="middle"/></a>
|
||||||
|
|
||||||
|
## 🤝 特別感謝
|
||||||
|
|
||||||
|
1. [ant-design](https://github.com/ant-design/ant-design)
|
||||||
|
2. [ant-design-pro](https://github.com/ant-design/ant-design-pro)
|
||||||
|
2. [arco-design](https://github.com/arco-design/arco-design)
|
||||||
|
2. [arco-design-pro](https://github.com/arco-design/arco-design-pro)
|
||||||
|
4. [gin](https://github.com/gin-gonic/gin)
|
||||||
|
5. [casbin](https://github.com/casbin/casbin)
|
||||||
|
6. [spf13/viper](https://github.com/spf13/viper)
|
||||||
|
7. [gorm](https://github.com/go-gorm/gorm)
|
||||||
|
8. [gin-swagger](https://github.com/swaggo/gin-swagger)
|
||||||
|
9. [golang-jwt](https://github.com/golang-jwt/jwt)
|
||||||
|
10. [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||||
|
11. [ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||||
|
12. [form-generator](https://github.com/JakHuang/form-generator)
|
||||||
|
|
||||||
|
## 🤟 贊助
|
||||||
|
|
||||||
|
> 如果你覺得這個專案幫助到了你,可以幫作者買一杯果汁表示鼓勵 :tropical_drink:
|
||||||
|
|
||||||
|
<img class="no-margin" src="https://raw.githubusercontent.com/wenjianzhang/image/master/img/pay.png" height="200px" >
|
||||||
|
|
||||||
|
## 🤝 連結
|
||||||
|
|
||||||
|
- [mss-boot-io](https://docs.mss-boot-io.top/)
|
||||||
|
|
||||||
|
## 🔑 License
|
||||||
|
|
||||||
|
[MIT](https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md)
|
||||||
|
|
||||||
|
Copyright (c) 2026 wenjianzhang
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/captcha"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type System struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateCaptchaHandler 获取验证码
|
||||||
|
// @Summary 获取验证码
|
||||||
|
// @Description 获取验证码
|
||||||
|
// @Tags 登陆
|
||||||
|
// @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/captcha [get]
|
||||||
|
func (e System) GenerateCaptchaHandler(c *gin.Context) {
|
||||||
|
if err := e.MakeContext(c).Errors; err != nil {
|
||||||
|
e.Error(500, err, "服务初始化失败!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// The answer is deliberately discarded rather than logged. It used to be
|
||||||
|
// written at info level, which put a currently valid captcha answer in the
|
||||||
|
// application log - anyone able to read the log could bypass the check the
|
||||||
|
// captcha exists to enforce.
|
||||||
|
id, b64s, _, err := captcha.DriverDigitFunc()
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errorf("DriverDigitFunc error, %s", err.Error())
|
||||||
|
e.Error(500, err, "验证码获取失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.Custom(gin.H{
|
||||||
|
"code": 200,
|
||||||
|
"data": b64s,
|
||||||
|
"id": id,
|
||||||
|
"msg": "success",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package system
|
package apis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -11,13 +11,14 @@ const INDEX = `
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>GO-ADMIN欢迎您</title>
|
<title>GO-ADMIN欢迎您</title>
|
||||||
<style>
|
<style>
|
||||||
body{
|
html,body{
|
||||||
margin:0;
|
margin:0;
|
||||||
padding:0;
|
padding:0;
|
||||||
overflow-y:hidden
|
height:100%;
|
||||||
|
overflow-y:hidden;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
|
<script src="https://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.onerror=function(){return true;}
|
window.onerror=function(){return true;}
|
||||||
$(function(){
|
$(function(){
|
||||||
@@ -28,12 +29,12 @@ $(function(){
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<iframe id="iframe" frameborder="0" src="https://doc.go-admin.dev" style="width:100%;"></iframe>
|
<iframe id="iframe" frameborder="0" src="https://www.go-admin.pro" style="width:100%;height:100%;"></iframe>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
func HelloWorld(c *gin.Context) {
|
func GoAdmin(c *gin.Context) {
|
||||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
c.String(200, INDEX)
|
c.String(200, INDEX)
|
||||||
}
|
}
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package monitor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
"github.com/shirou/gopsutil/cpu"
|
|
||||||
"github.com/shirou/gopsutil/disk"
|
|
||||||
"github.com/shirou/gopsutil/mem"
|
|
||||||
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
B = 1
|
|
||||||
KB = 1024 * B
|
|
||||||
MB = 1024 * KB
|
|
||||||
GB = 1024 * MB
|
|
||||||
)
|
|
||||||
|
|
||||||
type Monitor struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 系统信息
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 系统信息
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/settings/serverInfo [get]
|
|
||||||
func (e Monitor) ServerInfo(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
|
|
||||||
osDic := make(map[string]interface{}, 0)
|
|
||||||
osDic["goOs"] = runtime.GOOS
|
|
||||||
osDic["arch"] = runtime.GOARCH
|
|
||||||
osDic["mem"] = runtime.MemProfileRate
|
|
||||||
osDic["compiler"] = runtime.Compiler
|
|
||||||
osDic["version"] = runtime.Version()
|
|
||||||
osDic["numGoroutine"] = runtime.NumGoroutine()
|
|
||||||
osDic["ip"] = pkg.GetLocaHonst()
|
|
||||||
osDic["projectDir"] = pkg.GetCurrentPath()
|
|
||||||
|
|
||||||
dis, _ := disk.Usage("/")
|
|
||||||
diskTotalGB := int(dis.Total) / GB
|
|
||||||
diskFreeGB := int(dis.Free) / GB
|
|
||||||
diskDic := make(map[string]interface{}, 0)
|
|
||||||
diskDic["total"] = diskTotalGB
|
|
||||||
diskDic["free"] = diskFreeGB
|
|
||||||
|
|
||||||
mem, _ := mem.VirtualMemory()
|
|
||||||
memUsedMB := int(mem.Used) / GB
|
|
||||||
memTotalMB := int(mem.Total) / GB
|
|
||||||
memFreeMB := int(mem.Free) / GB
|
|
||||||
memUsedPercent := int(mem.UsedPercent)
|
|
||||||
memDic := make(map[string]interface{}, 0)
|
|
||||||
memDic["total"] = memTotalMB
|
|
||||||
memDic["used"] = memUsedMB
|
|
||||||
memDic["free"] = memFreeMB
|
|
||||||
memDic["usage"] = memUsedPercent
|
|
||||||
|
|
||||||
cpuDic := make(map[string]interface{}, 0)
|
|
||||||
cpuDic["cpuInfo"], _ = cpu.Info()
|
|
||||||
percent, _ := cpu.Percent(0, false)
|
|
||||||
cpuDic["Percent"] = pkg.Round(percent[0], 2)
|
|
||||||
cpuDic["cpuNum"], _ = cpu.Counts(false)
|
|
||||||
|
|
||||||
e.Custom(gin.H{
|
|
||||||
"code": 200,
|
|
||||||
"os": osDic,
|
|
||||||
"mem": memDic,
|
|
||||||
"cpu": cpuDic,
|
|
||||||
"disk": diskDic,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
package public
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/utils"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"go-admin/common/apis"
|
|
||||||
"go-admin/common/file_store"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FileResponse struct {
|
|
||||||
Size int64 `json:"size"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
FullPath string `json:"full_path"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = "static/uploadfile/"
|
|
||||||
|
|
||||||
type File struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 上传图片
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 公共接口
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Param type query string true "type" (1:单图,2:多图, 3:base64图片)
|
|
||||||
// @Param file formData file true "file"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/public/uploadFile [post]
|
|
||||||
func (e File) UploadFile(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
|
|
||||||
tag, _ := c.GetPostForm("type")
|
|
||||||
urlPerfix := fmt.Sprintf("http://%s/", c.Request.Host)
|
|
||||||
var fileResponse FileResponse
|
|
||||||
if tag == "" {
|
|
||||||
e.Error(500, nil, "缺少标识")
|
|
||||||
//app.Error(c, 200, errors.New(""), "缺少标识")
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
switch tag {
|
|
||||||
case "1": // 单图
|
|
||||||
var done bool
|
|
||||||
fileResponse, done = e.singleFile(c, fileResponse, urlPerfix)
|
|
||||||
if done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(fileResponse, "上传成功")
|
|
||||||
return
|
|
||||||
case "2": // 多图
|
|
||||||
multipartFile := e.multipleFile(c, urlPerfix)
|
|
||||||
e.OK(multipartFile, "上传成功")
|
|
||||||
return
|
|
||||||
case "3": // base64
|
|
||||||
fileResponse = e.baseImg(c, fileResponse, urlPerfix)
|
|
||||||
e.OK(fileResponse, "上传成功")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e File) baseImg(c *gin.Context, fileResponse FileResponse, urlPerfix string) FileResponse {
|
|
||||||
files, _ := c.GetPostForm("file")
|
|
||||||
file2list := strings.Split(files, ",")
|
|
||||||
ddd, _ := base64.StdEncoding.DecodeString(file2list[1])
|
|
||||||
guid := uuid.New().String()
|
|
||||||
fileName := guid + ".jpg"
|
|
||||||
err := utils.IsNotExistMkDir(path)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(500, errors.New(""), "初始化文件路径失败")
|
|
||||||
}
|
|
||||||
base64File := path + fileName
|
|
||||||
_ = ioutil.WriteFile(base64File, ddd, 0666)
|
|
||||||
typeStr := strings.Replace(strings.Replace(file2list[0], "data:", "", -1), ";base64", "", -1)
|
|
||||||
fileResponse = FileResponse{
|
|
||||||
Size: pkg.GetFileSize(base64File),
|
|
||||||
Path: base64File,
|
|
||||||
FullPath: urlPerfix + base64File,
|
|
||||||
Name: "",
|
|
||||||
Type: typeStr,
|
|
||||||
}
|
|
||||||
source, _ := c.GetPostForm("source")
|
|
||||||
err = thirdUpload(source, fileName, base64File)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(200, errors.New(""), "上传第三方失败")
|
|
||||||
return fileResponse
|
|
||||||
}
|
|
||||||
if source != "1" {
|
|
||||||
fileResponse.Path = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
fileResponse.FullPath = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
}
|
|
||||||
return fileResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e File) multipleFile(c *gin.Context, urlPerfix string) []FileResponse {
|
|
||||||
files := c.Request.MultipartForm.File["file"]
|
|
||||||
source, _ := c.GetPostForm("source")
|
|
||||||
var multipartFile []FileResponse
|
|
||||||
for _, f := range files {
|
|
||||||
guid := uuid.New().String()
|
|
||||||
fileName := guid + utils.GetExt(f.Filename)
|
|
||||||
|
|
||||||
err := utils.IsNotExistMkDir(path)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(500, errors.New(""), "初始化文件路径失败")
|
|
||||||
}
|
|
||||||
multipartFileName := path + fileName
|
|
||||||
err1 := c.SaveUploadedFile(f, multipartFileName)
|
|
||||||
fileType, _ := utils.GetType(multipartFileName)
|
|
||||||
if err1 == nil {
|
|
||||||
err := thirdUpload(source, fileName, multipartFileName)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(500, errors.New(""), "上传第三方失败")
|
|
||||||
} else {
|
|
||||||
fileResponse := FileResponse{
|
|
||||||
Size: pkg.GetFileSize(multipartFileName),
|
|
||||||
Path: multipartFileName,
|
|
||||||
FullPath: urlPerfix + multipartFileName,
|
|
||||||
Name: f.Filename,
|
|
||||||
Type: fileType,
|
|
||||||
}
|
|
||||||
if source != "1" {
|
|
||||||
fileResponse.Path = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
fileResponse.FullPath = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
}
|
|
||||||
multipartFile = append(multipartFile, fileResponse)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return multipartFile
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e File) singleFile(c *gin.Context, fileResponse FileResponse, urlPerfix string) (FileResponse, bool) {
|
|
||||||
files, err := c.FormFile("file")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
e.Error(200, errors.New(""), "图片不能为空")
|
|
||||||
return FileResponse{}, true
|
|
||||||
}
|
|
||||||
// 上传文件至指定目录
|
|
||||||
guid := uuid.New().String()
|
|
||||||
|
|
||||||
fileName := guid + utils.GetExt(files.Filename)
|
|
||||||
|
|
||||||
err = utils.IsNotExistMkDir(path)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(500, errors.New(""), "初始化文件路径失败")
|
|
||||||
}
|
|
||||||
singleFile := path + fileName
|
|
||||||
_ = c.SaveUploadedFile(files, singleFile)
|
|
||||||
fileType, _ := utils.GetType(singleFile)
|
|
||||||
fileResponse = FileResponse{
|
|
||||||
Size: pkg.GetFileSize(singleFile),
|
|
||||||
Path: singleFile,
|
|
||||||
FullPath: urlPerfix + singleFile,
|
|
||||||
Name: files.Filename,
|
|
||||||
Type: fileType,
|
|
||||||
}
|
|
||||||
source, _ := c.GetPostForm("source")
|
|
||||||
err = thirdUpload(source, fileName, singleFile)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(200, errors.New(""), "上传第三方失败")
|
|
||||||
return FileResponse{}, true
|
|
||||||
}
|
|
||||||
fileResponse.Path = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
fileResponse.FullPath = "https://youshikeji.oss-cn-shanghai.aliyuncs.com/img/" + fileName
|
|
||||||
return fileResponse, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func thirdUpload(source string, name string, path string) error {
|
|
||||||
switch source {
|
|
||||||
case "2":
|
|
||||||
return ossUpload("img/"+name, path)
|
|
||||||
case "3":
|
|
||||||
return qiniuUpload("img/"+name, path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ossUpload(name string, path string) error {
|
|
||||||
oss := file_store.ALiYunOSS{}
|
|
||||||
return oss.UpLoad(name, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func qiniuUpload(name string, path string) error {
|
|
||||||
oss := file_store.ALiYunOSS{}
|
|
||||||
return oss.UpLoad(name, path)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
"go-admin/common/actions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysApi struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage 获取接口管理列表
|
||||||
|
// @Summary 获取接口管理列表
|
||||||
|
// @Description 获取接口管理列表
|
||||||
|
// @Tags 接口管理
|
||||||
|
// @Param name query string false "名称"
|
||||||
|
// @Param title query string false "标题"
|
||||||
|
// @Param path query string false "地址"
|
||||||
|
// @Param action query string false "类型"
|
||||||
|
// @Param pageSize query int false "页条数"
|
||||||
|
// @Param pageIndex query int false "页码"
|
||||||
|
// @Success 200 {object} response.Response{data=response.Page{list=[]models.SysApi}} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-api [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysApi) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysApi{}
|
||||||
|
req := dto.SysApiGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
list := make([]models.SysApi, 0)
|
||||||
|
var count int64
|
||||||
|
err = s.GetPage(&req, p, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 获取接口管理
|
||||||
|
// @Summary 获取接口管理
|
||||||
|
// @Description 获取接口管理
|
||||||
|
// @Tags 接口管理
|
||||||
|
// @Param id path string false "id"
|
||||||
|
// @Success 200 {object} response.Response{data=models.SysApi} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-api/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysApi) Get(c *gin.Context) {
|
||||||
|
req := dto.SysApiGetReq{}
|
||||||
|
s := service.SysApi{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
var object models.SysApi
|
||||||
|
err = s.Get(&req, p, &object).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 修改接口管理
|
||||||
|
// @Summary 修改接口管理
|
||||||
|
// @Description 修改接口管理
|
||||||
|
// @Tags 接口管理
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysApiUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||||
|
// @Router /api/v1/sys-api/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysApi) Update(c *gin.Context) {
|
||||||
|
req := dto.SysApiUpdateReq{}
|
||||||
|
s := service.SysApi{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
err = s.Update(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "更新失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSysApi 删除接口管理
|
||||||
|
// @Summary 删除接口管理
|
||||||
|
// @Description 删除接口管理
|
||||||
|
// @Tags 接口管理
|
||||||
|
// @Param data body dto.SysApiDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
|
||||||
|
// @Router /api/v1/sys-api [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysApi) DeleteSysApi(c *gin.Context) {
|
||||||
|
req := dto.SysApiDeleteReq{}
|
||||||
|
s := service.SysApi{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
err = s.Remove(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
package sys_china_area_data
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysChinaAreaData struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysChinaAreaData) GetSysChinaAreaDataList(c *gin.Context) {
|
|
||||||
e.SetContext(c)
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysChinaAreaDataSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
list := make([]models.SysChinaAreaData, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysChinaAreaData{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysChinaAreaDataPage(d, p, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysChinaAreaData) GetSysChinaAreaData(c *gin.Context) {
|
|
||||||
e.SetContext(c)
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysChinaAreaDataById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object models.SysChinaAreaData
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysChinaAreaData := service.SysChinaAreaData{}
|
|
||||||
serviceSysChinaAreaData.Log = log
|
|
||||||
serviceSysChinaAreaData.Orm = db
|
|
||||||
err = serviceSysChinaAreaData.GetSysChinaAreaData(control, p, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysChinaAreaData) InsertSysChinaAreaData(c *gin.Context) {
|
|
||||||
e.SetContext(c)
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysChinaAreaDataControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysChinaAreaData := service.SysChinaAreaData{}
|
|
||||||
serviceSysChinaAreaData.Orm = db
|
|
||||||
serviceSysChinaAreaData.Log = log
|
|
||||||
err = serviceSysChinaAreaData.InsertSysChinaAreaData(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysChinaAreaData) UpdateSysChinaAreaData(c *gin.Context) {
|
|
||||||
e.SetContext(c)
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysChinaAreaDataControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysChinaAreaData := service.SysChinaAreaData{}
|
|
||||||
serviceSysChinaAreaData.Orm = db
|
|
||||||
serviceSysChinaAreaData.Log = log
|
|
||||||
err = serviceSysChinaAreaData.UpdateSysChinaAreaData(object, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysChinaAreaData) DeleteSysChinaAreaData(c *gin.Context) {
|
|
||||||
e.SetContext(c)
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysChinaAreaDataById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
control.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysChinaAreaData := service.SysChinaAreaData{}
|
|
||||||
serviceSysChinaAreaData.Orm = db
|
|
||||||
serviceSysChinaAreaData.Log = log
|
|
||||||
err = serviceSysChinaAreaData.RemoveSysChinaAreaData(control, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysChinaAreaData error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysConfig struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage 获取配置管理列表
|
||||||
|
// @Summary 获取配置管理列表
|
||||||
|
// @Description 获取配置管理列表
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Param configName query string false "名称"
|
||||||
|
// @Param configKey query string false "key"
|
||||||
|
// @Param configType query string false "类型"
|
||||||
|
// @Param isFrontend query int false "是否前端"
|
||||||
|
// @Param pageSize query int false "页条数"
|
||||||
|
// @Param pageIndex query int false "页码"
|
||||||
|
// @Success 200 {object} response.Response{data=response.Page{list=[]models.SysApi}} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-config [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := dto.SysConfigGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]models.SysConfig, 0)
|
||||||
|
var count int64
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 获取配置管理
|
||||||
|
// @Summary 获取配置管理
|
||||||
|
// @Description 获取配置管理
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Param id path string false "id"
|
||||||
|
// @Success 200 {object} response.Response{data=models.SysConfig} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-config/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Get(c *gin.Context) {
|
||||||
|
req := dto.SysConfigGetReq{}
|
||||||
|
s := service.SysConfig{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysConfig
|
||||||
|
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert 创建配置管理
|
||||||
|
// @Summary 创建配置管理
|
||||||
|
// @Description 创建配置管理
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysConfigControl true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "创建成功"}"
|
||||||
|
// @Router /api/v1/sys-config [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Insert(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := dto.SysConfigControl{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "创建失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 修改配置管理
|
||||||
|
// @Summary 修改配置管理
|
||||||
|
// @Description 修改配置管理
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysConfigControl true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||||
|
// @Router /api/v1/sys-config/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Update(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := dto.SysConfigControl{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Update(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "更新失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 删除配置管理
|
||||||
|
// @Summary 删除配置管理
|
||||||
|
// @Description 删除配置管理
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Param ids body []int false "ids"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
|
||||||
|
// @Router /api/v1/sys-config [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Delete(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := dto.SysConfigDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get2SysApp 获取系统配置信息
|
||||||
|
// @Summary 获取系统前台配置信息,主要注意这里不在验证权限
|
||||||
|
// @Description 获取系统配置信息,主要注意这里不在验证权限
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Success 200 {object} response.Response{data=map[string]string} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/app-config [get]
|
||||||
|
func (e SysConfig) Get2SysApp(c *gin.Context) {
|
||||||
|
req := dto.SysConfigGetToSysAppReq{}
|
||||||
|
s := service.SysConfig{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 控制只读前台的数据
|
||||||
|
req.IsFrontend = "1"
|
||||||
|
list := make([]models.SysConfig, 0)
|
||||||
|
err = s.GetWithKeyList(&req, &list)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mp := make(map[string]string)
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
key := list[i].ConfigKey
|
||||||
|
if key != "" {
|
||||||
|
mp[key] = list[i].ConfigValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.OK(mp, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get2Set 获取配置
|
||||||
|
// @Summary 获取配置
|
||||||
|
// @Description 界面操作设置配置值的获取
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Success 200 {object} response.Response{data=map[string]interface{}} "{"code": 200, "message": "修改成功"}"
|
||||||
|
// @Router /api/v1/set-config [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Get2Set(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := make([]dto.GetSetSysConfigReq, 0)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = s.GetForSet(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m := make(map[string]interface{}, 0)
|
||||||
|
for _, v := range req {
|
||||||
|
m[v.ConfigKey] = v.ConfigValue
|
||||||
|
}
|
||||||
|
e.OK(m, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update2Set 设置配置
|
||||||
|
// @Summary 设置配置
|
||||||
|
// @Description 界面操作设置配置值
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body []dto.GetSetSysConfigReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||||
|
// @Router /api/v1/set-config [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) Update2Set(c *gin.Context) {
|
||||||
|
s := service.SysConfig{}
|
||||||
|
req := make([]dto.GetSetSysConfigReq, 0)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.UpdateForSet(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK("", "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSysConfigByKEYForService 根据Key获取SysConfig的Service
|
||||||
|
// @Summary 根据Key获取SysConfig的Service
|
||||||
|
// @Description 根据Key获取SysConfig的Service
|
||||||
|
// @Tags 配置管理
|
||||||
|
// @Param configKey path string false "configKey"
|
||||||
|
// @Success 200 {object} response.Response{data=dto.SysConfigByKeyReq} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-config/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysConfig) GetSysConfigByKEYForService(c *gin.Context) {
|
||||||
|
var s = new(service.SysConfig)
|
||||||
|
var req = new(dto.SysConfigByKeyReq)
|
||||||
|
var resp = new(dto.GetSysConfigByKEYForServiceResp)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.GetWithKey(req, resp)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(resp, s.Msg)
|
||||||
|
}
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/pkg"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysDept struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage
|
||||||
|
// @Summary 分页部门列表数据
|
||||||
|
// @Description 分页列表
|
||||||
|
// @Tags 部门
|
||||||
|
// @Param deptName query string false "deptName"
|
||||||
|
// @Param deptId query string false "deptId"
|
||||||
|
// @Param position query string false "position"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dept [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDept) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]models.SysDept, 0)
|
||||||
|
list, err = s.SetDeptPage(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(list, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
// @Summary 获取部门数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 部门
|
||||||
|
// @Param deptId path string false "deptId"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dept/{deptId} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDept) Get(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysDept
|
||||||
|
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert 添加部门
|
||||||
|
// @Summary 添加部门
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 部门
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysDeptInsertReq true "data"
|
||||||
|
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
||||||
|
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
||||||
|
// @Router /api/v1/dept [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDept) Insert(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置创建人
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "创建失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
// @Summary 修改部门
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 部门
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param id path int true "id"
|
||||||
|
// @Param data body dto.SysDeptUpdateReq true "body"
|
||||||
|
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
||||||
|
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
||||||
|
// @Router /api/v1/dept/{deptId} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDept) Update(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Update(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除部门
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 部门
|
||||||
|
// @Param data body dto.SysDeptDeleteReq true "body"
|
||||||
|
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
||||||
|
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
||||||
|
// @Router /api/v1/dept [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDept) Delete(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get2Tree 用户管理 左侧部门树
|
||||||
|
func (e SysDept) Get2Tree(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
req := dto.SysDeptGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]dto.DeptLabel, 0)
|
||||||
|
list, err = s.SetDeptTree(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(list, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDeptTreeRoleSelect TODO: 此接口需要调整不应该将list和选中放在一起
|
||||||
|
func (e SysDept) GetDeptTreeRoleSelect(c *gin.Context) {
|
||||||
|
s := service.SysDept{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := pkg.StringToInt(c.Param("roleId"))
|
||||||
|
result, err := s.SetDeptLabel()
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
menuIds := make([]int, 0)
|
||||||
|
if id != 0 {
|
||||||
|
menuIds, err = s.GetWithRoleId(id)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.OK(gin.H{
|
||||||
|
"depts": result,
|
||||||
|
"checkedKeys": menuIds,
|
||||||
|
}, "")
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysDictData struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage
|
||||||
|
// @Summary 字典数据列表
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Param status query string false "status"
|
||||||
|
// @Param dictCode query string false "dictCode"
|
||||||
|
// @Param dictType query string false "dictType"
|
||||||
|
// @Param pageSize query int false "页条数"
|
||||||
|
// @Param pageIndex query int false "页码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/data [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]models.SysDictData, 0)
|
||||||
|
var count int64
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
// @Summary 通过编码获取字典数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Param dictCode path int true "字典编码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/data/{dictCode} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) Get(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var object models.SysDictData
|
||||||
|
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Warnf("Get error: %s", err.Error())
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert
|
||||||
|
// @Summary 添加字典数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysDictDataInsertReq true "data"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
|
||||||
|
// @Router /api/v1/dict/data [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) Insert(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "创建失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
// @Summary 修改字典数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysDictDataUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
|
||||||
|
// @Router /api/v1/dict/data/{dictCode} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) Update(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Update(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "更新失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除字典数据
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Param dictCode body dto.SysDictDataDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
|
||||||
|
// @Router /api/v1/dict/data [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) Delete(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll 数据字典根据key获取 业务页面使用
|
||||||
|
// @Summary 数据字典根据key获取
|
||||||
|
// @Description 数据字典根据key获取
|
||||||
|
// @Tags 字典数据
|
||||||
|
// @Param dictType query int true "dictType"
|
||||||
|
// @Success 200 {object} response.Response{data=[]dto.SysDictDataGetAllResp} "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict-data/option-select [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictData) GetAll(c *gin.Context) {
|
||||||
|
s := service.SysDictData{}
|
||||||
|
req := dto.SysDictDataGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]models.SysDictData, 0)
|
||||||
|
err = s.GetAll(&req, &list)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l := make([]dto.SysDictDataGetAllResp, 0)
|
||||||
|
for _, i := range list {
|
||||||
|
d := dto.SysDictDataGetAllResp{}
|
||||||
|
e.Translate(i, &d)
|
||||||
|
l = append(l, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(l, "查询成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysDictType struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage 字典类型列表数据
|
||||||
|
// @Summary 字典类型列表数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Param dictName query string false "dictName"
|
||||||
|
// @Param dictId query string false "dictId"
|
||||||
|
// @Param dictType query string false "dictType"
|
||||||
|
// @Param pageSize query int false "页条数"
|
||||||
|
// @Param pageIndex query int false "页码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]models.SysDictType, 0)
|
||||||
|
var count int64
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 字典类型通过字典id获取
|
||||||
|
// @Summary 字典类型通过字典id获取
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Param dictId path int true "字典类型编码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type/{dictId} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) Get(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysDictType
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert 字典类型创建
|
||||||
|
// @Summary 添加字典类型
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysDictTypeInsertReq true "data"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) Insert(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, fmt.Sprintf(" 创建字典类型失败,详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
// @Summary 修改字典类型
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysDictTypeUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type/{dictId} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) Update(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Update(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除字典类型
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Param dictCode body dto.SysDictTypeDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) Delete(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll
|
||||||
|
// @Summary 字典类型全部数据 代码生成使用接口
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 字典类型
|
||||||
|
// @Param dictName query string false "dictName"
|
||||||
|
// @Param dictId query string false "dictId"
|
||||||
|
// @Param dictType query string false "dictType"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/dict/type-option-select [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysDictType) GetAll(c *gin.Context) {
|
||||||
|
s := service.SysDictType{}
|
||||||
|
req := dto.SysDictTypeGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]models.SysDictType, 0)
|
||||||
|
err = s.GetAll(&req, &list)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(list, "查询成功")
|
||||||
|
}
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
package sys_file
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysFileDir struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileDir) GetSysFileDirList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
search := new(dto.SysFileDirSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.ShouldBind(search)
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("ShouldBind error: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
var list *[]models.SysFileDirL
|
|
||||||
serviceStudent := service.SysFileDir{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
list, err = serviceStudent.SetSysFileDir(search)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("SetSysFileDir error, %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(list, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileDir) GetSysFileDir(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileDirById)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("ShouldBindUri error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
}
|
|
||||||
|
|
||||||
var object models.SysFileDir
|
|
||||||
|
|
||||||
serviceSysFileDir := service.SysFileDir{}
|
|
||||||
serviceSysFileDir.Log = log
|
|
||||||
serviceSysFileDir.Orm = db
|
|
||||||
err = serviceSysFileDir.GetSysFileDir(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetSysFileDir error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileDir) InsertSysFileDir(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileDirControl)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("ShouldBindUri error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("ShouldBind error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
control.CreateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
serviceSysFileDir := service.SysFileDir{}
|
|
||||||
serviceSysFileDir.Orm = db
|
|
||||||
serviceSysFileDir.Log = log
|
|
||||||
err = serviceSysFileDir.InsertSysFileDir(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("InsertSysFileDir error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(control.ID, "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileDir) UpdateSysFileDir(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileDirControl)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("ShouldBindUri error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("ShouldBind error: %#v", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
control.UpdateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysFileDir := service.SysFileDir{}
|
|
||||||
serviceSysFileDir.Orm = db
|
|
||||||
serviceSysFileDir.Log = log
|
|
||||||
err = serviceSysFileDir.UpdateSysFileDir(control, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("UpdateSysFileDir error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "更新失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.ID, "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileDir) DeleteSysFileDir(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileDirById)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msgID := pkg.GenerateMsgIDFromContext(c)
|
|
||||||
//删除操作
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("MsgID[%s] ShouldBindUri error: %s", msgID, err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("MsgID[%s] ShouldBind error: %#v", msgID, err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
control.UpdateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysFileDir := service.SysFileDir{}
|
|
||||||
serviceSysFileDir.Orm = db
|
|
||||||
serviceSysFileDir.MsgID = msgID
|
|
||||||
err = serviceSysFileDir.RemoveSysFileDir(control, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysFileDir error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.Id, "删除成功")
|
|
||||||
}
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
package sys_file
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysFileInfo struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileInfo) GetSysFileInfoList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
search := new(dto.SysFileInfoSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(search)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
list := make([]models.SysFileInfo, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysFileInfo{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysFileInfoPage(search, p, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetSysFileInfoPage error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), search.PageIndex, search.PageSize, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileInfo) GetSysFileInfo(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileInfoById)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error:%s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var object models.SysFileInfo
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysFileInfo := service.SysFileInfo{}
|
|
||||||
serviceSysFileInfo.Log = log
|
|
||||||
serviceSysFileInfo.Orm = db
|
|
||||||
err = serviceSysFileInfo.GetSysFileInfo(control, p, &object)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetSysFileInfo error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileInfo) InsertSysFileInfo(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileInfoControl)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
control.CreateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
serviceSysFileInfo := service.SysFileInfo{}
|
|
||||||
serviceSysFileInfo.Orm = db
|
|
||||||
serviceSysFileInfo.Log = log
|
|
||||||
err = serviceSysFileInfo.InsertSysFileInfo(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("InsertSysFileInfo error: %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(control.ID, "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileInfo) UpdateSysFileInfo(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileInfoControl)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error:%s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
control.UpdateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysFileInfo := service.SysFileInfo{}
|
|
||||||
serviceSysFileInfo.Orm = db
|
|
||||||
serviceSysFileInfo.Log = log
|
|
||||||
err = serviceSysFileInfo.UpdateSysFileInfo(control, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("UpdateSysFileInfo error: %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.ID, "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysFileInfo) DeleteSysFileInfo(c *gin.Context) {
|
|
||||||
control := new(dto.SysFileInfoById)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = c.ShouldBindUri(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(422, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.ShouldBind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("参数验证错误, error: %s", err)
|
|
||||||
e.Error(422, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
control.UpdateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysFileInfo := service.SysFileInfo{}
|
|
||||||
serviceSysFileInfo.Orm = db
|
|
||||||
serviceSysFileInfo.Log = log
|
|
||||||
err = serviceSysFileInfo.RemoveSysFileInfo(control, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysFileInfo error: %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.Id, "删除成功")
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysLoginLog struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage 登录日志列表
|
||||||
|
// @Summary 登录日志列表
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 登录日志
|
||||||
|
// @Param username query string false "用户名"
|
||||||
|
// @Param ipaddr query string false "ip地址"
|
||||||
|
// @Param loginLocation query string false "归属地"
|
||||||
|
// @Param status query string false "状态"
|
||||||
|
// @Param beginTime query string false "开始时间"
|
||||||
|
// @Param endTime query string false "结束时间"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-login-log [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysLoginLog) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysLoginLog{}
|
||||||
|
req := dto.SysLoginLogGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list := make([]models.SysLoginLog, 0)
|
||||||
|
var count int64
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 登录日志通过id获取
|
||||||
|
// @Summary 登录日志通过id获取
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 登录日志
|
||||||
|
// @Param id path string false "id"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-login-log/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysLoginLog) Get(c *gin.Context) {
|
||||||
|
s := service.SysLoginLog{}
|
||||||
|
req := dto.SysLoginLogGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysLoginLog
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 登录日志删除
|
||||||
|
// @Summary 登录日志删除
|
||||||
|
// @Description 登录日志删除
|
||||||
|
// @Tags 登录日志
|
||||||
|
// @Param data body dto.SysLoginLogDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-login-log [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysLoginLog) Delete(c *gin.Context) {
|
||||||
|
s := service.SysLoginLog{}
|
||||||
|
req := dto.SysLoginLogDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysMenu struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage Menu列表数据
|
||||||
|
// @Summary Menu列表数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Param menuName query string false "menuName"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menu [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysMenu{}
|
||||||
|
req := dto.SysMenuGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var list = make([]models.SysMenu, 0)
|
||||||
|
err = s.GetPage(&req, &list).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(list, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 获取菜单详情
|
||||||
|
// @Summary Menu详情数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Param id path string false "id"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menu/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) Get(c *gin.Context) {
|
||||||
|
req := dto.SysMenuGetReq{}
|
||||||
|
s := new(service.SysMenu)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object = models.SysMenu{}
|
||||||
|
|
||||||
|
err = s.Get(&req, &object).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert 创建菜单
|
||||||
|
// @Summary 创建菜单
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysMenuInsertReq true "data"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menu [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) Insert(c *gin.Context) {
|
||||||
|
req := dto.SysMenuInsertReq{}
|
||||||
|
s := new(service.SysMenu)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 设置创建人
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "创建失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 修改菜单
|
||||||
|
// @Summary 修改菜单
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param id path int true "id"
|
||||||
|
// @Param data body dto.SysMenuUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menu/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) Update(c *gin.Context) {
|
||||||
|
req := dto.SysMenuUpdateReq{}
|
||||||
|
s := new(service.SysMenu)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Update(&req).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "更新失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 删除菜单
|
||||||
|
// @Summary 删除菜单
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Param data body dto.SysMenuDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menu [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) Delete(c *gin.Context) {
|
||||||
|
control := new(dto.SysMenuDeleteReq)
|
||||||
|
s := new(service.SysMenu)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(control, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = s.Remove(control).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errorf("RemoveSysMenu error, %s", err)
|
||||||
|
e.Error(500, err, "删除失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(control.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMenuRole 根据登录角色名称获取菜单列表数据(左菜单使用)
|
||||||
|
// @Summary 根据登录角色名称获取菜单列表数据(左菜单使用)
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menurole [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) GetMenuRole(c *gin.Context) {
|
||||||
|
s := new(service.SysMenu)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := s.SetMenuRole(user.GetRoleName(c))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(result, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMenuTreeSelect 根据角色ID查询菜单下拉树结构
|
||||||
|
// @Summary 角色修改使用的菜单列表
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 菜单
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param roleId path int true "roleId"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/menuTreeselect/{roleId} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysMenu) GetMenuTreeSelect(c *gin.Context) {
|
||||||
|
m := service.SysMenu{}
|
||||||
|
r := service.SysRole{}
|
||||||
|
req := dto.SelectRole{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&m.Service).
|
||||||
|
MakeService(&r.Service).
|
||||||
|
Bind(&req, nil).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := m.SetLabel()
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
menuIds := make([]int, 0)
|
||||||
|
if req.RoleId != 0 {
|
||||||
|
menuIds, err = r.GetRoleMenuId(req.RoleId)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.OK(gin.H{
|
||||||
|
"menus": result,
|
||||||
|
"checkedKeys": menuIds,
|
||||||
|
}, "获取成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysOperaLog struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage 操作日志列表
|
||||||
|
// @Summary 操作日志列表
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 操作日志
|
||||||
|
// @Param title query string false "title"
|
||||||
|
// @Param method query string false "method"
|
||||||
|
// @Param requestMethod query string false "requestMethod"
|
||||||
|
// @Param operUrl query string false "operUrl"
|
||||||
|
// @Param operIp query string false "operIp"
|
||||||
|
// @Param status query string false "status"
|
||||||
|
// @Param beginTime query string false "beginTime"
|
||||||
|
// @Param endTime query string false "endTime"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-opera-log [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysOperaLog) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysOperaLog{}
|
||||||
|
req := new(dto.SysOperaLogGetPageReq)
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]models.SysOperaLog, 0)
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
err = s.GetPage(req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 操作日志通过id获取
|
||||||
|
// @Summary 操作日志通过id获取
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 操作日志
|
||||||
|
// @Param id path string false "id"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-opera-log/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysOperaLog) Get(c *gin.Context) {
|
||||||
|
s := new(service.SysOperaLog)
|
||||||
|
req := dto.SysOperaLogGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysOperaLog
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 操作日志删除
|
||||||
|
// DeleteSysMenu 操作日志删除
|
||||||
|
// @Summary 删除操作日志
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 操作日志
|
||||||
|
// @Param data body dto.SysOperaLogDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-opera-log [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysOperaLog) Delete(c *gin.Context) {
|
||||||
|
s := new(service.SysOperaLog)
|
||||||
|
req := dto.SysOperaLogDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, fmt.Sprintf("删除失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysPost struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage
|
||||||
|
// @Summary 岗位列表数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Param postName query string false "postName"
|
||||||
|
// @Param postCode query string false "postCode"
|
||||||
|
// @Param postId query string false "postId"
|
||||||
|
// @Param status query string false "status"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/post [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysPost) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]models.SysPost, 0)
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
// @Summary 获取岗位信息
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Param id path int true "编码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/post/{postId} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysPost) Get(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysPost
|
||||||
|
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("岗位信息获取失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert
|
||||||
|
// @Summary 添加岗位
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysPostInsertReq true "data"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/post [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysPost) Insert(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("新建岗位失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
// @Summary 修改岗位
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysPostUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/post/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysPost) Update(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
err = s.Update(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("岗位更新失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除岗位
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 岗位
|
||||||
|
// @Param id body dto.SysPostDeleteReq true "请求参数"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/post [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysPost) Delete(c *gin.Context) {
|
||||||
|
s := service.SysPost{}
|
||||||
|
req := dto.SysPostDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.Remove(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("岗位删除失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go-admin/common/global"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysRole struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage
|
||||||
|
// @Summary 角色列表数据
|
||||||
|
// @Description Get JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Param roleName query string false "roleName"
|
||||||
|
// @Param status query string false "status"
|
||||||
|
// @Param roleKey query string false "roleKey"
|
||||||
|
// @Param pageSize query int false "页条数"
|
||||||
|
// @Param pageIndex query int false "页码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.SysRoleGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.Form).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list := make([]models.SysRole, 0)
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
err = s.GetPage(&req, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
// @Summary 获取Role数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Param roleId path string false "roleId"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role/{id} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Get(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.SysRoleGetReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, fmt.Sprintf(" %s ", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var object models.SysRole
|
||||||
|
|
||||||
|
err = s.Get(&req, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert
|
||||||
|
// @Summary 创建角色
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysRoleInsertReq true "data"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Insert(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.SysRoleInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置创建人
|
||||||
|
req.CreateBy = user.GetUserId(c)
|
||||||
|
if req.Status == "" {
|
||||||
|
req.Status = "2"
|
||||||
|
}
|
||||||
|
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
|
||||||
|
err = s.Insert(&req, cb)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, "创建失败,"+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = global.LoadPolicy(c)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, "创建失败,"+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 修改用户角色
|
||||||
|
// @Summary 修改用户角色
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysRoleUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Update(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.SysRoleUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
|
||||||
|
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
err = s.Update(&req, cb)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = global.LoadPolicy(c)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, "更新失败,"+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除用户角色
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Param data body dto.SysRoleDeleteReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Delete(c *gin.Context) {
|
||||||
|
s := new(service.SysRole)
|
||||||
|
req := dto.SysRoleDeleteReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, fmt.Sprintf("删除角色 %v 失败,\r\n失败信息 %s", req.Ids, err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cb := sdk.Runtime.GetCasbinByTenant(c.Request.Host)
|
||||||
|
err = s.Remove(&req, cb)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(req.GetId(), fmt.Sprintf("删除角色角色 %v 状态成功!", req.GetId()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update2Status 修改用户角色状态
|
||||||
|
// @Summary 修改用户角色
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.UpdateStatusReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role-status/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Update2Status(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.UpdateStatusReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, fmt.Sprintf("更新角色状态失败,失败原因:%s ", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
err = s.UpdateStatus(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("更新角色状态失败,失败原因:%s ", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), fmt.Sprintf("更新角色 %v 状态成功!", req.GetId()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update2DataScope 更新角色数据权限
|
||||||
|
// @Summary 更新角色数据权限
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 角色/Role
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.RoleDataScopeReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/role-status/{id} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysRole) Update2DataScope(c *gin.Context) {
|
||||||
|
s := service.SysRole{}
|
||||||
|
req := dto.RoleDataScopeReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := &models.SysRole{
|
||||||
|
RoleId: req.RoleId,
|
||||||
|
DataScope: req.DataScope,
|
||||||
|
DeptIds: req.DeptIds,
|
||||||
|
}
|
||||||
|
data.UpdateBy = user.GetUserId(c)
|
||||||
|
err = s.UpdateDataScope(&req).Error
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, fmt.Sprintf("更新角色数据权限失败!错误详情:%s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(nil, "操作成功")
|
||||||
|
}
|
||||||
@@ -0,0 +1,489 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth/user"
|
||||||
|
_ "github.com/go-admin-team/go-admin-core/v2/response"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/api"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"go-admin/app/admin/service"
|
||||||
|
"go-admin/app/admin/service/dto"
|
||||||
|
"go-admin/common/actions"
|
||||||
|
"go-admin/common/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysUser struct {
|
||||||
|
api.Api
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPage
|
||||||
|
// @Summary 列表用户信息数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Param username query string false "username"
|
||||||
|
// @Success 200 {string} {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-user [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) GetPage(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserGetPageReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
list := make([]models.SysUser, 0)
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
err = s.GetPage(&req, p, &list, &count)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(500, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get
|
||||||
|
// @Summary 获取用户
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Param userId path int true "用户编码"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-user/{userId} [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) Get(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserById{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var object models.SysUser
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
err = s.Get(&req, p, &object)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(object, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert
|
||||||
|
// @Summary 创建用户
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysUserInsertReq true "用户数据"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-user [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) Insert(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserInsertReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 设置创建人
|
||||||
|
req.SetCreateBy(user.GetUserId(c))
|
||||||
|
err = s.Insert(&req)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(req.GetId(), "创建成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
// @Summary 修改用户数据
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.SysUserUpdateReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-user/{userId} [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) Update(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserUpdateReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
callerId := user.GetUserId(c)
|
||||||
|
|
||||||
|
// This route is in CasbinExclude so the personal-center screen can edit
|
||||||
|
// the caller's own record without a policy grant (see settings.go). That
|
||||||
|
// exclusion covers the whole route, not just the caller's own record, and
|
||||||
|
// the request carries the target userId in the body - so without this
|
||||||
|
// check here, any authenticated caller could edit any other user, up to
|
||||||
|
// and including their roleId. When the target is someone else, ask Casbin
|
||||||
|
// directly for the permission AuthCheckRole skipped.
|
||||||
|
if req.UserId != callerId {
|
||||||
|
allowed, err := middleware.EnforceRoleFor(c, c.Request.URL.Path, c.Request.Method)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
e.Error(http.StatusForbidden, errors.New("无权更新其他用户数据"), "对不起,您没有该接口访问权限,请联系管理员")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetUpdateBy(callerId)
|
||||||
|
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
err = s.Update(&req, p, callerId)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
// @Summary 删除用户数据
|
||||||
|
// @Description 删除数据
|
||||||
|
// @Tags 用户
|
||||||
|
// @Param userId path int true "userId"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/sys-user/{userId} [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) Delete(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserById{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置编辑人
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
// 数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
err = s.Remove(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "删除成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsetAvatar
|
||||||
|
// @Summary 修改头像
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 个人中心
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Param file formData file true "file"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/user/avatar [post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) InsetAvatar(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.UpdateSysUserAvatarReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
form, _ := c.MultipartForm()
|
||||||
|
files := form.File["upload[]"]
|
||||||
|
guid := uuid.New().String()
|
||||||
|
filPath := "static/uploadfile/" + guid + ".jpg"
|
||||||
|
for _, file := range files {
|
||||||
|
e.Logger.Debugf("upload avatar file: %s", file.Filename)
|
||||||
|
// 上传文件至指定目录
|
||||||
|
err = c.SaveUploadedFile(file, filPath)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errorf("save file error, %s", err.Error())
|
||||||
|
e.Error(500, err, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req.UserId = p.UserId
|
||||||
|
req.Avatar = "/" + filPath
|
||||||
|
|
||||||
|
err = s.UpdateAvatar(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(filPath, "修改成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStatus 修改用户状态
|
||||||
|
// @Summary 修改用户状态
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.UpdateSysUserStatusReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/user/status [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) UpdateStatus(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.UpdateSysUserStatusReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON, nil).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
err = s.UpdateStatus(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetPwd 重置用户密码
|
||||||
|
// @Summary 重置用户密码
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.ResetSysUserPwdReq true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/user/pwd/reset [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) ResetPwd(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.ResetSysUserPwdReq{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req, binding.JSON).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.SetUpdateBy(user.GetUserId(c))
|
||||||
|
|
||||||
|
//数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
|
||||||
|
err = s.ResetPwd(&req, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(req.GetId(), "更新成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePwd
|
||||||
|
// @Summary 修改密码
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 用户
|
||||||
|
// @Accept application/json
|
||||||
|
// @Product application/json
|
||||||
|
// @Param data body dto.PassWord true "body"
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/user/pwd/set [put]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) UpdatePwd(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.PassWord{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
Bind(&req).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据权限检查
|
||||||
|
p := actions.GetPermissionFromContext(c)
|
||||||
|
var hash []byte
|
||||||
|
if hash, err = bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost); err != nil {
|
||||||
|
req.NewPassword = string(hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.UpdatePwd(user.GetUserId(c), req.OldPassword, req.NewPassword, p)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(http.StatusForbidden, err, "密码修改失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.OK(nil, "密码修改成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProfile
|
||||||
|
// @Summary 获取个人中心用户
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 个人中心
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/user/profile [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) GetProfile(c *gin.Context) {
|
||||||
|
s := service.SysUser{}
|
||||||
|
req := dto.SysUserById{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Id = user.GetUserId(c)
|
||||||
|
|
||||||
|
sysUser := models.SysUser{}
|
||||||
|
roles := make([]models.SysRole, 0)
|
||||||
|
posts := make([]models.SysPost, 0)
|
||||||
|
err = s.GetProfile(&req, &sysUser, &roles, &posts)
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errorf("get user profile error, %s", err.Error())
|
||||||
|
e.Error(500, err, "获取用户信息失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.OK(gin.H{
|
||||||
|
"user": sysUser,
|
||||||
|
"roles": roles,
|
||||||
|
"posts": posts,
|
||||||
|
}, "查询成功")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInfo
|
||||||
|
// @Summary 获取个人信息
|
||||||
|
// @Description 获取JSON
|
||||||
|
// @Tags 个人中心
|
||||||
|
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
||||||
|
// @Router /api/v1/getinfo [get]
|
||||||
|
// @Security Bearer
|
||||||
|
func (e SysUser) GetInfo(c *gin.Context) {
|
||||||
|
req := dto.SysUserById{}
|
||||||
|
s := service.SysUser{}
|
||||||
|
r := service.SysRole{}
|
||||||
|
err := e.MakeContext(c).
|
||||||
|
MakeOrm().
|
||||||
|
MakeService(&r.Service).
|
||||||
|
MakeService(&s.Service).
|
||||||
|
Errors
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Error(err)
|
||||||
|
e.Error(500, err, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var roles = make([]string, 1)
|
||||||
|
roles[0] = user.GetRoleName(c)
|
||||||
|
var permissions = make([]string, 1)
|
||||||
|
permissions[0] = "*:*:*"
|
||||||
|
var buttons = make([]string, 1)
|
||||||
|
buttons[0] = "*:*:*"
|
||||||
|
|
||||||
|
var mp = make(map[string]interface{})
|
||||||
|
mp["roles"] = roles
|
||||||
|
if user.GetRoleName(c) == "admin" || user.GetRoleName(c) == "系统管理员" {
|
||||||
|
mp["permissions"] = permissions
|
||||||
|
mp["buttons"] = buttons
|
||||||
|
} else {
|
||||||
|
list, _ := r.GetById(user.GetRoleId(c))
|
||||||
|
mp["permissions"] = list
|
||||||
|
mp["buttons"] = list
|
||||||
|
}
|
||||||
|
sysUser := models.SysUser{}
|
||||||
|
req.Id = user.GetUserId(c)
|
||||||
|
// Unscoped on purpose: the id is the caller's own, taken from the token.
|
||||||
|
// This used to go through Get with whatever GetPermissionFromContext
|
||||||
|
// returned - and this route installs no PermissionAction, so that was the
|
||||||
|
// zero value. An unset scope is not a recognised one, so once unknown
|
||||||
|
// scopes started failing closed rather than silently matching everything,
|
||||||
|
// every login on a deployment with enabledp: true ended here with a 401
|
||||||
|
// and the browser went straight back to the login page.
|
||||||
|
err = s.GetSelf(&req, &sysUser)
|
||||||
|
if err != nil {
|
||||||
|
e.Error(http.StatusUnauthorized, err, "登录失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mp["introduction"] = " am a super administrator"
|
||||||
|
mp["avatar"] = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"
|
||||||
|
if sysUser.Avatar != "" {
|
||||||
|
mp["avatar"] = sysUser.Avatar
|
||||||
|
}
|
||||||
|
mp["userName"] = sysUser.Username
|
||||||
|
mp["userId"] = sysUser.UserId
|
||||||
|
mp["deptId"] = sysUser.DeptId
|
||||||
|
mp["name"] = sysUser.NickName
|
||||||
|
mp["code"] = 200
|
||||||
|
e.OK(mp, "")
|
||||||
|
}
|
||||||
@@ -1,472 +0,0 @@
|
|||||||
package sys_user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
common "go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysUser struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 列表用户信息数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Param username query string false "username"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/sysUser [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysUser) GetSysUserList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysUserSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := d.Generate()
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
list := make([]system.SysUser, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysUser{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysUserPage(req, p, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取用户
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Param userId path int true "用户编码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/sysUser/{userId} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysUser) GetSysUser(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysUserById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
req := control.Generate()
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysUser
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
err = serviceSysUser.GetSysUser(req, p, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 创建用户
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysUserControl true "用户数据"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/sysUser [post]
|
|
||||||
func (e SysUser) InsertSysUser(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysUserControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
req := control.Generate()
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object common.ActiveRecord
|
|
||||||
object, err = req.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
err = serviceSysUser.InsertSysUser(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改用户数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysUserControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "修改成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "修改失败"}"
|
|
||||||
// @Router /api/v1/sysuser/{userId} [put]
|
|
||||||
func (e SysUser) UpdateSysUser(c *gin.Context) {
|
|
||||||
control := new(dto.SysUserControl)
|
|
||||||
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := control.Generate()
|
|
||||||
//更新操作
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object common.ActiveRecord
|
|
||||||
object, err = req.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
err = serviceSysUser.UpdateSysUser(object, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除用户数据
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 用户
|
|
||||||
// @Param userId path int true "userId"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/sysuser/{userId} [delete]
|
|
||||||
func (e SysUser) DeleteSysUser(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysUserById)
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
req := control.Generate()
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object common.ActiveRecord
|
|
||||||
object, err = req.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
err = serviceSysUser.RemoveSysUser(req, object, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改头像
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Param file formData file true "file"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/user/avatar [post]
|
|
||||||
func (e SysUser) InsetSysUserAvatar(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
form, _ := c.MultipartForm()
|
|
||||||
files := form.File["upload[]"]
|
|
||||||
guid := uuid.New().String()
|
|
||||||
filPath := "static/uploadfile/" + guid + ".jpg"
|
|
||||||
for _, file := range files {
|
|
||||||
log.Debugf("upload avatar file: %s", file.Filename)
|
|
||||||
// 上传文件至指定目录
|
|
||||||
err = c.SaveUploadedFile(file, filPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("save file error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object := &system.SysUser{
|
|
||||||
UserId: p.UserId,
|
|
||||||
Avatar: "/" + filPath,
|
|
||||||
}
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
err = serviceSysUser.UpdateSysUser(object, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(filPath, "修改成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 重置密码
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 用户
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.PassWord true "body"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/user/pwd [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysUser) SysUserUpdatePwd(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var pwd dto.PassWord
|
|
||||||
err = c.Bind(&pwd)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
err = serviceSysUser.UpdateSysUserPwd(user.GetUserId(c), pwd.OldPassword, pwd.NewPassword, p)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusForbidden, err, "密码修改失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(nil, "密码修改成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取个人中心用户
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 个人中心
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/user/profile [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysUser) GetSysUserProfile(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
id := user.GetUserId(c)
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
user := new(system.SysUser)
|
|
||||||
roles := make([]system.SysRole, 0)
|
|
||||||
posts := make([]system.SysPost, 0)
|
|
||||||
err = serviceSysUser.GetSysUserProfile(id, user, &roles, &posts)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("get user profile error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "获取用户信息失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(gin.H{
|
|
||||||
"user": user,
|
|
||||||
"roles": roles,
|
|
||||||
"posts": posts,
|
|
||||||
}, "查询成功")
|
|
||||||
//var SysUser models.SysUser
|
|
||||||
//userId := tools.GetUserIdStr(c)
|
|
||||||
//SysUser.UserId, _ = tools.StringToInt(userId)
|
|
||||||
//result, err := SysUser.Get()
|
|
||||||
//tools.HasError(err, "抱歉未找到相关信息", -1)
|
|
||||||
//var SysRole models.SysRole
|
|
||||||
//var Post models.Post
|
|
||||||
//var Dept models.SysDepts
|
|
||||||
////获取角色列表
|
|
||||||
//roles, err := SysRole.GetList()
|
|
||||||
////获取职位列表
|
|
||||||
//posts, err := Post.GetList()
|
|
||||||
////获取部门列表
|
|
||||||
//Dept.DeptId = result.DeptId
|
|
||||||
//dept, err := Dept.Get()
|
|
||||||
//
|
|
||||||
//postIds := make([]int, 0)
|
|
||||||
//postIds = append(postIds, result.PostId)
|
|
||||||
//
|
|
||||||
//roleIds := make([]int, 0)
|
|
||||||
//roleIds = append(roleIds, result.RoleId)
|
|
||||||
//
|
|
||||||
//app.Custum(c, gin.H{
|
|
||||||
// "code": 200,
|
|
||||||
// "data": result,
|
|
||||||
// "postIds": postIds,
|
|
||||||
// "roleIds": roleIds,
|
|
||||||
// "roles": roles,
|
|
||||||
// "posts": posts,
|
|
||||||
// "dept": dept,
|
|
||||||
//})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysUser) GetInfo(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//数据权限检查
|
|
||||||
p := actions.GetPermissionFromContext(c)
|
|
||||||
|
|
||||||
var roles = make([]string, 1)
|
|
||||||
roles[0] = user.GetRoleName(c)
|
|
||||||
|
|
||||||
var permissions = make([]string, 1)
|
|
||||||
permissions[0] = "*:*:*"
|
|
||||||
|
|
||||||
var buttons = make([]string, 1)
|
|
||||||
buttons[0] = "*:*:*"
|
|
||||||
|
|
||||||
RoleMenu := system.RoleMenu{}
|
|
||||||
RoleMenu.RoleId = user.GetRoleId(c)
|
|
||||||
|
|
||||||
var mp = make(map[string]interface{})
|
|
||||||
mp["roles"] = roles
|
|
||||||
if user.GetRoleName(c) == "admin" || user.GetRoleName(c) == "系统管理员" {
|
|
||||||
mp["permissions"] = permissions
|
|
||||||
mp["buttons"] = buttons
|
|
||||||
} else {
|
|
||||||
list, _ := RoleMenu.GetPermis(db)
|
|
||||||
mp["permissions"] = list
|
|
||||||
mp["buttons"] = list
|
|
||||||
}
|
|
||||||
|
|
||||||
var sysUser system.SysUser
|
|
||||||
req := new(dto.SysUserById)
|
|
||||||
req.Id = user.GetUserId(c)
|
|
||||||
serviceSysUser := service.SysUser{}
|
|
||||||
serviceSysUser.Log = log
|
|
||||||
serviceSysUser.Orm = db
|
|
||||||
err = serviceSysUser.GetSysUser(req, p, &sysUser)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnauthorized, err, "登录失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mp["introduction"] = " am a super administrator"
|
|
||||||
|
|
||||||
mp["avatar"] = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"
|
|
||||||
if sysUser.Avatar != "" {
|
|
||||||
mp["avatar"] = sysUser.Avatar
|
|
||||||
}
|
|
||||||
mp["userName"] = sysUser.NickName
|
|
||||||
mp["userId"] = sysUser.UserId
|
|
||||||
mp["deptId"] = sysUser.DeptId
|
|
||||||
mp["name"] = sysUser.NickName
|
|
||||||
e.OK(mp, "")
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package apis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
mycasbin "github.com/go-admin-team/go-admin-core/v2/casbin"
|
||||||
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/logger"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/pkg"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"go-admin/app/admin/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PUT /api/v1/sys-user is in settings.go's CasbinExclude so the
|
||||||
|
// personal-center screen (go-admin-ui's userInfo.vue) can edit the caller's
|
||||||
|
// own record without holding a policy grant on this route. AuthCheckRole
|
||||||
|
// skips Enforce entirely for an excluded route, so this file's job is to pin
|
||||||
|
// what the handler itself now has to hold shut: the target userId comes from
|
||||||
|
// the request body, and nothing upstream of the handler ever checked it
|
||||||
|
// against the caller.
|
||||||
|
|
||||||
|
// setupPrivescDB wires an in-memory database and a Casbin enforcer with an
|
||||||
|
// empty policy - the state of a fresh install for any role but admin - under
|
||||||
|
// a tenant unique to the calling test, so mycasbin's process-wide enforcer
|
||||||
|
// cache can't hand one test's database to another.
|
||||||
|
func setupPrivescDB(t *testing.T) (*gorm.DB, string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
// Fatalf, not Skipf: this database is in-memory sqlite with no external
|
||||||
|
// dependency, so failing to open or migrate it means the environment is
|
||||||
|
// actually broken. Skipping here would let these two anti-privesc
|
||||||
|
// regression tests silently stop running while CI stays green - a
|
||||||
|
// standing assertion that never fires is worse than no assertion.
|
||||||
|
db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("sqlite unavailable: %v", err)
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.SysUser{}); err != nil {
|
||||||
|
t.Fatalf("automigrate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tenant := "sys-user-privesc-" + t.Name()
|
||||||
|
|
||||||
|
previousInterval := mycasbin.ReloadInterval
|
||||||
|
mycasbin.ReloadInterval = 0 // opt out of the background reload goroutine; the test never writes a policy
|
||||||
|
t.Cleanup(func() { mycasbin.ReloadInterval = previousInterval })
|
||||||
|
|
||||||
|
e := mycasbin.Setup(db, tenant)
|
||||||
|
previousEnforcer := sdk.Runtime.GetCasbinByTenant(tenant)
|
||||||
|
sdk.Runtime.SetCasbinByTenant(tenant, e)
|
||||||
|
t.Cleanup(func() { sdk.Runtime.SetCasbinByTenant(tenant, previousEnforcer) })
|
||||||
|
|
||||||
|
return db, tenant
|
||||||
|
}
|
||||||
|
|
||||||
|
// callUpdate drives SysUser.Update the way the router does for an
|
||||||
|
// authenticated, non-admin caller: JWT claims already decoded into the
|
||||||
|
// context (that is jwtauth's job, not this handler's) and a database - but
|
||||||
|
// without AuthCheckRole, since that middleware never runs Enforce for this
|
||||||
|
// route at all.
|
||||||
|
func callUpdate(t *testing.T, db *gorm.DB, tenant string, callerId int, body map[string]interface{}) *httptest.ResponseRecorder {
|
||||||
|
t.Helper()
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
|
||||||
|
raw, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal request body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := gin.CreateTestContext(w)
|
||||||
|
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/sys-user", bytes.NewReader(raw))
|
||||||
|
c.Request.Host = tenant
|
||||||
|
c.Request.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
c.Set("db", db)
|
||||||
|
c.Set(pkg.LoggerKey, logger.NewHelper(logger.DefaultLogger))
|
||||||
|
c.Set(jwt.JwtPayloadKey, jwt.MapClaims{
|
||||||
|
"identity": float64(callerId),
|
||||||
|
"rolekey": "ordinary-role", // holds no Casbin policy anywhere in this test
|
||||||
|
})
|
||||||
|
|
||||||
|
SysUser{}.Update(c)
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUpdate_CannotEscalatePrivilegeThroughAnotherUsersRecord is the
|
||||||
|
// regression for H6. Before the fix, an ordinary authenticated user could PUT
|
||||||
|
// a body naming another user's id and change that user's roleId - the route
|
||||||
|
// being Casbin-excluded meant no permission check ever ran, and the data
|
||||||
|
// permission scope that would otherwise gate this is off by default.
|
||||||
|
func TestUpdate_CannotEscalatePrivilegeThroughAnotherUsersRecord(t *testing.T) {
|
||||||
|
db, tenant := setupPrivescDB(t)
|
||||||
|
|
||||||
|
victim := models.SysUser{Username: "bob", NickName: "Bob", RoleId: 2, DeptId: 1, Status: "1"}
|
||||||
|
if err := db.Create(&victim).Error; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
attacker := models.SysUser{Username: "alice", NickName: "Alice", RoleId: 2, DeptId: 1, Status: "1"}
|
||||||
|
if err := db.Create(&attacker).Error; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const elevatedRoleId = 1 // a role the attacker does not hold and has no policy for
|
||||||
|
|
||||||
|
callUpdate(t, db, tenant, attacker.UserId, map[string]interface{}{
|
||||||
|
"userId": victim.UserId,
|
||||||
|
"username": victim.Username,
|
||||||
|
"nickName": "pwned",
|
||||||
|
"phone": "13800000000",
|
||||||
|
"email": "bob@example.com",
|
||||||
|
"roleId": elevatedRoleId,
|
||||||
|
"deptId": victim.DeptId,
|
||||||
|
"status": victim.Status,
|
||||||
|
})
|
||||||
|
|
||||||
|
var after models.SysUser
|
||||||
|
if err := db.First(&after, victim.UserId).Error; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if after.RoleId == elevatedRoleId {
|
||||||
|
t.Fatalf("an attacker with no Casbin permission on this route escalated the victim's roleId to %d", after.RoleId)
|
||||||
|
}
|
||||||
|
if after.NickName == "pwned" {
|
||||||
|
t.Fatalf("an attacker with no Casbin permission on this route modified another user's record: %+v", after)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUpdate_SelfEditCannotChangePrivilegedFields covers the case the
|
||||||
|
// CasbinExclude entry exists for: the personal-center screen has to keep
|
||||||
|
// working for the caller's own record. The fields that screen exposes
|
||||||
|
// (nickName/phone/email/sex) must still save, while roleId/deptId/status stay
|
||||||
|
// whatever the database already had even if the request carries something
|
||||||
|
// else - a compromised or hand-crafted client is the only way that request
|
||||||
|
// would ever differ from what the honest form sends.
|
||||||
|
func TestUpdate_SelfEditCannotChangePrivilegedFields(t *testing.T) {
|
||||||
|
db, tenant := setupPrivescDB(t)
|
||||||
|
|
||||||
|
self := models.SysUser{Username: "carol", NickName: "Carol", RoleId: 2, DeptId: 1, Status: "1"}
|
||||||
|
if err := db.Create(&self).Error; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const elevatedRoleId = 1
|
||||||
|
|
||||||
|
callUpdate(t, db, tenant, self.UserId, map[string]interface{}{
|
||||||
|
"userId": self.UserId,
|
||||||
|
"username": self.Username,
|
||||||
|
"nickName": "Carol Updated",
|
||||||
|
"phone": "13900000000",
|
||||||
|
"email": "carol@example.com",
|
||||||
|
"roleId": elevatedRoleId, // tampered; must not take effect
|
||||||
|
"deptId": self.DeptId,
|
||||||
|
"status": self.Status,
|
||||||
|
})
|
||||||
|
|
||||||
|
var after models.SysUser
|
||||||
|
if err := db.First(&after, self.UserId).Error; err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if after.RoleId == elevatedRoleId {
|
||||||
|
t.Fatalf("a self-edit changed the caller's own roleId to %d", after.RoleId)
|
||||||
|
}
|
||||||
|
if after.NickName != "Carol Updated" {
|
||||||
|
t.Fatalf("the legitimate personal-center edit did not go through: %+v", after)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/captcha"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type System struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e System) GenerateCaptchaHandler(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
id, b64s, err := captcha.DriverDigitFunc()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("DriverDigitFunc error, %s", err.Error())
|
|
||||||
e.Error(500, err, "验证码获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.Custom(gin.H{
|
|
||||||
"code": 200,
|
|
||||||
"data": b64s,
|
|
||||||
"id": id,
|
|
||||||
"msg": "success",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
package dict
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
common "go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysDictData struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 字典数据列表
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典数据
|
|
||||||
// @Param status query string false "status"
|
|
||||||
// @Param dictCode query string false "dictCode"
|
|
||||||
// @Param dictType query string false "dictType"
|
|
||||||
// @Param pageSize query int false "页条数"
|
|
||||||
// @Param pageIndex query int false "页码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dict/data [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictData) GetSysDictDataList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictDataSearch{}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysDictData, 0)
|
|
||||||
var count int64
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db.Debug()
|
|
||||||
err = s.GetPage(req, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetPage error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 通过编码获取字典数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典数据
|
|
||||||
// @Param dictCode path int true "字典编码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dict/data/{dictCode} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictData) GetSysDictData(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
req := &dto.SysDictDataById{}
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysDictData
|
|
||||||
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.Get(req, &object)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Get error: %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 添加字典数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典数据
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysDictDataControl true "data"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dict/data [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictData) InsertSysDictData(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
req := &dto.SysDictDataControl{}
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, _ := req.GenerateM()
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Insert(object.(*system.SysDictData))
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改字典数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典数据
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysDictDataControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dict/data/{dictCode} [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictData) UpdateSysDictData(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictDataControl{}
|
|
||||||
//更新操作
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("request validate error, %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, _ := req.GenerateM()
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Update(object.(*system.SysDictData))
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Update error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "更新失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除字典数据
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 字典数据
|
|
||||||
// @Param dictCode path int true "dictCode"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/dict/data/{dictCode} [delete]
|
|
||||||
func (e SysDictData) DeleteSysDictData(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
req := new(dto.SysDictDataById)
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object common.ActiveRecord
|
|
||||||
object, err = req.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GenerateM error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Remove(req, object.(*system.SysDictData))
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Remove error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysDictData) GetSysDictDataAll(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictDataSearch{}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysDictData, 0)
|
|
||||||
s := service.SysDictData{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetAll(req, &list)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetAll error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(list, "查询成功")
|
|
||||||
}
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
package dict
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
common "go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysDictType struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 字典类型列表数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Param dictName query string false "dictName"
|
|
||||||
// @Param dictId query string false "dictId"
|
|
||||||
// @Param dictType query string false "dictType"
|
|
||||||
// @Param pageSize query int false "页条数"
|
|
||||||
// @Param pageIndex query int false "页码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dict/type [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictType) GetSysDictTypeList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictTypeSearch{}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysDictType, 0)
|
|
||||||
var count int64
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db.Debug()
|
|
||||||
err = s.GetPage(req, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 通过字典id获取字典类型
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Param dictId path int true "字典类型编码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dict/type/{dictId} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictType) GetSysDictType(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
req := &dto.SysDictTypeById{}
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysDictType
|
|
||||||
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.Get(req, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 添加字典类型
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysDictTypeControl true "data"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dict/type [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictType) InsertSysDictType(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
req := &dto.SysDictTypeControl{}
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, _ := req.GenerateM()
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Insert(object.(*system.SysDictType))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改字典类型
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysDictTypeControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dict/type/{dictId} [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictType) UpdateSysDictType(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictTypeControl{}
|
|
||||||
//更新操作
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, _ := req.GenerateM()
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Update(object.(*system.SysDictType))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除字典类型
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Param dictId path int true "dictId"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/dict/type/{dictId} [delete]
|
|
||||||
func (e SysDictType) DeleteSysDictType(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
req := new(dto.SysDictTypeById)
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object common.ActiveRecord
|
|
||||||
object, err = req.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.Remove(req, object.(*system.SysDictType))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 字典类型全部数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 字典类型
|
|
||||||
// @Param dictName query string false "dictName"
|
|
||||||
// @Param dictId query string false "dictId"
|
|
||||||
// @Param dictType query string false "dictType"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dict/type-option-select [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDictType) GetSysDictTypeAll(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req := &dto.SysDictTypeSearch{}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = req.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysDictType, 0)
|
|
||||||
s := service.SysDictType{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetAll(req, &list)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(list, "查询成功")
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysSetting struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 查询系统信息
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 系统信息
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/setting [get]
|
|
||||||
func (e SysSetting) GetSetting(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sysSettingService := service.SysSetting{}
|
|
||||||
sysSettingService.Log = log
|
|
||||||
sysSettingService.Orm = db
|
|
||||||
var model = models.SysSetting{}
|
|
||||||
err = sysSettingService.GetSysSetting(&model)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if model.Logo != "" {
|
|
||||||
if !strings.HasPrefix(model.Logo, "http") {
|
|
||||||
model.Logo = fmt.Sprintf("http://%s/%s", c.Request.Host, model.Logo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(model, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 更新或提交系统信息
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 系统信息
|
|
||||||
// @Param data body dto.SysSettingControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/system/setting [post]
|
|
||||||
func (e SysSetting) CreateOrUpdateSetting(c *gin.Context) {
|
|
||||||
control := new(dto.SysSettingControl)
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sysSettingService := service.SysSetting{}
|
|
||||||
sysSettingService.Log = log
|
|
||||||
sysSettingService.Orm = db
|
|
||||||
err = sysSettingService.UpdateSysSetting(object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "更新失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if object.Logo != "" {
|
|
||||||
if !strings.HasPrefix(object.Logo, "http") {
|
|
||||||
object.Logo = fmt.Sprintf("http://%s/%s", c.Request.Host, object.Logo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.OK(object, "提交成功")
|
|
||||||
}
|
|
||||||
@@ -1,277 +0,0 @@
|
|||||||
package sys_config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysConfig struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysConfig) GetSysConfigList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysConfigSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("参数验证失败, error:%s", err)
|
|
||||||
e.Error(500, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysConfig, 0)
|
|
||||||
var count int64
|
|
||||||
s := service.SysConfig{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetSysConfigPage(d, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetSysConfigPage 查询失败, error:%s", err)
|
|
||||||
e.Error(500, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSysConfigBySysApp 获取系统配置信息,主要注意这里不在验证数据权限
|
|
||||||
func (e SysConfig) GetSysConfigBySysApp(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysConfigSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("参数验证失败, error:%s", err)
|
|
||||||
e.Error(500, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 控制只读前台的数据
|
|
||||||
d.IsFrontend = 1
|
|
||||||
|
|
||||||
list := make([]system.SysConfig, 0)
|
|
||||||
s := service.SysConfig{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetSysConfigByKey(d, &list)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetSysConfigPage 查询失败, error:%s", err)
|
|
||||||
e.Error(500, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mp := make(map[string]string)
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
key := list[i].ConfigKey
|
|
||||||
if key != "" {
|
|
||||||
mp[key] = list[i].ConfigValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.OK(mp, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysConfig) GetSysConfig(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysConfigById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysConfig
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysConfig{}
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
err = serviceSysLoginLog.GetSysConfig(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysConfig) InsertSysConfig(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysConfigControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysConfig{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.InsertSysConfig(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysConfig) UpdateSysConfig(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysConfigControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysConfig{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.UpdateSysConfig(object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "更新失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysConfig) DeleteSysConfig(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysConfigById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysConfig{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.RemoveSysConfig(control, object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "删除失败")
|
|
||||||
log.Errorf("Orm获取失败, error:%s", err)
|
|
||||||
e.Error(500, err, "Orm获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSysConfigByKEYForService 根据Key获取SysConfig的Service
|
|
||||||
func (e SysConfig) GetSysConfigByKEYForService(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var v dto.SysConfigControl
|
|
||||||
err = v.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("参数验证错误, error:%s", err)
|
|
||||||
e.Error(422, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s := service.SysConfig{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetSysConfigByKEY(&v)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("通过Key获取配置失败, error:%s", err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(v, s.Msg)
|
|
||||||
}
|
|
||||||
@@ -1,294 +0,0 @@
|
|||||||
package sys_dept
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysDept struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 分页部门列表数据
|
|
||||||
// @Description 分页列表
|
|
||||||
// @Tags 部门
|
|
||||||
// @Param name query string false "name"
|
|
||||||
// @Param id query string false "id"
|
|
||||||
// @Param position query string false "position"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dept [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDept) GetSysDeptList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysDeptSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysDept, 0)
|
|
||||||
serviceStudent := service.SysDept{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
list, err = serviceStudent.SetDeptPage(d)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(list, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 部门列表数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 部门
|
|
||||||
// @Param deptId path string false "deptId"
|
|
||||||
// @Param position query string false "position"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/dept/{deptId} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDept) GetSysDept(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysDeptById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysDept
|
|
||||||
|
|
||||||
serviceSysOperlog := service.SysDept{}
|
|
||||||
serviceSysOperlog.Log = log
|
|
||||||
serviceSysOperlog.Orm = db
|
|
||||||
err = serviceSysOperlog.GetSysDept(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 添加部门
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 部门
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysDeptControl true "data"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dept [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDept) InsertSysDept(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysDeptControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysDept := service.SysDept{}
|
|
||||||
serviceSysDept.Orm = db
|
|
||||||
serviceSysDept.Log = log
|
|
||||||
err = serviceSysDept.InsertSysDept(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改部门
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 部门
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Param data body dto.SysDeptControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/dept/{deptId} [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysDept) UpdateSysDept(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysDeptControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysDept := service.SysDept{}
|
|
||||||
serviceSysDept.Orm = db
|
|
||||||
serviceSysDept.Log = log
|
|
||||||
err = serviceSysDept.UpdateSysDept(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除部门
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 部门
|
|
||||||
// @Param data body dto.SysDeptById true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/dept [delete]
|
|
||||||
func (e SysDept) DeleteSysDept(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysDeptById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysDept := service.SysDept{}
|
|
||||||
serviceSysDept.Orm = db
|
|
||||||
serviceSysDept.Log = log
|
|
||||||
err = serviceSysDept.RemoveSysDept(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysDept error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDeptTree 用户管理 左侧部门树
|
|
||||||
func (e SysDept) GetDeptTree(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysDeptSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]dto.DeptLabel, 0)
|
|
||||||
serviceStudent := service.SysDept{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
list, err = serviceStudent.SetDeptTree(d)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//var Dept models.SysDepts
|
|
||||||
//Dept.DeptName = c.Request.FormValue("deptName")
|
|
||||||
//Dept.Status = c.Request.FormValue("status")
|
|
||||||
//Dept.DeptId, _ = tools.StringToInt(c.Request.FormValue("deptId"))
|
|
||||||
//result, err := Dept.SetDept(false)
|
|
||||||
//tools.HasError(err, "抱歉未找到相关信息", -1)
|
|
||||||
e.OK(list, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysDept) GetDeptTreeRoleSelect(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s := service.SysDept{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
id, err := pkg.StringToInt(c.Param("roleId"))
|
|
||||||
result, err := s.SetDeptLabel()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("SetDeptLabel error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
}
|
|
||||||
menuIds := make([]int, 0)
|
|
||||||
if id != 0 {
|
|
||||||
menuIds, err = s.GetRoleDeptId(id)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("抱歉未找到相关信息, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.OK(gin.H{
|
|
||||||
"depts": result,
|
|
||||||
"checkedKeys": menuIds,
|
|
||||||
}, "")
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
package sys_login_log
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysLoginLog struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysLoginLog) GetSysLoginLogList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysLoginLogSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysLoginLog, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysLoginLog{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysLoginLogPage(d, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysLoginLog) GetSysLoginLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysLoginLogById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysLoginLog
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysLoginLog{}
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
err = serviceSysLoginLog.GetSysLoginLog(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysLoginLog) InsertSysLoginLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysLoginLogControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysLoginLog{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.InsertSysLoginLog(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("InsertSysLoginLog error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysLoginLog) UpdateSysLoginLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysLoginLogControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysLoginLog{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.UpdateSysLoginLog(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("UpdateSysLoginLog error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "更新失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysLoginLog) DeleteSysLoginLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysLoginLogById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.GenerateM()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置编辑人
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysLoginLog := service.SysLoginLog{}
|
|
||||||
serviceSysLoginLog.Orm = db
|
|
||||||
serviceSysLoginLog.Log = log
|
|
||||||
err = serviceSysLoginLog.RemoveSysLoginLog(control, object)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysLoginLog error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
@@ -1,369 +0,0 @@
|
|||||||
package sys_menu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysMenu struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Menu列表数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Param menuName query string false "menuName"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/menulist [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) GetSysMenuList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysMenuSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var list *[]system.SysMenu
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
list, err = serviceSysMenu.GetSysMenuPage(d)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(list, "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Menu详情数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Param menuName query string false "menuName"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/menu/{id} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) GetSysMenu(c *gin.Context) {
|
|
||||||
control := new(dto.SysMenuById)
|
|
||||||
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysMenu
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
err = serviceSysMenu.GetSysMenu(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 创建菜单
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Accept application/x-www-form-urlencoded
|
|
||||||
// @Product application/x-www-form-urlencoded
|
|
||||||
// @Param menuName formData string true "menuName"
|
|
||||||
// @Param Path formData string false "Path"
|
|
||||||
// @Param Action formData string true "Action"
|
|
||||||
// @Param Permission formData string true "Permission"
|
|
||||||
// @Param ParentId formData string true "ParentId"
|
|
||||||
// @Param IsDel formData string true "IsDel"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/menu [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) InsertSysMenu(c *gin.Context) {
|
|
||||||
control := new(dto.SysMenuControl)
|
|
||||||
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
err = serviceSysMenu.InsertSysMenu(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改菜单
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Accept application/x-www-form-urlencoded
|
|
||||||
// @Product application/x-www-form-urlencoded
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Param data body dto.SysMenuControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "修改成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "修改失败"}"
|
|
||||||
// @Router /api/v1/menu/{id} [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) UpdateSysMenu(c *gin.Context) {
|
|
||||||
control := new(dto.SysMenuControl)
|
|
||||||
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
err = serviceSysMenu.UpdateSysMenu(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除菜单
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Param data body dto.SysMenuById true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/menu/ [delete]
|
|
||||||
func (e SysMenu) DeleteSysMenu(c *gin.Context) {
|
|
||||||
control := new(dto.SysMenuById)
|
|
||||||
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
err = serviceSysMenu.RemoveSysMenu(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("RemoveSysMenu error, %s", err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "删除失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 根据角色名称获取菜单列表数据(左菜单使用)
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/menurole [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) GetMenuRole(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
result, err := serviceSysMenu.SetMenuRole(user.GetRoleName(c))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(result, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取角色对应的菜单id数组
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/menuids/{id} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) GetMenuIDS(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var data system.RoleMenu
|
|
||||||
data.RoleName = c.GetString("role")
|
|
||||||
data.UpdateBy = user.GetUserId(c)
|
|
||||||
result, err := data.GetIDS(db)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetIDS error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(result, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
//// GetMenuTreeRoleselect 角色修改中的菜单列表
|
|
||||||
//func (e SysMenu) GetMenuTreeRoleselect(c *gin.Context) {
|
|
||||||
// var Menu models.Menu
|
|
||||||
// var SysRole models.SysRole
|
|
||||||
//
|
|
||||||
// id, err := tools.StringToInt(c.Param("roleId"))
|
|
||||||
// SysRole.RoleId = id
|
|
||||||
// //var r *models.SysRole
|
|
||||||
// r, err := SysRole.Get()
|
|
||||||
//
|
|
||||||
// var result *[]models.MenuLable
|
|
||||||
// menuIds := make([]int, 0)
|
|
||||||
// if r.RoleKey != "admin" {
|
|
||||||
// result, err = Menu.SetMenuLabel()
|
|
||||||
// tools.HasError(err, "抱歉未找到相关信息", -1)
|
|
||||||
// if id != 0 {
|
|
||||||
// menuIds, err = SysRole.GetRoleMeunId()
|
|
||||||
// tools.HasError(err, "抱歉未找到相关信息", -1)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// app.Custum(c, gin.H{
|
|
||||||
// "code": 200,
|
|
||||||
// "menus": result,
|
|
||||||
// "checkedKeys": menuIds,
|
|
||||||
// })
|
|
||||||
//}
|
|
||||||
|
|
||||||
// @Summary 获取菜单树
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 菜单
|
|
||||||
// @Accept application/x-www-form-urlencoded
|
|
||||||
// @Product application/x-www-form-urlencoded
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/menuTreeselect [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysMenu) GetMenuTreeSelect(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
d := new(dto.SelectRole)
|
|
||||||
|
|
||||||
err = c.BindUri(d)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysMenu := service.SysMenu{}
|
|
||||||
serviceSysMenu.Log = log
|
|
||||||
serviceSysMenu.Orm = db
|
|
||||||
result, err := serviceSysMenu.SetSysMenuLabel()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
menuIds, err := s.GetRoleMenuId(db, d.RoleId)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("GetIDS error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(gin.H{
|
|
||||||
"menus": result,
|
|
||||||
"checkedKeys": menuIds,
|
|
||||||
}, "获取成功")
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
package sys_opera_log
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysOperaLog struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysOperaLog) GetSysOperaLogList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysOperaLogSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysOperaLog, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysOperaLog{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysOperaLogPage(d, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysOperaLog) GetSysOperaLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysOperaLogById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysOperaLog
|
|
||||||
|
|
||||||
serviceSysOperlog := service.SysOperaLog{}
|
|
||||||
serviceSysOperlog.Log = log
|
|
||||||
serviceSysOperlog.Orm = db
|
|
||||||
err = serviceSysOperlog.GetSysOperaLog(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysOperaLog) InsertSysOperaLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysOperaLogControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysOperaLog := service.SysOperaLog{}
|
|
||||||
serviceSysOperaLog.Orm = db
|
|
||||||
serviceSysOperaLog.Log = log
|
|
||||||
err = serviceSysOperaLog.InsertSysOperaLog(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysOperaLog) UpdateSysOperaLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysOperaLogControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysOperaLog := service.SysOperaLog{}
|
|
||||||
serviceSysOperaLog.Orm = db
|
|
||||||
serviceSysOperaLog.Log = log
|
|
||||||
err = serviceSysOperaLog.UpdateSysOperaLog(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysOperaLog) DeleteSysOperaLog(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysOperaLogById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysOperaLog := service.SysOperaLog{}
|
|
||||||
serviceSysOperaLog.Orm = db
|
|
||||||
serviceSysOperaLog.Log = log
|
|
||||||
err = serviceSysOperaLog.RemoveSysOperaLog(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
package sys_post
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysPost struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 岗位列表数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 岗位
|
|
||||||
// @Param postName query string false "postName"
|
|
||||||
// @Param postCode query string false "postCode"
|
|
||||||
// @Param postId query string false "postId"
|
|
||||||
// @Param status query string false "status"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/post [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysPost) GetSysPostList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysPostSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysPost, 0)
|
|
||||||
var count int64
|
|
||||||
serviceStudent := service.SysPost{}
|
|
||||||
serviceStudent.Log = log
|
|
||||||
serviceStudent.Orm = db
|
|
||||||
err = serviceStudent.GetSysPostPage(d, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取岗位信息
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 岗位
|
|
||||||
// @Param postId path int true "postId"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/post/{postId} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysPost) GetSysPost(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysPostById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysPost
|
|
||||||
|
|
||||||
serviceSysOperlog := service.SysPost{}
|
|
||||||
serviceSysOperlog.Log = log
|
|
||||||
serviceSysOperlog.Orm = db
|
|
||||||
err = serviceSysOperlog.GetSysPost(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 添加岗位
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 岗位
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysPostControl true "data"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/post [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysPost) InsertSysPost(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysPostControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.SetCreateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysPost := service.SysPost{}
|
|
||||||
serviceSysPost.Orm = db
|
|
||||||
serviceSysPost.Log = log
|
|
||||||
err = serviceSysPost.InsertSysPost(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改岗位
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 岗位
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysPostControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/post/ [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysPost) UpdateSysPost(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysPostControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.SetUpdateBy(user.GetUserId(c))
|
|
||||||
|
|
||||||
serviceSysPost := service.SysPost{}
|
|
||||||
serviceSysPost.Orm = db
|
|
||||||
serviceSysPost.Log = log
|
|
||||||
err = serviceSysPost.UpdateSysPost(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除岗位
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 岗位
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 500 {string} string "{"code": 500, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/post/{postId} [delete]
|
|
||||||
func (e SysPost) DeleteSysPost(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysPostById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceSysPost := service.SysPost{}
|
|
||||||
serviceSysPost.Orm = db
|
|
||||||
serviceSysPost.Log = log
|
|
||||||
err = serviceSysPost.RemoveSysPost(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
package sys_role
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
|
|
||||||
_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
"go-admin/app/admin/service"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
"go-admin/common/global"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysRole struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 角色列表数据
|
|
||||||
// @Description Get JSON
|
|
||||||
// @Tags 角色/Role
|
|
||||||
// @Param roleName query string false "roleName"
|
|
||||||
// @Param status query string false "status"
|
|
||||||
// @Param roleKey query string false "roleKey"
|
|
||||||
// @Param pageSize query int false "页条数"
|
|
||||||
// @Param pageIndex query int false "页码"
|
|
||||||
// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
|
|
||||||
// @Router /api/v1/role [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysRole) GetSysRoleList(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
d := new(dto.SysRoleSearch)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询列表
|
|
||||||
err = d.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
list := make([]system.SysRole, 0)
|
|
||||||
var count int64
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetSysRolePage(d, &list, &count)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.PageOK(list, int(count), d.GetPageIndex(), d.GetPageSize(), "查询成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取Role数据
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 角色/Role
|
|
||||||
// @Param roleId path string false "roleId"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "data": [...]}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "抱歉未找到相关信息"}"
|
|
||||||
// @Router /api/v1/role/{id} [get]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysRole) GetSysRole(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysRoleById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//查看详情
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var object system.SysRole
|
|
||||||
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Log = log
|
|
||||||
s.Orm = db
|
|
||||||
err = s.GetSysRole(control, &object)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "查询失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK(object, "查看成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 创建角色
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 角色/Role
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysRoleControl true "data"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
|
|
||||||
// @Router /api/v1/role [post]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysRole) InsertSysRole(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysRoleControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置创建人
|
|
||||||
object.CreateBy = user.GetUserId(c)
|
|
||||||
if object.Status == "" {
|
|
||||||
object.Status = "2"
|
|
||||||
}
|
|
||||||
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.InsertSysRole(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "创建失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = global.LoadPolicy(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "创建成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 修改用户角色
|
|
||||||
// @Description 获取JSON
|
|
||||||
// @Tags 角色/Role
|
|
||||||
// @Accept application/json
|
|
||||||
// @Product application/json
|
|
||||||
// @Param data body dto.SysRoleControl true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "修改成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "修改失败"}"
|
|
||||||
// @Router /api/v1/role/{id} [put]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysRole) UpdateSysRole(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysRoleControl)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object, err := control.Generate()
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "模型生成失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
object.UpdateBy = user.GetUserId(c)
|
|
||||||
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.UpdateSysRole(object)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = global.LoadPolicy(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(object.GetId(), "更新成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除用户角色
|
|
||||||
// @Description 删除数据
|
|
||||||
// @Tags 角色/Role
|
|
||||||
// @Param data body dto.SysRoleById true "body"
|
|
||||||
// @Success 200 {string} string "{"code": 200, "message": "删除成功"}"
|
|
||||||
// @Success 200 {string} string "{"code": -1, "message": "删除失败"}"
|
|
||||||
// @Router /api/v1/role [delete]
|
|
||||||
// @Security Bearer
|
|
||||||
func (e SysRole) DeleteSysRole(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.SysRoleById)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除操作
|
|
||||||
err = control.Bind(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Bind error: %s", err)
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s := service.SysRole{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.RemoveSysRole(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = global.LoadPolicy(c)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(control.GetId(), "删除成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e SysRole) UpdateRoleDataScope(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
control := new(dto.RoleDataScopeReq)
|
|
||||||
db, err := e.GetOrm()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//更新操作
|
|
||||||
err = c.Bind(control)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("request bind error, %s", err.Error())
|
|
||||||
e.Error(http.StatusUnprocessableEntity, err, "参数验证失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := &system.SysRole{
|
|
||||||
RoleId: control.RoleId,
|
|
||||||
DataScope: control.DataScope,
|
|
||||||
DeptIds: control.DeptIds,
|
|
||||||
}
|
|
||||||
data.UpdateBy = user.GetUserId(c)
|
|
||||||
s := &service.SysRole{}
|
|
||||||
s.Orm = db
|
|
||||||
s.Log = log
|
|
||||||
err = s.UpdateDataScope(data)
|
|
||||||
if err != nil {
|
|
||||||
e.Error(http.StatusInternalServerError, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.OK(nil, "操作成功")
|
|
||||||
}
|
|
||||||
@@ -1,582 +0,0 @@
|
|||||||
package tools
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"text/template"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/config"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/models/tools"
|
|
||||||
"go-admin/common/apis"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Gen struct {
|
|
||||||
apis.Api
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) Preview(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
table := tools.SysTables{}
|
|
||||||
id, err := pkg.StringToInt(c.Param("tableId"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
table.TableId = id
|
|
||||||
t1, err := template.ParseFiles("template/v4/model.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t2, err := template.ParseFiles("template/v4/no_actions/apis.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t3, err := template.ParseFiles("template/v4/js.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t4, err := template.ParseFiles("template/v4/vue.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t5, err := template.ParseFiles("template/v4/no_actions/router_check_role.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t6, err := template.ParseFiles("template/v4/dto.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t7, err := template.ParseFiles("template/v4/no_actions/service.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := pkg.GetOrm(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("get db connection error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "数据库连接获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tab, _ := table.Get(db)
|
|
||||||
var b1 bytes.Buffer
|
|
||||||
err = t1.Execute(&b1, tab)
|
|
||||||
var b2 bytes.Buffer
|
|
||||||
err = t2.Execute(&b2, tab)
|
|
||||||
var b3 bytes.Buffer
|
|
||||||
err = t3.Execute(&b3, tab)
|
|
||||||
var b4 bytes.Buffer
|
|
||||||
err = t4.Execute(&b4, tab)
|
|
||||||
var b5 bytes.Buffer
|
|
||||||
err = t5.Execute(&b5, tab)
|
|
||||||
var b6 bytes.Buffer
|
|
||||||
err = t6.Execute(&b6, tab)
|
|
||||||
var b7 bytes.Buffer
|
|
||||||
err = t7.Execute(&b7, tab)
|
|
||||||
|
|
||||||
mp := make(map[string]interface{})
|
|
||||||
mp["template/model.go.template"] = b1.String()
|
|
||||||
mp["template/api.go.template"] = b2.String()
|
|
||||||
mp["template/js.go.template"] = b3.String()
|
|
||||||
mp["template/vue.go.template"] = b4.String()
|
|
||||||
mp["template/router.go.template"] = b5.String()
|
|
||||||
mp["template/dto.go.template"] = b6.String()
|
|
||||||
mp["template/service.go.template"] = b7.String()
|
|
||||||
e.OK(mp, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) GenCode(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
table := tools.SysTables{}
|
|
||||||
id, err := pkg.StringToInt(c.Param("tableId"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := pkg.GetOrm(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("get db connection error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "数据库连接获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
table.TableId = id
|
|
||||||
tab, _ := table.Get(db)
|
|
||||||
|
|
||||||
if tab.IsActions == 1 {
|
|
||||||
e.ActionsGen(c, tab)
|
|
||||||
} else {
|
|
||||||
e.NOActionsGen(c, tab)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.OK("", "Code generated successfully!")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) GenApiToFile(c *gin.Context) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
table := tools.SysTables{}
|
|
||||||
id, err := pkg.StringToInt(c.Param("tableId"))
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := pkg.GetOrm(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("get db connection error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "数据库连接获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
table.TableId = id
|
|
||||||
tab, _ := table.Get(db)
|
|
||||||
e.genApiToFile(c, tab)
|
|
||||||
|
|
||||||
e.OK("", "Code generated successfully!")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) NOActionsGen(c *gin.Context, tab tools.SysTables) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
basePath := "template/v4/"
|
|
||||||
routerFile := basePath + "no_actions/router_check_role.go.template"
|
|
||||||
|
|
||||||
if tab.IsAuth == 2 {
|
|
||||||
routerFile = basePath + "no_actions/router_no_check_role.go.template"
|
|
||||||
}
|
|
||||||
|
|
||||||
t1, err := template.ParseFiles(basePath + "model.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t2, err := template.ParseFiles(basePath + "no_actions/apis.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t3, err := template.ParseFiles(routerFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t4, err := template.ParseFiles(basePath + "js.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t5, err := template.ParseFiles(basePath + "vue.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t6, err := template.ParseFiles(basePath + "dto.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t7, err := template.ParseFiles(basePath + "no_actions/service.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/apis/" + tab.ModuleName)
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/models/")
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/router/")
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/service/dto/")
|
|
||||||
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/")
|
|
||||||
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.BusinessName)
|
|
||||||
|
|
||||||
var b1 bytes.Buffer
|
|
||||||
err = t1.Execute(&b1, tab)
|
|
||||||
var b2 bytes.Buffer
|
|
||||||
err = t2.Execute(&b2, tab)
|
|
||||||
var b3 bytes.Buffer
|
|
||||||
err = t3.Execute(&b3, tab)
|
|
||||||
var b4 bytes.Buffer
|
|
||||||
err = t4.Execute(&b4, tab)
|
|
||||||
var b5 bytes.Buffer
|
|
||||||
err = t5.Execute(&b5, tab)
|
|
||||||
var b6 bytes.Buffer
|
|
||||||
err = t6.Execute(&b6, tab)
|
|
||||||
var b7 bytes.Buffer
|
|
||||||
err = t7.Execute(&b7, tab)
|
|
||||||
pkg.FileCreate(b1, "./app/"+tab.PackageName+"/models/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b2, "./app/"+tab.PackageName+"/apis/"+tab.ModuleName+"/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b3, "./app/"+tab.PackageName+"/router/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.BusinessName+".js")
|
|
||||||
pkg.FileCreate(b5, config.GenConfig.FrontPath+"/views/"+tab.BusinessName+"/index.vue")
|
|
||||||
pkg.FileCreate(b6, "./app/"+tab.PackageName+"/service/dto/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b7, "./app/"+tab.PackageName+"/service/"+tab.BusinessName+".go")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) genApiToFile(c *gin.Context, tab tools.SysTables) {
|
|
||||||
e.Context = c
|
|
||||||
log := e.GetLogger()
|
|
||||||
|
|
||||||
basePath := "template/"
|
|
||||||
|
|
||||||
t1, err := template.ParseFiles(basePath + "api_migrate.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
|
|
||||||
var b1 bytes.Buffer
|
|
||||||
err = t1.Execute(&b1, struct {
|
|
||||||
tools.SysTables
|
|
||||||
GenerateTime string
|
|
||||||
}{tab, i})
|
|
||||||
|
|
||||||
pkg.FileCreate(b1, "./cmd/migrate/migration/version-local/"+i+"_migrate.go")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) ActionsGen(c *gin.Context, tab tools.SysTables) {
|
|
||||||
e.Context = c
|
|
||||||
log := api.GetRequestLogger(c)
|
|
||||||
basePath := "template/v4/"
|
|
||||||
routerFile := basePath + "actions/router_check_role.go.template"
|
|
||||||
|
|
||||||
if tab.IsAuth == 2 {
|
|
||||||
routerFile = basePath + "actions/router_no_check_role.go.template"
|
|
||||||
}
|
|
||||||
|
|
||||||
t1, err := template.ParseFiles(basePath + "model.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t3, err := template.ParseFiles(routerFile)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t4, err := template.ParseFiles(basePath + "js.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t5, err := template.ParseFiles(basePath + "vue.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t6, err := template.ParseFiles(basePath + "dto.go.template")
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
e.Error(500, err, "")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/models/")
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/router/")
|
|
||||||
_ = pkg.PathCreate("./app/" + tab.PackageName + "/service/dto/")
|
|
||||||
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/api/")
|
|
||||||
_ = pkg.PathCreate(config.GenConfig.FrontPath + "/views/" + tab.BusinessName)
|
|
||||||
|
|
||||||
var b1 bytes.Buffer
|
|
||||||
err = t1.Execute(&b1, tab)
|
|
||||||
var b3 bytes.Buffer
|
|
||||||
err = t3.Execute(&b3, tab)
|
|
||||||
var b4 bytes.Buffer
|
|
||||||
err = t4.Execute(&b4, tab)
|
|
||||||
var b5 bytes.Buffer
|
|
||||||
err = t5.Execute(&b5, tab)
|
|
||||||
var b6 bytes.Buffer
|
|
||||||
err = t6.Execute(&b6, tab)
|
|
||||||
|
|
||||||
pkg.FileCreate(b1, "./app/"+tab.PackageName+"/models/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b3, "./app/"+tab.PackageName+"/router/"+tab.BusinessName+".go")
|
|
||||||
pkg.FileCreate(b4, config.GenConfig.FrontPath+"/api/"+tab.BusinessName+".js")
|
|
||||||
pkg.FileCreate(b5, config.GenConfig.FrontPath+"/views/"+tab.BusinessName+"/index.vue")
|
|
||||||
pkg.FileCreate(b6, "./app/"+tab.PackageName+"/service/dto/"+tab.BusinessName+".go")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Gen) GenMenuAndApi(c *gin.Context) {
|
|
||||||
log := api.GetRequestLogger(c)
|
|
||||||
e.Context = c
|
|
||||||
table := tools.SysTables{}
|
|
||||||
timeNow := pkg.GetCurrentTime()
|
|
||||||
id, err := pkg.StringToInt(c.Param("tableId"))
|
|
||||||
pkg.HasError(err, "", -1)
|
|
||||||
|
|
||||||
db, err := pkg.GetOrm(c)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("get db connection error, %s", err.Error())
|
|
||||||
e.Error(http.StatusInternalServerError, err, "数据库连接获取失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
table.TableId = id
|
|
||||||
tab, _ := table.Get(db)
|
|
||||||
Mmenu := models.Menu{}
|
|
||||||
Mmenu.MenuName = tab.TBName + "Manage"
|
|
||||||
Mmenu.Title = tab.TableComment
|
|
||||||
Mmenu.Icon = "pass"
|
|
||||||
Mmenu.Path = "/" + tab.TBName
|
|
||||||
Mmenu.MenuType = "M"
|
|
||||||
Mmenu.Action = "无"
|
|
||||||
Mmenu.ParentId = 0
|
|
||||||
Mmenu.NoCache = false
|
|
||||||
Mmenu.Component = "Layout"
|
|
||||||
Mmenu.Sort = 0
|
|
||||||
Mmenu.Visible = "0"
|
|
||||||
Mmenu.IsFrame = "0"
|
|
||||||
Mmenu.CreateBy = "1"
|
|
||||||
Mmenu.UpdateBy = "1"
|
|
||||||
Mmenu.CreatedAt = timeNow
|
|
||||||
Mmenu.UpdatedAt = timeNow
|
|
||||||
Mmenu.MenuId, err = Mmenu.Create(db)
|
|
||||||
|
|
||||||
Cmenu := models.Menu{}
|
|
||||||
Cmenu.MenuName = tab.TBName
|
|
||||||
Cmenu.Title = tab.TableComment
|
|
||||||
Cmenu.Icon = "pass"
|
|
||||||
Cmenu.Path = tab.TBName
|
|
||||||
Cmenu.MenuType = "C"
|
|
||||||
Cmenu.Action = "无"
|
|
||||||
Cmenu.Permission = tab.PackageName + ":" + tab.BusinessName + ":list"
|
|
||||||
Cmenu.ParentId = Mmenu.MenuId
|
|
||||||
Cmenu.NoCache = false
|
|
||||||
Cmenu.Component = "/" + tab.BusinessName + "/index"
|
|
||||||
Cmenu.Sort = 0
|
|
||||||
Cmenu.Visible = "0"
|
|
||||||
Cmenu.IsFrame = "0"
|
|
||||||
Cmenu.CreateBy = "1"
|
|
||||||
Cmenu.UpdateBy = "1"
|
|
||||||
Cmenu.CreatedAt = timeNow
|
|
||||||
Cmenu.UpdatedAt = timeNow
|
|
||||||
Cmenu.MenuId, err = Cmenu.Create(db)
|
|
||||||
|
|
||||||
MList := models.Menu{}
|
|
||||||
MList.MenuName = ""
|
|
||||||
MList.Title = "分页获取" + tab.TableComment
|
|
||||||
MList.Icon = ""
|
|
||||||
MList.Path = tab.TBName
|
|
||||||
MList.MenuType = "F"
|
|
||||||
MList.Action = "无"
|
|
||||||
MList.Permission = tab.PackageName + ":" + tab.BusinessName + ":query"
|
|
||||||
MList.ParentId = Cmenu.MenuId
|
|
||||||
MList.NoCache = false
|
|
||||||
MList.Sort = 0
|
|
||||||
MList.Visible = "0"
|
|
||||||
MList.IsFrame = "0"
|
|
||||||
MList.CreateBy = "1"
|
|
||||||
MList.UpdateBy = "1"
|
|
||||||
MList.CreatedAt = timeNow
|
|
||||||
MList.UpdatedAt = timeNow
|
|
||||||
MList.MenuId, err = MList.Create(db)
|
|
||||||
|
|
||||||
MCreate := models.Menu{}
|
|
||||||
MCreate.MenuName = ""
|
|
||||||
MCreate.Title = "创建" + tab.TableComment
|
|
||||||
MCreate.Icon = ""
|
|
||||||
MCreate.Path = tab.TBName
|
|
||||||
MCreate.MenuType = "F"
|
|
||||||
MCreate.Action = "无"
|
|
||||||
MCreate.Permission = tab.PackageName + ":" + tab.BusinessName + ":add"
|
|
||||||
MCreate.ParentId = Cmenu.MenuId
|
|
||||||
MCreate.NoCache = false
|
|
||||||
MCreate.Sort = 0
|
|
||||||
MCreate.Visible = "0"
|
|
||||||
MCreate.IsFrame = "0"
|
|
||||||
MCreate.CreateBy = "1"
|
|
||||||
MCreate.UpdateBy = "1"
|
|
||||||
MCreate.CreatedAt = timeNow
|
|
||||||
MCreate.UpdatedAt = timeNow
|
|
||||||
MCreate.MenuId, err = MCreate.Create(db)
|
|
||||||
|
|
||||||
MUpdate := models.Menu{}
|
|
||||||
MUpdate.MenuName = ""
|
|
||||||
MUpdate.Title = "修改" + tab.TableComment
|
|
||||||
MUpdate.Icon = ""
|
|
||||||
MUpdate.Path = tab.TBName
|
|
||||||
MUpdate.MenuType = "F"
|
|
||||||
MUpdate.Action = "无"
|
|
||||||
MUpdate.Permission = tab.PackageName + ":" + tab.BusinessName + ":edit"
|
|
||||||
MUpdate.ParentId = Cmenu.MenuId
|
|
||||||
MUpdate.NoCache = false
|
|
||||||
MUpdate.Sort = 0
|
|
||||||
MUpdate.Visible = "0"
|
|
||||||
MUpdate.IsFrame = "0"
|
|
||||||
MUpdate.CreateBy = "1"
|
|
||||||
MUpdate.UpdateBy = "1"
|
|
||||||
MUpdate.CreatedAt = timeNow
|
|
||||||
MUpdate.UpdatedAt = timeNow
|
|
||||||
MUpdate.MenuId, err = MUpdate.Create(db)
|
|
||||||
|
|
||||||
MDelete := models.Menu{}
|
|
||||||
MDelete.MenuName = ""
|
|
||||||
MDelete.Title = "删除" + tab.TableComment
|
|
||||||
MDelete.Icon = ""
|
|
||||||
MDelete.Path = tab.TBName
|
|
||||||
MDelete.MenuType = "F"
|
|
||||||
MDelete.Action = "无"
|
|
||||||
MDelete.Permission = tab.PackageName + ":" + tab.BusinessName + ":remove"
|
|
||||||
MDelete.ParentId = Cmenu.MenuId
|
|
||||||
MDelete.NoCache = false
|
|
||||||
MDelete.Sort = 0
|
|
||||||
MDelete.Visible = "0"
|
|
||||||
MDelete.IsFrame = "0"
|
|
||||||
MDelete.CreateBy = "1"
|
|
||||||
MDelete.UpdateBy = "1"
|
|
||||||
MDelete.CreatedAt = timeNow
|
|
||||||
MDelete.UpdatedAt = timeNow
|
|
||||||
MDelete.MenuId, err = MDelete.Create(db)
|
|
||||||
|
|
||||||
var InterfaceId = 63
|
|
||||||
Amenu := models.Menu{}
|
|
||||||
Amenu.MenuName = tab.TBName
|
|
||||||
Amenu.Title = tab.TableComment
|
|
||||||
Amenu.Icon = "bug"
|
|
||||||
Amenu.Path = tab.TBName
|
|
||||||
Amenu.MenuType = "M"
|
|
||||||
Amenu.Action = "无"
|
|
||||||
Amenu.ParentId = InterfaceId
|
|
||||||
Amenu.NoCache = false
|
|
||||||
Amenu.Sort = 0
|
|
||||||
Amenu.Visible = "1"
|
|
||||||
Amenu.IsFrame = "0"
|
|
||||||
Amenu.CreateBy = "1"
|
|
||||||
Amenu.UpdateBy = "1"
|
|
||||||
Amenu.CreatedAt = timeNow
|
|
||||||
Amenu.UpdatedAt = timeNow
|
|
||||||
Amenu.MenuId, err = Amenu.Create(db)
|
|
||||||
|
|
||||||
AList := models.Menu{}
|
|
||||||
AList.MenuName = ""
|
|
||||||
AList.Title = "分页获取" + tab.TableComment
|
|
||||||
AList.Icon = "bug"
|
|
||||||
AList.Path = "/api/v1/" + tab.ModuleName
|
|
||||||
AList.MenuType = "A"
|
|
||||||
AList.Action = "GET"
|
|
||||||
AList.ParentId = Amenu.MenuId
|
|
||||||
AList.NoCache = false
|
|
||||||
AList.Sort = 0
|
|
||||||
AList.Visible = "1"
|
|
||||||
AList.IsFrame = "0"
|
|
||||||
AList.CreateBy = "1"
|
|
||||||
AList.UpdateBy = "1"
|
|
||||||
AList.CreatedAt = timeNow
|
|
||||||
AList.UpdatedAt = timeNow
|
|
||||||
AList.MenuId, err = AList.Create(db)
|
|
||||||
|
|
||||||
AGet := models.Menu{}
|
|
||||||
AGet.MenuName = ""
|
|
||||||
AGet.Title = "根据id获取" + tab.TableComment
|
|
||||||
AGet.Icon = "bug"
|
|
||||||
AGet.Path = "/api/v1/" + tab.ModuleName + "/:id"
|
|
||||||
AGet.MenuType = "A"
|
|
||||||
AGet.Action = "GET"
|
|
||||||
AGet.ParentId = Amenu.MenuId
|
|
||||||
AGet.NoCache = false
|
|
||||||
AGet.Sort = 0
|
|
||||||
AGet.Visible = "1"
|
|
||||||
AGet.IsFrame = "0"
|
|
||||||
AGet.CreateBy = "1"
|
|
||||||
AGet.UpdateBy = "1"
|
|
||||||
AGet.CreatedAt = timeNow
|
|
||||||
AGet.UpdatedAt = timeNow
|
|
||||||
AGet.MenuId, err = AGet.Create(db)
|
|
||||||
|
|
||||||
ACreate := models.Menu{}
|
|
||||||
ACreate.MenuName = ""
|
|
||||||
ACreate.Title = "创建" + tab.TableComment
|
|
||||||
ACreate.Icon = "bug"
|
|
||||||
ACreate.Path = "/api/v1/" + tab.ModuleName
|
|
||||||
ACreate.MenuType = "A"
|
|
||||||
ACreate.Action = "POST"
|
|
||||||
ACreate.ParentId = Amenu.MenuId
|
|
||||||
ACreate.NoCache = false
|
|
||||||
ACreate.Sort = 0
|
|
||||||
ACreate.Visible = "1"
|
|
||||||
ACreate.IsFrame = "0"
|
|
||||||
ACreate.CreateBy = "1"
|
|
||||||
ACreate.UpdateBy = "1"
|
|
||||||
ACreate.CreatedAt = timeNow
|
|
||||||
ACreate.UpdatedAt = timeNow
|
|
||||||
ACreate.MenuId, err = ACreate.Create(db)
|
|
||||||
|
|
||||||
AUpdate := models.Menu{}
|
|
||||||
AUpdate.MenuName = ""
|
|
||||||
AUpdate.Title = "修改" + tab.TableComment
|
|
||||||
AUpdate.Icon = "bug"
|
|
||||||
AUpdate.Path = "/api/v1/" + tab.ModuleName + "/:id"
|
|
||||||
AUpdate.MenuType = "A"
|
|
||||||
AUpdate.Action = "PUT"
|
|
||||||
AUpdate.ParentId = Amenu.MenuId
|
|
||||||
AUpdate.NoCache = false
|
|
||||||
AUpdate.Sort = 0
|
|
||||||
AUpdate.Visible = "1"
|
|
||||||
AUpdate.IsFrame = "0"
|
|
||||||
AUpdate.CreateBy = "1"
|
|
||||||
AUpdate.UpdateBy = "1"
|
|
||||||
AUpdate.CreatedAt = timeNow
|
|
||||||
AUpdate.UpdatedAt = timeNow
|
|
||||||
AUpdate.MenuId, err = AUpdate.Create(db)
|
|
||||||
|
|
||||||
ADelete := models.Menu{}
|
|
||||||
ADelete.MenuName = ""
|
|
||||||
ADelete.Title = "删除" + tab.TableComment
|
|
||||||
ADelete.Icon = "bug"
|
|
||||||
ADelete.Path = "/api/v1/" + tab.ModuleName
|
|
||||||
ADelete.MenuType = "A"
|
|
||||||
ADelete.Action = "DELETE"
|
|
||||||
ADelete.ParentId = Amenu.MenuId
|
|
||||||
ADelete.NoCache = false
|
|
||||||
ADelete.Sort = 0
|
|
||||||
ADelete.Visible = "1"
|
|
||||||
ADelete.IsFrame = "0"
|
|
||||||
ADelete.CreateBy = "1"
|
|
||||||
ADelete.UpdateBy = "1"
|
|
||||||
ADelete.CreatedAt = timeNow
|
|
||||||
ADelete.UpdatedAt = timeNow
|
|
||||||
ADelete.MenuId, err = ADelete.Create(db)
|
|
||||||
|
|
||||||
e.OK("", "数据生成成功!")
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type CasbinRule struct {
|
||||||
|
ID uint `gorm:"primaryKey;autoIncrement"`
|
||||||
|
Ptype string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V0 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V1 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V2 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V3 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V4 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
V5 string `gorm:"size:512;uniqueIndex:unique_index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (CasbinRule) TableName() string {
|
||||||
|
return "sys_casbin_rule"
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ func ExecSql(db *gorm.DB, filePath string) error {
|
|||||||
fmt.Println(sqlList[i])
|
fmt.Println(sqlList[i])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sql := strings.Replace(sqlList[i]+";", "\n", "", 0)
|
sql := strings.Replace(sqlList[i]+";", "\n", "", -1)
|
||||||
sql = strings.TrimSpace(sql)
|
sql = strings.TrimSpace(sql)
|
||||||
if err = db.Exec(sql).Error; err != nil {
|
if err = db.Exec(sql).Error; err != nil {
|
||||||
log.Printf("error sql: %s", sql)
|
log.Printf("error sql: %s", sql)
|
||||||
|
|||||||
@@ -1,343 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"go-admin/common/models"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
"go-admin/app/admin/models/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Menu struct {
|
|
||||||
MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"`
|
|
||||||
MenuName string `json:"menuName" gorm:"size:128;"`
|
|
||||||
Title string `json:"title" gorm:"size:128;"`
|
|
||||||
Icon string `json:"icon" gorm:"size:128;"`
|
|
||||||
Path string `json:"path" gorm:"size:128;"`
|
|
||||||
Paths string `json:"paths" gorm:"size:128;"`
|
|
||||||
MenuType string `json:"menuType" gorm:"size:1;"`
|
|
||||||
Action string `json:"action" gorm:"size:16;"`
|
|
||||||
Permission string `json:"permission" gorm:"size:255;"`
|
|
||||||
ParentId int `json:"parentId" gorm:"size:11;"`
|
|
||||||
NoCache bool `json:"noCache" gorm:"size:8;"`
|
|
||||||
Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
|
|
||||||
Component string `json:"component" gorm:"size:255;"`
|
|
||||||
Sort int `json:"sort" gorm:"size:4;"`
|
|
||||||
Visible string `json:"visible" gorm:"size:1;"`
|
|
||||||
CreateBy string `json:"createBy" gorm:"size:128;"`
|
|
||||||
UpdateBy string `json:"updateBy" gorm:"size:128;"`
|
|
||||||
IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
|
|
||||||
DataScope string `json:"dataScope" gorm:"-"`
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
RoleId int `gorm:"-"`
|
|
||||||
Children []Menu `json:"children" gorm:"-"`
|
|
||||||
IsSelect bool `json:"is_select" gorm:"-"`
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Menu) TableName() string {
|
|
||||||
return "sys_menu"
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuLable struct {
|
|
||||||
Id int `json:"id" gorm:"-"`
|
|
||||||
Label string `json:"label" gorm:"-"`
|
|
||||||
Children []MenuLable `json:"children" gorm:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Menus struct {
|
|
||||||
MenuId int `json:"menuId" gorm:"column:menu_id;primaryKey;autoIncrement;"`
|
|
||||||
MenuName string `json:"menuName" gorm:"column:menu_name"`
|
|
||||||
Title string `json:"title" gorm:"column:title"`
|
|
||||||
Icon string `json:"icon" gorm:"column:icon"`
|
|
||||||
Path string `json:"path" gorm:"column:path"`
|
|
||||||
MenuType string `json:"menuType" gorm:"column:menu_type"`
|
|
||||||
Action string `json:"action" gorm:"column:action"`
|
|
||||||
Permission string `json:"permission" gorm:"column:permission"`
|
|
||||||
ParentId int `json:"parentId" gorm:"column:parent_id"`
|
|
||||||
NoCache bool `json:"noCache" gorm:"column:no_cache"`
|
|
||||||
Breadcrumb string `json:"breadcrumb" gorm:"column:breadcrumb"`
|
|
||||||
Component string `json:"component" gorm:"column:component"`
|
|
||||||
Sort int `json:"sort" gorm:"column:sort"`
|
|
||||||
|
|
||||||
Visible string `json:"visible" gorm:"column:visible"`
|
|
||||||
Children []Menu `json:"children" gorm:"-"`
|
|
||||||
|
|
||||||
CreateBy string `json:"createBy" gorm:"column:create_by"`
|
|
||||||
UpdateBy string `json:"updateBy" gorm:"column:update_by"`
|
|
||||||
DataScope string `json:"dataScope" gorm:"-"`
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
BaseModel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Menus) TableName() string {
|
|
||||||
return "sys_menu"
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuRole struct {
|
|
||||||
Menus
|
|
||||||
IsSelect bool `json:"is_select" gorm:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MS []Menu
|
|
||||||
|
|
||||||
//func (e *Menu) GetByMenuId() (Menu Menu, err error) {
|
|
||||||
//
|
|
||||||
// table := orm.Eloquent.Table(e.TableName())
|
|
||||||
// table = table.Where("menu_id = ?", e.MenuId)
|
|
||||||
// if err = table.Find(&Menu).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *Menu) SetMenu() (m []Menu, err error) {
|
|
||||||
// menulist, err := e.GetPage()
|
|
||||||
//
|
|
||||||
// m = make([]Menu, 0)
|
|
||||||
// for i := 0; i < len(menulist); i++ {
|
|
||||||
// if menulist[i].ParentId != 0 {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// menusInfo := DiguiMenu(&menulist, menulist[i])
|
|
||||||
//
|
|
||||||
// m = append(m, menusInfo)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func DiguiMenu(menulist *[]Menu, menu Menu) Menu {
|
|
||||||
// list := *menulist
|
|
||||||
//
|
|
||||||
// min := make([]Menu, 0)
|
|
||||||
// for j := 0; j < len(list); j++ {
|
|
||||||
//
|
|
||||||
// if menu.MenuId != list[j].ParentId {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// mi := Menu{}
|
|
||||||
// mi.MenuId = list[j].MenuId
|
|
||||||
// mi.MenuName = list[j].MenuName
|
|
||||||
// mi.Title = list[j].Title
|
|
||||||
// mi.Icon = list[j].Icon
|
|
||||||
// mi.Path = list[j].Path
|
|
||||||
// mi.MenuType = list[j].MenuType
|
|
||||||
// mi.Action = list[j].Action
|
|
||||||
// mi.Permission = list[j].Permission
|
|
||||||
// mi.ParentId = list[j].ParentId
|
|
||||||
// mi.NoCache = list[j].NoCache
|
|
||||||
// mi.Breadcrumb = list[j].Breadcrumb
|
|
||||||
// mi.Component = list[j].Component
|
|
||||||
// mi.Sort = list[j].Sort
|
|
||||||
// mi.Visible = list[j].Visible
|
|
||||||
// mi.CreatedAt = list[j].CreatedAt
|
|
||||||
// mi.Children = []Menu{}
|
|
||||||
//
|
|
||||||
// if mi.MenuType != "F" {
|
|
||||||
// ms := DiguiMenu(menulist, mi)
|
|
||||||
// min = append(min, ms)
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// min = append(min, mi)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// menu.Children = min
|
|
||||||
// return menu
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *Menu) SetMenuLabel() (m *[]MenuLable, err error) {
|
|
||||||
// menulist, err := e.Get()
|
|
||||||
//
|
|
||||||
// ml := make([]MenuLable, 0)
|
|
||||||
// for i := 0; i < len(menulist); i++ {
|
|
||||||
// if menulist[i].ParentId != 0 {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// e := MenuLable{}
|
|
||||||
// e.Id = menulist[i].MenuId
|
|
||||||
// e.Label = menulist[i].Title
|
|
||||||
// menusInfo := MenuLabelCall(&menulist, e)
|
|
||||||
//
|
|
||||||
// ml = append(ml, menusInfo)
|
|
||||||
// }
|
|
||||||
// return &ml, err
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func MenuLabelCall(menulist *[]Menu, menu MenuLable) MenuLable {
|
|
||||||
// list := *menulist
|
|
||||||
//
|
|
||||||
// min := make([]MenuLable, 0)
|
|
||||||
// for j := 0; j < len(list); j++ {
|
|
||||||
//
|
|
||||||
// if menu.Id != list[j].ParentId {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// mi := MenuLable{}
|
|
||||||
// mi.Id = list[j].MenuId
|
|
||||||
// mi.Label = list[j].Title
|
|
||||||
// mi.Children = []MenuLable{}
|
|
||||||
// if list[j].MenuType != "F" {
|
|
||||||
// ms := MenuLabelCall(menulist, mi)
|
|
||||||
// min = append(min, ms)
|
|
||||||
// } else {
|
|
||||||
// min = append(min, mi)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// if len(min) > 0 {
|
|
||||||
// menu.Children = min
|
|
||||||
// } else {
|
|
||||||
// menu.Children = nil
|
|
||||||
// }
|
|
||||||
// return menu
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *Menu) SetMenuRole(roleName string) (m []Menu, err error) {
|
|
||||||
//
|
|
||||||
// menus, err := e.GetByRoleName(roleName)
|
|
||||||
//
|
|
||||||
// m = make([]Menu, 0)
|
|
||||||
// for i := 0; i < len(menus); i++ {
|
|
||||||
// if menus[i].ParentId != 0 {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// menusInfo := DiguiMenu(&menus, menus[i])
|
|
||||||
//
|
|
||||||
// m = append(m, menusInfo)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *MenuRole) Get(tx *gorm.DB) (Menus []MenuRole, err error) {
|
|
||||||
// table := tx.Table(e.TableName())
|
|
||||||
// if e.MenuName != "" {
|
|
||||||
// table = table.Where("menu_name = ?", e.MenuName)
|
|
||||||
// }
|
|
||||||
// if err = table.Order("sort").Find(&Menus).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *Menu) GetByRoleName(roleName string) (Menus []Menu, err error) {
|
|
||||||
// var table *gorm.DB
|
|
||||||
// if roleName == "admin" {
|
|
||||||
// table = orm.Eloquent.Table(e.TableName()).Select("sys_menu.*")
|
|
||||||
// table = table.Where(" menu_type in ('M','C')")
|
|
||||||
// } else {
|
|
||||||
// table = orm.Eloquent.Table(e.TableName()).Select("sys_menu.*").Joins("left join sys_role_menu on sys_role_menu.menu_id=sys_menu.menu_id")
|
|
||||||
// table = table.Where("sys_role_menu.role_name=? and menu_type in ('M','C')", roleName)
|
|
||||||
// }
|
|
||||||
// if err = table.Order("sort").Find(&Menus).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (e *Menu) Get(tx *gorm.DB) (Menus []Menu, err error) {
|
|
||||||
table := tx.Table(e.TableName())
|
|
||||||
if e.MenuName != "" {
|
|
||||||
table = table.Where("menu_name = ?", e.MenuName)
|
|
||||||
}
|
|
||||||
if e.Path != "" {
|
|
||||||
table = table.Where("path = ?", e.Path)
|
|
||||||
}
|
|
||||||
if e.Action != "" {
|
|
||||||
table = table.Where("action = ?", e.Action)
|
|
||||||
}
|
|
||||||
if e.MenuType != "" {
|
|
||||||
table = table.Where("menu_type = ?", e.MenuType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = table.Order("sort").Find(&Menus).Error; err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Menu) GetPage(tx *gorm.DB) (Menus []Menu, err error) {
|
|
||||||
table := tx.Table(e.TableName())
|
|
||||||
if e.MenuName != "" {
|
|
||||||
table = table.Where("menu_name = ?", e.MenuName)
|
|
||||||
}
|
|
||||||
if e.Title != "" {
|
|
||||||
table = table.Where("title = ?", e.Title)
|
|
||||||
}
|
|
||||||
if e.Visible != "" {
|
|
||||||
table = table.Where("visible = ?", e.Visible)
|
|
||||||
}
|
|
||||||
if e.MenuType != "" {
|
|
||||||
table = table.Where("menu_type = ?", e.MenuType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据权限控制
|
|
||||||
dataPermission := new(system.DataPermission)
|
|
||||||
dataPermission.UserId, _ = pkg.StringToInt(e.DataScope)
|
|
||||||
table, err = dataPermission.GetDataScope("sys_menu", table)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err = table.Order("sort").Find(&Menus).Error; err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Menu) Create(tx *gorm.DB) (id int, err error) {
|
|
||||||
result := tx.Table(e.TableName()).Create(&e)
|
|
||||||
if result.Error != nil {
|
|
||||||
err = result.Error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = InitPaths(tx, e)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id = e.MenuId
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitPaths(tx *gorm.DB, menu *Menu) (err error) {
|
|
||||||
parentMenu := new(Menu)
|
|
||||||
if menu.ParentId != 0 {
|
|
||||||
tx.Table("sys_menu").Where("menu_id = ?", menu.ParentId).First(parentMenu)
|
|
||||||
if parentMenu.Paths == "" {
|
|
||||||
err = errors.New("父级paths异常,请尝试对当前节点父级菜单进行更新操作!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
menu.Paths = parentMenu.Paths + "/" + pkg.IntToString(menu.MenuId)
|
|
||||||
} else {
|
|
||||||
menu.Paths = "/0/" + pkg.IntToString(menu.MenuId)
|
|
||||||
}
|
|
||||||
tx.Table("sys_menu").Where("menu_id = ?", menu.MenuId).Update("paths", menu.Paths)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//func (e *Menu) Update(tx *gorm.DB, id int) (update Menu, err error) {
|
|
||||||
// if err = tx.Table(e.TableName()).First(&update, id).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //参数1:是要修改的数据
|
|
||||||
// //参数2:是修改的数据
|
|
||||||
// if err = tx.Table(e.TableName()).Model(&update).Updates(&e).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// err = InitPaths(tx, e)
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (e *Menu) Delete(tx *gorm.DB, id int) (success bool, err error) {
|
|
||||||
// if err = tx.Table(e.TableName()).Where("menu_id = ?", id).Delete(&Menu{}).Error; err != nil {
|
|
||||||
// success = false
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// success = true
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BaseModel struct {
|
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
|
||||||
DeletedAt *time.Time `json:"deletedAt"`
|
|
||||||
}
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import "go-admin/common/models"
|
|
||||||
|
|
||||||
type SysRole struct {
|
|
||||||
RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码
|
|
||||||
RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称
|
|
||||||
Status string `json:"status" gorm:"size:4;"` //
|
|
||||||
RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码
|
|
||||||
RoleSort int `json:"roleSort" gorm:""` //角色排序
|
|
||||||
Flag string `json:"flag" gorm:"size:128;"` //
|
|
||||||
Remark string `json:"remark" gorm:"size:255;"` //备注
|
|
||||||
Admin bool `json:"admin" gorm:"size:4;"`
|
|
||||||
DataScope string `json:"dataScope" gorm:"size:128;"`
|
|
||||||
models.ModelTime
|
|
||||||
models.ControlBy
|
|
||||||
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
MenuIds []int `json:"menuIds" gorm:"-"`
|
|
||||||
DeptIds []int `json:"deptIds" gorm:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysRole) TableName() string {
|
|
||||||
return "sys_role"
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuIdList struct {
|
|
||||||
MenuId int `json:"menuId"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//func (role *SysRole) GetById(tx *gorm.DB, id interface{}) error {
|
|
||||||
// return tx.First(role, id).Error
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) GetPage(pageSize int, pageIndex int) ([]SysRole, int, error) {
|
|
||||||
// var doc []SysRole
|
|
||||||
//
|
|
||||||
// table := orm.Eloquent.Table("sys_role")
|
|
||||||
// if role.RoleId != 0 {
|
|
||||||
// table = table.Where("role_id = ?", role.RoleId)
|
|
||||||
// }
|
|
||||||
// if role.RoleName != "" {
|
|
||||||
// table = table.Where("role_name = ?", role.RoleName)
|
|
||||||
// }
|
|
||||||
// if role.Status != "" {
|
|
||||||
// table = table.Where("status = ?", role.Status)
|
|
||||||
// }
|
|
||||||
// if role.RoleKey != "" {
|
|
||||||
// table = table.Where("role_key = ?", role.RoleKey)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 数据权限控制
|
|
||||||
// dataPermission := new(DataPermission)
|
|
||||||
// dataPermission.UserId, _ = tools.StringToInt(role.DataScope)
|
|
||||||
// table, err := dataPermission.GetDataScope("sys_role", table)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, 0, err
|
|
||||||
// }
|
|
||||||
// var count int64
|
|
||||||
//
|
|
||||||
// if err := table.Order("role_sort").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil {
|
|
||||||
// return nil, 0, err
|
|
||||||
// }
|
|
||||||
// //table.Where("`deleted_at` IS NULL").Count(&count)
|
|
||||||
// return doc, int(count), nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) Get() (SysRole SysRole, err error) {
|
|
||||||
// table := orm.Eloquent.Table("sys_role")
|
|
||||||
// if role.RoleId != 0 {
|
|
||||||
// table = table.Where("role_id = ?", role.RoleId)
|
|
||||||
// }
|
|
||||||
// if role.RoleName != "" {
|
|
||||||
// table = table.Where("role_name = ?", role.RoleName)
|
|
||||||
// }
|
|
||||||
// if err = table.First(&SysRole).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) GetOne(sysRole *SysRole) (err error) {
|
|
||||||
// table := orm.Eloquent.Table("sys_role")
|
|
||||||
// if role.RoleId != 0 {
|
|
||||||
// table = table.Where("role_id = ?", role.RoleId)
|
|
||||||
// }
|
|
||||||
// if role.RoleName != "" {
|
|
||||||
// table = table.Where("role_name = ?", role.RoleName)
|
|
||||||
// }
|
|
||||||
// if err = table.First(sysRole).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) GetList() (SysRole []SysRole, err error) {
|
|
||||||
// table := orm.Eloquent.Table("sys_role")
|
|
||||||
// if role.RoleId != 0 {
|
|
||||||
// table = table.Where("role_id = ?", role.RoleId)
|
|
||||||
// }
|
|
||||||
// if role.RoleName != "" {
|
|
||||||
// table = table.Where("role_name = ?", role.RoleName)
|
|
||||||
// }
|
|
||||||
// if err = table.Order("role_sort").Find(&SysRole).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// 获取角色对应的菜单ids
|
|
||||||
//func (role *SysRole) GetRoleMeunId() ([]int, error) {
|
|
||||||
// menuIds := make([]int, 0)
|
|
||||||
// menuList := make([]MenuIdList, 0)
|
|
||||||
// if err := orm.Eloquent.Table("sys_role_menu").
|
|
||||||
// Select("sys_role_menu.menu_id").
|
|
||||||
// Where("role_id = ? ", role.RoleId).
|
|
||||||
// Where(" sys_role_menu.menu_id not in(select sys_menu.parent_id from sys_role_menu " +
|
|
||||||
// "LEFT JOIN sys_menu on sys_menu.menu_id=sys_role_menu.menu_id where role_id =? and parent_id is not null)", role.RoleId).
|
|
||||||
// Find(&menuList).Error; err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for i := 0; i < len(menuList); i++ {
|
|
||||||
// menuIds = append(menuIds, menuList[i].MenuId)
|
|
||||||
// }
|
|
||||||
// return menuIds, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) Insert() (id int, err error) {
|
|
||||||
// var i int64
|
|
||||||
// orm.Eloquent.Table(role.TableName()).Where("role_name=? or role_key = ?", role.RoleName, role.RoleKey).Count(&i)
|
|
||||||
// if i > 0 {
|
|
||||||
// return 0, errors.New("角色名称或者角色标识已经存在!")
|
|
||||||
// }
|
|
||||||
// role.UpdateBy = ""
|
|
||||||
// result := orm.Eloquent.Table(role.TableName()).Create(&role)
|
|
||||||
// if result.Error != nil {
|
|
||||||
// err = result.Error
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// id = role.RoleId
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//type DeptIdList struct {
|
|
||||||
// DeptId int `json:"DeptId"`
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func (role *SysRole) GetRoleDeptId() ([]int, error) {
|
|
||||||
// deptIds := make([]int, 0)
|
|
||||||
// deptList := make([]DeptIdList, 0)
|
|
||||||
// if err := orm.Eloquent.Table("sys_role_dept").Select("sys_role_dept.dept_id").Joins("LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id").Where("role_id = ? ", role.RoleId).Where(" sys_role_dept.dept_id not in(select sys_dept.parent_id from sys_role_dept LEFT JOIN sys_dept on sys_dept.dept_id=sys_role_dept.dept_id where role_id =? )", role.RoleId).Find(&deptList).Error; err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for i := 0; i < len(deptList); i++ {
|
|
||||||
// deptIds = append(deptIds, deptList[i].DeptId)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return deptIds, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
////修改
|
|
||||||
//func (role *SysRole) Update(id int) (update SysRole, err error) {
|
|
||||||
// if err = orm.Eloquent.Table(role.TableName()).First(&update, id).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if role.RoleName != "" && role.RoleName != update.RoleName {
|
|
||||||
// return update, errors.New("角色名称不允许修改!")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if role.RoleKey != "" && role.RoleKey != update.RoleKey {
|
|
||||||
// return update, errors.New("角色标识不允许修改!")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //参数1:是要修改的数据
|
|
||||||
// //参数2:是修改的数据
|
|
||||||
// if err = orm.Eloquent.Table(role.TableName()).Model(&update).Updates(&role).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
////批量删除
|
|
||||||
//func (role *SysRole) BatchDelete(id []int) (Result bool, err error) {
|
|
||||||
// tx := orm.Eloquent.Begin()
|
|
||||||
//
|
|
||||||
// defer func() {
|
|
||||||
// if r := recover(); r != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
//
|
|
||||||
// if err := tx.Error; err != nil {
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
// // 查询角色
|
|
||||||
// var roles []SysRole
|
|
||||||
// if err := tx.Table("sys_role").Where("role_id in (?)", id).Find(&roles).Error; err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var count int64
|
|
||||||
// if err := tx.Table("sys_user").Where("role_id in (?)", id).Count(&count).Error; err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
// if count > 0 {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, errors.New("存在绑定用户,请解绑后重试")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 删除角色
|
|
||||||
// if err = tx.Table(role.TableName()).Where("role_id in (?)", id).Unscoped().Delete(&SysRole{}).Error; err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 删除角色菜单
|
|
||||||
// if err := tx.Table("sys_role_menu").Where("role_id in (?)", id).Delete(&RoleMenu{}).Error; err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 删除casbin配置
|
|
||||||
// for i := 0; i < len(roles); i++ {
|
|
||||||
// if err := tx.Table("sys_casbin_rule").Where("v0 in (?)", roles[0].RoleKey).Delete(&CasbinRule{}).Error; err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err := tx.Commit().Error; err != nil {
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return true, nil
|
|
||||||
//}
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bitly/go-simplejson"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk/runtime"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/storage"
|
||||||
|
|
||||||
|
"go-admin/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysApi struct {
|
||||||
|
Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"`
|
||||||
|
Handle string `json:"handle" gorm:"size:128;comment:handle"`
|
||||||
|
Title string `json:"title" gorm:"size:128;comment:标题"`
|
||||||
|
Path string `json:"path" gorm:"size:128;comment:地址"`
|
||||||
|
Action string `json:"action" gorm:"size:16;comment:请求类型"`
|
||||||
|
Type string `json:"type" gorm:"size:16;comment:接口类型"`
|
||||||
|
// AppCode identifies which application's seed.SeedMenus call wrote this
|
||||||
|
// row; empty for the host's own built-in APIs. Same NOT NULL DEFAULT ''
|
||||||
|
// reasoning as SysMenu.AppCode.
|
||||||
|
AppCode string `json:"appCode" gorm:"type:varchar(64);not null;default:'';index:idx_sys_api_app_code;comment:AppCode"`
|
||||||
|
models.ModelTime
|
||||||
|
models.ControlBy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysApi) TableName() string {
|
||||||
|
return "sys_api"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysApi) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysApi) GetId() interface{} {
|
||||||
|
return e.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
func SaveSysApi(message storage.Messager) (err error) {
|
||||||
|
var rb []byte
|
||||||
|
rb, err = json.Marshal(message.GetValues())
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("json Marshal error, %v", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var l runtime.Routers
|
||||||
|
err = json.Unmarshal(rb, &l)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("json Unmarshal error, %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dbList := sdk.Runtime.GetAllDb()
|
||||||
|
for _, d := range dbList {
|
||||||
|
for _, v := range l.List {
|
||||||
|
if v.HttpMethod != "HEAD" ||
|
||||||
|
strings.Contains(v.RelativePath, "/swagger/") ||
|
||||||
|
strings.Contains(v.RelativePath, "/static/") ||
|
||||||
|
strings.Contains(v.RelativePath, "/form-generator/") ||
|
||||||
|
strings.Contains(v.RelativePath, "/sys/tables") {
|
||||||
|
|
||||||
|
// 根据接口方法注释里的@Summary填充接口名称,适用于代码生成器
|
||||||
|
// 可在此处增加配置路径前缀的if判断,只对代码生成的自建应用进行定向的接口名称填充
|
||||||
|
jsonFile, _ := ioutil.ReadFile("docs/swagger.json")
|
||||||
|
jsonData, _ := simplejson.NewFromReader(bytes.NewReader(jsonFile))
|
||||||
|
urlPath := v.RelativePath
|
||||||
|
idPatten := "(.*)/:(\\w+)" // 正则替换,把:id换成{id}
|
||||||
|
reg, _ := regexp.Compile(idPatten)
|
||||||
|
if reg.MatchString(urlPath) {
|
||||||
|
urlPath = reg.ReplaceAllString(v.RelativePath, "${1}/{${2}}") // 把:id换成{id}
|
||||||
|
}
|
||||||
|
apiTitle, _ := jsonData.Get("paths").Get(urlPath).Get(strings.ToLower(v.HttpMethod)).Get("summary").String()
|
||||||
|
|
||||||
|
err := d.Debug().Where(SysApi{Path: v.RelativePath, Action: v.HttpMethod}).
|
||||||
|
Attrs(SysApi{Handle: v.Handler, Title: apiTitle}).
|
||||||
|
FirstOrCreate(&SysApi{}).
|
||||||
|
//Update("handle", v.Handler).
|
||||||
|
Error
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Models SaveSysApi error: %s \r\n ", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go-admin/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The values sys_app.status takes.
|
||||||
|
//
|
||||||
|
// Three states rather than a single "installed", because an install that
|
||||||
|
// stopped partway has to be an observable row rather than the absence of one:
|
||||||
|
// the versions an app installs are separate migration files, and on MySQL a
|
||||||
|
// DDL statement commits the transaction around it - taking an outer
|
||||||
|
// transaction and every savepoint under it with it - so they cannot be
|
||||||
|
// wrapped in one.
|
||||||
|
//
|
||||||
|
// AppInstalling is also what a row reads as after the process was killed
|
||||||
|
// mid-install, which is why it is not treated as "installed" by anything.
|
||||||
|
const (
|
||||||
|
AppInstalling = 1
|
||||||
|
AppInstalled = 2
|
||||||
|
AppFailed = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// SysApp is the sys_app row model: one row per installed application (PRD
|
||||||
|
// 008 F2). It deliberately does not embed models.ModelTime - see the design
|
||||||
|
// doc (docs-prd/008-应用清单与安装器/数据库变更.md) §1.1 for why an
|
||||||
|
// installed-app registry does not need the millisecond soft-delete marker
|
||||||
|
// every other sys_* table follows. Uninstalling an app deletes its row
|
||||||
|
// outright; a later reinstall creates a fresh one.
|
||||||
|
type SysApp struct {
|
||||||
|
models.Model // Id int, primary key, autoincrement
|
||||||
|
|
||||||
|
// AppCode is the app.Manifest.Code / migration.ForApp / seed.SeedMenus
|
||||||
|
// identity, already lower-cased by migration.NormalizeAppCode before
|
||||||
|
// anything reaches this table. Unique: row existence alone answers G2
|
||||||
|
// ("is app X installed").
|
||||||
|
AppCode string `json:"appCode" gorm:"type:varchar(64);not null;uniqueIndex:uk_sys_app_app_code;comment:app code"`
|
||||||
|
|
||||||
|
Name string `json:"name" gorm:"size:128;not null;comment:display name, from Manifest.Name"`
|
||||||
|
// Version is the version this row currently reflects - attempted or
|
||||||
|
// confirmed, disambiguated by Status. It does not drive which
|
||||||
|
// migrations run next; sys_migration's per-version rows do that (see
|
||||||
|
// design doc §1.5's resume flow). This field is descriptive, refreshed
|
||||||
|
// from the manifest on every install/upgrade/resume attempt.
|
||||||
|
Version string `json:"version" gorm:"size:32;not null;comment:version this row currently reflects, see Status"`
|
||||||
|
Description string `json:"description" gorm:"size:255;not null;default:'';comment:from Manifest.Description"`
|
||||||
|
Author string `json:"author" gorm:"size:128;not null;default:'';comment:from Manifest.Author"`
|
||||||
|
|
||||||
|
// Requires is a comma-separated list of app codes this app declared as
|
||||||
|
// dependencies (Manifest.Requires). Stored as plain VARCHAR CSV, not
|
||||||
|
// JSON - see design doc §1.3 for why. F8 (P1) is what validates and
|
||||||
|
// orders on this; this batch only stores what the manifest declared.
|
||||||
|
Requires string `json:"requires" gorm:"size:255;not null;default:'';comment:declared dependency app codes, comma separated"`
|
||||||
|
|
||||||
|
// Pricing/License are reserved passthrough fields (PRD 003; PRD 008
|
||||||
|
// open question 1). This batch stores whatever the manifest carries and
|
||||||
|
// does not interpret either one.
|
||||||
|
Pricing string `json:"pricing" gorm:"size:64;not null;default:'';comment:reserved, not interpreted by this batch"`
|
||||||
|
License string `json:"license" gorm:"size:64;not null;default:'';comment:reserved, not interpreted by this batch"`
|
||||||
|
|
||||||
|
// Status: 1=installing 2=installed 3=failed. Three states, not a
|
||||||
|
// single "1=installed", because a partial, stuck install has to be an
|
||||||
|
// observable row rather than "the row doesn't exist yet" - see design
|
||||||
|
// doc §1.5 for why cross-migration-file atomicity is not available on
|
||||||
|
// MySQL (implicit commit on DDL).
|
||||||
|
Status int `json:"status" gorm:"size:4;not null;default:1;comment:1=installing 2=installed 3=failed"`
|
||||||
|
|
||||||
|
// FailedVersion and LastError are DIAGNOSTIC TEXT ONLY - what a human
|
||||||
|
// looking at this row is told about the last failure, nothing more. No
|
||||||
|
// code anywhere may read either one to decide what to do next.
|
||||||
|
//
|
||||||
|
// The question "where should a resume pick up" has exactly one
|
||||||
|
// authoritative answer, and it is not these two columns: subtract
|
||||||
|
// sys_migration's applied rows for this app_code from what the app's
|
||||||
|
// own compiled-in code has registered (migration.Snapshot()/ForApp -
|
||||||
|
// the same set F7's `migrate status` already walks). That answer can
|
||||||
|
// never go stale, because it is not stored anywhere to go stale - it is
|
||||||
|
// recomputed from sys_migration every time it is asked. FailedVersion
|
||||||
|
// is a snapshot of what that computation returned at the moment of
|
||||||
|
// failure, kept only so an operator does not have to go find the
|
||||||
|
// process's logs; if it and a fresh recomputation from sys_migration
|
||||||
|
// ever disagree, sys_migration is right and this column is stale, by
|
||||||
|
// definition, and nothing should ever notice or care except a human
|
||||||
|
// reading the row.
|
||||||
|
FailedVersion string `json:"failedVersion" gorm:"size:64;not null;default:'';comment:diagnostic snapshot only, not a judgment basis; meaningful only when status=3"`
|
||||||
|
LastError string `json:"lastError" gorm:"size:255;not null;default:'';comment:diagnostic text only, not a judgment basis; meaningful only when status=3"`
|
||||||
|
|
||||||
|
// InstalledAt is when this app first reached status=installed - set
|
||||||
|
// once, never moved by a later upgrade (see design doc §1.4). Nullable,
|
||||||
|
// unlike every other column here: a row can exist before it has a
|
||||||
|
// value (a fresh install starts at status=installing). This is not the
|
||||||
|
// deleted_at problem 1786700003000_soft_delete_marker.go fixed - that
|
||||||
|
// column sat inside a unique index, where NULL <> NULL let two live
|
||||||
|
// rows coexist under the same key. InstalledAt is in no index at all,
|
||||||
|
// so nullability here opens no such hole.
|
||||||
|
InstalledAt *time.Time `json:"installedAt" gorm:"comment:first successful install time; null until status first reaches installed"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt" gorm:"comment:last updated time"`
|
||||||
|
|
||||||
|
models.ControlBy // CreateBy/UpdateBy: which operator triggered the attempt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysApp) TableName() string {
|
||||||
|
return "sys_app"
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// SysAppCasbinGrant is a ledger of casbin_rule rows an app install created,
|
||||||
|
// keyed by the exact natural key casbin_rule itself is unique on. It exists
|
||||||
|
// because casbin_rule is not a table this project owns (see design doc
|
||||||
|
// docs-prd/008-应用清单与安装器/数据库变更.md §2.2): we cannot add an
|
||||||
|
// app_code column to it without that column being silently zeroed the first
|
||||||
|
// time anything calls the gorm-adapter's SavePolicy/SavePolicyCtx. Recording
|
||||||
|
// the natural key here, instead of a foreign key into casbin_rule, is also
|
||||||
|
// what survives SysRole.Update's RemoveFilteredPolicy+re-add cycle for a
|
||||||
|
// role's policies (app/admin/service/sys_role.go): that cycle replaces the
|
||||||
|
// underlying row (a new auto-increment ID) but reproduces the same
|
||||||
|
// (ptype,v0,v1,v2) tuple from the same sys_menu/sys_api data, so a
|
||||||
|
// natural-key match here still finds it. What it does not survive is the
|
||||||
|
// role being renamed, or the tuple being rebuilt from a completely different
|
||||||
|
// source (a future SavePolicy call from outside this seeder) - in both cases
|
||||||
|
// the match legitimately fails, and business rule 3 says the uninstaller
|
||||||
|
// should report and skip, not delete something else that happens to look
|
||||||
|
// the same.
|
||||||
|
type SysAppCasbinGrant struct {
|
||||||
|
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
|
||||||
|
|
||||||
|
AppCode string `json:"appCode" gorm:"type:varchar(64);not null;index:idx_sys_app_casbin_grant_app_code;comment:app code that created this grant"`
|
||||||
|
|
||||||
|
// Column widths mirror gorm-adapter's own CasbinRule struct exactly, so
|
||||||
|
// a value that fits into casbin_rule always fits here, and the unique
|
||||||
|
// index below matches the one createTable() puts on casbin_rule itself.
|
||||||
|
Ptype string `json:"ptype" gorm:"size:100;not null;uniqueIndex:uk_sys_app_casbin_grant_rule;comment:casbin ptype, 'p' today"`
|
||||||
|
V0 string `json:"v0" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:role_key at grant time"`
|
||||||
|
V1 string `json:"v1" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:api path"`
|
||||||
|
V2 string `json:"v2" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:http method"`
|
||||||
|
V3 string `json:"v3" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:unused today"`
|
||||||
|
V4 string `json:"v4" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:unused today"`
|
||||||
|
V5 string `json:"v5" gorm:"size:100;not null;default:'';uniqueIndex:uk_sys_app_casbin_grant_rule;comment:unused today"`
|
||||||
|
|
||||||
|
CreatedAt time.Time `json:"createdAt" gorm:"comment:when this grant was recorded"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysAppCasbinGrant) TableName() string {
|
||||||
|
return "sys_app_casbin_grant"
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysCategory struct {
|
|
||||||
models.Model
|
|
||||||
Name string `json:"name" gorm:"type:varchar(255);comment:名称"` //
|
|
||||||
Img string `json:"img" gorm:"type:varchar(255);comment:图标"` //
|
|
||||||
Sort int `json:"sort" gorm:"type:int(4);comment:排序"` //
|
|
||||||
Status int `json:"status" gorm:"type:int(1);comment:状态"` //
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` //
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysCategory) TableName() string {
|
|
||||||
return "sys_category"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysCategory) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysCategory) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysChinaAreaData struct {
|
|
||||||
models.Model
|
|
||||||
|
|
||||||
PId string `json:"pId" gorm:"type:int(11);comment:上级编码"`
|
|
||||||
Name string `json:"name" gorm:"type:varchar(128);comment:名称"`
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysChinaAreaData) TableName() string {
|
|
||||||
return "sys_china_area_data"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysChinaAreaData) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysChinaAreaData) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-admin/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysConfig struct {
|
||||||
|
models.Model
|
||||||
|
ConfigName string `json:"configName" gorm:"size:128;comment:ConfigName"` //
|
||||||
|
ConfigKey string `json:"configKey" gorm:"size:128;comment:ConfigKey"` //
|
||||||
|
ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` //
|
||||||
|
ConfigType string `json:"configType" gorm:"size:64;comment:ConfigType"`
|
||||||
|
IsFrontend string `json:"isFrontend" gorm:"size:64;comment:是否前台"` //
|
||||||
|
Remark string `json:"remark" gorm:"size:128;comment:Remark"` //
|
||||||
|
models.ControlBy
|
||||||
|
models.ModelTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysConfig) TableName() string {
|
||||||
|
return "sys_config"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysConfig) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysConfig) GetId() interface{} {
|
||||||
|
return e.Id
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysContent struct {
|
|
||||||
models.Model
|
|
||||||
CateId int `json:"cateId" gorm:"type:int(11);comment:分类id"`
|
|
||||||
Name string `json:"name" gorm:"type:varchar(255);comment:名称"`
|
|
||||||
Status int `json:"status" gorm:"type:int(1);comment:状态"`
|
|
||||||
Img string `json:"img" gorm:"type:varchar(255);comment:图片"`
|
|
||||||
Content string `json:"content" gorm:"type:text;comment:内容"`
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
|
||||||
Sort int `json:"sort" gorm:"type:int(4);comment:排序"`
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// TableName
|
|
||||||
func (SysContent) TableName() string {
|
|
||||||
return "sys_content"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate
|
|
||||||
func (e *SysContent) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysContent) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package system
|
package models
|
||||||
|
|
||||||
import "go-admin/common/models"
|
import "go-admin/common/models"
|
||||||
|
|
||||||
@@ -7,11 +7,11 @@ type SysDept struct {
|
|||||||
ParentId int `json:"parentId" gorm:""` //上级部门
|
ParentId int `json:"parentId" gorm:""` //上级部门
|
||||||
DeptPath string `json:"deptPath" gorm:"size:255;"` //
|
DeptPath string `json:"deptPath" gorm:"size:255;"` //
|
||||||
DeptName string `json:"deptName" gorm:"size:128;"` //部门名称
|
DeptName string `json:"deptName" gorm:"size:128;"` //部门名称
|
||||||
Sort int `json:"sort" gorm:""` //排序
|
Sort int `json:"sort" gorm:"size:4;"` //排序
|
||||||
Leader string `json:"leader" gorm:"size:128;"` //负责人
|
Leader string `json:"leader" gorm:"size:128;"` //负责人
|
||||||
Phone string `json:"phone" gorm:"size:11;"` //手机
|
Phone string `json:"phone" gorm:"size:11;"` //手机
|
||||||
Email string `json:"email" gorm:"size:64;"` //邮箱
|
Email string `json:"email" gorm:"size:64;"` //邮箱
|
||||||
Status string `json:"status" gorm:"size:4;"` //状态
|
Status int `json:"status" gorm:"size:4;"` //状态
|
||||||
models.ControlBy
|
models.ControlBy
|
||||||
models.ModelTime
|
models.ModelTime
|
||||||
DataScope string `json:"dataScope" gorm:"-"`
|
DataScope string `json:"dataScope" gorm:"-"`
|
||||||
@@ -19,7 +19,7 @@ type SysDept struct {
|
|||||||
Children []SysDept `json:"children" gorm:"-"`
|
Children []SysDept `json:"children" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SysDept) TableName() string {
|
func (*SysDept) TableName() string {
|
||||||
return "sys_dept"
|
return "sys_dept"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-admin/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysDictData struct {
|
||||||
|
DictCode int `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"`
|
||||||
|
DictSort int `json:"dictSort" gorm:"size:20;comment:DictSort"`
|
||||||
|
DictLabel string `json:"dictLabel" gorm:"size:128;comment:DictLabel"`
|
||||||
|
DictValue string `json:"dictValue" gorm:"size:255;comment:DictValue"`
|
||||||
|
DictType string `json:"dictType" gorm:"size:64;comment:DictType"`
|
||||||
|
CssClass string `json:"cssClass" gorm:"size:128;comment:CssClass"`
|
||||||
|
ListClass string `json:"listClass" gorm:"size:128;comment:ListClass"`
|
||||||
|
IsDefault string `json:"isDefault" gorm:"size:8;comment:IsDefault"`
|
||||||
|
Status int `json:"status" gorm:"size:4;comment:Status"`
|
||||||
|
Default string `json:"default" gorm:"size:8;comment:Default"`
|
||||||
|
Remark string `json:"remark" gorm:"size:255;comment:Remark"`
|
||||||
|
models.ControlBy
|
||||||
|
models.ModelTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysDictData) TableName() string {
|
||||||
|
return "sys_dict_data"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysDictData) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysDictData) GetId() interface{} {
|
||||||
|
return e.DictCode
|
||||||
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
package system
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go-admin/common/models"
|
"go-admin/common/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SysDictType struct {
|
type SysDictType struct {
|
||||||
|
ID int `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"`
|
||||||
|
DictName string `json:"dictName" gorm:"size:128;comment:DictName"`
|
||||||
|
DictType string `json:"dictType" gorm:"size:128;comment:DictType"`
|
||||||
|
Status int `json:"status" gorm:"size:4;comment:Status"`
|
||||||
|
Remark string `json:"remark" gorm:"size:255;comment:Remark"`
|
||||||
models.ControlBy
|
models.ControlBy
|
||||||
models.ModelTime
|
models.ModelTime
|
||||||
|
|
||||||
ID int `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"`
|
|
||||||
DictName string `json:"dictName" gorm:"type:varchar(128);comment:DictName"`
|
|
||||||
DictType string `json:"dictType" gorm:"type:varchar(128);comment:DictType"`
|
|
||||||
Status string `json:"status" gorm:"type:varchar(4);comment:Status"`
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:Remark"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SysDictType) TableName() string {
|
func (*SysDictType) TableName() string {
|
||||||
return "sys_dict_type"
|
return "sys_dict_type"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysFileDir struct {
|
|
||||||
models.Model
|
|
||||||
Label string `json:"label" gorm:"type:varchar(255);comment:目录名称"` // 目录名称
|
|
||||||
PId int `json:"pId" gorm:"type:int(11);comment:上级目录"` // 上级目录
|
|
||||||
Sort string `json:"sort" gorm:"type:bigint(20);comment:排序"` // 排序
|
|
||||||
Path string `json:"path" gorm:"type:varchar(255);comment:路径"` // 路径
|
|
||||||
Children []SysFileDir `json:"children,omitempty" gorm:"-"` // 下级信息
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
type SysFileDirL struct {
|
|
||||||
models.Model
|
|
||||||
Label string `json:"label" gorm:"type:varchar(255);comment:目录名称"` // 目录名称
|
|
||||||
PId int `json:"pId" gorm:"type:int(11);comment:上级目录"` // 上级目录
|
|
||||||
Sort string `json:"sort" gorm:"type:bigint(20);comment:排序"` // 排序
|
|
||||||
Path string `json:"path" gorm:"type:varchar(255);comment:路径"` // 路径
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
Children []SysFileDirL `json:"children,omitempty" gorm:"-"` // 下级信息
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysFileDir) TableName() string { /**/
|
|
||||||
return "sys_file_dir"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysFileDir) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysFileDir) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysFileInfo struct {
|
|
||||||
models.Model
|
|
||||||
Type string `json:"type" gorm:"type:varchar(255);comment:类型"` //
|
|
||||||
Name string `json:"name" gorm:"type:varchar(255);comment:名称"` //
|
|
||||||
Size string `json:"size" gorm:"type:int(11);comment:大小"` //
|
|
||||||
PId int `json:"pId" gorm:"type:int(11);comment:目录"` //
|
|
||||||
Source string `json:"source" gorm:"type:varchar(255);comment:来源"` //
|
|
||||||
Url string `json:"url" gorm:"type:varchar(255);comment:地址"` //
|
|
||||||
FullUrl string `json:"fullUrl" gorm:"type:varchar(255);comment:全地址"` //
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysFileInfo) TableName() string {
|
|
||||||
return "sys_file_info"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysFileInfo) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysFileInfo) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
package system
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
log "github.com/go-admin-team/go-admin-core/v2/logger"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk"
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
"github.com/go-admin-team/go-admin-core/storage"
|
"github.com/go-admin-team/go-admin-core/v2/storage"
|
||||||
|
|
||||||
"go-admin/common/models"
|
"go-admin/common/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SysLoginLog struct {
|
type SysLoginLog struct {
|
||||||
models.Model
|
models.Model
|
||||||
Username string `json:"username" gorm:"type:varchar(128);comment:用户名"`
|
Username string `json:"username" gorm:"size:128;comment:用户名"`
|
||||||
Status string `json:"status" gorm:"type:varchar(4);comment:状态"`
|
Status string `json:"status" gorm:"size:4;comment:状态"`
|
||||||
Ipaddr string `json:"ipaddr" gorm:"type:varchar(255);comment:ip地址"`
|
Ipaddr string `json:"ipaddr" gorm:"size:255;comment:ip地址"`
|
||||||
LoginLocation string `json:"loginLocation" gorm:"type:varchar(255);comment:归属地"`
|
LoginLocation string `json:"loginLocation" gorm:"size:255;comment:归属地"`
|
||||||
Browser string `json:"browser" gorm:"type:varchar(255);comment:浏览器"`
|
Browser string `json:"browser" gorm:"size:255;comment:浏览器"`
|
||||||
Os string `json:"os" gorm:"type:varchar(255);comment:系统"`
|
Os string `json:"os" gorm:"size:255;comment:系统"`
|
||||||
Platform string `json:"platform" gorm:"type:varchar(255);comment:固件"`
|
Platform string `json:"platform" gorm:"size:255;comment:固件"`
|
||||||
LoginTime time.Time `json:"loginTime" gorm:"type:timestamp;comment:登录时间"`
|
LoginTime time.Time `json:"loginTime" gorm:"comment:登录时间"`
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
Remark string `json:"remark" gorm:"size:255;comment:备注"`
|
||||||
Msg string `json:"msg" gorm:"type:varchar(255);comment:信息"`
|
Msg string `json:"msg" gorm:"size:255;comment:信息"`
|
||||||
CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"`
|
CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"`
|
||||||
UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
|
UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
|
||||||
models.ControlBy
|
models.ControlBy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SysLoginLog) TableName() string {
|
func (*SysLoginLog) TableName() string {
|
||||||
return "sys_login_log"
|
return "sys_login_log"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ func (e *SysLoginLog) GetId() interface{} {
|
|||||||
// SaveLoginLog 从队列中获取登录日志
|
// SaveLoginLog 从队列中获取登录日志
|
||||||
func SaveLoginLog(message storage.Messager) (err error) {
|
func SaveLoginLog(message storage.Messager) (err error) {
|
||||||
//准备db
|
//准备db
|
||||||
db := sdk.Runtime.GetDbByKey(message.GetPrefix())
|
db := sdk.Runtime.GetDbByTenant(message.GetPrefix())
|
||||||
if db == nil {
|
if db == nil {
|
||||||
err = errors.New("db not exist")
|
err = errors.New("db not exist")
|
||||||
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
|
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "go-admin/common/models"
|
||||||
|
|
||||||
|
type SysMenu struct {
|
||||||
|
MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"`
|
||||||
|
MenuName string `json:"menuName" gorm:"size:128;"`
|
||||||
|
Title string `json:"title" gorm:"size:128;"`
|
||||||
|
Icon string `json:"icon" gorm:"size:128;"`
|
||||||
|
Path string `json:"path" gorm:"size:128;"`
|
||||||
|
Paths string `json:"paths" gorm:"size:128;"`
|
||||||
|
MenuType string `json:"menuType" gorm:"size:1;"`
|
||||||
|
Action string `json:"action" gorm:"size:16;"`
|
||||||
|
Permission string `json:"permission" gorm:"size:255;"`
|
||||||
|
ParentId int `json:"parentId" gorm:"size:11;"`
|
||||||
|
NoCache bool `json:"noCache" gorm:"size:8;"`
|
||||||
|
Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
|
||||||
|
Component string `json:"component" gorm:"size:255;"`
|
||||||
|
Sort int `json:"sort" gorm:"size:4;"`
|
||||||
|
Visible string `json:"visible" gorm:"size:1;"`
|
||||||
|
IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
|
||||||
|
SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"`
|
||||||
|
Apis []int `json:"apis" gorm:"-"`
|
||||||
|
DataScope string `json:"dataScope" gorm:"-"`
|
||||||
|
Params string `json:"params" gorm:"-"`
|
||||||
|
RoleId int `gorm:"-"`
|
||||||
|
Children []SysMenu `json:"children,omitempty" gorm:"-"`
|
||||||
|
IsSelect bool `json:"is_select" gorm:"-"`
|
||||||
|
// AppCode identifies which application's seed.SeedMenus call wrote this
|
||||||
|
// row; empty for the host's own built-in menus. NOT NULL DEFAULT '' for
|
||||||
|
// the same reason sys_migration.app_code is (see contract/models.Migration):
|
||||||
|
// AutoMigrate adding this column to an existing table leaves every
|
||||||
|
// pre-existing row reading back as "" rather than NULL.
|
||||||
|
AppCode string `json:"appCode" gorm:"type:varchar(64);not null;default:'';index:idx_sys_menu_app_code;comment:AppCode"`
|
||||||
|
// SeedCode is the raw seed.MenuSpec.Code this row was created from, kept
|
||||||
|
// so seedMenuTree can ask "did I already write this node" without
|
||||||
|
// relying on MenuName's PascalCase concatenation, which is not
|
||||||
|
// injective (see design doc §1.6). Nullable, unlike AppCode: every row
|
||||||
|
// seed.SeedMenus writes sets a real value, but every pre-existing row -
|
||||||
|
// the host's own hand-placed menus, and every app-seeded row written
|
||||||
|
// before this column existed - has none, and there is no way to
|
||||||
|
// backfill one that means anything. NULL is what lets an unbounded
|
||||||
|
// number of those coexist under the same app_code without tripping the
|
||||||
|
// unique index below: the database never treats two NULLs as equal, so
|
||||||
|
// only rows that do carry a real code participate in the uniqueness
|
||||||
|
// check at all.
|
||||||
|
// uk_sys_menu_app_seed_code_del is created by the migration, not from
|
||||||
|
// this tag, and deliberately: it covers (app_code, seed_code,
|
||||||
|
// deleted_at), and this struct cannot say so. A named uniqueIndex tag
|
||||||
|
// puts every field carrying that name into one index, and deleted_at
|
||||||
|
// comes from the shared ModelTime embed, which no single model can add a
|
||||||
|
// tag to. Naming it here anyway declared a unique index on seed_code
|
||||||
|
// alone under the same name - stricter than the real one, forbidding two
|
||||||
|
// applications from both having a "dir" node - and AutoMigrate on this
|
||||||
|
// model would have created that one first, after which the migration's
|
||||||
|
// HasIndex guard finds the name taken and leaves the wrong index in
|
||||||
|
// place.
|
||||||
|
SeedCode *string `json:"seedCode" gorm:"size:64;comment:raw MenuSpec.Code, null for rows not written through SeedMenus"`
|
||||||
|
models.ControlBy
|
||||||
|
models.ModelTime
|
||||||
|
}
|
||||||
|
|
||||||
|
type SysMenuSlice []SysMenu
|
||||||
|
|
||||||
|
func (x SysMenuSlice) Len() int { return len(x) }
|
||||||
|
func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort }
|
||||||
|
func (x SysMenuSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
|
|
||||||
|
func (*SysMenu) TableName() string {
|
||||||
|
return "sys_menu"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysMenu) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysMenu) GetId() interface{} {
|
||||||
|
return e.MenuId
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ptr(s string) *string { return &s }
|
||||||
|
|
||||||
|
// uk_sys_menu_app_seed_code_del covers (app_code, seed_code, deleted_at) and
|
||||||
|
// is created by 1786700008000, not from a struct tag. It cannot come from a
|
||||||
|
// tag: a named uniqueIndex collects every field carrying that name, and
|
||||||
|
// deleted_at lives in the shared ModelTime embed that no single model can tag.
|
||||||
|
//
|
||||||
|
// Naming it on SeedCode alone anyway produced a unique index on seed_code by
|
||||||
|
// itself under the same name - stricter than the real one - and AutoMigrate
|
||||||
|
// here would create that one, after which the migration's HasIndex guard
|
||||||
|
// finds the name taken and leaves the wrong index in place. Nothing in
|
||||||
|
// production AutoMigrates this model (the initial table migration uses a
|
||||||
|
// frozen snapshot that has neither column), which is why this never showed up
|
||||||
|
// as a broken database; it showed up the first time a test built the schema
|
||||||
|
// from the live model and seeded two applications.
|
||||||
|
func TestSysMenuDeclaresNoSeedCodeIndexOfItsOwn(t *testing.T) {
|
||||||
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
||||||
|
Logger: logger.Default.LogMode(logger.Silent),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open: %v", err)
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&SysMenu{}); err != nil {
|
||||||
|
t.Fatalf("automigrate: %v", err)
|
||||||
|
}
|
||||||
|
if db.Migrator().HasIndex(&SysMenu{}, "uk_sys_menu_app_seed_code_del") {
|
||||||
|
t.Error("AutoMigrate created uk_sys_menu_app_seed_code_del from a tag; " +
|
||||||
|
"the migration's HasIndex guard will now skip the composite index it should create")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two applications, the same seed code. The real index allows it because
|
||||||
|
// app_code is part of the key; an index on seed_code alone does not.
|
||||||
|
for _, app := range []string{"order", "crm"} {
|
||||||
|
row := SysMenu{MenuName: app + "Dir", AppCode: app, SeedCode: ptr("dir")}
|
||||||
|
if err := db.Create(&row).Error; err != nil {
|
||||||
|
t.Fatalf("%s could not use the seed code \"dir\": %v", app, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/go-admin-team/go-admin-core/v2/logger"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
|
"github.com/go-admin-team/go-admin-core/v2/storage"
|
||||||
|
|
||||||
|
"go-admin/common/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysOperaLog struct {
|
||||||
|
models.Model
|
||||||
|
Title string `json:"title" gorm:"size:255;comment:操作模块"`
|
||||||
|
BusinessType string `json:"businessType" gorm:"size:128;comment:操作类型"`
|
||||||
|
BusinessTypes string `json:"businessTypes" gorm:"size:128;comment:BusinessTypes"`
|
||||||
|
Method string `json:"method" gorm:"size:128;comment:函数"`
|
||||||
|
RequestMethod string `json:"requestMethod" gorm:"size:128;comment:请求方式 GET POST PUT DELETE"`
|
||||||
|
OperatorType string `json:"operatorType" gorm:"size:128;comment:操作类型"`
|
||||||
|
OperName string `json:"operName" gorm:"size:128;comment:操作者"`
|
||||||
|
DeptName string `json:"deptName" gorm:"size:128;comment:部门名称"`
|
||||||
|
OperUrl string `json:"operUrl" gorm:"size:255;comment:访问地址"`
|
||||||
|
OperIp string `json:"operIp" gorm:"size:128;comment:客户端ip"`
|
||||||
|
OperLocation string `json:"operLocation" gorm:"size:128;comment:访问位置"`
|
||||||
|
OperParam string `json:"operParam" gorm:"text;comment:请求参数"`
|
||||||
|
Status string `json:"status" gorm:"size:4;comment:操作状态 1:正常 2:关闭"`
|
||||||
|
OperTime time.Time `json:"operTime" gorm:"comment:操作时间"`
|
||||||
|
JsonResult string `json:"jsonResult" gorm:"size:255;comment:返回数据"`
|
||||||
|
Remark string `json:"remark" gorm:"size:255;comment:备注"`
|
||||||
|
LatencyTime string `json:"latencyTime" gorm:"size:128;comment:耗时"`
|
||||||
|
UserAgent string `json:"userAgent" gorm:"size:255;comment:ua"`
|
||||||
|
CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"`
|
||||||
|
UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
|
||||||
|
models.ControlBy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysOperaLog) TableName() string {
|
||||||
|
return "sys_opera_log"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysOperaLog) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysOperaLog) GetId() interface{} {
|
||||||
|
return e.Id
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveOperaLog 从队列中获取操作日志
|
||||||
|
func SaveOperaLog(message storage.Messager) (err error) {
|
||||||
|
//准备db
|
||||||
|
db := sdk.Runtime.GetDbByTenant(message.GetPrefix())
|
||||||
|
if db == nil {
|
||||||
|
err = errors.New("db not exist")
|
||||||
|
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
|
||||||
|
// Log writing to the database ignores error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var rb []byte
|
||||||
|
rb, err = json.Marshal(message.GetValues())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("json Marshal error, %s", err.Error())
|
||||||
|
// Log writing to the database ignores error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var l SysOperaLog
|
||||||
|
err = json.Unmarshal(rb, &l)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("json Unmarshal error, %s", err.Error())
|
||||||
|
// Log writing to the database ignores error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// 超出100个字符返回值截断
|
||||||
|
if len(l.JsonResult) > 100 {
|
||||||
|
l.JsonResult = l.JsonResult[:100]
|
||||||
|
}
|
||||||
|
err = db.Create(&l).Error
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("db create error, %s", err.Error())
|
||||||
|
// Log writing to the database ignores error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package system
|
package models
|
||||||
|
|
||||||
import "go-admin/common/models"
|
import "go-admin/common/models"
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ type SysPost struct {
|
|||||||
PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号
|
PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号
|
||||||
PostName string `gorm:"size:128;" json:"postName"` //岗位名称
|
PostName string `gorm:"size:128;" json:"postName"` //岗位名称
|
||||||
PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码
|
PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码
|
||||||
Sort int `gorm:"" json:"sort"` //岗位排序
|
Sort int `gorm:"size:4;" json:"sort"` //岗位排序
|
||||||
Status int `gorm:"size:4;" json:"status"` //状态
|
Status int `gorm:"size:4;" json:"status"` //状态
|
||||||
Remark string `gorm:"size:255;" json:"remark"` //描述
|
Remark string `gorm:"size:255;" json:"remark"` //描述
|
||||||
models.ControlBy
|
models.ControlBy
|
||||||
@@ -16,7 +16,7 @@ type SysPost struct {
|
|||||||
Params string `gorm:"-" json:"params"`
|
Params string `gorm:"-" json:"params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SysPost) TableName() string {
|
func (*SysPost) TableName() string {
|
||||||
return "sys_post"
|
return "sys_post"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "go-admin/common/models"
|
||||||
|
|
||||||
|
type SysRole struct {
|
||||||
|
RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码
|
||||||
|
RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称
|
||||||
|
Status string `json:"status" gorm:"size:4;"` // 状态 1禁用 2正常
|
||||||
|
RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码
|
||||||
|
RoleSort int `json:"roleSort" gorm:""` //角色排序
|
||||||
|
Flag string `json:"flag" gorm:"size:128;"` //
|
||||||
|
Remark string `json:"remark" gorm:"size:255;"` //备注
|
||||||
|
Admin bool `json:"admin" gorm:"size:4;"`
|
||||||
|
DataScope string `json:"dataScope" gorm:"size:128;"`
|
||||||
|
Params string `json:"params" gorm:"-"`
|
||||||
|
MenuIds []int `json:"menuIds" gorm:"-"`
|
||||||
|
DeptIds []int `json:"deptIds" gorm:"-"`
|
||||||
|
SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"`
|
||||||
|
SysMenu *[]SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"`
|
||||||
|
models.ControlBy
|
||||||
|
models.ModelTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysRole) TableName() string {
|
||||||
|
return "sys_role"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysRole) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysRole) GetId() interface{} {
|
||||||
|
return e.RoleId
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-admin/common/models"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SysUser struct {
|
||||||
|
UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"`
|
||||||
|
Username string `json:"username" gorm:"size:64;comment:用户名"`
|
||||||
|
Password string `json:"-" gorm:"size:128;comment:密码"`
|
||||||
|
NickName string `json:"nickName" gorm:"size:128;comment:昵称"`
|
||||||
|
Phone string `json:"phone" gorm:"size:11;comment:手机号"`
|
||||||
|
RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"`
|
||||||
|
Salt string `json:"-" gorm:"size:255;comment:加盐"`
|
||||||
|
Avatar string `json:"avatar" gorm:"size:255;comment:头像"`
|
||||||
|
Sex string `json:"sex" gorm:"size:255;comment:性别"`
|
||||||
|
Email string `json:"email" gorm:"size:128;comment:邮箱"`
|
||||||
|
DeptId int `json:"deptId" gorm:"size:20;comment:部门"`
|
||||||
|
PostId int `json:"postId" gorm:"size:20;comment:岗位"`
|
||||||
|
Remark string `json:"remark" gorm:"size:255;comment:备注"`
|
||||||
|
Status string `json:"status" gorm:"size:4;comment:状态"`
|
||||||
|
DeptIds []int `json:"deptIds" gorm:"-"`
|
||||||
|
PostIds []int `json:"postIds" gorm:"-"`
|
||||||
|
RoleIds []int `json:"roleIds" gorm:"-"`
|
||||||
|
Dept *SysDept `json:"dept"`
|
||||||
|
models.ControlBy
|
||||||
|
models.ModelTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SysUser) TableName() string {
|
||||||
|
return "sys_user"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysUser) Generate() models.ActiveRecord {
|
||||||
|
o := *e
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysUser) GetId() interface{} {
|
||||||
|
return e.UserId
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt hashes Password, unless it already holds a hash.
|
||||||
|
//
|
||||||
|
// The hooks below run on whatever is in the struct, and a user read from the
|
||||||
|
// database carries the stored hash in that field. Hashing it again produces a
|
||||||
|
// hash of a hash, and the password that user knows no longer matches anything:
|
||||||
|
// they cannot log in, and nothing reports an error. The only thing preventing
|
||||||
|
// that today is an Omit("password") on the one update that loads a user first,
|
||||||
|
// which makes every other write to this model one line away from destroying
|
||||||
|
// credentials.
|
||||||
|
//
|
||||||
|
// bcrypt.Cost parses a hash and fails on anything else, so it distinguishes
|
||||||
|
// the two cases without the call site having to say which it is. The cost is
|
||||||
|
// that a password which is itself a well-formed bcrypt hash would be stored
|
||||||
|
// unchanged - a 60-character string beginning "$2a$", not something a person
|
||||||
|
// types, and it grants whoever set it no access they did not already have.
|
||||||
|
func (e *SysUser) Encrypt() error {
|
||||||
|
if e.Password == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if _, err := bcrypt.Cost([]byte(e.Password)); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Password = string(hash)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysUser) BeforeCreate(_ *gorm.DB) error {
|
||||||
|
return e.Encrypt()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysUser) BeforeUpdate(_ *gorm.DB) error {
|
||||||
|
return e.Encrypt()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SysUser) AfterFind(_ *gorm.DB) error {
|
||||||
|
e.DeptIds = []int{e.DeptId}
|
||||||
|
e.PostIds = []int{e.PostId}
|
||||||
|
e.RoleIds = []int{e.RoleId}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const knownPassword = "correct-horse-battery-staple"
|
||||||
|
|
||||||
|
// A user loaded from the database carries the stored hash in Password, and the
|
||||||
|
// hooks run on whatever is in the struct. Hashing it a second time produces a
|
||||||
|
// hash of a hash: the password the user knows stops matching, they cannot log
|
||||||
|
// in, and nothing reports an error.
|
||||||
|
//
|
||||||
|
// Only an Omit("password") on one call site stood between this and every write
|
||||||
|
// to the model. This is the test that removes the need for it.
|
||||||
|
func TestEncryptLeavesAnAlreadyHashedPasswordAlone(t *testing.T) {
|
||||||
|
fresh := SysUser{Password: knownPassword}
|
||||||
|
if err := fresh.Encrypt(); err != nil {
|
||||||
|
t.Fatalf("Encrypt: %v", err)
|
||||||
|
}
|
||||||
|
stored := fresh.Password
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(stored), []byte(knownPassword)); err != nil {
|
||||||
|
t.Fatalf("setup failed: the password was not hashed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// What a query puts in the struct, and what an update then hands the hook.
|
||||||
|
loaded := SysUser{Password: stored}
|
||||||
|
if err := loaded.Encrypt(); err != nil {
|
||||||
|
t.Fatalf("Encrypt on a loaded user: %v", err)
|
||||||
|
}
|
||||||
|
if loaded.Password != stored {
|
||||||
|
t.Error("Encrypt re-hashed a stored hash; the user can no longer log in")
|
||||||
|
}
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(loaded.Password), []byte(knownPassword)); err != nil {
|
||||||
|
t.Errorf("the user can no longer log in with their password: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The other half: a password that is not a hash still gets hashed, on create
|
||||||
|
// and on update alike.
|
||||||
|
func TestEncryptHashesAPlaintextPassword(t *testing.T) {
|
||||||
|
for _, c := range []struct {
|
||||||
|
name string
|
||||||
|
hook func(*SysUser) error
|
||||||
|
}{
|
||||||
|
{"BeforeCreate", func(u *SysUser) error { return u.BeforeCreate(nil) }},
|
||||||
|
{"BeforeUpdate", func(u *SysUser) error { return u.BeforeUpdate(nil) }},
|
||||||
|
} {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
u := SysUser{Password: knownPassword}
|
||||||
|
if err := c.hook(&u); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if u.Password == knownPassword {
|
||||||
|
t.Fatal("the password was stored as it was typed")
|
||||||
|
}
|
||||||
|
if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(knownPassword)); err != nil {
|
||||||
|
t.Errorf("the stored value does not verify the password: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An empty Password means "not being set", and must not become a hash of "".
|
||||||
|
func TestEncryptIgnoresAnEmptyPassword(t *testing.T) {
|
||||||
|
u := SysUser{}
|
||||||
|
if err := u.Encrypt(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if u.Password != "" {
|
||||||
|
t.Errorf("an unset password became %q", u.Password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt runs on every update of this model, including the ones that change
|
||||||
|
// something else entirely. What it costs when there is nothing to do is the
|
||||||
|
// difference between a profile update and a bcrypt round; the correctness test
|
||||||
|
// above is what catches a regression, this reports the size of it.
|
||||||
|
func BenchmarkEncrypt(b *testing.B) {
|
||||||
|
fresh := SysUser{Password: knownPassword}
|
||||||
|
if err := fresh.Encrypt(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Run("already hashed", func(b *testing.B) {
|
||||||
|
u := SysUser{Password: fresh.Password}
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if err := u.Encrypt(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("plaintext", func(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
u := SysUser{Password: knownPassword}
|
||||||
|
if err := u.Encrypt(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysSetting struct {
|
|
||||||
SettingsId int `json:"settings_id" gorm:"primary_key;AUTO_INCREMENT"`
|
|
||||||
Name string `json:"name" gorm:"type:varchar(256);"`
|
|
||||||
Logo string `json:"logo" gorm:"type:varchar(256);"`
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysSetting) TableName() string {
|
|
||||||
return "sys_setting"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SysSetting) GetId() interface{} {
|
|
||||||
return s.SettingsId
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询
|
|
||||||
//func (s *SysSetting) Get() (create SysSetting, err error) {
|
|
||||||
// result := orm.Eloquent.Table("sys_setting").First(&create)
|
|
||||||
// if result.Error != nil {
|
|
||||||
// err = result.Error
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return create, nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
//修改
|
|
||||||
//func (s *SysSetting) Update() (update SysSetting, err error) {
|
|
||||||
// if err = orm.Eloquent.Table("sys_setting").Model(&update).Where("settings_id = ?", s.SettingsId).Updates(&s).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
type ResponseSystemConfig struct {
|
|
||||||
Name string `json:"name" binding:"required"` // 名称
|
|
||||||
Logo string `json:"logo" binding:"required"` // 头像
|
|
||||||
SettingsId int `json:"settings_id" binding:"required"` // 头像
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
//sys_casbin_rule
|
|
||||||
type CasbinRule struct {
|
|
||||||
PType string `json:"p_type" gorm:"size:100;"`
|
|
||||||
V0 string `json:"v0" gorm:"size:100;"`
|
|
||||||
V1 string `json:"v1" gorm:"size:100;"`
|
|
||||||
V2 string `json:"v2" gorm:"size:100;"`
|
|
||||||
V3 string `json:"v3" gorm:"size:100;"`
|
|
||||||
V4 string `json:"v4" gorm:"size:100;"`
|
|
||||||
V5 string `json:"v5" gorm:"size:100;"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (CasbinRule) TableName() string {
|
|
||||||
return "sys_casbin_rule"
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DataPermission struct {
|
|
||||||
DataScope string
|
|
||||||
UserId int
|
|
||||||
DeptId int
|
|
||||||
RoleId int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *DataPermission) GetDataScope(tableName string, db *gorm.DB) (*gorm.DB, error) {
|
|
||||||
|
|
||||||
if !config.ApplicationConfig.EnableDP {
|
|
||||||
usageStr := `数据权限已经为您` + pkg.Green(`关闭`) + `,如需开启请参考配置文件字段说明`
|
|
||||||
log.Debug("%s\n", usageStr)
|
|
||||||
return db, nil
|
|
||||||
}
|
|
||||||
user := new(SysUser)
|
|
||||||
role := new(SysRole)
|
|
||||||
err := db.Find(user, e.UserId).Error
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("获取用户数据出错 msg:" + err.Error())
|
|
||||||
}
|
|
||||||
err = db.Find(role, user.RoleId).Error
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("获取用户数据出错 msg:" + err.Error())
|
|
||||||
}
|
|
||||||
if role.DataScope == "2" {
|
|
||||||
db = db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", user.RoleId)
|
|
||||||
}
|
|
||||||
if role.DataScope == "3" {
|
|
||||||
db = db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", user.DeptId)
|
|
||||||
}
|
|
||||||
if role.DataScope == "4" {
|
|
||||||
db = db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%"+pkg.IntToString(user.DeptId)+"%")
|
|
||||||
}
|
|
||||||
if role.DataScope == "5" || role.DataScope == "" {
|
|
||||||
db = db.Where(tableName+".create_by = ?", e.UserId)
|
|
||||||
}
|
|
||||||
|
|
||||||
return db, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DataScopes(tableName string, userId int) func(db *gorm.DB) *gorm.DB {
|
|
||||||
return func(db *gorm.DB) *gorm.DB {
|
|
||||||
user := new(SysUser)
|
|
||||||
role := new(SysRole)
|
|
||||||
user.UserId = userId
|
|
||||||
err := db.Find(user, userId).Error
|
|
||||||
if err != nil {
|
|
||||||
db.Error = errors.New("获取用户数据出错 msg:" + err.Error())
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
err = db.Find(role, user.RoleId).Error
|
|
||||||
if err != nil {
|
|
||||||
db.Error = errors.New("获取用户数据出错 msg:" + err.Error())
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
if role.DataScope == "2" {
|
|
||||||
return db.Where(tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", user.RoleId)
|
|
||||||
}
|
|
||||||
if role.DataScope == "3" {
|
|
||||||
return db.Where(tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", user.DeptId)
|
|
||||||
}
|
|
||||||
if role.DataScope == "4" {
|
|
||||||
return db.Where(tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%"+pkg.IntToString(user.DeptId)+"%")
|
|
||||||
}
|
|
||||||
if role.DataScope == "5" || role.DataScope == "" {
|
|
||||||
return db.Where(tableName+".create_by = ?", userId)
|
|
||||||
}
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
//sys_role_dept
|
|
||||||
type SysRoleDept struct {
|
|
||||||
RoleId int `gorm:"size:11;primaryKey"`
|
|
||||||
DeptId int `gorm:"size:11;primaryKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysRoleDept) TableName() string {
|
|
||||||
return "sys_role_dept"
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RoleMenu struct {
|
|
||||||
RoleId int `gorm:""`
|
|
||||||
MenuId int `gorm:""`
|
|
||||||
RoleName string `gorm:"size:128"`
|
|
||||||
models.ControlBy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (RoleMenu) TableName() string {
|
|
||||||
return "sys_role_menu"
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuPath struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) Get(tx *gorm.DB) ([]RoleMenu, error) {
|
|
||||||
var r []RoleMenu
|
|
||||||
table := tx.Table("sys_role_menu")
|
|
||||||
if rm.RoleId != 0 {
|
|
||||||
table = table.Where("role_id = ?", rm.RoleId)
|
|
||||||
|
|
||||||
}
|
|
||||||
if err := table.Find(&r).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) GetPermis(tx *gorm.DB) ([]string, error) {
|
|
||||||
var r []SysMenu
|
|
||||||
table := tx.Select("sys_menu.permission").Table("sys_menu").Joins("left join sys_role_menu on sys_menu.menu_id = sys_role_menu.menu_id")
|
|
||||||
|
|
||||||
table = table.Where("role_id = ?", rm.RoleId)
|
|
||||||
|
|
||||||
table = table.Where("sys_menu.menu_type in('F','C')")
|
|
||||||
if err := table.Find(&r).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var list []string
|
|
||||||
for i := 0; i < len(r); i++ {
|
|
||||||
list = append(list, r[i].Permission)
|
|
||||||
}
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) GetIDS(tx *gorm.DB) ([]MenuPath, error) {
|
|
||||||
var r []MenuPath
|
|
||||||
table := tx.Select("sys_menu.path").Table("sys_role_menu")
|
|
||||||
table = table.Joins("left join sys_role on sys_role.role_id=sys_role_menu.role_id")
|
|
||||||
table = table.Joins("left join sys_menu on sys_menu.id=sys_role_menu.menu_id")
|
|
||||||
table = table.Where("sys_role.role_name = ? and sys_menu.type=1", rm.RoleName)
|
|
||||||
if err := table.Find(&r).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) DeleteRoleMenu(tx *gorm.DB, roleId int) error {
|
|
||||||
if err := tx.Table("sys_role_dept").Where("role_id = ?", roleId).Delete(&rm).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := tx.Table("sys_role_menu").Where("role_id = ?", roleId).Delete(&rm).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var role SysRole
|
|
||||||
if err := tx.Table("sys_role").Where("role_id = ?", roleId).First(&role).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sql3 := "delete from sys_casbin_rule where v0= '" + role.RoleKey + "';"
|
|
||||||
if err := tx.Exec(sql3).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 该方法即将弃用
|
|
||||||
func (rm *RoleMenu) BatchDeleteRoleMenu(tx *gorm.DB, roleIds []int) error {
|
|
||||||
if err := tx.Table("sys_role_menu").Where("role_id in (?)", roleIds).Delete(&rm).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var role []SysRole
|
|
||||||
if err := tx.Table("sys_role").Where("role_id in (?)", roleIds).Find(&role).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sql := ""
|
|
||||||
for i := 0; i < len(role); i++ {
|
|
||||||
sql += "delete from sys_casbin_rule where v0= '" + role[i].RoleName + "';"
|
|
||||||
}
|
|
||||||
if err := tx.Exec(sql).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := tx.Commit().Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) Insert(tx *gorm.DB, enforcer *casbin.SyncedEnforcer, roleId int, menuId []int) error {
|
|
||||||
var err error
|
|
||||||
var (
|
|
||||||
role SysRole
|
|
||||||
menu []SysMenu
|
|
||||||
casbinRules []CasbinRule // casbinRule 待插入队列
|
|
||||||
)
|
|
||||||
// 在事务中做一些数据库操作(从这一点使用'tx',而不是'db')
|
|
||||||
if err = tx.Table("sys_role").Where("role_id = ?", roleId).First(&role).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = tx.Table("sys_menu").Where("menu_id in (?)", menuId).Find(&menu).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
//ORM不支持批量插入所以需要拼接 sql 串
|
|
||||||
sysRoleMenuSql := "INSERT INTO `sys_role_menu` (`role_id`,`menu_id`,`role_name`) VALUES "
|
|
||||||
|
|
||||||
for i, m := range menu {
|
|
||||||
// 拼装'role_menu'表批量插入SQL语句
|
|
||||||
sysRoleMenuSql += fmt.Sprintf("(%d,%d,'%s')", role.RoleId, m.MenuId, role.RoleKey)
|
|
||||||
if i == len(menu)-1 {
|
|
||||||
sysRoleMenuSql += ";" //最后一条数据 以分号结尾
|
|
||||||
} else {
|
|
||||||
sysRoleMenuSql += ","
|
|
||||||
}
|
|
||||||
if m.MenuType == "A" {
|
|
||||||
// 加入队列
|
|
||||||
casbinRules = append(casbinRules,
|
|
||||||
CasbinRule{
|
|
||||||
V0: role.RoleKey,
|
|
||||||
V1: m.Path,
|
|
||||||
V2: m.Action,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 执行批量插入sys_role_menu
|
|
||||||
if err = tx.Exec(sysRoleMenuSql).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行批量插入sys_casbin_rule
|
|
||||||
if len(casbinRules) > 0 {
|
|
||||||
if err = tx.Create(&casbinRules).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rm *RoleMenu) Delete(tx *gorm.DB, RoleId string, MenuID string) (bool, error) {
|
|
||||||
rm.RoleId, _ = pkg.StringToInt(RoleId)
|
|
||||||
table := tx.Table("sys_role_menu").Where("role_id = ?", RoleId)
|
|
||||||
if MenuID != "" {
|
|
||||||
table = table.Where("menu_id = ?", MenuID)
|
|
||||||
}
|
|
||||||
if err := table.Delete(&rm).Error; err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysConfig struct {
|
|
||||||
models.Model
|
|
||||||
ConfigName string `json:"configName" gorm:"type:varchar(128);comment:ConfigName"` //
|
|
||||||
ConfigKey string `json:"configKey" gorm:"type:varchar(128);comment:ConfigKey"` //
|
|
||||||
ConfigValue string `json:"configValue" gorm:"type:varchar(255);comment:ConfigValue"` //
|
|
||||||
ConfigType string `json:"configType" gorm:"type:varchar(64);comment:ConfigType"`
|
|
||||||
IsFrontend int `json:"isFrontend" gorm:"type:varchar(64);comment:是否前台"` //
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(128);comment:Remark"` //
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysConfig) TableName() string {
|
|
||||||
return "sys_config"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysConfig) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysConfig) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysDictData struct {
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
|
|
||||||
DictCode int `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"`
|
|
||||||
DictSort int `json:"dictSort" gorm:"type:bigint(20);comment:DictSort"`
|
|
||||||
DictLabel string `json:"dictLabel" gorm:"type:varchar(128);comment:DictLabel"`
|
|
||||||
DictValue string `json:"dictValue" gorm:"type:varchar(255);comment:DictValue"`
|
|
||||||
DictType string `json:"dictType" gorm:"type:varchar(64);comment:DictType"`
|
|
||||||
CssClass string `json:"cssClass" gorm:"type:varchar(128);comment:CssClass"`
|
|
||||||
ListClass string `json:"listClass" gorm:"type:varchar(128);comment:ListClass"`
|
|
||||||
IsDefault string `json:"isDefault" gorm:"type:varchar(8);comment:IsDefault"`
|
|
||||||
Status string `json:"status" gorm:"type:varchar(4);comment:Status"`
|
|
||||||
Default string `json:"default" gorm:"type:varchar(8);comment:Default"`
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:Remark"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysDictData) TableName() string {
|
|
||||||
return "sys_dict_data"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysDictData) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysDictData) GetId() interface{} {
|
|
||||||
return e.DictCode
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import "go-admin/common/models"
|
|
||||||
|
|
||||||
type SysMenu struct {
|
|
||||||
MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"`
|
|
||||||
MenuName string `json:"menuName" gorm:"size:128;"`
|
|
||||||
Title string `json:"title" gorm:"size:128;"`
|
|
||||||
Icon string `json:"icon" gorm:"size:128;"`
|
|
||||||
Path string `json:"path" gorm:"size:128;"`
|
|
||||||
Paths string `json:"paths" gorm:"size:128;"`
|
|
||||||
MenuType string `json:"menuType" gorm:"size:1;"`
|
|
||||||
Action string `json:"action" gorm:"size:16;"`
|
|
||||||
Permission string `json:"permission" gorm:"size:255;"`
|
|
||||||
ParentId int `json:"parentId" gorm:"size:11;"`
|
|
||||||
NoCache bool `json:"noCache" gorm:"size:8;"`
|
|
||||||
Breadcrumb string `json:"breadcrumb" gorm:"size:255;"`
|
|
||||||
Component string `json:"component" gorm:"size:255;"`
|
|
||||||
Sort int `json:"sort" gorm:"size:4;"`
|
|
||||||
Visible string `json:"visible" gorm:"size:1;"`
|
|
||||||
IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"`
|
|
||||||
DataScope string `json:"dataScope" gorm:"-"`
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
RoleId int `gorm:"-"`
|
|
||||||
Children []SysMenu `json:"children" gorm:"-"`
|
|
||||||
IsSelect bool `json:"is_select" gorm:"-"`
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
type SysMenus struct {
|
|
||||||
MenuId int `json:"menuId" gorm:"column:menu_id;primaryKey;autoIncrement;"`
|
|
||||||
MenuName string `json:"menuName" gorm:"column:menu_name"`
|
|
||||||
Title string `json:"title" gorm:"column:title"`
|
|
||||||
Icon string `json:"icon" gorm:"column:icon"`
|
|
||||||
Path string `json:"path" gorm:"column:path"`
|
|
||||||
MenuType string `json:"menuType" gorm:"column:menu_type"`
|
|
||||||
Action string `json:"action" gorm:"column:action"`
|
|
||||||
Permission string `json:"permission" gorm:"column:permission"`
|
|
||||||
ParentId int `json:"parentId" gorm:"column:parent_id"`
|
|
||||||
NoCache bool `json:"noCache" gorm:"column:no_cache"`
|
|
||||||
Breadcrumb string `json:"breadcrumb" gorm:"column:breadcrumb"`
|
|
||||||
Component string `json:"component" gorm:"column:component"`
|
|
||||||
Sort int `json:"sort" gorm:"column:sort"`
|
|
||||||
Visible string `json:"visible" gorm:"column:visible"`
|
|
||||||
Children []SysMenu `json:"children" gorm:"-"`
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
DataScope string `json:"dataScope" gorm:"-"`
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysMenu) TableName() string {
|
|
||||||
return "sys_menu"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysMenu) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysMenu) GetId() interface{} {
|
|
||||||
return e.MenuId
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk"
|
|
||||||
"github.com/go-admin-team/go-admin-core/storage"
|
|
||||||
|
|
||||||
"go-admin/common/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysOperaLog struct {
|
|
||||||
models.Model
|
|
||||||
Title string `json:"title" gorm:"type:varchar(255);comment:操作模块"`
|
|
||||||
BusinessType string `json:"businessType" gorm:"type:varchar(128);comment:操作类型"`
|
|
||||||
BusinessTypes string `json:"businessTypes" gorm:"type:varchar(128);comment:BusinessTypes"`
|
|
||||||
Method string `json:"method" gorm:"type:varchar(128);comment:函数"`
|
|
||||||
RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式"`
|
|
||||||
OperatorType string `json:"operatorType" gorm:"type:varchar(128);comment:操作类型"`
|
|
||||||
OperName string `json:"operName" gorm:"type:varchar(128);comment:操作者"`
|
|
||||||
DeptName string `json:"deptName" gorm:"type:varchar(128);comment:部门名称"`
|
|
||||||
OperUrl string `json:"operUrl" gorm:"type:varchar(255);comment:访问地址"`
|
|
||||||
OperIp string `json:"operIp" gorm:"type:varchar(128);comment:客户端ip"`
|
|
||||||
OperLocation string `json:"operLocation" gorm:"type:varchar(128);comment:访问位置"`
|
|
||||||
OperParam string `json:"operParam" gorm:"type:varchar(255);comment:请求参数"`
|
|
||||||
Status string `json:"status" gorm:"type:varchar(4);comment:操作状态"`
|
|
||||||
OperTime time.Time `json:"operTime" gorm:"type:timestamp;comment:操作时间"`
|
|
||||||
JsonResult string `json:"jsonResult" gorm:"type:varchar(255);comment:返回数据"`
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
|
||||||
LatencyTime string `json:"latencyTime" gorm:"type:varchar(128);comment:耗时"`
|
|
||||||
UserAgent string `json:"userAgent" gorm:"type:varchar(255);comment:ua"`
|
|
||||||
CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"`
|
|
||||||
UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"`
|
|
||||||
models.ControlBy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysOperaLog) TableName() string {
|
|
||||||
return "sys_opera_log"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysOperaLog) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysOperaLog) GetId() interface{} {
|
|
||||||
return e.Id
|
|
||||||
}
|
|
||||||
|
|
||||||
// SaveOperaLog 从队列中获取操作日志
|
|
||||||
func SaveOperaLog(message storage.Messager) (err error) {
|
|
||||||
//准备db
|
|
||||||
db := sdk.Runtime.GetDbByKey(message.GetPrefix())
|
|
||||||
if db == nil {
|
|
||||||
err = errors.New("db not exist")
|
|
||||||
log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var rb []byte
|
|
||||||
rb, err = json.Marshal(message.GetValues())
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("json Marshal error, %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var l SysOperaLog
|
|
||||||
err = json.Unmarshal(rb, &l)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("json Unmarshal error, %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if l.Title == "" {
|
|
||||||
m := &SysMenu{}
|
|
||||||
db.Model(m).Select("Title").Where("action = ?", l.Method).Where("path = ?", message.GetValues()["_fullPath"]).First(m)
|
|
||||||
l.Title = m.Title
|
|
||||||
}
|
|
||||||
err = db.Create(&l).Error
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db create error, %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import "go-admin/common/models"
|
|
||||||
|
|
||||||
type SysRole struct {
|
|
||||||
RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码
|
|
||||||
RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称
|
|
||||||
Status string `json:"status" gorm:"size:4;"` //
|
|
||||||
RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码
|
|
||||||
RoleSort int `json:"roleSort" gorm:""` //角色排序
|
|
||||||
Flag string `json:"flag" gorm:"size:128;"` //
|
|
||||||
Remark string `json:"remark" gorm:"size:255;"` //备注
|
|
||||||
Admin bool `json:"admin" gorm:"size:4;"`
|
|
||||||
DataScope string `json:"dataScope" gorm:"size:128;"`
|
|
||||||
Params string `json:"params" gorm:"-"`
|
|
||||||
MenuIds []int `json:"menuIds" gorm:"-"`
|
|
||||||
DeptIds []int `json:"deptIds" gorm:"-"`
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysRole) TableName() string {
|
|
||||||
return "sys_role"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysRole) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysRole) GetId() interface{} {
|
|
||||||
return e.RoleId
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
package system
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go-admin/common/models"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SysUser struct {
|
|
||||||
models.ControlBy
|
|
||||||
models.ModelTime
|
|
||||||
UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"`
|
|
||||||
Username string `json:"username" gorm:"type:varchar(64);comment:用户名"`
|
|
||||||
Password string `json:"-" gorm:"type:varchar(128);comment:密码"`
|
|
||||||
NickName string `json:"nickName" gorm:"type:varchar(128);comment:昵称"`
|
|
||||||
Phone string `json:"phone" gorm:"type:varchar(11);comment:手机号"`
|
|
||||||
RoleId int `json:"roleId" gorm:"type:bigint(20);comment:角色ID"`
|
|
||||||
Salt string `json:"-" gorm:"type:varchar(255);comment:加盐"`
|
|
||||||
Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像"`
|
|
||||||
Sex string `json:"sex" gorm:"type:varchar(255);comment:性别"`
|
|
||||||
Email string `json:"email" gorm:"type:varchar(128);comment:邮箱"`
|
|
||||||
DeptId int `json:"deptId" gorm:"type:bigint(20);comment:部门"`
|
|
||||||
PostId int `json:"postId" gorm:"type:bigint(20);comment:岗位"`
|
|
||||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
|
||||||
Status string `json:"status" gorm:"type:varchar(4);comment:状态"`
|
|
||||||
DeptIds []int `json:"deptIds" gorm:"-"`
|
|
||||||
PostIds []int `json:"postIds" gorm:"-"`
|
|
||||||
RoleIds []int `json:"roleIds" gorm:"-"`
|
|
||||||
Dept *SysDept `json:"dept"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (SysUser) TableName() string {
|
|
||||||
return "sys_user"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysUser) Generate() models.ActiveRecord {
|
|
||||||
o := *e
|
|
||||||
return &o
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysUser) GetId() interface{} {
|
|
||||||
return e.UserId
|
|
||||||
}
|
|
||||||
|
|
||||||
//加密
|
|
||||||
func (e *SysUser) Encrypt() (err error) {
|
|
||||||
if e.Password == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash []byte
|
|
||||||
if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
e.Password = string(hash)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysUser) BeforeCreate(_ *gorm.DB) error {
|
|
||||||
return e.Encrypt()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysUser) BeforeUpdate(_ *gorm.DB) error {
|
|
||||||
var err error
|
|
||||||
if e.Password != "" {
|
|
||||||
err = e.Encrypt()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SysUser) AfterFind(_ *gorm.DB) error {
|
|
||||||
e.DeptIds = []int{e.DeptId}
|
|
||||||
e.PostIds = []int{e.PostId}
|
|
||||||
e.RoleIds = []int{e.RoleId}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
package tools
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
|
|
||||||
config2 "github.com/go-admin-team/go-admin-core/sdk/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DBTables struct {
|
|
||||||
TableName string `gorm:"column:TABLE_NAME" json:"tableName"`
|
|
||||||
Engine string `gorm:"column:ENGINE" json:"engine"`
|
|
||||||
TableRows string `gorm:"column:TABLE_ROWS" json:"tableRows"`
|
|
||||||
TableCollation string `gorm:"column:TABLE_COLLATION" json:"tableCollation"`
|
|
||||||
CreateTime string `gorm:"column:CREATE_TIME" json:"createTime"`
|
|
||||||
UpdateTime string `gorm:"column:UPDATE_TIME" json:"updateTime"`
|
|
||||||
TableComment string `gorm:"column:TABLE_COMMENT" json:"tableComment"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *DBTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBTables, int, error) {
|
|
||||||
var doc []DBTables
|
|
||||||
table := new(gorm.DB)
|
|
||||||
var count int64
|
|
||||||
|
|
||||||
if config2.DatabaseConfig.Driver == "mysql" {
|
|
||||||
table = tx.Table("information_schema.tables")
|
|
||||||
table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ")
|
|
||||||
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
|
|
||||||
|
|
||||||
if e.TableName != "" {
|
|
||||||
table = table.Where("TABLE_NAME = ?", e.TableName)
|
|
||||||
}
|
|
||||||
if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pkg.Assert(true, "目前只支持mysql数据库", 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
//table.Count(&count)
|
|
||||||
return doc, int(count), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *DBTables) Get(tx *gorm.DB) (DBTables, error) {
|
|
||||||
var doc DBTables
|
|
||||||
if config2.DatabaseConfig.Driver == "mysql" {
|
|
||||||
table := tx.Table("information_schema.tables")
|
|
||||||
table = table.Where("table_schema= ? ", config2.GenConfig.DBName)
|
|
||||||
if e.TableName == "" {
|
|
||||||
return doc, errors.New("table name cannot be empty!")
|
|
||||||
}
|
|
||||||
table = table.Where("TABLE_NAME = ?", e.TableName)
|
|
||||||
if err := table.First(&doc).Error; err != nil {
|
|
||||||
return doc, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pkg.Assert(true, "目前只支持mysql数据库", 500)
|
|
||||||
}
|
|
||||||
return doc, nil
|
|
||||||
}
|
|
||||||
@@ -4,14 +4,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
log "github.com/go-admin-team/go-admin-core/v2/logger"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk"
|
"github.com/go-admin-team/go-admin-core/v2/sdk"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/api"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/config"
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg"
|
|
||||||
|
|
||||||
common "go-admin/common/middleware"
|
common "go-admin/common/middleware"
|
||||||
"go-admin/common/middleware/handler"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitRouter 路由初始化,不要怀疑,这里用到了
|
// InitRouter 路由初始化,不要怀疑,这里用到了
|
||||||
@@ -19,8 +14,8 @@ func InitRouter() {
|
|||||||
var r *gin.Engine
|
var r *gin.Engine
|
||||||
h := sdk.Runtime.GetEngine()
|
h := sdk.Runtime.GetEngine()
|
||||||
if h == nil {
|
if h == nil {
|
||||||
h = gin.New()
|
log.Fatal("not found engine...")
|
||||||
sdk.Runtime.SetEngine(h)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
switch h.(type) {
|
switch h.(type) {
|
||||||
case *gin.Engine:
|
case *gin.Engine:
|
||||||
@@ -29,19 +24,10 @@ func InitRouter() {
|
|||||||
log.Fatal("not support other engine")
|
log.Fatal("not support other engine")
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
if config.SslConfig.Enable {
|
|
||||||
r.Use(handler.TlsHandler())
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Use(common.Sentinel()).
|
// the jwt middleware: shared instance InitMiddleware built at startup,
|
||||||
Use(common.RequestId(pkg.TrafficKey)).
|
// not one built here per module (see common/middleware.GetAuthMiddleware).
|
||||||
Use(api.SetRequestLogger)
|
authMiddleware := common.GetAuthMiddleware()
|
||||||
common.InitMiddleware(r)
|
|
||||||
// the jwt middleware
|
|
||||||
authMiddleware, err := common.AuthInit()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("JWT Init Error, %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 注册系统路由
|
// 注册系统路由
|
||||||
InitSysRouter(r, authMiddleware)
|
InitSysRouter(r, authMiddleware)
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/go-admin-team/go-admin-core/sdk"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
log "github.com/go-admin-team/go-admin-core/logger"
|
|
||||||
"github.com/go-admin-team/go-admin-core/tools/transfer"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Monitor() {
|
|
||||||
var r *gin.Engine
|
|
||||||
h := sdk.Runtime.GetEngine()
|
|
||||||
if h == nil {
|
|
||||||
h = gin.New()
|
|
||||||
sdk.Runtime.SetEngine(h)
|
|
||||||
}
|
|
||||||
switch h.(type) {
|
|
||||||
case *gin.Engine:
|
|
||||||
r = h.(*gin.Engine)
|
|
||||||
default:
|
|
||||||
log.Fatal("not support other engine")
|
|
||||||
}
|
|
||||||
//开发环境启动监控指标
|
|
||||||
r.GET("/metrics", transfer.Handler(promhttp.Handler()))
|
|
||||||
//健康检查
|
|
||||||
r.GET("/health", func(c *gin.Context) {
|
|
||||||
c.Status(http.StatusOK)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,8 @@ package router
|
|||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/gin-gonic/gin"
|
_ "github.com/gin-gonic/gin"
|
||||||
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
"github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -12,7 +12,6 @@ var (
|
|||||||
routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
|
routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 路由示例
|
|
||||||
func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
|
func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine {
|
||||||
|
|
||||||
// 无需认证的路由
|
// 无需认证的路由
|
||||||
@@ -27,24 +26,15 @@ func InitExamplesRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gi
|
|||||||
func examplesNoCheckRoleRouter(r *gin.Engine) {
|
func examplesNoCheckRoleRouter(r *gin.Engine) {
|
||||||
// 可根据业务需求来设置接口版本
|
// 可根据业务需求来设置接口版本
|
||||||
v1 := r.Group("/api/v1")
|
v1 := r.Group("/api/v1")
|
||||||
// 空接口防止v1定义无使用报错
|
|
||||||
v1.GET("/nilcheckrole", nil)
|
|
||||||
|
|
||||||
for _, f := range routerNoCheckRole {
|
for _, f := range routerNoCheckRole {
|
||||||
f(v1)
|
f(v1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// {{无需认证路由自动补充在此处请勿删除}}
|
|
||||||
//registerSysFileInfoRouter(v1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 需要认证的路由示例
|
// 需要认证的路由示例
|
||||||
func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) {
|
func examplesCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) {
|
||||||
// 可根据业务需求来设置接口版本
|
// 可根据业务需求来设置接口版本
|
||||||
v1 := r.Group("/api/v1")
|
v1 := r.Group("/api/v1")
|
||||||
// 空接口防止v1定义无使用报错
|
|
||||||
v1.GET("/checkrole", nil)
|
|
||||||
|
|
||||||
for _, f := range routerCheckRole {
|
for _, f := range routerCheckRole {
|
||||||
f(v1, authMiddleware)
|
f(v1, authMiddleware)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
|
|
||||||
|
"go-admin/app/admin/apis"
|
||||||
|
"go-admin/common/actions"
|
||||||
|
"go-admin/common/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
routerCheckRole = append(routerCheckRole, registerSysApiRouter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerSysApiRouter
|
||||||
|
func registerSysApiRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
|
api := apis.SysApi{}
|
||||||
|
// PermissionAction is not optional here: all three handlers below read the
|
||||||
|
// data permission out of the context, and without it they read the zero
|
||||||
|
// value - an unset scope, which Permission now fails closed on.
|
||||||
|
r := v1.Group("/sys-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction())
|
||||||
|
{
|
||||||
|
r.GET("", api.GetPage)
|
||||||
|
r.GET("/:id", api.Get)
|
||||||
|
r.PUT("/:id", api.Update)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
|
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routerCheckRole = append(routerCheckRole, registerSysCategoryRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需认证的路由代码
|
|
||||||
func registerSysCategoryRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
||||||
r := v1.Group("/syscategory").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
|
||||||
model := &models.SysCategory{}
|
|
||||||
r.GET("", actions.PermissionAction(), actions.IndexAction(model, new(dto.SysCategorySearch), func() interface{} {
|
|
||||||
list := make([]models.SysCategory, 0)
|
|
||||||
return &list
|
|
||||||
}))
|
|
||||||
r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.SysCategoryById), nil))
|
|
||||||
r.POST("", actions.CreateAction(new(dto.SysCategoryControl)))
|
|
||||||
r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.SysCategoryControl)))
|
|
||||||
r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.SysCategoryById)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
||||||
"go-admin/app/admin/apis/sys_china_area_data"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routerCheckRole = append(routerCheckRole, registerSysChinaAreaDataRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需认证的路由代码
|
|
||||||
func registerSysChinaAreaDataRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
||||||
api := sys_china_area_data.SysChinaAreaData{}
|
|
||||||
r := v1.Group("/sys_china_area_data").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
|
||||||
r.GET("", api.GetSysChinaAreaDataList)
|
|
||||||
r.GET("/:id", api.GetSysChinaAreaData)
|
|
||||||
r.POST("", api.InsertSysChinaAreaData)
|
|
||||||
r.PUT("/:id", api.UpdateSysChinaAreaData)
|
|
||||||
r.DELETE("", api.DeleteSysChinaAreaData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go-admin/app/admin/apis"
|
||||||
|
"go-admin/common/middleware"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
"go-admin/app/admin/apis/system/sys_config"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -13,15 +14,14 @@ func init() {
|
|||||||
|
|
||||||
// 需认证的路由代码
|
// 需认证的路由代码
|
||||||
func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
api := sys_config.SysConfig{}
|
api := apis.SysConfig{}
|
||||||
r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
{
|
{
|
||||||
|
r.GET("", api.GetPage)
|
||||||
r.GET("", api.GetSysConfigList)
|
r.GET("/:id", api.Get)
|
||||||
r.GET("/:id", api.GetSysConfig)
|
r.POST("", api.Insert)
|
||||||
r.POST("", api.InsertSysConfig)
|
r.PUT("/:id", api.Update)
|
||||||
r.PUT("/:id", api.UpdateSysConfig)
|
r.DELETE("", api.Delete)
|
||||||
r.DELETE("", api.DeleteSysConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc())
|
r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc())
|
||||||
@@ -31,7 +31,13 @@ func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMidd
|
|||||||
|
|
||||||
r2 := v1.Group("/app-config")
|
r2 := v1.Group("/app-config")
|
||||||
{
|
{
|
||||||
r2.GET("", api.GetSysConfigBySysApp)
|
r2.GET("", api.Get2SysApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc())
|
||||||
|
{
|
||||||
|
r3.PUT("", api.Update2Set)
|
||||||
|
r3.GET("", api.Get2Set)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
||||||
"go-admin/app/admin/models"
|
|
||||||
"go-admin/app/admin/service/dto"
|
|
||||||
"go-admin/common/actions"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routerCheckRole = append(routerCheckRole, registerSysContentRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需认证的路由代码
|
|
||||||
func registerSysContentRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
||||||
|
|
||||||
r := v1.Group("/syscontent").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
|
||||||
//r.GET("", sys_content.GetSysContentList)
|
|
||||||
//r.GET("/:id", sys_content.GetSysContent)
|
|
||||||
//r.POST("", sys_content.InsertSysContent)
|
|
||||||
//r.PUT("", sys_content.UpdateSysContent)
|
|
||||||
//r.DELETE("/:id", sys_content.DeleteSysContent)
|
|
||||||
|
|
||||||
model := &models.SysContent{}
|
|
||||||
r.GET("", actions.PermissionAction(), actions.IndexAction(model, new(dto.SysContentSearch), func() interface{} {
|
|
||||||
list := make([]models.SysContent, 0)
|
|
||||||
return &list
|
|
||||||
}))
|
|
||||||
r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.SysContentById), nil))
|
|
||||||
r.POST("", actions.CreateAction(new(dto.SysContentControl)))
|
|
||||||
r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.SysContentControl)))
|
|
||||||
r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.SysContentById)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,9 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
"go-admin/app/admin/apis/system/sys_dept"
|
"go-admin/app/admin/apis"
|
||||||
middleware2 "go-admin/common/middleware"
|
"go-admin/common/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -13,19 +13,20 @@ func init() {
|
|||||||
|
|
||||||
// 需认证的路由代码
|
// 需认证的路由代码
|
||||||
func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
api := sys_dept.SysDept{}
|
api := apis.SysDept{}
|
||||||
r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
|
r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
{
|
{
|
||||||
r.GET("", api.GetSysDeptList)
|
r.GET("", api.GetPage)
|
||||||
r.GET("/:id", api.GetSysDept)
|
r.GET("/:id", api.Get)
|
||||||
r.POST("", api.InsertSysDept)
|
r.POST("", api.Insert)
|
||||||
r.PUT("/:id", api.UpdateSysDept)
|
r.PUT("/:id", api.Update)
|
||||||
r.DELETE("/:id", api.DeleteSysDept)
|
r.DELETE("", api.Delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
|
r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
|
||||||
{
|
{
|
||||||
r1.GET("/deptTree", api.GetDeptTree)
|
r1.GET("/deptTree", api.Get2Tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
|
"go-admin/app/admin/apis"
|
||||||
|
"go-admin/common/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
routerCheckRole = append(routerCheckRole, registerDictRouter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
|
dictApi := apis.SysDictType{}
|
||||||
|
dataApi := apis.SysDictData{}
|
||||||
|
dicts := v1.Group("/dict").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
|
{
|
||||||
|
|
||||||
|
dicts.GET("/data", dataApi.GetPage)
|
||||||
|
dicts.GET("/data/:dictCode", dataApi.Get)
|
||||||
|
dicts.POST("/data", dataApi.Insert)
|
||||||
|
dicts.PUT("/data/:dictCode", dataApi.Update)
|
||||||
|
dicts.DELETE("/data", dataApi.Delete)
|
||||||
|
|
||||||
|
dicts.GET("/type-option-select", dictApi.GetAll)
|
||||||
|
dicts.GET("/type", dictApi.GetPage)
|
||||||
|
dicts.GET("/type/:id", dictApi.Get)
|
||||||
|
dicts.POST("/type", dictApi.Insert)
|
||||||
|
dicts.PUT("/type/:id", dictApi.Update)
|
||||||
|
dicts.DELETE("/type", dictApi.Delete)
|
||||||
|
}
|
||||||
|
opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
|
{
|
||||||
|
opSelect.GET("/option-select", dataApi.GetAll)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
||||||
"go-admin/app/admin/apis/sys_file"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routerCheckRole = append(routerCheckRole, registerSysFileDirRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需认证的路由代码
|
|
||||||
func registerSysFileDirRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
||||||
api := sys_file.SysFileDir{}
|
|
||||||
r := v1.Group("/sysfiledir").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
|
||||||
r.GET("", api.GetSysFileDirList)
|
|
||||||
r.GET("/:id", api.GetSysFileDir)
|
|
||||||
r.POST("", api.InsertSysFileDir)
|
|
||||||
r.PUT("/:id", api.UpdateSysFileDir)
|
|
||||||
r.DELETE("/:id", api.DeleteSysFileDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
|
||||||
"go-admin/app/admin/apis/sys_file"
|
|
||||||
middleware2 "go-admin/common/middleware"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
routerCheckRole = append(routerCheckRole, registerSysFileInfoRouter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 需认证的路由代码
|
|
||||||
func registerSysFileInfoRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
|
||||||
api := sys_file.SysFileInfo{}
|
|
||||||
r := v1.Group("/sysfileinfo").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
|
||||||
r.GET("", api.GetSysFileInfoList)
|
|
||||||
r.GET("/:id", api.GetSysFileInfo)
|
|
||||||
r.POST("", api.InsertSysFileInfo)
|
|
||||||
r.PUT("/:id", api.UpdateSysFileInfo)
|
|
||||||
r.DELETE("/:id", api.DeleteSysFileInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,9 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
"go-admin/app/admin/apis/system/sys_login_log"
|
"go-admin/app/admin/apis"
|
||||||
middleware2 "go-admin/common/middleware"
|
"go-admin/common/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -13,13 +13,12 @@ func init() {
|
|||||||
|
|
||||||
// 需认证的路由代码
|
// 需认证的路由代码
|
||||||
func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
api := sys_login_log.SysLoginLog{}
|
api := apis.SysLoginLog{}
|
||||||
r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
|
r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
{
|
{
|
||||||
r.GET("", api.GetSysLoginLogList)
|
r.GET("", api.GetPage)
|
||||||
r.GET("/:id", api.GetSysLoginLog)
|
r.GET("/:id", api.Get)
|
||||||
r.POST("", api.InsertSysLoginLog)
|
r.DELETE("", api.Delete)
|
||||||
r.PUT("/:id", api.UpdateSysLoginLog)
|
|
||||||
r.DELETE("", api.DeleteSysLoginLog)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"
|
jwt "github.com/go-admin-team/go-admin-core/v2/jwtauth"
|
||||||
"go-admin/app/admin/apis/system/sys_menu"
|
"go-admin/app/admin/apis"
|
||||||
middleware2 "go-admin/common/middleware"
|
"go-admin/common/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -13,27 +13,21 @@ func init() {
|
|||||||
|
|
||||||
// 需认证的路由代码
|
// 需认证的路由代码
|
||||||
func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
api := sys_menu.SysMenu{}
|
api := apis.SysMenu{}
|
||||||
//menu := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
|
||||||
//{
|
r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
|
||||||
// menu.GET("/:id", system.GetMenu)
|
|
||||||
// menu.POST("", system.InsertMenu)
|
|
||||||
// menu.PUT("", system.UpdateMenu)
|
|
||||||
// menu.DELETE("/:id", system.DeleteMenu)
|
|
||||||
//}
|
|
||||||
r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware2.AuthCheckRole())
|
|
||||||
{
|
{
|
||||||
r.GET("", api.GetSysMenuList)
|
r.GET("", api.GetPage)
|
||||||
r.GET("/:id", api.GetSysMenu)
|
r.GET("/:id", api.Get)
|
||||||
r.POST("", api.InsertSysMenu)
|
r.POST("", api.Insert)
|
||||||
r.PUT("/:id", api.UpdateSysMenu)
|
r.PUT("/:id", api.Update)
|
||||||
r.DELETE("/:id", api.DeleteSysMenu)
|
r.DELETE("", api.Delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
|
r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc())
|
||||||
{
|
{
|
||||||
r1.GET("/menurole", api.GetMenuRole)
|
r1.GET("/menurole", api.GetMenuRole)
|
||||||
r1.GET("/menuids", api.GetMenuIDS)
|
//r1.GET("/menuids", api.GetMenuIDS)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user