mirror of
https://github.com/flipped-aurora/gin-vue-admin.git
synced 2026-09-25 05:50:19 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fba9ab0ae6 | ||
|
|
e18518b4d3 | ||
|
|
074a7145d2 | ||
|
|
46372f0e6c | ||
|
|
1acd2e3238 | ||
|
|
a2e7827aa8 | ||
|
|
ac71aafe83 | ||
|
|
0b1cc913d9 | ||
|
|
84b967ae82 | ||
|
|
cf9002a377 | ||
|
|
829fa4dac5 | ||
|
|
5529d5f46d | ||
|
|
08e9c6b38a | ||
|
|
5c94c73004 | ||
|
|
8ebb1fda77 | ||
|
|
96380bd031 | ||
|
|
c342e63e63 | ||
|
|
4fa43c232d | ||
|
|
d07cbc8783 | ||
|
|
f7667ad3e1 | ||
|
|
5fe66b7abc | ||
|
|
856c09c38d | ||
|
|
b947f043ee | ||
|
|
ebd515f057 | ||
|
|
636faaf93b | ||
|
|
ed1c6c7a47 | ||
|
|
e4340641ad | ||
|
|
35738cfda8 | ||
|
|
e749adaa10 | ||
|
|
26a1a89d60 | ||
|
|
2daa65f00d | ||
|
|
d2579d390c | ||
|
|
261e34a5c2 | ||
|
|
b4bad21e35 | ||
|
|
699f53e8b2 | ||
|
|
820c9f733f | ||
|
|
99bd217080 | ||
|
|
c86c05f380 | ||
|
|
544901bf45 | ||
|
|
8db0e2fb06 | ||
|
|
c5ed47192e | ||
|
|
3d56cb7eb2 | ||
|
|
ada8818960 | ||
|
|
2f97f4b979 | ||
|
|
0a4e81138a | ||
|
|
c61350643a | ||
|
|
9f59275652 | ||
|
|
1da644b96a | ||
|
|
1de825ee43 | ||
|
|
2e18f3f5e1 | ||
|
|
653f73b989 | ||
|
|
9c5b9729d8 | ||
|
|
6950e493f2 | ||
|
|
286f0b74da | ||
|
|
a1191abc43 | ||
|
|
75799b81e8 | ||
|
|
511a187f49 | ||
|
|
01ecfcdf8d | ||
|
|
14a55fcb83 | ||
|
|
49c146b3dc | ||
|
|
e2c5988bea | ||
|
|
3d2e9ef063 | ||
|
|
28c7d178c4 | ||
|
|
024f461e94 | ||
|
|
a25823f5b5 | ||
|
|
4d4d8e4955 | ||
|
|
7488db81c1 | ||
|
|
e8c6d388f2 | ||
|
|
10d8d7f28a | ||
|
|
986406a880 | ||
|
|
2946c8ce34 | ||
|
|
fef12cb747 | ||
|
|
4d8d4b77c1 | ||
|
|
7cb172d60a | ||
|
|
970b2d21a9 | ||
|
|
f7804b627e | ||
|
|
a7bb4a7ac4 | ||
|
|
06c67c1024 | ||
|
|
03024f192a | ||
|
|
b1baccf0a5 | ||
|
|
ad047f4c06 | ||
|
|
6f589d7af9 | ||
|
|
eeaaa40259 | ||
|
|
45cc0aec93 | ||
|
|
0bd80ad900 | ||
|
|
1214241dab | ||
|
|
6a03008ac9 | ||
|
|
cc215d6ad0 | ||
|
|
e28217e5ec | ||
|
|
0d8edbbb64 | ||
|
|
2baf392129 | ||
|
|
d478246edc | ||
|
|
ea375a026d | ||
|
|
9101d5bdb8 | ||
|
|
811df12524 | ||
|
|
3ee469aef3 | ||
|
|
7b503337b1 | ||
|
|
dd65a4a716 | ||
|
|
45f2bd4a15 | ||
|
|
1848ceb8f7 | ||
|
|
938c598cfb | ||
|
|
bea9ede941 | ||
|
|
6c4b217b1b | ||
|
|
f1de3e6b84 | ||
|
|
6cc9a420bf | ||
|
|
5b1eb546fd | ||
|
|
3c9d81756b | ||
|
|
51b6c1086e | ||
|
|
63012b31ac | ||
|
|
f5c6f95b27 | ||
|
|
b7fd730c5e | ||
|
|
3df918ef00 | ||
|
|
a200c2ebe0 | ||
|
|
a471bae727 | ||
|
|
9f73219c85 | ||
|
|
5a474585b5 | ||
|
|
c48048bd32 | ||
|
|
8fd8296c69 | ||
|
|
130910308d | ||
|
|
56cc369a77 | ||
|
|
8aee3b27af | ||
|
|
63edd741ba | ||
|
|
d7007eec59 | ||
|
|
277a732df0 | ||
|
|
a4b15b4731 | ||
|
|
07c6bbd7e1 | ||
|
|
ad504a17e0 | ||
|
|
d16ca6967f | ||
|
|
785fde0eaf | ||
|
|
af761f7472 | ||
|
|
5235511041 | ||
|
|
272f6c7b39 | ||
|
|
22bc9f43bd | ||
|
|
c2747590e0 | ||
|
|
794f8a631c | ||
|
|
04c0071b83 | ||
|
|
e5de639757 | ||
|
|
553980cf73 | ||
|
|
ff7390f1e6 | ||
|
|
4927f414f7 | ||
|
|
329d3fc622 | ||
|
|
1b6d80dfe9 | ||
|
|
dd45558e6a | ||
|
|
dc273edf3c | ||
|
|
621069eee7 | ||
|
|
a385d41cc3 | ||
|
|
9e6414fcb1 | ||
|
|
f6a3c65129 | ||
|
|
d930a9e95a | ||
|
|
3dea48b54e | ||
|
|
f1c00c6b20 | ||
|
|
099ff42404 | ||
|
|
f8e1832172 | ||
|
|
9e19684d40 | ||
|
|
56c226919e | ||
|
|
c6d6180c3c | ||
|
|
9265397f29 | ||
|
|
7aea8d71aa | ||
|
|
40f8ab6101 | ||
|
|
d7f490a0e8 | ||
|
|
01a5b859a9 | ||
|
|
bafe18f6e1 | ||
|
|
cd310eac17 | ||
|
|
cbdf1cd92e | ||
|
|
759dd34c76 | ||
|
|
3fbb2ab0ca | ||
|
|
ad107aadf1 | ||
|
|
e6e0f1d5db | ||
|
|
d3dfdace9f | ||
|
|
88abbc26d1 | ||
|
|
095b2ff27e | ||
|
|
28f03c3d7e | ||
|
|
3db0cedf7e | ||
|
|
11fdd96352 | ||
|
|
b6dfb393a1 | ||
|
|
268af2e84e | ||
|
|
225ef0fc8d | ||
|
|
d382d15f78 | ||
|
|
0833c09e98 | ||
|
|
3e62007e6a | ||
|
|
d5550bf99c | ||
|
|
1bdf0cb2ea | ||
|
|
e3ccccd1f3 | ||
|
|
ecfc8cd1e7 | ||
|
|
ba0bcefec4 | ||
|
|
93d1fdae31 | ||
|
|
35d0ab10a9 | ||
|
|
d9db6c1b36 | ||
|
|
096fa511f4 | ||
|
|
df69c96bd3 | ||
|
|
9b40ea5913 | ||
|
|
c9b484bec2 | ||
|
|
c6700a72bc | ||
|
|
630300cf37 | ||
|
|
fd0f741a01 | ||
|
|
6631aa35db | ||
|
|
e9ef8f7882 | ||
|
|
be9c85ae42 | ||
|
|
a8b01b6314 | ||
|
|
513259f65f | ||
|
|
11cde72962 | ||
|
|
fb6dfcbd72 | ||
|
|
734ff79890 | ||
|
|
2fdb014717 | ||
|
|
377777e2c1 | ||
|
|
e810a08c0e | ||
|
|
14ea27749c | ||
|
|
012f2569b1 | ||
|
|
01c4206443 | ||
|
|
a46859987e | ||
|
|
34bc072efd | ||
|
|
d7813c3507 | ||
|
|
0403ec3ffe | ||
|
|
f8cb44b51d | ||
|
|
b31a8d34d6 | ||
|
|
2c5a19fe8f | ||
|
|
67ec569fc1 | ||
|
|
ccdb695c06 | ||
|
|
db0bddf1d4 | ||
|
|
c1dc629daf | ||
|
|
dd789b3991 | ||
|
|
be8bac1ea1 | ||
|
|
602a64b879 | ||
|
|
3a8ea28ea2 | ||
|
|
39e7b641ea | ||
|
|
a104453aae | ||
|
|
59af022125 | ||
|
|
e92df293d5 | ||
|
|
4805879702 | ||
|
|
f90d4745c1 | ||
|
|
f53f8ddc65 | ||
|
|
6ec20fce3a | ||
|
|
88e7b46f32 | ||
|
|
f707f70f80 | ||
|
|
16722ccd31 | ||
|
|
7e1cfc6f09 | ||
|
|
d6fe1339b2 | ||
|
|
aab91dec6c | ||
|
|
40e2344629 | ||
|
|
8fb0df69b9 | ||
|
|
8a45a686a0 | ||
|
|
d4101f7f34 | ||
|
|
cf73dbd0d9 | ||
|
|
6c9f8b5eba | ||
|
|
5a9247509a | ||
|
|
98d5cab1d5 | ||
|
|
87ee4436ea | ||
|
|
2bbb51c41e | ||
|
|
7fca9c7ce0 | ||
|
|
aee6748c49 | ||
|
|
ee9b19bb0b | ||
|
|
f69b40a532 | ||
|
|
48e6ac39e2 | ||
|
|
363ff3ba70 | ||
|
|
f130aec168 | ||
|
|
10ea953bfd | ||
|
|
9f1504e88a | ||
|
|
0239f7b97c | ||
|
|
9679616935 | ||
|
|
2022a417ab | ||
|
|
980436807c | ||
|
|
fd74cc719d | ||
|
|
d1502d2b7d | ||
|
|
a5558badf1 | ||
|
|
f99bfe2c84 | ||
|
|
834a233d19 | ||
|
|
61fdaefe24 | ||
|
|
cf217bde03 | ||
|
|
e6e99d0b52 | ||
|
|
73d55910e5 | ||
|
|
f643abd549 | ||
|
|
fe40c28814 | ||
|
|
5233bf2e5b | ||
|
|
971dafbb8d | ||
|
|
8ae25dc264 | ||
|
|
a8524fa30f | ||
|
|
b9b3a30f75 | ||
|
|
d97b49c950 | ||
|
|
d303955747 | ||
|
|
211ba42fed | ||
|
|
f61f4d6b77 | ||
|
|
152ec2423c | ||
|
|
fee4af62c4 | ||
|
|
2483581158 | ||
|
|
9cb7ae871d | ||
|
|
06cbc9c3a3 | ||
|
|
fb0ac5356e | ||
|
|
8dfdb21c36 | ||
|
|
60341e2881 | ||
|
|
d53fe1f32c | ||
|
|
41c4b8f0a5 | ||
|
|
fbca3eaa7b | ||
|
|
de1d090c31 | ||
|
|
6be75b61a8 | ||
|
|
0f7a6a548f | ||
|
|
9a12fbf48c | ||
|
|
2f8c532713 | ||
|
|
6ddda9f77e | ||
|
|
174a300172 | ||
|
|
7ca11b979a | ||
|
|
a586375724 | ||
|
|
4d9da856f7 | ||
|
|
cea3618e74 | ||
|
|
aec64e4e79 | ||
|
|
4adf2f1b04 | ||
|
|
eeb9f0aae6 | ||
|
|
cea8a12a37 | ||
|
|
c2c8d4fa3b | ||
|
|
55cea812b5 | ||
|
|
555dd46296 | ||
|
|
86ad612884 | ||
|
|
df0312e60e | ||
|
|
1a75f23615 | ||
|
|
f8c0896775 | ||
|
|
71ba8e7b55 | ||
|
|
0e256bc912 | ||
|
|
943913b443 | ||
|
|
a7e2ef171f | ||
|
|
152946ac42 | ||
|
|
35b507204c | ||
|
|
7a31de2960 | ||
|
|
e27066d9ac | ||
|
|
9068ca6ea7 | ||
|
|
8f21a2158f | ||
|
|
fe7364b301 | ||
|
|
783e355501 | ||
|
|
9a582877ea | ||
|
|
537e7ced45 | ||
|
|
ceeb00043a | ||
|
|
79c2d33a01 | ||
|
|
1c99c3a377 | ||
|
|
44c4b2764e | ||
|
|
06976adb00 | ||
|
|
ec53501431 | ||
|
|
92f82af3d2 | ||
|
|
4153eb9435 | ||
|
|
ecab8cf918 | ||
|
|
46e0960c3a | ||
|
|
974b7c7b81 | ||
|
|
9a0c74e04c | ||
|
|
bd45ec083f | ||
|
|
ce013d31c2 | ||
|
|
33340c2eb8 | ||
|
|
7b1a87116c | ||
|
|
6adfab6d8a | ||
|
|
02df16d2f0 | ||
|
|
30f1ee77e0 | ||
|
|
f6c951dd13 | ||
|
|
9c40447071 | ||
|
|
990fd1f4f3 | ||
|
|
a9961f1f19 | ||
|
|
413f4bca17 | ||
|
|
472e5039fb | ||
|
|
fa3b53d1fd | ||
|
|
96bd856405 | ||
|
|
08301fde62 | ||
|
|
0e72e9f9f9 | ||
|
|
666ad8c14e | ||
|
|
3791e573d3 | ||
|
|
fab3d5402f | ||
|
|
f09c081b5d | ||
|
|
27e5c1786c | ||
|
|
f54c6f2124 | ||
|
|
88aab4666d | ||
|
|
937239b7ba | ||
|
|
6411c5cb9c | ||
|
|
052534210b | ||
|
|
0da10baf19 | ||
|
|
8853992c1a | ||
|
|
17d73b1262 | ||
|
|
561b20efe2 | ||
|
|
8ec30ac3b7 | ||
|
|
98eb6bd796 | ||
|
|
aa2d304682 | ||
|
|
738175a9d8 | ||
|
|
884c8a433e | ||
|
|
5f5e105c87 | ||
|
|
682d92e00b | ||
|
|
2d01841b9e | ||
|
|
7e574cb525 | ||
|
|
eca0a38678 | ||
|
|
fe3256175d | ||
|
|
e5fd2fa1a7 | ||
|
|
c7ea8ccb7d | ||
|
|
3b18442e76 | ||
|
|
7ad73a09b3 | ||
|
|
2da199145d | ||
|
|
671e450a99 | ||
|
|
fde276e159 | ||
|
|
bb64ea839b | ||
|
|
8173ff6fc2 | ||
|
|
c4a6b33f62 | ||
|
|
db26f5b8f5 | ||
|
|
5d411c021e | ||
|
|
1597eeacfc | ||
|
|
d94d7c4c29 | ||
|
|
3cd2ea25e5 | ||
|
|
fb2794adde | ||
|
|
318f688259 | ||
|
|
e51e8aef73 | ||
|
|
f237557b99 | ||
|
|
291c30cfed | ||
|
|
518bdba578 | ||
|
|
5cb3d7bc86 | ||
|
|
7b52618f53 | ||
|
|
a7141feff7 | ||
|
|
f2a0f9776d | ||
|
|
9bfb5eba97 | ||
|
|
0de756512f | ||
|
|
68296e6f4f | ||
|
|
3d9837b7e3 | ||
|
|
6c991962fc | ||
|
|
75432c45ba | ||
|
|
c96a7732b4 | ||
|
|
8c5ae61a13 | ||
|
|
af3b6919be | ||
|
|
ad4562b026 | ||
|
|
0f7cb13821 | ||
|
|
8186d9ef3a | ||
|
|
625bd91b94 | ||
|
|
67fb113648 | ||
|
|
c958853c14 | ||
|
|
1d38214fe5 | ||
|
|
bcdc7b266a | ||
|
|
7544b9dcf6 | ||
|
|
dd699b1546 | ||
|
|
cfb6f5038b | ||
|
|
927c8ab248 | ||
|
|
e63394a355 | ||
|
|
1264272ff8 | ||
|
|
b09e54c205 | ||
|
|
5e2687a742 | ||
|
|
905ad0e2d2 | ||
|
|
56ff0c69cb | ||
|
|
1110a3f7dc | ||
|
|
f567ce80e6 | ||
|
|
fa50c11a67 | ||
|
|
e878d35b6f | ||
|
|
dc27fe21b2 | ||
|
|
00077b6b85 | ||
|
|
2cbd21635d | ||
|
|
cb51890c25 | ||
|
|
9d9404b3c5 | ||
|
|
10a5390327 | ||
|
|
d04acfd39b | ||
|
|
865b66b3db | ||
|
|
73e31c6d23 | ||
|
|
db9b3dce10 | ||
|
|
7072d7e981 | ||
|
|
95781e858d | ||
|
|
cec6f164fb | ||
|
|
e58cf2544b | ||
|
|
b81ea1a22e | ||
|
|
6ac8fe871b | ||
|
|
9c9f4d1244 | ||
|
|
07b030d9a8 | ||
|
|
efe539dbd2 | ||
|
|
0306efb866 | ||
|
|
262c6b1594 | ||
|
|
5e7570e557 | ||
|
|
bf4344323d | ||
|
|
760a242118 | ||
|
|
c059390538 | ||
|
|
2756d2041c | ||
|
|
8699d6f534 | ||
|
|
625ca336e7 | ||
|
|
e424421585 | ||
|
|
731e8ec609 | ||
|
|
235c2a75a8 | ||
|
|
b95db1de3b | ||
|
|
133b1c3bb7 | ||
|
|
e3920f4ee9 | ||
|
|
ef0c5f3b24 | ||
|
|
098705e48e | ||
|
|
f415428740 | ||
|
|
717bc28b5d | ||
|
|
828dc6cfe8 | ||
|
|
10b943c57c | ||
|
|
9fe459afe1 | ||
|
|
5fe8a85be3 | ||
|
|
06c2e5639c | ||
|
|
462e396486 | ||
|
|
7e9d32651b | ||
|
|
a58330c0ff | ||
|
|
eb2361f9ac | ||
|
|
b44c5f76e1 | ||
|
|
890adbfa4e | ||
|
|
315e71e851 | ||
|
|
a48910f696 | ||
|
|
5878ffe937 | ||
|
|
c20a266662 | ||
|
|
6d53a47b59 | ||
|
|
9510177350 | ||
|
|
ba1dd82988 | ||
|
|
cafc344def | ||
|
|
6ce439597b | ||
|
|
c731b87f90 | ||
|
|
71c57ec382 | ||
|
|
08e21621d7 | ||
|
|
8c605efdbe | ||
|
|
a3110de71f | ||
|
|
019e28fb13 | ||
|
|
166d73b124 | ||
|
|
215c955e19 | ||
|
|
0044f1da1f | ||
|
|
53de9c7511 | ||
|
|
431e53cb45 | ||
|
|
f9764fcebf | ||
|
|
9290b3b68c | ||
|
|
bb42fc86eb | ||
|
|
5745afaea8 | ||
|
|
7dd0512e67 | ||
|
|
113d59fdf9 | ||
|
|
3ae83b25ff | ||
|
|
0468584851 | ||
|
|
5bce3a1567 | ||
|
|
4bf6371bee | ||
|
|
36b07a3006 | ||
|
|
29fe71b482 | ||
|
|
176362448a | ||
|
|
0afed943a5 | ||
|
|
40a78d8228 | ||
|
|
9185d573ab | ||
|
|
9b2acbae11 | ||
|
|
4b07123509 | ||
|
|
b7a0a6ee08 | ||
|
|
666b79f584 | ||
|
|
34faaf8c19 | ||
|
|
af4f83d4cb | ||
|
|
377241276c | ||
|
|
1077e8e40f | ||
|
|
fee540735a | ||
|
|
3d91c3768d | ||
|
|
b1fe359cd5 | ||
|
|
c2454d998f | ||
|
|
8369584880 | ||
|
|
2680da2873 | ||
|
|
0bd9a21318 | ||
|
|
ca7d06780f | ||
|
|
eba0f4f495 | ||
|
|
09e06dd278 | ||
|
|
6ace32ee78 | ||
|
|
6da7424fcd | ||
|
|
5e63794cbd | ||
|
|
a815c1b599 | ||
|
|
de2f19ae50 | ||
|
|
386a4d38b4 | ||
|
|
283830fc53 | ||
|
|
5375234c23 | ||
|
|
784c8705b7 | ||
|
|
68a853b755 | ||
|
|
c65732d0e1 | ||
|
|
0533c6b01a | ||
|
|
2acbde21b8 | ||
|
|
3c87b3d449 | ||
|
|
dcd0420892 | ||
|
|
03e14142e3 | ||
|
|
e0f2153172 | ||
|
|
ee6d5883b1 | ||
|
|
0f6bc8dc31 | ||
|
|
26820458d1 | ||
|
|
3a3be3b23f | ||
|
|
5834f19746 | ||
|
|
8034ca5e13 | ||
|
|
4f94e846c9 | ||
|
|
5305bf3680 | ||
|
|
aba79bb3d0 | ||
|
|
a2b12cf37a | ||
|
|
10ef49e4e8 | ||
|
|
dd4563c9e4 | ||
|
|
75352f45cd | ||
|
|
25b5947587 | ||
|
|
2eab2a6a22 | ||
|
|
78670f79af | ||
|
|
0be0ec9a2f | ||
|
|
a55d5e2f1a | ||
|
|
eea245e405 | ||
|
|
75035b9038 | ||
|
|
538c8ba0df | ||
|
|
e3aae896ad | ||
|
|
645d0fd842 | ||
|
|
72f725bb4f | ||
|
|
992b8446cf | ||
|
|
a766be61d8 | ||
|
|
ff82bc47e6 | ||
|
|
093cde16c2 | ||
|
|
04536fe226 | ||
|
|
832100f39d | ||
|
|
02bee9b6f2 | ||
|
|
a837638672 | ||
|
|
569abbeb53 | ||
|
|
5698c207a1 | ||
|
|
57167b6c38 | ||
|
|
cd0b1e0336 | ||
|
|
ea3f49d68a | ||
|
|
91a3b5b3ce | ||
|
|
6a03835d66 | ||
|
|
2fbbde2581 | ||
|
|
6b61abdf96 | ||
|
|
f1c92e5b96 | ||
|
|
20156e2a34 | ||
|
|
8804ef6b67 | ||
|
|
6ac385f45a | ||
|
|
be2bef5600 | ||
|
|
f68947d50e | ||
|
|
1632c6361f | ||
|
|
959aa9cd38 | ||
|
|
7b9f8f19c0 | ||
|
|
f1d225375f | ||
|
|
58ca2231e1 | ||
|
|
f71bf74c48 | ||
|
|
6003728944 | ||
|
|
001f7a2676 | ||
|
|
2f0b39af3d | ||
|
|
836e4aad86 | ||
|
|
ba46a6effd | ||
|
|
05cbc853f7 | ||
|
|
c9bf4e6e72 | ||
|
|
f5e29733e0 | ||
|
|
571df5a415 | ||
|
|
98455325cb | ||
|
|
dfa4ef100a | ||
|
|
c6a8a47932 | ||
|
|
0ff3bdc64f | ||
|
|
71fd0eb9ad | ||
|
|
47a45e2d67 | ||
|
|
3ebbd7690f | ||
|
|
7c48de76c4 | ||
|
|
ae3b3b3579 | ||
|
|
339490e20d | ||
|
|
ed289aeb49 | ||
|
|
7b6eea6974 | ||
|
|
b35169ca20 | ||
|
|
c11f6d428a | ||
|
|
da8a1c20b6 | ||
|
|
8a2f903576 | ||
|
|
849f0dcf43 | ||
|
|
63e23ff367 | ||
|
|
a2bef96512 | ||
|
|
d6fbe7c8de | ||
|
|
b15fe4493e | ||
|
|
013a44f480 | ||
|
|
d27b152a09 | ||
|
|
e0916eeb63 | ||
|
|
b5197b0013 | ||
|
|
74201dfcd0 | ||
|
|
641adca61f | ||
|
|
ee24387a79 | ||
|
|
b308c6e416 | ||
|
|
7993e878cc | ||
|
|
5b753f2e72 | ||
|
|
26bba8ead8 | ||
|
|
4399994b80 | ||
|
|
19548446e2 | ||
|
|
6bf46327bc | ||
|
|
f683d89517 | ||
|
|
4d2c13d83a | ||
|
|
aabf7c0656 | ||
|
|
f93bd6020a | ||
|
|
d2bc6ba615 | ||
|
|
6f3e3188b2 | ||
|
|
443922c7de | ||
|
|
3a778ccdf1 | ||
|
|
a68628efbe | ||
|
|
ea9bd37fe8 | ||
|
|
f87ae7a2ea | ||
|
|
060961e312 | ||
|
|
73a141d2b4 | ||
|
|
0a832dfe24 | ||
|
|
d447913056 | ||
|
|
5586f1ddc3 | ||
|
|
cbe2e9a729 | ||
|
|
5b29b661dc | ||
|
|
71095f3e2e | ||
|
|
a9651d1ce4 | ||
|
|
d198856633 | ||
|
|
1051db5d4c | ||
|
|
4277505c6a | ||
|
|
5d222585dd | ||
|
|
2c35adaffc | ||
|
|
137db98ee4 | ||
|
|
433bd0dd03 | ||
|
|
604d6dcd42 | ||
|
|
38ccce5182 | ||
|
|
55d96245c2 | ||
|
|
13ead70368 | ||
|
|
2d7cd2e61a | ||
|
|
1e70d266ac | ||
|
|
688742aa42 | ||
|
|
3dcdd36d76 | ||
|
|
de8557781e | ||
|
|
5dac0b17b0 | ||
|
|
7318e0cfae | ||
|
|
0401b2c00b | ||
|
|
1f2c77a49b | ||
|
|
43994c7bfd | ||
|
|
4332607f40 | ||
|
|
df76e190fb | ||
|
|
8d24342a90 | ||
|
|
12f90505b1 | ||
|
|
7da3980c78 | ||
|
|
11691cdd13 | ||
|
|
209db0c4c3 | ||
|
|
f9c80aed27 | ||
|
|
e22af46d92 | ||
|
|
8bd8b54993 | ||
|
|
8bd1bf0b22 | ||
|
|
44cd748ee4 | ||
|
|
90d371124e | ||
|
|
1b47200a42 | ||
|
|
3996cb8e82 | ||
|
|
6373800be2 | ||
|
|
9495215d07 | ||
|
|
a2a439c45a | ||
|
|
bc00db8d1b | ||
|
|
0e5b3e638a | ||
|
|
fb45acc42b | ||
|
|
f6e38d5cd1 | ||
|
|
002f6d4159 | ||
|
|
29be427f5f | ||
|
|
640e5feb6f | ||
|
|
2415cb26fa | ||
|
|
478cce60c8 | ||
|
|
e6ea76e03e | ||
|
|
4b5a102cb5 | ||
|
|
fbf4a33a31 | ||
|
|
79254bd64c | ||
|
|
2467522d30 | ||
|
|
733d062683 | ||
|
|
3a4b729b8e | ||
|
|
b076ae5704 | ||
|
|
f538e7b99a | ||
|
|
1e4daaba4e | ||
|
|
9766f12016 | ||
|
|
fddfdf44a1 | ||
|
|
dc4ebc5851 | ||
|
|
13c30d4c55 | ||
|
|
39f256b4b7 | ||
|
|
63fe673169 | ||
|
|
9d99777b1f | ||
|
|
7c52c05280 | ||
|
|
81a54b5a44 | ||
|
|
c755120c8d | ||
|
|
08ff55ffce | ||
|
|
1891c1bcbc | ||
|
|
6db275ca39 | ||
|
|
1b9adea284 | ||
|
|
d1e0ab1db9 | ||
|
|
54bdc9b834 | ||
|
|
ffdd677d8f | ||
|
|
a1583ad2a4 | ||
|
|
5ed41ddd8c | ||
|
|
f545048e60 | ||
|
|
1c30ae1080 | ||
|
|
f32c1d93bb | ||
|
|
40ef40afa8 | ||
|
|
abc88cdbe0 | ||
|
|
5810791099 | ||
|
|
507d4620ca | ||
|
|
29dee32b47 | ||
|
|
825ffa2dcb | ||
|
|
c08b8fdc49 | ||
|
|
13295bb9e7 | ||
|
|
1ea720093a | ||
|
|
c2e90af0c9 | ||
|
|
11c3ff681a | ||
|
|
42bec5811c | ||
|
|
7f5504f840 | ||
|
|
aa145bc905 |
@@ -0,0 +1,26 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
#access_log logs/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
rewrite ^/api/(.*)$ /$1 break; #重写
|
||||
proxy_pass http://177.7.0.12:8888; # 设置代理服务器的协议和地址
|
||||
}
|
||||
|
||||
location /api/swagger/index.html {
|
||||
proxy_pass http://127.0.0.1:8888/swagger/index.html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#! /bin/bash
|
||||
|
||||
rm -f ./config.yaml
|
||||
# 生成config.yaml文件, 用于docker-compose的使用
|
||||
touch ./config.yaml
|
||||
filename="./config.yaml"
|
||||
cat>"${filename}"<<EOF
|
||||
# Gin-Vue-Admin Global Configuration
|
||||
|
||||
# jwt configuration
|
||||
jwt:
|
||||
signing-key: 'qmPlus'
|
||||
|
||||
# zap logger configuration
|
||||
zap:
|
||||
level: 'info'
|
||||
format: 'console'
|
||||
prefix: '[GIN-VUE-ADMIN]'
|
||||
director: 'log'
|
||||
link-name: 'latest_log'
|
||||
show-line: true
|
||||
encode-level: 'LowercaseColorLevelEncoder'
|
||||
stacktrace-key: 'stacktrace'
|
||||
log-in-console: true
|
||||
|
||||
# redis configuration
|
||||
redis:
|
||||
db: 0
|
||||
addr: '177.7.0.14:6379'
|
||||
password: ''
|
||||
|
||||
# email configuration
|
||||
email:
|
||||
to: 'xxx@qq.com'
|
||||
port: 465
|
||||
from: 'xxx@163.com'
|
||||
host: 'smtp.163.com'
|
||||
is-ssl: true
|
||||
secret: 'xxx'
|
||||
nickname: 'test'
|
||||
|
||||
# casbin configuration
|
||||
casbin:
|
||||
model-path: './resource/rbac_model.conf'
|
||||
|
||||
# system configuration
|
||||
system:
|
||||
env: 'public' # Change to "develop" to skip authentication for development mode
|
||||
addr: 8888
|
||||
db-type: 'mysql'
|
||||
oss-type: 'local'
|
||||
use-multipoint: false
|
||||
|
||||
# captcha configuration
|
||||
captcha:
|
||||
key-long: 6
|
||||
img-width: 240
|
||||
img-height: 80
|
||||
|
||||
# mysql connect configuration
|
||||
mysql:
|
||||
path: '177.7.0.13:3306'
|
||||
config: 'charset=utf8mb4&parseTime=True&loc=Local'
|
||||
db-name: 'qmPlus'
|
||||
username: 'root'
|
||||
password: 'Aa@6447985'
|
||||
max-idle-conns: 10
|
||||
max-open-conns: 10
|
||||
log-mode: false
|
||||
|
||||
# local configuration
|
||||
local:
|
||||
path: 'uploads/file'
|
||||
|
||||
# qiniu configuration (请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址)
|
||||
qiniu:
|
||||
zone: 'ZoneHuadong'
|
||||
bucket: 'qm-plus-img'
|
||||
img-path: 'http://qmplusimg.henrongyi.top'
|
||||
use-https: false
|
||||
access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
|
||||
secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
|
||||
use-cdn-domains: false
|
||||
EOF
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.pnp.*
|
||||
|
||||
**/node_modules
|
||||
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://www.gin-vue-admin.com/docs/coffee
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: issues模板
|
||||
about: 请严格按照要求进行提交issues! 如果未能按照要求,我们将会close您的issues,敬请谅解!
|
||||
---
|
||||
<!-- 在提交问题之前,请先回答这些问题。谢谢! -->
|
||||
|
||||
### 1. 您使用的是哪个版本的`Go`和系统类型/架构 ?
|
||||
|
||||
<!--
|
||||
请从您的终端粘贴命令 `go version` 的输出。
|
||||
期望看到像: `go version go1.14.4 darwin/amd64`
|
||||
-->
|
||||
|
||||
### 2. 您使用的是哪个版本的 `Nodejs` 和 `npm` 或 `cnpm` ?
|
||||
|
||||
<!--
|
||||
请从您的终端粘贴命令 `node -v` 的输出。
|
||||
期望看到像: `v12.16.1`
|
||||
-->
|
||||
|
||||
<!--
|
||||
请从您的终端粘贴命令 `npm -v` 的输出。
|
||||
期望看到像: `6.13.4`
|
||||
-->
|
||||
|
||||
<!--
|
||||
请从您的终端粘贴命令 `cnpm -v` 的输出。
|
||||
期望看到的像: `
|
||||
cnpm@6.1.1 (/usr/local/lib/node_modules/cnpm/lib/parse_argv.js)
|
||||
npm@6.14.2 (/usr/local/lib/node_modules/cnpm/node_modules/npm/lib/npm.js)
|
||||
node@12.16.1 (/usr/local/bin/node)
|
||||
npminstall@3.27.0 (/usr/local/lib/node_modules/cnpm/node_modules/npminstall/lib/index.js)
|
||||
prefix=/usr/local
|
||||
darwin x64 19.6.0
|
||||
registry=https://r.npm.taobao.org
|
||||
`
|
||||
-->
|
||||
|
||||
### 3. 您使用的是哪个版本的 `gin-vue-admin` ?
|
||||
|
||||
<!--
|
||||
您如果克隆的是master就写master,
|
||||
如果是在Releases中下载的zip/tar.gz对应的tag版本,
|
||||
如:`v2.3.0`
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### 4. 可以在master版本中复现此问题吗 ?
|
||||
|
||||
|
||||
|
||||
### 5. 您做了什么 ?
|
||||
|
||||
<!--
|
||||
如果可能,请提供最短代码的副本以重现该错误。
|
||||
一个完整的可运行程序是最好的。
|
||||
-->
|
||||
|
||||
|
||||
|
||||
### 6. 您期望看到什么 ?
|
||||
|
||||
|
||||
|
||||
### 7. 您看到了什么 ?
|
||||
|
||||
|
||||
|
||||
### 8. 错误堆栈或者SQL打印
|
||||
@@ -0,0 +1,64 @@
|
||||
name: gin-vue-admin build test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
paths-ignore:
|
||||
- "./db/**"
|
||||
- "**.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
paths-ignore:
|
||||
- "./db/**"
|
||||
- "**.md"
|
||||
|
||||
jobs:
|
||||
frontend:
|
||||
name: Frontend build
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Build test
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
working-directory: ./web
|
||||
|
||||
backend:
|
||||
name: Backend build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go 1.14
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.14
|
||||
id: go
|
||||
|
||||
- name: Check out branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
if [ -f Gopkg.toml ]; then
|
||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
dep ensure
|
||||
fi
|
||||
working-directory: ./server
|
||||
|
||||
- name: Test and Build
|
||||
run: |
|
||||
go build -v -race
|
||||
working-directory: ./server
|
||||
+29
@@ -1 +1,30 @@
|
||||
.idea/
|
||||
/web/node_modules
|
||||
/web/dist
|
||||
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
go.sum
|
||||
/server/log/
|
||||
/server/gva
|
||||
/server/latest_log
|
||||
|
||||
*.iml
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
### Contributing Guide
|
||||
#### 1 Issue Guidelines
|
||||
|
||||
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly. If any questions come up when you are using Element, please hit [Gitter](https://gitter.im/element-en/Lobby) for help.
|
||||
|
||||
- Before submitting an issue, please check if similar problems have already been issued.
|
||||
|
||||
#### 2 Pull Request Guidelines
|
||||
|
||||
- Fork this repository to your own account. Do not create branches here.
|
||||
|
||||
- Commit info should be formatted as `[File Name]: Info about commit.` (e.g. `README.md: Fix xxx bug`)
|
||||
|
||||
- <font color=red>Make sure PRs are created to `develop` branch instead of `master` branch.</font>
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
- Merging a PR takes two maintainers: one approves the changes after reviewing, and then the other reviews and merges.
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
FROM golang:alpine as builder
|
||||
RUN apk add --update --no-cache yarn make g++
|
||||
RUN yarn global add cross-env node-sass
|
||||
|
||||
ENV GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||
GO111MODULE=on \
|
||||
CGO_ENABLED=1
|
||||
WORKDIR /go/src/gin-vue-admin
|
||||
RUN go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct
|
||||
COPY server/ ./
|
||||
RUN go env && go list && go build -v -a -ldflags "-extldflags \"-static\" " -o gvadmin .
|
||||
|
||||
WORKDIR /web
|
||||
COPY web/ ./
|
||||
RUN yarn install && yarn run build
|
||||
|
||||
|
||||
FROM nginx:alpine
|
||||
LABEL MAINTAINER="rikugun"
|
||||
|
||||
RUN apk add --no-cache gettext tzdata && \
|
||||
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo "Asia/Shanghai" > /etc/timezone && \
|
||||
date && \
|
||||
apk del tzdata
|
||||
|
||||
COPY docker/etc/nginx/nginx.conf.tpl /etc/nginx/nginx.conf.tpl
|
||||
WORKDIR /app
|
||||
#copy web
|
||||
COPY --from=builder /web/dist/ /var/www/
|
||||
#copy go app
|
||||
COPY --from=builder /go/src/gin-vue-admin/gvadmin ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/db.db ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/config.yaml ./
|
||||
COPY --from=builder /go/src/gin-vue-admin/resource ./resource
|
||||
COPY docker/docker-start.sh ./
|
||||
|
||||
ENV API_SERVER="http://localhost:8888/"
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["./docker-start.sh"]
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright 2019 JiZhao Jiang
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
go.sum
|
||||
.idea/
|
||||
log/
|
||||
@@ -1,16 +0,0 @@
|
||||
FROM golang:1.12 AS build
|
||||
|
||||
WORKDIR /go/src/gin-vue-admin
|
||||
COPY . .
|
||||
|
||||
ENV GO111MODULE=on
|
||||
ENV GOPROXY=https://goproxy.cn
|
||||
RUN go get ./... \
|
||||
&& go build -o gin-vue-admin
|
||||
|
||||
FROM golang:1.12 AS serve
|
||||
|
||||
COPY --from=build /go/src/gin-vue-admin /go/src/gin-vue-admin
|
||||
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT [ "./gin-vue-admin" ]
|
||||
@@ -1,31 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/initlog"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func RunWindowsServer(Router *gin.Engine) {
|
||||
address := fmt.Sprintf(":%d", config.GinVueAdminconfig.System.Addr)
|
||||
s := &http.Server{
|
||||
Addr: address,
|
||||
Handler: Router,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
log.L.Debug("server run success on ", address)
|
||||
|
||||
fmt.Printf(`欢迎使用 Gin-Vue-Admin
|
||||
作者:奇淼 And Spike666
|
||||
微信:shouzi_1994
|
||||
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
|
||||
默认前端文件运行地址:http://127.0.0.1:8080
|
||||
`, s.Addr)
|
||||
_ = s.ListenAndServe()
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
MysqlAdmin MysqlAdmin `json:"mysqlAdmin"`
|
||||
Qiniu Qiniu `json:"qiniu"`
|
||||
CasbinConfig CasbinConfig `json:"casbinConfig"`
|
||||
RedisAdmin RedisAdmin `json:"redisAdmin"`
|
||||
System System `json:"system"`
|
||||
JWT JWT `json:"jwt"`
|
||||
Captcha Captcha `json:"captcha"`
|
||||
Log Log `json:"log"`
|
||||
}
|
||||
|
||||
type System struct { // 系统配置
|
||||
UseMultipoint bool `json:"useMultipoint"`
|
||||
Env string `json:"env"`
|
||||
Addr int `json:"addr"`
|
||||
}
|
||||
|
||||
type JWT struct { // jwt签名
|
||||
SigningKey string `json:"signingKey"`
|
||||
}
|
||||
|
||||
type CasbinConfig struct { //casbin配置
|
||||
ModelPath string `json:"modelPath"` // casbin model地址配置
|
||||
}
|
||||
|
||||
type MysqlAdmin struct { // mysql admin 数据库配置
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Path string `json:"path"`
|
||||
Dbname string `json:"dbname"`
|
||||
Config string `json:"config"`
|
||||
MaxIdleConns int `json:"maxIdleConns"`
|
||||
MaxOpenConns int `json:"maxOpenConns"`
|
||||
LogMode bool `json:"maxOpenConns"`
|
||||
}
|
||||
|
||||
type RedisAdmin struct { // Redis admin 数据库配置
|
||||
Addr string `json:"addr"`
|
||||
Password string `json:"password"`
|
||||
DB int `json:"db"`
|
||||
}
|
||||
type Qiniu struct { // 七牛 密钥配置
|
||||
AccessKey string `json:"accessKey"`
|
||||
SecretKey string `json:"secretKey"`
|
||||
}
|
||||
|
||||
type Captcha struct { // 验证码配置
|
||||
KeyLong int `json:"keyLong"`
|
||||
ImgWidth int `json:"imgWidth"`
|
||||
ImgHeight int `json:"imgHeight"`
|
||||
}
|
||||
|
||||
/**
|
||||
Log Config
|
||||
|
||||
"CRITICAL"
|
||||
"ERROR"
|
||||
"WARNING"
|
||||
"NOTICE"
|
||||
"INFO"
|
||||
"DEBUG"
|
||||
*/
|
||||
type Log struct {
|
||||
// log 打印的前缀
|
||||
Prefix string `json:"prefix"`
|
||||
// 是否显示打印log的文件具体路径
|
||||
LogFile bool `json:"logFile"`
|
||||
// 在控制台打印log的级别, []默认不打印
|
||||
Stdout []string `json:"stdout"`
|
||||
// 在文件中打印log的级别 []默认不打印
|
||||
File []string `json:"file"`
|
||||
}
|
||||
|
||||
var GinVueAdminconfig Config
|
||||
var VTool *viper.Viper
|
||||
|
||||
func init() {
|
||||
v := viper.New()
|
||||
v.SetConfigName("config") // 设置配置文件名 (不带后缀)
|
||||
v.AddConfigPath("./static/config/") // 第一个搜索路径
|
||||
v.SetConfigType("json")
|
||||
err := v.ReadInConfig() // 搜索路径,并读取配置数据
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||
}
|
||||
v.WatchConfig()
|
||||
v.OnConfigChange(func(e fsnotify.Event) {
|
||||
fmt.Println("config file changed:", e.Name)
|
||||
if err := v.Unmarshal(&GinVueAdminconfig); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
})
|
||||
if err := v.Unmarshal(&GinVueAdminconfig); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
VTool = v
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/dbModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 断点续传到服务器
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "断点续传示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /fileUploadAndDownload/breakpointContinue [post]
|
||||
func BreakpointContinue(c *gin.Context) {
|
||||
fileMd5 := c.Request.FormValue("fileMd5")
|
||||
fileName := c.Request.FormValue("fileName")
|
||||
chunkMd5 := c.Request.FormValue("chunkMd5")
|
||||
chunkNumber, _ := strconv.Atoi(c.Request.FormValue("chunkNumber"))
|
||||
chunkTotal, _ := strconv.Atoi(c.Request.FormValue("chunkTotal"))
|
||||
_, FileHeader, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
f, err := FileHeader.Open()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
cen, _ := ioutil.ReadAll(f)
|
||||
defer f.Close()
|
||||
if flag := servers.CheckMd5(cen, chunkMd5); flag {
|
||||
err, file := new(dbModel.ExaFile).FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
err, pathc := servers.BreakPointContinue(cen, fileName, chunkNumber, chunkTotal, fileMd5)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
err = file.CreateFileChunk(pathc, chunkNumber)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "切片创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "查找文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func FindFile(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
chunkTotal, _ := strconv.Atoi(c.Query("chunkTotal"))
|
||||
err, file := new(dbModel.ExaFile).FindOrCreateFile(fileMd5, fileName, chunkTotal)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("查找失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "查找成功", gin.H{"file": file})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 查找文件
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "查找文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/findFile [post]
|
||||
func BreakpointContinueFinish(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
err, filePath := servers.MakeFile(fileName, fileMd5)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, true, fmt.Sprintf("文件创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "文件创建成功", gin.H{"filePath": filePath})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除切片
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "查找文件"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
|
||||
// @Router /fileUploadAndDownload/removeChunk [post]
|
||||
func RemoveChunk(c *gin.Context) {
|
||||
fileMd5 := c.Query("fileMd5")
|
||||
fileName := c.Query("fileName")
|
||||
filePath := c.Query("filePath")
|
||||
err := servers.RemoveChunk(fileMd5)
|
||||
err = new(dbModel.ExaFile).DeleteFileChunk(fileMd5, fileName, filePath)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, true, fmt.Sprintf("缓存切片删除失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "缓存切片删除成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/middleware"
|
||||
"gin-vue-admin/model/dbModel"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.ExaCustomer true "创建客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/createExaCustomer [post]
|
||||
func CreateExaCustomer(c *gin.Context) {
|
||||
var cu dbModel.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*middleware.CustomClaims)
|
||||
cu.SysUserID = waitUse.ID
|
||||
cu.SysUserAuthorityID = waitUse.AuthorityId
|
||||
err := cu.CreateExaCustomer()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 删除客户
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.ExaCustomer true "删除客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/deleteExaCustomer [post]
|
||||
func DeleteExaCustomer(c *gin.Context) {
|
||||
var cu dbModel.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
err := cu.DeleteExaCustomer()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 更新客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.ExaCustomer true "创建客户"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/updataExaCustomer [post]
|
||||
func UpdataExaCustomer(c *gin.Context) {
|
||||
var cu dbModel.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
err := cu.UpdataExaCustomer()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取单一客户信息
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.ExaCustomer true "获取单一客户信息"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/getExaCustomer [post]
|
||||
func GetExaCustomer(c *gin.Context) {
|
||||
var cu dbModel.ExaCustomer
|
||||
_ = c.ShouldBindJSON(&cu)
|
||||
err, customer := cu.GetExaCustomer()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{
|
||||
"customer": customer,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取权限客户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "获取权限客户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /customer/getExaCustomerList [post]
|
||||
func GetExaCustomerList(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*middleware.CustomClaims)
|
||||
var cu dbModel.ExaCustomer
|
||||
cu.SysUserAuthorityID = waitUse.AuthorityId
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, customerList, total := cu.GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{
|
||||
"customer": customerList,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/dbModel"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/gin-gonic/gin"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 上传文件示例
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param file formData file true "上传文件示例"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /fileUploadAndDownload/upload [post]
|
||||
func UploadFile(c *gin.Context) {
|
||||
noSave := c.DefaultQuery("noSave", "0")
|
||||
_, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("上传文件失败,%v", err), gin.H{})
|
||||
} else {
|
||||
//文件上传后拿到文件路径
|
||||
err, filePath, key := servers.Upload(header, USER_HEADER_BUCKET, USER_HEADER_IMG_PATH)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("接收返回值失败,%v", err), gin.H{})
|
||||
} else {
|
||||
//修改数据库后得到修改后的user并且返回供前端使用
|
||||
var file dbModel.ExaFileUploadAndDownload
|
||||
file.Url = filePath
|
||||
file.Name = header.Filename
|
||||
s := strings.Split(file.Name, ".")
|
||||
file.Tag = s[len(s)-1]
|
||||
file.Key = key
|
||||
if noSave == "0" {
|
||||
err = file.Upload()
|
||||
}
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("修改数据库链接失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "上传成功", gin.H{"file": file})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 删除文件
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body dbModel.ExaFileUploadAndDownload true "传入文件里面id即可"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /fileUploadAndDownload/deleteFile [post]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
var file dbModel.ExaFileUploadAndDownload
|
||||
_ = c.ShouldBindJSON(&file)
|
||||
err, f := file.FindFile()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败,%v", err), gin.H{})
|
||||
} else {
|
||||
err = servers.DeleteFile(USER_HEADER_BUCKET, f.Key)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败,%v", err), gin.H{})
|
||||
} else {
|
||||
err = f.DeleteFile()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, fmt.Sprintf("删除成功,%v", err), gin.H{})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags ExaFileUploadAndDownload
|
||||
// @Summary 分页文件列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取文件户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /fileUploadAndDownload/getFileList [post]
|
||||
func GetFileList(c *gin.Context) {
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := new(dbModel.ExaFileUploadAndDownload).GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type CreateApiParams struct {
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type DeleteApiParams struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.CreateApiParams true "创建api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/createApi [post]
|
||||
func CreateApi(c *gin.Context) {
|
||||
var api sysModel.SysApi
|
||||
_ = c.ShouldBindJSON(&api)
|
||||
err := api.CreateApi()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 删除指定api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysApi true "删除api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/deleteApi [post]
|
||||
func DeleteApi(c *gin.Context) {
|
||||
var a sysModel.SysApi
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
err := a.DeleteApi()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "删除成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
type AuthAndPathIn struct {
|
||||
AuthorityId string `json:"authorityId"`
|
||||
ApiIds []uint `json:"apiIds"`
|
||||
}
|
||||
|
||||
//条件搜索后端看此api
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 分页获取API列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取API列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getApiList [post]
|
||||
func GetApiList(c *gin.Context) {
|
||||
// 此结构体仅本方法使用
|
||||
type searchParams struct {
|
||||
sysModel.SysApi
|
||||
modelInterface.PageInfo
|
||||
}
|
||||
var sp searchParams
|
||||
_ = c.ShouldBindJSON(&sp)
|
||||
err, list, total := sp.SysApi.GetInfoList(sp.PageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"page": sp.PageInfo.Page,
|
||||
"pageSize": sp.PageInfo.PageSize,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 根据id获取api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getApiById [post]
|
||||
func GetApiById(c *gin.Context) {
|
||||
var idInfo GetById
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
err, api := new(sysModel.SysApi).GetApiById(idInfo.Id)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"api": api,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 创建基础api
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.CreateApiParams true "创建api"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/updataApi [post]
|
||||
func UpdataApi(c *gin.Context) {
|
||||
var api sysModel.SysApi
|
||||
_ = c.ShouldBindJSON(&api)
|
||||
err := api.UpdataApi()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("修改数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "修改数据成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 获取所有的Api 不分页
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getAllApis [post]
|
||||
func GetAllApis(c *gin.Context) {
|
||||
err, apis := new(sysModel.SysApi).GetAllApis()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"apis": apis,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 创建角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysAuthority true "创建角色"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/createAuthority [post]
|
||||
func CreateAuthority(c *gin.Context) {
|
||||
var auth sysModel.SysAuthority
|
||||
_ = c.ShouldBindJSON(&auth)
|
||||
err, authBack := auth.CreateAuthority()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{
|
||||
"authority": authBack,
|
||||
})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{
|
||||
"authority": authBack,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 删除角色
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysAuthority true "删除角色"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/deleteAuthority [post]
|
||||
func DeleteAuthority(c *gin.Context) {
|
||||
var a sysModel.SysAuthority
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
//删除角色之前需要判断是否有用户正在使用此角色
|
||||
err := a.DeleteAuthority()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "删除成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 分页获取角色列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /authority/getAuthorityList [post]
|
||||
func GetAuthorityList(c *gin.Context) {
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := new(sysModel.SysAuthority).GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authority
|
||||
// @Summary 设置角色资源权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysAuthority true "设置角色资源权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
|
||||
// @Router /authority/setDataAuthority [post]
|
||||
func SetDataAuthority(c *gin.Context) {
|
||||
var auth sysModel.SysAuthority
|
||||
_ = c.ShouldBindJSON(&auth)
|
||||
err := auth.SetDataAuthority()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("设置关联失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "设置关联成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/autoCodeModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
"os"
|
||||
)
|
||||
|
||||
// @Tags SysApi
|
||||
// @Summary 自动代码模板
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body autoCodeModel.AutoCodeStruct true "创建自动代码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
|
||||
// @Router /autoCode/createTemp [post]
|
||||
func CreateTemp(c *gin.Context) {
|
||||
var a autoCodeModel.AutoCodeStruct
|
||||
_ = c.ShouldBindJSON(&a)
|
||||
err := a.CreateTemp()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
os.Remove("./ginvueadmin.zip")
|
||||
} else {
|
||||
c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", "ginvueadmin.zip")) //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名
|
||||
c.Writer.Header().Add("Content-Type", "application/json")
|
||||
c.Writer.Header().Add("success", "true")
|
||||
c.File("./ginvueadmin.zip")
|
||||
os.Remove("./ginvueadmin.zip")
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"github.com/dchest/captcha"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 获取图片验证码id
|
||||
// @Tags base
|
||||
// @Summary 生成验证码
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /base/captcha [post]
|
||||
func Captcha(c *gin.Context) {
|
||||
captchaId := captcha.NewLen(config.GinVueAdminconfig.Captcha.KeyLong)
|
||||
servers.ReportFormat(c, true, "验证码获取成功", gin.H{
|
||||
"captchaId": captchaId,
|
||||
"picPath": "/base/captcha/" + captchaId + ".png",
|
||||
})
|
||||
}
|
||||
|
||||
// @Tags base
|
||||
// @Summary 生成验证码图片路径
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /base/captcha/:captchaId [get]
|
||||
func CaptchaImg(c *gin.Context) {
|
||||
servers.GinCapthcaServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary 更改角色api权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.CasbinInReceive true "更改角色api权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/casbinPUpdata [post]
|
||||
func CasbinPUpdata(c *gin.Context) {
|
||||
var cmr sysModel.CasbinInReceive
|
||||
_ = c.ShouldBindJSON(&cmr)
|
||||
err := new(sysModel.CasbinModel).CasbinPUpdata(cmr.AuthorityId, cmr.CasbinInfos)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("添加规则失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "添加规则成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary 获取权限列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.CreateAuthorityParams true "获取权限列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/getPolicyPathByAuthorityId [post]
|
||||
func GetPolicyPathByAuthorityId(c *gin.Context) {
|
||||
var cmr sysModel.CasbinInReceive
|
||||
_ = c.ShouldBindJSON(&cmr)
|
||||
paths := new(sysModel.CasbinModel).GetPolicyPathByAuthorityId(cmr.AuthorityId)
|
||||
servers.ReportFormat(c, true, "获取规则成功", gin.H{"paths": paths})
|
||||
}
|
||||
|
||||
// @Tags casbin
|
||||
// @Summary casb RBAC RESTFUL测试路由
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.CreateAuthorityParams true "获取权限列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /casbin/CasbinTest [get]
|
||||
func CasbinTest(c *gin.Context) {
|
||||
// 测试restful以及占位符代码 随意书写
|
||||
pathParam := c.Param("pathParam")
|
||||
query := c.Query("query")
|
||||
servers.ReportFormat(c, true, "获取规则成功", gin.H{"pathParam": pathParam, "query": query})
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags jwt
|
||||
// @Summary jwt加入黑名单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"拉黑成功"}"
|
||||
// @Router /jwt/jsonInBlacklist [post]
|
||||
func JsonInBlacklist(c *gin.Context){
|
||||
token := c.Request.Header.Get("x-token")
|
||||
ModelJwt := sysModel.JwtBlacklist{
|
||||
Jwt:token,
|
||||
}
|
||||
err := ModelJwt.JsonInBlacklist()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("jwt作废失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "jwt作废成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/middleware"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body api.RegistAndLoginStuct true "可以什么都不填"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /menu/getMenu [post]
|
||||
func GetMenu(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*middleware.CustomClaims)
|
||||
err, menus := new(sysModel.SysMenu).GetMenuTree(waitUse.AuthorityId)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{"menus": menus})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 分页获取基础menu列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取基础menu列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/getMenuList [post]
|
||||
func GetMenuList(c *gin.Context) {
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, menuList, total := new(sysModel.SysBaseMenu).GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"list": menuList,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 新增菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysBaseMenu true "新增菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/addBaseMenu [post]
|
||||
func AddBaseMenu(c *gin.Context) {
|
||||
var addMenu sysModel.SysBaseMenu
|
||||
_ = c.ShouldBindJSON(&addMenu)
|
||||
err := addMenu.AddBaseMenu()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("添加失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, fmt.Sprintf("添加成功,%v", err), gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取用户动态路由
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body api.RegistAndLoginStuct true "可以什么都不填"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /menu/getBaseMenuTree [post]
|
||||
func GetBaseMenuTree(c *gin.Context) {
|
||||
err, menus := new(sysModel.SysBaseMenu).GetBaseMenuTree()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{"menus": menus})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
|
||||
}
|
||||
}
|
||||
|
||||
type AddMenuAuthorityInfo struct {
|
||||
Menus []sysModel.SysBaseMenu
|
||||
AuthorityId string
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 增加menu和角色关联关系
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.AddMenuAuthorityInfo true "增加menu和角色关联关系"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/addMenuAuthority [post]
|
||||
func AddMenuAuthority(c *gin.Context) {
|
||||
var addMenuAuthorityInfo AddMenuAuthorityInfo
|
||||
_ = c.ShouldBindJSON(&addMenuAuthorityInfo)
|
||||
err := new(sysModel.SysMenu).AddMenuAuthority(addMenuAuthorityInfo.Menus, addMenuAuthorityInfo.AuthorityId)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("添加失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, fmt.Sprintf("添加成功,%v", err), gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
type AuthorityIdInfo struct {
|
||||
AuthorityId string
|
||||
}
|
||||
|
||||
// @Tags authorityAndMenu
|
||||
// @Summary 获取指定角色menu
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.AuthorityIdInfo true "增加menu和角色关联关系"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/addMenuAuthority [post]
|
||||
func GetMenuAuthority(c *gin.Context) {
|
||||
var authorityIdInfo AuthorityIdInfo
|
||||
_ = c.ShouldBindJSON(&authorityIdInfo)
|
||||
err, menus := new(sysModel.SysMenu).GetMenuAuthority(authorityIdInfo.AuthorityId)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{"menus": menus})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
|
||||
}
|
||||
}
|
||||
|
||||
type IdInfo struct {
|
||||
Id float64
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 删除菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.IdInfo true "删除菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/deleteBaseMenu [post]
|
||||
func DeleteBaseMenu(c *gin.Context) {
|
||||
var idInfo IdInfo
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
err := new(sysModel.SysBaseMenu).DeleteBaseMenu(idInfo.Id)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "删除成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 更新菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysBaseMenu true "更新菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/updataBaseMen [post]
|
||||
func UpdataBaseMenu(c *gin.Context) {
|
||||
var menu sysModel.SysBaseMenu
|
||||
_ = c.ShouldBindJSON(&menu)
|
||||
err := menu.UpdataBaseMenu()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("修改失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "修改成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
type GetById struct {
|
||||
Id float64 `json:"id"`
|
||||
}
|
||||
|
||||
// @Tags menu
|
||||
// @Summary 根据id获取菜单
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.GetById true "根据id获取菜单"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /menu/getBaseMenuById [post]
|
||||
func GetBaseMenuById(c *gin.Context) {
|
||||
var idInfo GetById
|
||||
_ = c.ShouldBindJSON(&idInfo)
|
||||
err, menu := new(sysModel.SysBaseMenu).GetBaseMenuById(idInfo.Id)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("查询失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "查询成功", gin.H{"menu": menu})
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags system
|
||||
// @Summary 获取配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/getSystemConfig [post]
|
||||
func GetSystemConfig(c *gin.Context) {
|
||||
err, config := new(sysModel.System).GetSystemConfig()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取成功", gin.H{"config": config})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags system
|
||||
// @Summary 设置配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.System true "设置配置文件内容"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/setSystemConfig [post]
|
||||
func SetSystemConfig(c *gin.Context) {
|
||||
var sys sysModel.System
|
||||
_ = c.ShouldBindJSON(&sys)
|
||||
err := sys.SetSystemConfig()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("设置失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "设置成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//本方法开发中 开发者windows系统 缺少linux系统所需的包 因此搁置
|
||||
// @Tags system
|
||||
// @Summary 设置配置文件内容
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.System true "设置配置文件内容"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}"
|
||||
// @Router /system/ReloadSystem [post]
|
||||
func ReloadSystem(c *gin.Context) {
|
||||
var sys sysModel.System
|
||||
_ = c.ShouldBindJSON(&sys)
|
||||
err := sys.SetSystemConfig()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("设置失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "设置成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/middleware"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/dchest/captcha"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
USER_HEADER_IMG_PATH string = "http://qmplusimg.henrongyi.top"
|
||||
USER_HEADER_BUCKET string = "qm-plus-img"
|
||||
)
|
||||
|
||||
type RegistAndLoginStuct struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Captcha string `json:"captcha"`
|
||||
CaptchaId string `json:"captchaId"`
|
||||
}
|
||||
|
||||
type RegestStuct struct {
|
||||
Username string `json:"userName"`
|
||||
Password string `json:"passWord"`
|
||||
NickName string `json:"nickName" gorm:"default:'QMPlusUser'"`
|
||||
HeaderImg string `json:"headerImg" gorm:"default:'http://www.henrongyi.top/avatar/lufu.jpg'"`
|
||||
AuthorityId string `json:"authorityId" gorm:"default:888"`
|
||||
}
|
||||
|
||||
// @Tags Base
|
||||
// @Summary 用户注册账号
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysUser true "用户注册接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
|
||||
// @Router /base/regist [post]
|
||||
func Regist(c *gin.Context) {
|
||||
var R RegestStuct
|
||||
_ = c.ShouldBindJSON(&R)
|
||||
user := &sysModel.SysUser{Username: R.Username, NickName: R.NickName, Password: R.Password, HeaderImg: R.HeaderImg, AuthorityId: R.AuthorityId}
|
||||
err, user := user.Regist()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{
|
||||
"user": user,
|
||||
})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{
|
||||
"user": user,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags Base
|
||||
// @Summary 用户登录
|
||||
// @Produce application/json
|
||||
// @Param data body api.RegistAndLoginStuct true "用户登录接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"登陆成功"}"
|
||||
// @Router /base/login [post]
|
||||
func Login(c *gin.Context) {
|
||||
var L RegistAndLoginStuct
|
||||
_ = c.ShouldBindJSON(&L)
|
||||
if captcha.VerifyString(L.CaptchaId, L.Captcha) {
|
||||
U := &sysModel.SysUser{Username: L.Username, Password: L.Password}
|
||||
if err, user := U.Login(); err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("用户名密码错误或%v", err), gin.H{})
|
||||
} else {
|
||||
tokenNext(c, *user)
|
||||
}
|
||||
} else {
|
||||
servers.ReportFormat(c, false, "验证码错误", gin.H{})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//登录以后签发jwt
|
||||
func tokenNext(c *gin.Context, user sysModel.SysUser) {
|
||||
j := &middleware.JWT{
|
||||
[]byte(config.GinVueAdminconfig.JWT.SigningKey), // 唯一签名
|
||||
}
|
||||
clams := middleware.CustomClaims{
|
||||
UUID: user.UUID,
|
||||
ID: user.ID,
|
||||
NickName: user.NickName,
|
||||
AuthorityId: user.AuthorityId,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
NotBefore: int64(time.Now().Unix() - 1000), // 签名生效时间
|
||||
ExpiresAt: int64(time.Now().Unix() + 60*60*24*7), // 过期时间 一周
|
||||
Issuer: "qmPlus", //签名的发行者
|
||||
},
|
||||
}
|
||||
token, err := j.CreateToken(clams)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, "获取token失败", gin.H{})
|
||||
} else {
|
||||
if config.GinVueAdminconfig.System.UseMultipoint {
|
||||
var loginJwt sysModel.JwtBlacklist
|
||||
loginJwt.Jwt = token
|
||||
err, jwtStr := loginJwt.GetRedisJWT(user.Username)
|
||||
if err == redis.Nil {
|
||||
err2 := loginJwt.SetRedisJWT(user.Username)
|
||||
if err2 != nil {
|
||||
servers.ReportFormat(c, false, "设置登录状态失败", gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
|
||||
}
|
||||
} else if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("%v", err), gin.H{})
|
||||
} else {
|
||||
var blackjWT sysModel.JwtBlacklist
|
||||
blackjWT.Jwt = jwtStr
|
||||
err3 := blackjWT.JsonInBlacklist()
|
||||
if err3 != nil {
|
||||
servers.ReportFormat(c, false, "jwt作废失败", gin.H{})
|
||||
} else {
|
||||
err2 := loginJwt.SetRedisJWT(user.Username)
|
||||
if err2 != nil {
|
||||
servers.ReportFormat(c, false, "设置登录状态失败", gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "登录成功", gin.H{"user": user, "token": token, "expiresAt": clams.StandardClaims.ExpiresAt * 1000})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ChangePasswordStutrc struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 用户修改密码
|
||||
// @Security ApiKeyAuth
|
||||
// @Produce application/json
|
||||
// @Param data body api.ChangePasswordStutrc true "用户修改密码"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
|
||||
// @Router /user/changePassword [post]
|
||||
func ChangePassword(c *gin.Context) {
|
||||
var params ChangePasswordStutrc
|
||||
_ = c.ShouldBindJSON(¶ms)
|
||||
U := &sysModel.SysUser{Username: params.Username, Password: params.Password}
|
||||
if err, _ := U.ChangePassword(params.NewPassword); err != nil {
|
||||
servers.ReportFormat(c, false, "修改失败,请检查用户名密码", gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "修改成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
type UserHeaderImg struct {
|
||||
HeaderImg multipart.File `json:"headerImg"`
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 用户上传头像
|
||||
// @Security ApiKeyAuth
|
||||
// @accept multipart/form-data
|
||||
// @Produce application/json
|
||||
// @Param headerImg formData file true "用户上传头像"
|
||||
// @Param username formData string true "用户上传头像"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
|
||||
// @Router /user/uploadHeaderImg [post]
|
||||
func UploadHeaderImg(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
//获取头像文件
|
||||
// 这里我们通过断言获取 claims内的所有内容
|
||||
waitUse := claims.(*middleware.CustomClaims)
|
||||
uuid := waitUse.UUID
|
||||
_, header, err := c.Request.FormFile("headerImg")
|
||||
//便于找到用户 以后从jwt中取
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("上传文件失败,%v", err), gin.H{})
|
||||
} else {
|
||||
//文件上传后拿到文件路径
|
||||
err, filePath, _ := servers.Upload(header, USER_HEADER_BUCKET, USER_HEADER_IMG_PATH)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("接收返回值失败,%v", err), gin.H{})
|
||||
} else {
|
||||
//修改数据库后得到修改后的user并且返回供前端使用
|
||||
err, user := new(sysModel.SysUser).UploadHeaderImg(uuid, filePath)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("修改数据库链接失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "上传成功", gin.H{"user": user})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 分页获取用户列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /user/getUserList [post]
|
||||
func GetUserList(c *gin.Context) {
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := new(sysModel.SysUser).GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"userList": list,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type SetUserAuth struct {
|
||||
UUID uuid.UUID `json:"uuid"`
|
||||
AuthorityId string `json:"authorityId"`
|
||||
}
|
||||
|
||||
// @Tags SysUser
|
||||
// @Summary 设置用户权限
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body api.SetUserAuth true "设置用户权限"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}"
|
||||
// @Router /user/setUserAuthority [post]
|
||||
func SetUserAuthority(c *gin.Context) {
|
||||
var sua SetUserAuth
|
||||
_ = c.ShouldBindJSON(&sua)
|
||||
err := new(sysModel.SysUser).SetUserAuthority(sua.UUID, sua.AuthorityId)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("修改失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "修改成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// @Tags workflow
|
||||
// @Summary 注册工作流
|
||||
// @Produce application/json
|
||||
// @Param data body sysModel.SysWorkflow true "注册工作流接口"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"注册成功"}"
|
||||
// @Router /workflow/createWorkFlow [post]
|
||||
func CreateWorkFlow(c *gin.Context) {
|
||||
var wk sysModel.SysWorkflow
|
||||
_ = c.ShouldBindJSON(&wk)
|
||||
err := wk.Create()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取成功", gin.H{})
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"gin-vue-admin/config"
|
||||
"github.com/dchest/captcha"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 这里需要自行实现captcha 的gin模式
|
||||
func GinCapthcaServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
dir, file := path.Split(r.URL.Path)
|
||||
ext := path.Ext(file)
|
||||
id := file[:len(file)-len(ext)]
|
||||
if ext == "" || id == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
fmt.Println("reload : " + r.FormValue("reload"))
|
||||
if r.FormValue("reload") != "" {
|
||||
captcha.Reload(id)
|
||||
}
|
||||
lang := strings.ToLower(r.FormValue("lang"))
|
||||
download := path.Base(dir) == "download"
|
||||
if Serve(w, r, id, ext, lang, download, config.GinVueAdminconfig.Captcha.ImgWidth, config.GinVueAdminconfig.Captcha.ImgHeight) == captcha.ErrNotFound {
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func Serve(w http.ResponseWriter, r *http.Request, id, ext, lang string, download bool, width, height int) error {
|
||||
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||
w.Header().Set("Pragma", "no-cache")
|
||||
w.Header().Set("Expires", "0")
|
||||
var content bytes.Buffer
|
||||
switch ext {
|
||||
case ".png":
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
captcha.WriteImage(&content, id, width, height)
|
||||
case ".wav":
|
||||
w.Header().Set("Content-Type", "audio/x-wav")
|
||||
captcha.WriteAudio(&content, id, lang)
|
||||
default:
|
||||
return captcha.ErrNotFound
|
||||
}
|
||||
|
||||
if download {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
}
|
||||
http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes()))
|
||||
return nil
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//获取分页功能 接收实现了分页接口的结构体 返回搜索完成的结果 许需要自行scan 或者find
|
||||
func PagingServer(paging modelInterface.Paging, info modelInterface.PageInfo) (err error, db *gorm.DB, total int) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
err = qmsql.DEFAULTDB.Model(paging).Count(&total).Error
|
||||
db = qmsql.DEFAULTDB.Limit(limit).Offset(offset).Order("id desc")
|
||||
return err, db, total
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ReportFormat(c *gin.Context, success bool, msg string, json gin.H) {
|
||||
// 开始时间
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": success,
|
||||
"msg": msg,
|
||||
"data": json,
|
||||
})
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
module gin-vue-admin
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
||||
github.com/casbin/casbin v1.9.1
|
||||
github.com/casbin/gorm-adapter v1.0.0
|
||||
github.com/dchest/captcha v0.0.0-20170622155422-6a29415a8364
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/gin-gonic/gin v1.6.1
|
||||
github.com/go-openapi/spec v0.19.7 // indirect
|
||||
github.com/go-openapi/swag v0.19.8 // indirect
|
||||
github.com/go-redis/redis v6.15.7+incompatible
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/golang/protobuf v1.3.5 // indirect
|
||||
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
|
||||
github.com/jinzhu/gorm v1.9.12
|
||||
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect
|
||||
github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
|
||||
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
|
||||
github.com/lib/pq v1.3.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.2.2 // indirect
|
||||
github.com/onsi/ginkgo v1.7.0 // indirect
|
||||
github.com/onsi/gomega v1.4.3 // indirect
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/pelletier/go-toml v1.6.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/qiniu/api.v7 v7.2.5+incompatible
|
||||
github.com/qiniu/x v7.0.8+incompatible // indirect
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/spf13/afero v1.2.2 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.6.2
|
||||
github.com/swaggo/gin-swagger v1.2.0
|
||||
github.com/swaggo/swag v1.6.5
|
||||
github.com/tebeka/strftime v0.1.3 // indirect
|
||||
github.com/unrolled/secure v1.0.7
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 // indirect
|
||||
golang.org/x/net v0.0.0-20200320220750-118fecf932d8 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
|
||||
golang.org/x/tools v0.0.0-20200324003944-a576cf524670 // indirect
|
||||
gopkg.in/ini.v1 v1.55.0 // indirect
|
||||
qiniupkg.com/x v7.0.8+incompatible // indirect
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
package initRedis
|
||||
|
||||
import (
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/initlog"
|
||||
"github.com/go-redis/redis"
|
||||
)
|
||||
|
||||
var DEFAULTREDIS *redis.Client
|
||||
|
||||
func InitRedis() (client *redis.Client) {
|
||||
client = redis.NewClient(&redis.Options{
|
||||
Addr: config.GinVueAdminconfig.RedisAdmin.Addr,
|
||||
Password: config.GinVueAdminconfig.RedisAdmin.Password, // no password set
|
||||
DB: config.GinVueAdminconfig.RedisAdmin.DB, // use default DB
|
||||
})
|
||||
pong, err := client.Ping().Result()
|
||||
if err != nil {
|
||||
log.L.Error(err)
|
||||
} else {
|
||||
log.L.Info("redis connect ping response:", pong)
|
||||
DEFAULTREDIS = client
|
||||
}
|
||||
return client
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package log
|
||||
|
||||
// Custom Logger
|
||||
type Logger interface {
|
||||
Debug(v ...interface{})
|
||||
Info(v ...interface{})
|
||||
Warning(v ...interface{})
|
||||
Error(v ...interface{})
|
||||
Critical(v ...interface{})
|
||||
Fatal(v ...interface{})
|
||||
}
|
||||
|
||||
var L Logger
|
||||
|
||||
func SetLogger(logger Logger) {
|
||||
L = logger
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package qmlog
|
||||
|
||||
// Register logger
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/initlog"
|
||||
"gin-vue-admin/tools"
|
||||
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
|
||||
oplogging "github.com/op/go-logging"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
logDir = "log"
|
||||
logSoftLink = "api.log"
|
||||
module = "gin-vue-admin"
|
||||
)
|
||||
|
||||
var (
|
||||
configNotFound = errors.New("logger prefix not found")
|
||||
|
||||
defaultFormatter = `%{time:2006/01/02 - 15:04:05.000} %{longfile} %{color:bold}▶ [%{level:.6s}] %{message}%{color:reset}`
|
||||
)
|
||||
|
||||
type Logger struct{
|
||||
logger *oplogging.Logger
|
||||
}
|
||||
|
||||
func NewLogger() error {
|
||||
c := config.GinVueAdminconfig.Log
|
||||
if c.Prefix == "" {
|
||||
return configNotFound
|
||||
}
|
||||
logger := oplogging.MustGetLogger(module)
|
||||
var backends []oplogging.Backend
|
||||
backends = registerStdout(c, backends)
|
||||
backends = registerFile(c, backends)
|
||||
|
||||
oplogging.SetBackend(backends...)
|
||||
log.SetLogger(logger)
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerStdout(c config.Log, backends []oplogging.Backend) []oplogging.Backend {
|
||||
for _, v := range c.Stdout {
|
||||
level, err := oplogging.LogLevel(v)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
backends = append(backends, createBackend(os.Stdout, c, level))
|
||||
}
|
||||
|
||||
return backends
|
||||
}
|
||||
|
||||
func registerFile(c config.Log, backends []oplogging.Backend) []oplogging.Backend {
|
||||
if len(c.File) > 0 {
|
||||
if ok, _ := tools.PathExists(logDir); !ok {
|
||||
// directory not exist
|
||||
fmt.Println("create log directory")
|
||||
_ = os.Mkdir(logDir, os.ModePerm)
|
||||
}
|
||||
apiLogPath := logDir + string(os.PathSeparator) + logSoftLink
|
||||
fileWriter, err := rotatelogs.New(
|
||||
apiLogPath+".%Y-%m-%d-%H-%M.log",
|
||||
// generate soft link, point to latest log file
|
||||
rotatelogs.WithLinkName(apiLogPath),
|
||||
// maximum time to save log files
|
||||
rotatelogs.WithMaxAge(7*24*time.Hour),
|
||||
// time period of log file switching
|
||||
rotatelogs.WithRotationTime(24*time.Hour),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return backends
|
||||
}
|
||||
for _, v := range c.File {
|
||||
level, err := oplogging.LogLevel(v)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
backends = append(backends, createBackend(fileWriter, c, level))
|
||||
}
|
||||
}
|
||||
|
||||
return backends
|
||||
}
|
||||
|
||||
func createBackend(w io.Writer, c config.Log, level oplogging.Level) oplogging.Backend {
|
||||
backend := oplogging.NewLogBackend(w, c.Prefix, 0)
|
||||
stdoutWriter := false
|
||||
if w == os.Stdout {
|
||||
stdoutWriter = true
|
||||
}
|
||||
format := getLogFormatter(c, stdoutWriter)
|
||||
backendLeveled := oplogging.AddModuleLevel(oplogging.NewBackendFormatter(backend, format))
|
||||
backendLeveled.SetLevel(level, module)
|
||||
return backendLeveled
|
||||
}
|
||||
|
||||
func getLogFormatter(c config.Log, stdoutWriter bool) oplogging.Formatter {
|
||||
pattern := defaultFormatter
|
||||
if !stdoutWriter {
|
||||
// Color is only required for console output
|
||||
// Other writers don't need %{color} tag
|
||||
pattern = strings.Replace(pattern, "%{color:bold}", "", -1)
|
||||
pattern = strings.Replace(pattern, "%{color:reset}", "", -1)
|
||||
}
|
||||
if !c.LogFile {
|
||||
// Remove %{logfile} tag
|
||||
pattern = strings.Replace(pattern, "%{longfile}", "", -1)
|
||||
}
|
||||
return oplogging.MustStringFormatter(pattern)
|
||||
}
|
||||
|
||||
func (l Logger) Debug(v ...interface{}) {
|
||||
l.logger.Debug(v)
|
||||
}
|
||||
|
||||
func (l Logger) Info(v ...interface{}) {
|
||||
l.logger.Info(v)
|
||||
}
|
||||
|
||||
func (l Logger) Warning(v ...interface{}) {
|
||||
l.logger.Warning(v)
|
||||
}
|
||||
|
||||
func (l Logger) Error(v ...interface{}) {
|
||||
l.logger.Error(v)
|
||||
}
|
||||
|
||||
func (l Logger) Critical(v ...interface{}) {
|
||||
l.logger.Critical(v)
|
||||
}
|
||||
|
||||
func (l Logger) Fatal(v ...interface{}) {
|
||||
l.logger.Fatal(v)
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package qmsql
|
||||
|
||||
import (
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/initlog"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
)
|
||||
|
||||
var DEFAULTDB *gorm.DB
|
||||
|
||||
//初始化数据库并产生数据库全局变量
|
||||
func InitMysql(admin config.MysqlAdmin) *gorm.DB {
|
||||
if db, err := gorm.Open("mysql", admin.Username+":"+admin.Password+"@("+admin.Path+")/"+admin.Dbname+"?"+admin.Config); err != nil {
|
||||
log.L.Error("DEFAULTDB数据库启动异常",err)
|
||||
} else {
|
||||
DEFAULTDB = db
|
||||
DEFAULTDB.DB().SetMaxIdleConns(admin.MaxIdleConns)
|
||||
DEFAULTDB.DB().SetMaxOpenConns(admin.MaxOpenConns)
|
||||
DEFAULTDB.LogMode(admin.LogMode)
|
||||
}
|
||||
return DEFAULTDB
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package registTable
|
||||
|
||||
import (
|
||||
"gin-vue-admin/init/initlog"
|
||||
"gin-vue-admin/model/dbModel"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//注册数据库表专用
|
||||
func RegistTable(db *gorm.DB) {
|
||||
db.AutoMigrate(sysModel.SysUser{},
|
||||
sysModel.SysAuthority{},
|
||||
sysModel.SysMenu{},
|
||||
sysModel.SysApi{},
|
||||
sysModel.SysBaseMenu{},
|
||||
sysModel.JwtBlacklist{},
|
||||
sysModel.SysWorkflow{},
|
||||
sysModel.SysWorkflowStepInfo{},
|
||||
dbModel.ExaFileUploadAndDownload{},
|
||||
dbModel.ExaFile{},
|
||||
dbModel.ExaFileChunk{},
|
||||
dbModel.ExaCustomer{},
|
||||
)
|
||||
log.L.Debug("register table success")
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gin-vue-admin/cmd"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/initRedis"
|
||||
"gin-vue-admin/init/initRouter"
|
||||
"gin-vue-admin/init/initlog/qmlog"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/init/registTable"
|
||||
"os"
|
||||
//"runtime"
|
||||
)
|
||||
|
||||
// @title Swagger Example API
|
||||
// @version 0.0.1
|
||||
// @description This is a sample Server pets
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name x-token
|
||||
// @BasePath /
|
||||
|
||||
var (
|
||||
mysqlHost = os.Getenv("MYSQLHOST")
|
||||
mysqlPort = os.Getenv("MYSQLPORT")
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := qmlog.NewLogger(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 可以通过环境变量来覆盖配置值
|
||||
// 未设定有效的环境变量时,使用配置值
|
||||
mysqlConfig := config.GinVueAdminconfig.MysqlAdmin
|
||||
if mysqlHost != "" && mysqlPort != "" {
|
||||
mysqlConfig.Path = mysqlHost + ":" + mysqlPort
|
||||
}
|
||||
// 链接初始化数据库
|
||||
db := qmsql.InitMysql(mysqlConfig) // 链接初始化数据库
|
||||
if config.GinVueAdminconfig.System.UseMultipoint {
|
||||
// 初始化redis服务
|
||||
_ = initRedis.InitRedis()
|
||||
}
|
||||
// 注册数据库表
|
||||
registTable.RegistTable(db)
|
||||
// 程序结束前关闭数据库链接
|
||||
defer qmsql.DEFAULTDB.Close()
|
||||
// 注册路由
|
||||
Router := initRouter.InitRouter()
|
||||
|
||||
Router.Static("/form-generator", "./static/form-generator")
|
||||
//Router.RunTLS(":443","ssl.pem", "ssl.key") // https支持 需要添加中间件
|
||||
//sysType := runtime.GOOS
|
||||
//
|
||||
//if sysType == "linux" {
|
||||
// // LINUX系统
|
||||
// // 借助endless开发无感知重启后台 以及前端接口重启后台功能
|
||||
//}
|
||||
//if sysType == "windows" {
|
||||
// WIN系统
|
||||
cmd.RunWindowsServer(Router)
|
||||
//}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//拦截器
|
||||
func CasbinHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
claims, _ := c.Get("claims")
|
||||
waitUse := claims.(*CustomClaims)
|
||||
//获取请求的URI
|
||||
obj := c.Request.URL.RequestURI()
|
||||
//获取请求方法
|
||||
act := c.Request.Method
|
||||
//获取用户的角色
|
||||
sub := waitUse.AuthorityId
|
||||
e := sysModel.Casbin()
|
||||
//判断策略中是否存在
|
||||
if e.Enforce(sub, obj, act) {
|
||||
c.Next()
|
||||
} else {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("权限不足"), gin.H{})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
func JWTAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
|
||||
token := c.Request.Header.Get("x-token")
|
||||
ModelToken := sysModel.JwtBlacklist{
|
||||
Jwt: token,
|
||||
}
|
||||
if token == "" {
|
||||
servers.ReportFormat(c, false, "未登录或非法访问", gin.H{
|
||||
"reload": true,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if ModelToken.IsBlacklist(token) {
|
||||
servers.ReportFormat(c, false, "您的帐户异地登陆或令牌失效", gin.H{
|
||||
"reload": true,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
j := NewJWT()
|
||||
// parseToken 解析token包含的信息
|
||||
claims, err := j.ParseToken(token)
|
||||
if err != nil {
|
||||
if err == TokenExpired {
|
||||
servers.ReportFormat(c, false, "授权已过期", gin.H{
|
||||
"reload": true,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
servers.ReportFormat(c, false, err.Error(), gin.H{
|
||||
"reload": true,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Set("claims", claims)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
type JWT struct {
|
||||
SigningKey []byte
|
||||
}
|
||||
|
||||
var (
|
||||
TokenExpired error = errors.New("Token is expired")
|
||||
TokenNotValidYet error = errors.New("Token not active yet")
|
||||
TokenMalformed error = errors.New("That's not even a token")
|
||||
TokenInvalid error = errors.New("Couldn't handle this token:")
|
||||
)
|
||||
|
||||
type CustomClaims struct {
|
||||
UUID uuid.UUID
|
||||
ID uint
|
||||
NickName string
|
||||
AuthorityId string
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func NewJWT() *JWT {
|
||||
return &JWT{
|
||||
[]byte(config.GinVueAdminconfig.JWT.SigningKey),
|
||||
}
|
||||
}
|
||||
|
||||
//创建一个token
|
||||
func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString(j.SigningKey)
|
||||
}
|
||||
|
||||
//解析 token
|
||||
func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
|
||||
return j.SigningKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
if ve, ok := err.(*jwt.ValidationError); ok {
|
||||
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||
return nil, TokenMalformed
|
||||
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
|
||||
// Token is expired
|
||||
return nil, TokenExpired
|
||||
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
|
||||
return nil, TokenNotValidYet
|
||||
} else {
|
||||
return nil, TokenInvalid
|
||||
}
|
||||
}
|
||||
}
|
||||
if token != nil {
|
||||
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
return nil, TokenInvalid
|
||||
|
||||
} else {
|
||||
return nil, TokenInvalid
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 更新token
|
||||
func (j *JWT) RefreshToken(tokenString string) (string, error) {
|
||||
jwt.TimeFunc = func() time.Time {
|
||||
return time.Unix(0, 0)
|
||||
}
|
||||
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return j.SigningKey, nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
|
||||
jwt.TimeFunc = time.Now
|
||||
claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
|
||||
return j.CreateToken(*claims)
|
||||
}
|
||||
return "", TokenInvalid
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"gin-vue-admin/init/initlog"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Logger() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// request time
|
||||
start := time.Now()
|
||||
// request path
|
||||
path := c.Request.URL.Path
|
||||
logFlag := true
|
||||
if strings.Contains(path, "swagger") {
|
||||
logFlag = false
|
||||
}
|
||||
// request ip
|
||||
clientIP := c.ClientIP()
|
||||
// method
|
||||
method := c.Request.Method
|
||||
// copy request content
|
||||
req, _ := httputil.DumpRequest(c.Request, true)
|
||||
if logFlag {
|
||||
log.L.Debug(
|
||||
"Request:", method, clientIP, path, string(req))
|
||||
}
|
||||
// replace writer
|
||||
cusWriter := &responseBodyWriter{
|
||||
ResponseWriter: c.Writer,
|
||||
body: bytes.NewBufferString(""),
|
||||
}
|
||||
c.Writer = cusWriter
|
||||
// handle request
|
||||
c.Next()
|
||||
// ending time
|
||||
end := time.Now()
|
||||
//execute time
|
||||
latency := end.Sub(start)
|
||||
statusCode := c.Writer.Status()
|
||||
if logFlag {
|
||||
log.L.Debug(
|
||||
"Response:",
|
||||
statusCode,
|
||||
latency,
|
||||
cusWriter.body.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type responseBodyWriter struct {
|
||||
gin.ResponseWriter
|
||||
body *bytes.Buffer
|
||||
}
|
||||
|
||||
func (w responseBodyWriter) Write(b []byte) (int, error) {
|
||||
w.body.Write(b)
|
||||
return w.ResponseWriter.Write(b)
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package autoCodeModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/tools"
|
||||
"html/template"
|
||||
"os"
|
||||
)
|
||||
|
||||
// 初始版本自动化代码工具
|
||||
type AutoCodeStruct struct {
|
||||
StructName string `json:"structName"`
|
||||
PackageName string `json:"packageName"`
|
||||
Abbreviation string `json:"abbreviation"`
|
||||
Fields []Field `json:"fields"`
|
||||
}
|
||||
|
||||
type Field struct {
|
||||
FieldName string `json:"fieldName"`
|
||||
FieldType string `json:"fieldType"`
|
||||
FieldJson string `json:"fieldJson"`
|
||||
ColumnName string `json:"columnName"`
|
||||
}
|
||||
|
||||
func (a *AutoCodeStruct) CreateTemp() (err error) {
|
||||
basePath := "./tpl"
|
||||
modelTmpl, err := template.ParseFiles(basePath + "/te/model.go.tpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiTmpl, err := template.ParseFiles(basePath + "/te/api.go.tpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
routerTmpl, err := template.ParseFiles(basePath + "/te/router.go.tpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
feapiTmpl, err := template.ParseFiles(basePath + "/fe/api.js.tpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readmeTmpl, err := template.ParseFiles(basePath + "/readme.txt.tpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//自动化总目录
|
||||
_autoCode := "./autoCode/"
|
||||
//自动化后台代码目录
|
||||
_te := "./autoCode/te/"
|
||||
_dir := _te + a.PackageName
|
||||
_modeldir := _te + a.PackageName + "/model"
|
||||
_apidir := _te + a.PackageName + "/api"
|
||||
_routerdir := _te + a.PackageName + "/router"
|
||||
//自动化前台代码目录
|
||||
_fe := "./autoCode/fe/"
|
||||
_fe_dir := _fe + a.PackageName
|
||||
_fe_apidir := _fe + a.PackageName + "/api"
|
||||
err = createDir(_autoCode, _te, _dir, _modeldir, _apidir, _routerdir, _fe, _fe_dir, _fe_apidir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
model, err := os.OpenFile(_te+a.PackageName+"/model/model.go", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
api, err := os.OpenFile(_te+a.PackageName+"/api/api.go", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
router, err := os.OpenFile(_te+a.PackageName+"/router/router.go", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
feapi, err := os.OpenFile(_fe+a.PackageName+"/api/api.js", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
readme, err := os.OpenFile(_autoCode+"readme.txt", os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 生成代码
|
||||
{
|
||||
err = modelTmpl.Execute(model, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = apiTmpl.Execute(api, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routerTmpl.Execute(router, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = feapiTmpl.Execute(feapi, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = readmeTmpl.Execute(readme, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_ = model.Close()
|
||||
_ = api.Close()
|
||||
_ = router.Close()
|
||||
_ = feapi.Close()
|
||||
_ = readme.Close()
|
||||
fileList := []string{
|
||||
_te + a.PackageName + "/model/model.go",
|
||||
_te + a.PackageName + "/api/api.go",
|
||||
_te + a.PackageName + "/router/router.go",
|
||||
_fe + a.PackageName + "/api/api.js",
|
||||
_autoCode + "readme.txt",
|
||||
}
|
||||
err = tools.ZipFiles("./ginvueadmin.zip", fileList, ".", ".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.RemoveAll(_autoCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//批量创建文件夹
|
||||
func createDir(dirs ...string) (err error) {
|
||||
for _, v := range dirs {
|
||||
exist, err := tools.PathExists(v)
|
||||
if err != nil {
|
||||
//log.L.Info(fmt.Sprintf("get dir error![%v]\n", err))
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
//log.L.Info(fmt.Sprintf("has dir![%v]\n"+_dir))
|
||||
} else {
|
||||
//log.L.Info(fmt.Sprintf("no dir![%v]\n"+_dir))
|
||||
// 创建文件夹
|
||||
err = os.Mkdir(v, os.ModePerm)
|
||||
if err != nil {
|
||||
//log.L.Error(fmt.Sprintf("mkdir error![%v]\n",err))
|
||||
} else {
|
||||
//log.L.Info("mkdir success!\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package dbModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//文件结构体
|
||||
type ExaFile struct {
|
||||
gorm.Model
|
||||
FileName string
|
||||
FileMd5 string
|
||||
FilePath string
|
||||
ExaFileChunk []ExaFileChunk
|
||||
ChunkTotal int
|
||||
IsFinish bool
|
||||
}
|
||||
|
||||
//切片结构体
|
||||
type ExaFileChunk struct {
|
||||
gorm.Model
|
||||
ExaFileId uint
|
||||
FileChunkNumber int
|
||||
FileChunkPath string
|
||||
}
|
||||
|
||||
//文件合成完成
|
||||
func (f *ExaFile) FileCreateComplete(FileMd5 string, FileName string, FilePath string) error {
|
||||
var file ExaFile
|
||||
upDateFile := make(map[string]interface{})
|
||||
upDateFile["FilePath"] = FilePath
|
||||
upDateFile["IsFinish"] = true
|
||||
err := qmsql.DEFAULTDB.Where("file_md5 = ? AND file_name = ?", FileMd5, FileName).First(&file).Updates(upDateFile).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//第一次上传或者断点续传时候检测当前文件属性,没有则创建,有则返回文件的当前切片
|
||||
func (f *ExaFile) FindOrCreateFile(FileMd5 string, FileName string, ChunkTotal int) (err error, file ExaFile) {
|
||||
var cfile ExaFile
|
||||
cfile.FileMd5 = FileMd5
|
||||
cfile.FileName = FileName
|
||||
cfile.ChunkTotal = ChunkTotal
|
||||
notHaveSameMd5Finish := qmsql.DEFAULTDB.Where("file_md5 = ? AND is_finish = ?", FileMd5, true).First(&file).RecordNotFound()
|
||||
if notHaveSameMd5Finish {
|
||||
err = qmsql.DEFAULTDB.Where("file_md5 = ? AND file_name = ?", FileMd5, FileName).Preload("ExaFileChunk").FirstOrCreate(&file, cfile).Error
|
||||
return err, file
|
||||
} else {
|
||||
cfile.IsFinish = true
|
||||
cfile.FilePath = file.FilePath
|
||||
err = qmsql.DEFAULTDB.Create(&cfile).Error
|
||||
return err, cfile
|
||||
}
|
||||
}
|
||||
|
||||
// 创建文件切片记录
|
||||
func (f *ExaFile) CreateFileChunk(FileChunkPath string, FileChunkNumber int) error {
|
||||
var chunk ExaFileChunk
|
||||
chunk.FileChunkPath = FileChunkPath
|
||||
chunk.ExaFileId = f.ID
|
||||
chunk.FileChunkNumber = FileChunkNumber
|
||||
err := qmsql.DEFAULTDB.Create(&chunk).Error
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除文件切片记录
|
||||
func (f *ExaFile) DeleteFileChunk(fileMd5 string, fileName string, filePath string) error {
|
||||
var chunks []ExaFileChunk
|
||||
var file ExaFile
|
||||
err := qmsql.DEFAULTDB.Where("file_md5 = ? AND file_name = ?", fileMd5, fileName).First(&file).Update("IsFinish", true).Update("file_path", filePath).Error
|
||||
err = qmsql.DEFAULTDB.Where("exa_file_id = ?", file.ID).Delete(&chunks).Unscoped().Error
|
||||
return err
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package dbModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/model/sysModel"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type ExaCustomer struct {
|
||||
gorm.Model
|
||||
CustomerName string `json:"customerName"`
|
||||
CustomerPhoneData string `json:"customerPhoneData"`
|
||||
SysUserID uint `json:"sysUserId"`
|
||||
SysUserAuthorityID string `json:"sysUserAuthorityID"`
|
||||
SysUser sysModel.SysUser `json:"sysUser"`
|
||||
}
|
||||
|
||||
//创建用户
|
||||
func (e *ExaCustomer)CreateExaCustomer()(err error){
|
||||
err = qmsql.DEFAULTDB.Create(e).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//删除用户
|
||||
func (e *ExaCustomer)DeleteExaCustomer()(err error){
|
||||
err = qmsql.DEFAULTDB.Delete(e).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//更新用户
|
||||
func (e *ExaCustomer)UpdataExaCustomer()(err error){
|
||||
err = qmsql.DEFAULTDB.Save(e).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//获取用户信息
|
||||
func (e *ExaCustomer)GetExaCustomer()(err error,customer ExaCustomer){
|
||||
err= qmsql.DEFAULTDB.Where("id = ?",e.ID).First(&customer).Error
|
||||
return
|
||||
}
|
||||
|
||||
//获取用户列表
|
||||
// 分页获取数据 需要分页实现这个接口即可
|
||||
func (e *ExaCustomer) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(e, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var a sysModel.SysAuthority
|
||||
a.AuthorityId = e.SysUserAuthorityID
|
||||
err,auth := a.GetAuthorityInfo()
|
||||
var dataId []string
|
||||
for _,v := range auth.DataAuthorityId{
|
||||
dataId = append(dataId, v.AuthorityId)
|
||||
}
|
||||
var CustomerList []ExaCustomer
|
||||
err = db.Where("sys_user_authority_id in (?)",dataId).Find(&CustomerList).Count(&total).Error
|
||||
if err!=nil{
|
||||
return err, CustomerList, total
|
||||
}else{
|
||||
err = db.Preload("SysUser").Where("sys_user_authority_id in (?)",dataId).Find(&CustomerList).Error
|
||||
}
|
||||
return err, CustomerList, total
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package dbModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type ExaFileUploadAndDownload struct {
|
||||
gorm.Model
|
||||
Name string `json:"name"`
|
||||
Url string `json:"url"`
|
||||
Tag string `json:"tag"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
func (f *ExaFileUploadAndDownload) Upload() error {
|
||||
err := qmsql.DEFAULTDB.Create(f).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *ExaFileUploadAndDownload) DeleteFile() error {
|
||||
err := qmsql.DEFAULTDB.Where("id = ?", f.ID).Unscoped().Delete(f).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *ExaFileUploadAndDownload) FindFile() (error, ExaFileUploadAndDownload) {
|
||||
var file ExaFileUploadAndDownload
|
||||
err := qmsql.DEFAULTDB.Where("id = ?", f.ID).First(&file).Error
|
||||
return err, file
|
||||
}
|
||||
|
||||
// 分页获取数据 需要分页实现这个接口即可
|
||||
func (f *ExaFileUploadAndDownload) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(f, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var fileLists []ExaFileUploadAndDownload
|
||||
err = db.Order("updated_at desc").Find(&fileLists).Error
|
||||
return err, fileLists, total
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package modelInterface
|
||||
|
||||
// 因为我也不确定项目要不要多人维护 所以定义了CURD接口 作为接口参考
|
||||
// 由于很多接口使用Restful模式 暂时不用泛型 有需要可以iss提供示例
|
||||
|
||||
type PageInfo struct {
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
//分页接口
|
||||
type Paging interface {
|
||||
GetInfoList(PageInfo) (err error, list interface{}, total int)
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type SysApi struct {
|
||||
gorm.Model
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
Group string `json:"group"`
|
||||
Method string `json:"method" gorm:"default:'POST'"`
|
||||
}
|
||||
|
||||
//新增基础api
|
||||
func (a *SysApi) CreateApi() (err error) {
|
||||
findOne := qmsql.DEFAULTDB.Where("path = ?", a.Path).Find(&SysMenu{}).Error
|
||||
if findOne == nil {
|
||||
return errors.New("存在相同api")
|
||||
} else {
|
||||
err = qmsql.DEFAULTDB.Create(a).Error
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//删除基础api
|
||||
func (a *SysApi) DeleteApi() (err error) {
|
||||
err = qmsql.DEFAULTDB.Delete(a).Error
|
||||
new(CasbinModel).clearCasbin(1, a.Path)
|
||||
return err
|
||||
}
|
||||
|
||||
//更新api
|
||||
func (a *SysApi) UpdataApi() (err error) {
|
||||
var oldA SysApi
|
||||
err = qmsql.DEFAULTDB.Where("id = ?", a.ID).First(&oldA).Error
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
err = new(CasbinModel).CasbinApiUpdata(oldA.Path, a.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
err = qmsql.DEFAULTDB.Save(a).Error
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//获取选中角色所拥有的api
|
||||
func (a *SysApi) GetApiById(id float64) (err error, api SysApi) {
|
||||
err = qmsql.DEFAULTDB.Where("id = ?", id).First(&api).Error
|
||||
return
|
||||
}
|
||||
|
||||
// 获取所有api信息
|
||||
func (a *SysApi) GetAllApis() (err error, apis []SysApi) {
|
||||
err = qmsql.DEFAULTDB.Find(&apis).Error
|
||||
return
|
||||
}
|
||||
|
||||
// 分页获取数据 需要分页实现这个接口即可
|
||||
func (a *SysApi) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(a, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var apiList []SysApi
|
||||
err = qmsql.DEFAULTDB.Where("path LIKE ?", "%"+a.Path+"%").Find(&apiList).Count(&total).Error
|
||||
if err!=nil{
|
||||
return err, apiList, total
|
||||
}else{
|
||||
err = db.Order("group", true).Where("path LIKE ?", "%"+a.Path+"%").Find(&apiList).Error
|
||||
}
|
||||
return err, apiList, total
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type SysAuthority struct {
|
||||
gorm.Model
|
||||
AuthorityId string `json:"authorityId" gorm:"not null;unique"`
|
||||
AuthorityName string `json:"authorityName"`
|
||||
ParentId string `json:"parentId"`
|
||||
DataAuthorityId []SysAuthority `json:"dataAuthorityId" gorm:"many2many:sys_data_authority_id;association_jointable_foreignkey:data_id"`
|
||||
Children []SysAuthority `json:"children"`
|
||||
}
|
||||
|
||||
// 创建角色
|
||||
func (a *SysAuthority) CreateAuthority() (err error, authority *SysAuthority) {
|
||||
err = qmsql.DEFAULTDB.Create(a).Error
|
||||
return err, a
|
||||
}
|
||||
|
||||
// 删除角色
|
||||
func (a *SysAuthority) DeleteAuthority() (err error) {
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ?", a.AuthorityId).Find(&SysUser{}).Error
|
||||
if err != nil {
|
||||
err = qmsql.DEFAULTDB.Where("parent_id = ?", a.AuthorityId).Find(&SysAuthority{}).Error
|
||||
if err != nil {
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ?", a.AuthorityId).First(a).Unscoped().Delete(a).Error
|
||||
new(CasbinModel).clearCasbin(0, a.AuthorityId)
|
||||
} else {
|
||||
err = errors.New("此角色存在子角色不允许删除")
|
||||
}
|
||||
} else {
|
||||
err = errors.New("此角色有用户正在使用禁止删除")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 分页获取数据 需要分页实现这个接口即可
|
||||
func (a *SysAuthority) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(a, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var authority []SysAuthority
|
||||
err = db.Preload("DataAuthorityId").Where("parent_id = 0").Find(&authority).Error
|
||||
if len(authority) > 0 {
|
||||
for k, _ := range authority {
|
||||
err = findChildrenAuthority(&authority[k])
|
||||
}
|
||||
}
|
||||
return err, authority, total
|
||||
}
|
||||
}
|
||||
|
||||
func findChildrenAuthority(authority *SysAuthority) (err error) {
|
||||
err = qmsql.DEFAULTDB.Preload("DataAuthorityId").Where("parent_id = ?", authority.AuthorityId).Find(&authority.Children).Error
|
||||
if len(authority.Children) > 0 {
|
||||
for k, _ := range authority.Children {
|
||||
err = findChildrenAuthority(&authority.Children[k])
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *SysAuthority) SetDataAuthority() error {
|
||||
var s SysAuthority
|
||||
qmsql.DEFAULTDB.Preload("DataAuthorityId").First(&s, "id = ?", a.ID)
|
||||
err := qmsql.DEFAULTDB.Model(&s).Association("DataAuthorityId").Replace(&a.DataAuthorityId).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *SysAuthority) GetAuthorityInfo() (err error, sa SysAuthority) {
|
||||
err = qmsql.DEFAULTDB.Preload("DataAuthorityId").Where("authority_id = ?", a.AuthorityId).First(&sa).Error
|
||||
return err, sa
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type SysBaseMenu struct {
|
||||
gorm.Model
|
||||
MenuLevel uint `json:"-"`
|
||||
ParentId string `json:"parentId"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Hidden bool `json:"hidden"`
|
||||
Component string `json:"component"`
|
||||
Sort string `json:"sort"`
|
||||
Meta `json:"meta"`
|
||||
NickName string `json:"nickName"`
|
||||
Children []SysBaseMenu `json:"children"`
|
||||
}
|
||||
|
||||
//增加基础路由
|
||||
func (b *SysBaseMenu) AddBaseMenu() (err error) {
|
||||
findOne := qmsql.DEFAULTDB.Where("name = ?", b.Name).Find(&SysBaseMenu{}).Error
|
||||
if findOne != nil {
|
||||
b.NickName = b.Title
|
||||
err = qmsql.DEFAULTDB.Create(b).Error
|
||||
} else {
|
||||
err = errors.New("存在重复name,请修改name")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//删除基础路由
|
||||
func (b *SysBaseMenu) DeleteBaseMenu(id float64) (err error) {
|
||||
err = qmsql.DEFAULTDB.Where("parent_id = ?", id).First(&SysBaseMenu{}).Error
|
||||
if err != nil {
|
||||
err = qmsql.DEFAULTDB.Where("id = ?", id).Delete(&b).Error
|
||||
err = qmsql.DEFAULTDB.Where("menu_id = ?", id).Unscoped().Delete(&SysMenu{}).Error
|
||||
} else {
|
||||
return errors.New("此菜单存在子菜单不可删除")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//更新路由
|
||||
func (b *SysBaseMenu) UpdataBaseMenu() (err error) {
|
||||
upDataMap := make(map[string]interface{})
|
||||
upDataMap["parent_id"] = b.ParentId
|
||||
upDataMap["path"] = b.Path
|
||||
upDataMap["name"] = b.Name
|
||||
upDataMap["hidden"] = b.Hidden
|
||||
upDataMap["component"] = b.Component
|
||||
upDataMap["title"] = b.Title
|
||||
upDataMap["icon"] = b.Icon
|
||||
upDataMap["sort"] = b.Sort
|
||||
upDataMap["nick_name"] = b.Title
|
||||
err = qmsql.DEFAULTDB.Where("id = ?", b.ID).Find(&SysBaseMenu{}).Updates(upDataMap).Error
|
||||
err1 := qmsql.DEFAULTDB.Where("menu_id = ?", b.ID).Find(&[]SysMenu{}).Updates(upDataMap).Error
|
||||
fmt.Printf("菜单修改时候,关联菜单err1:%v,err:%v", err1, err)
|
||||
return err
|
||||
}
|
||||
|
||||
//当前选中角色所拥有的路由
|
||||
func (b *SysBaseMenu) GetBaseMenuById(id float64) (err error, menu SysBaseMenu) {
|
||||
err = qmsql.DEFAULTDB.Where("id = ?", id).First(&menu).Error
|
||||
return
|
||||
}
|
||||
|
||||
//获取路由分页
|
||||
func (b *SysBaseMenu) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(b, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var menuList []SysBaseMenu
|
||||
err = db.Where("parent_id = 0").Order("sort", true).Find(&menuList).Error
|
||||
for i := 0; i < len(menuList); i++ {
|
||||
err = getBaseChildrenList(&menuList[i])
|
||||
}
|
||||
return err, menuList, total
|
||||
}
|
||||
}
|
||||
|
||||
//获取基础路由树
|
||||
func (m *SysBaseMenu) GetBaseMenuTree() (err error, menus []SysBaseMenu) {
|
||||
err = qmsql.DEFAULTDB.Where(" parent_id = ?", 0).Order("sort", true).Find(&menus).Error
|
||||
for i := 0; i < len(menus); i++ {
|
||||
err = getBaseChildrenList(&menus[i])
|
||||
}
|
||||
return err, menus
|
||||
}
|
||||
|
||||
func getBaseChildrenList(menu *SysBaseMenu) (err error) {
|
||||
err = qmsql.DEFAULTDB.Where("parent_id = ?", menu.ID).Order("sort", true).Find(&menu.Children).Error
|
||||
for i := 0; i < len(menu.Children); i++ {
|
||||
err = getBaseChildrenList(&menu.Children[i])
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"github.com/casbin/casbin"
|
||||
"github.com/casbin/casbin/util"
|
||||
gormadapter "github.com/casbin/gorm-adapter"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CasbinModel struct {
|
||||
ID uint `json:"id" gorm:"column:_id"`
|
||||
Ptype string `json:"ptype" gorm:"column:ptype"`
|
||||
AuthorityId string `json:"rolename" gorm:"column:v0"`
|
||||
Path string `json:"path" gorm:"column:v1"`
|
||||
Method string `json:"method" gorm:"column:v2"`
|
||||
}
|
||||
|
||||
// 供入参使用
|
||||
type CasbinInfo struct {
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
// 供入参使用
|
||||
type CasbinInReceive struct {
|
||||
AuthorityId string `json:"authorityId"`
|
||||
CasbinInfos []CasbinInfo `json:"casbinInfos"`
|
||||
}
|
||||
|
||||
// 更新权限
|
||||
func (c *CasbinModel) CasbinPUpdata(AuthorityId string, casbinInfos []CasbinInfo) error {
|
||||
c.clearCasbin(0, AuthorityId)
|
||||
for _, v := range casbinInfos {
|
||||
cm := CasbinModel{
|
||||
ID: 0,
|
||||
Ptype: "p",
|
||||
AuthorityId: AuthorityId,
|
||||
Path: v.Path,
|
||||
Method: v.Method,
|
||||
}
|
||||
addflag := c.AddCasbin(cm)
|
||||
if addflag == false {
|
||||
return errors.New("存在相同api,添加失败,请联系管理员")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// API更新随动
|
||||
func (c *CasbinModel) CasbinApiUpdata(oldPath string, newPath string) error {
|
||||
var cs []CasbinModel
|
||||
err := qmsql.DEFAULTDB.Table("casbin_rule").Where("v1 = ?", oldPath).Find(&cs).Update("v1", newPath).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//添加权限
|
||||
func (c *CasbinModel) AddCasbin(cm CasbinModel) bool {
|
||||
e := Casbin()
|
||||
return e.AddPolicy(cm.AuthorityId, cm.Path, cm.Method)
|
||||
}
|
||||
|
||||
//获取权限列表
|
||||
func (c *CasbinModel) GetPolicyPathByAuthorityId(AuthorityId string) []string {
|
||||
e := Casbin()
|
||||
var pathList []string
|
||||
list := e.GetFilteredPolicy(0, AuthorityId)
|
||||
for _, v := range list {
|
||||
pathList = append(pathList, v[1])
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
//清除匹配的权限
|
||||
func (c *CasbinModel) clearCasbin(v int, p string) bool {
|
||||
e := Casbin()
|
||||
return e.RemoveFilteredPolicy(v, p)
|
||||
|
||||
}
|
||||
|
||||
// 自定义规则函数
|
||||
func ParamsMatch(fullNameKey1 string, key2 string) bool {
|
||||
key1 := strings.Split(fullNameKey1, "?")[0]
|
||||
//剥离路径后再使用casbin的keyMatch2
|
||||
return util.KeyMatch2(key1, key2)
|
||||
}
|
||||
|
||||
// 自定义规则函数
|
||||
func ParamsMatchFunc(args ...interface{}) (interface{}, error) {
|
||||
name1 := args[0].(string)
|
||||
name2 := args[1].(string)
|
||||
|
||||
return (bool)(ParamsMatch(name1, name2)), nil
|
||||
}
|
||||
|
||||
//持久化到数据库 引入自定义规则
|
||||
func Casbin() *casbin.Enforcer {
|
||||
a := gormadapter.NewAdapterByDB(qmsql.DEFAULTDB)
|
||||
e := casbin.NewEnforcer(config.GinVueAdminconfig.CasbinConfig.ModelPath, a)
|
||||
e.AddFunction("ParamsMatch", ParamsMatchFunc)
|
||||
e.LoadPolicy()
|
||||
return e
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/init/initRedis"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type JwtBlacklist struct {
|
||||
gorm.Model
|
||||
Jwt string `gorm:"type:text"`
|
||||
}
|
||||
|
||||
func (j *JwtBlacklist) JsonInBlacklist() (err error) {
|
||||
err = qmsql.DEFAULTDB.Create(j).Error
|
||||
return
|
||||
}
|
||||
|
||||
//判断JWT是否在黑名单内部
|
||||
func (j *JwtBlacklist) IsBlacklist(Jwt string) bool {
|
||||
isNotFound := qmsql.DEFAULTDB.Where("jwt = ?", Jwt).First(j).RecordNotFound()
|
||||
return !isNotFound
|
||||
}
|
||||
|
||||
//判断当前用户是否在线
|
||||
func (j *JwtBlacklist) GetRedisJWT(userName string) (err error, RedisJWT string) {
|
||||
RedisJWT, err = initRedis.DEFAULTREDIS.Get(userName).Result()
|
||||
return err, RedisJWT
|
||||
}
|
||||
|
||||
//设置当前用户在线
|
||||
func (j *JwtBlacklist) SetRedisJWT(userName string) (err error) {
|
||||
err = initRedis.DEFAULTREDIS.Set(userName, j.Jwt, 1000*1000*1000*60*60*24*7).Err()
|
||||
return err
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
)
|
||||
|
||||
// menu需要构建的点有点多 这里关联关系表直接把所有数据拿过来 用代码实现关联 后期实现主外键模式
|
||||
type SysMenu struct {
|
||||
SysBaseMenu
|
||||
MenuId string `json:"menuId"`
|
||||
AuthorityId string `json:"-"`
|
||||
Children []SysMenu `json:"children"`
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
Title string `json:"title"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
// 为角色增加menu树
|
||||
func (m *SysMenu) AddMenuAuthority(menus []SysBaseMenu, authorityId string) (err error) {
|
||||
var menu SysMenu
|
||||
qmsql.DEFAULTDB.Where("authority_id = ? ", authorityId).Unscoped().Delete(&SysMenu{})
|
||||
for _, v := range menus {
|
||||
menu.SysBaseMenu = v
|
||||
menu.AuthorityId = authorityId
|
||||
menu.MenuId = fmt.Sprintf("%v", v.ID)
|
||||
menu.ID = 0
|
||||
err = qmsql.DEFAULTDB.Create(&menu).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 查看当前角色树
|
||||
func (m *SysMenu) GetMenuAuthority(authorityId string) (err error, menus []SysMenu) {
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ?", authorityId).Find(&menus).Error
|
||||
return err, menus
|
||||
}
|
||||
|
||||
//获取动态路由树
|
||||
func (m *SysMenu) GetMenuTree(authorityId string) (err error, menus []SysMenu) {
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", authorityId, 0).Order("sort", true).Find(&menus).Error
|
||||
for i := 0; i < len(menus); i++ {
|
||||
err = getChildrenList(&menus[i])
|
||||
}
|
||||
return err, menus
|
||||
}
|
||||
|
||||
func getChildrenList(menu *SysMenu) (err error) {
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", menu.AuthorityId, menu.MenuId).Order("sort", true).Find(&menu.Children).Error
|
||||
for i := 0; i < len(menu.Children); i++ {
|
||||
err = getChildrenList(&menu.Children[i])
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/tools"
|
||||
)
|
||||
|
||||
//配置文件结构体
|
||||
type System struct {
|
||||
Config config.Config
|
||||
}
|
||||
|
||||
//读取配置文件
|
||||
func (s *System) GetSystemConfig() (err error, conf config.Config) {
|
||||
return nil, config.GinVueAdminconfig
|
||||
}
|
||||
|
||||
//设置配置文件
|
||||
func (s *System) SetSystemConfig() (err error) {
|
||||
confs := tools.StructToMap(s.Config)
|
||||
for k, v := range confs {
|
||||
config.VTool.Set(k, v)
|
||||
}
|
||||
err = config.VTool.WriteConfig()
|
||||
return err
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"gin-vue-admin/tools"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type SysUser struct {
|
||||
gorm.Model
|
||||
UUID uuid.UUID `json:"uuid"`
|
||||
Username string `json:"userName"`
|
||||
Password string `json:"-"`
|
||||
NickName string `json:"nickName" gorm:"default:'QMPlusUser'"`
|
||||
HeaderImg string `json:"headerImg" gorm:"default:'http://www.henrongyi.top/avatar/lufu.jpg'"`
|
||||
Authority SysAuthority `json:"authority" gorm:"ForeignKey:AuthorityId;AssociationForeignKey:AuthorityId"`
|
||||
AuthorityId string `json:"authorityId" gorm:"default:888"`
|
||||
}
|
||||
|
||||
//type Propertie struct {
|
||||
// gorm.Model
|
||||
//}
|
||||
|
||||
//注册接口model方法
|
||||
func (u *SysUser) Regist() (err error, userInter *SysUser) {
|
||||
var user SysUser
|
||||
//判断用户名是否注册
|
||||
notResigt := qmsql.DEFAULTDB.Where("username = ?", u.Username).First(&user).RecordNotFound()
|
||||
//notResigt为false表明读取到了 不能注册
|
||||
if !notResigt {
|
||||
return errors.New("用户名已注册"), nil
|
||||
} else {
|
||||
// 否则 附加uuid 密码md5简单加密 注册
|
||||
u.Password = tools.MD5V([]byte(u.Password))
|
||||
u.UUID = uuid.NewV4()
|
||||
err = qmsql.DEFAULTDB.Create(u).Error
|
||||
}
|
||||
return err, u
|
||||
}
|
||||
|
||||
//修改用户密码
|
||||
func (u *SysUser) ChangePassword(newPassword string) (err error, userInter *SysUser) {
|
||||
var user SysUser
|
||||
//后期修改jwt+password模式
|
||||
u.Password = tools.MD5V([]byte(u.Password))
|
||||
err = qmsql.DEFAULTDB.Where("username = ? AND password = ?", u.Username, u.Password).First(&user).Update("password", tools.MD5V([]byte(newPassword))).Error
|
||||
return err, u
|
||||
}
|
||||
|
||||
//用户更新接口
|
||||
func (u *SysUser) SetUserAuthority(uuid uuid.UUID, AuthorityId string) (err error) {
|
||||
err = qmsql.DEFAULTDB.Where("uuid = ?", uuid).First(&SysUser{}).Update("authority_id", AuthorityId).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//用户登录
|
||||
func (u *SysUser) Login() (err error, userInter *SysUser) {
|
||||
var user SysUser
|
||||
u.Password = tools.MD5V([]byte(u.Password))
|
||||
err = qmsql.DEFAULTDB.Where("username = ? AND password = ?", u.Username, u.Password).First(&user).Error
|
||||
if err != nil {
|
||||
return err, &user
|
||||
}
|
||||
err = qmsql.DEFAULTDB.Where("authority_id = ?", user.AuthorityId).First(&user.Authority).Error
|
||||
return err, &user
|
||||
}
|
||||
|
||||
// 用户头像上传更新地址
|
||||
func (u *SysUser) UploadHeaderImg(uuid uuid.UUID, filePath string) (err error, userInter *SysUser) {
|
||||
var user SysUser
|
||||
err = qmsql.DEFAULTDB.Where("uuid = ?", uuid).First(&user).Update("header_img", filePath).First(&user).Error
|
||||
return err, &user
|
||||
}
|
||||
|
||||
// 分页获取数据 需要分页实现这个接口即可
|
||||
func (u *SysUser) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer(u, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var userList []SysUser
|
||||
err = db.Preload("Authority").Find(&userList).Error
|
||||
return err, userList, total
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import (
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//工作流属性表
|
||||
type SysWorkflow struct {
|
||||
gorm.Model
|
||||
WorkflowNickName string `json:"workflowNickName"` // 工作流名称
|
||||
WorkflowName string `json:"workflowName"` // 工作流英文id
|
||||
WorkflowDescription string `json:"workflowDescription"` // 工作流描述
|
||||
WorkflowStepInfo []SysWorkflowStepInfo `json:"workflowStep"` // 工作流步骤
|
||||
}
|
||||
|
||||
// 工作流状态表
|
||||
type SysWorkflowStepInfo struct {
|
||||
gorm.Model
|
||||
SysWorkflowID uint `json:"workflowID"` // 所属工作流ID
|
||||
IsStrat bool `json:"isStrat"` // 是否是开始流节点
|
||||
StepName string `json:"stepName"` // 工作流名称
|
||||
StepNo float64 `json:"stepNo"` // 步骤id (第几步)
|
||||
StepAuthorityID string `json:"stepAuthorityID"` // 操作者级别id
|
||||
IsEnd bool `json:"isEnd"` // 是否是完结流节点
|
||||
}
|
||||
|
||||
//创建工作流
|
||||
func (wk *SysWorkflow) Create() error {
|
||||
err := qmsql.DEFAULTDB.Create(&wk).Error
|
||||
return err
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package sysModel
|
||||
|
||||
import "github.com/jinzhu/gorm"
|
||||
|
||||
// 工作流流转表
|
||||
type SysWorkFlowProcess struct {
|
||||
gorm.Model
|
||||
ApplicationID uint // 当前工作流所属申请的ID
|
||||
CurrentNode string // 当前进度节点
|
||||
HistoricalNode string //上一个进度节点
|
||||
CurrentUser string // 当前进度操作人
|
||||
HistoricalUser string // 上一个进度的操作人
|
||||
State bool // 状态 是否是正在进行的状态
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitCustomerRouter(Router *gin.RouterGroup) {
|
||||
ApiRouter := Router.Group("customer").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
ApiRouter.POST("createExaCustomer", api.CreateExaCustomer) // 创建客户
|
||||
ApiRouter.POST("updataExaCustomer", api.UpdataExaCustomer) // 更新客户
|
||||
ApiRouter.POST("deleteExaCustomer", api.DeleteExaCustomer) // 删除客户
|
||||
ApiRouter.POST("getExaCustomer", api.GetExaCustomer) // 获取单一客户信息
|
||||
ApiRouter.POST("getExaCustomerList", api.GetExaCustomerList) // 获取客户列表
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitFileUploadAndDownloadRouter(Router *gin.RouterGroup) {
|
||||
FileUploadAndDownloadGroup := Router.Group("fileUploadAndDownload")
|
||||
//.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
FileUploadAndDownloadGroup.POST("/upload", api.UploadFile) // 上传文件
|
||||
FileUploadAndDownloadGroup.POST("/getFileList", api.GetFileList) // 获取上传文件列表
|
||||
FileUploadAndDownloadGroup.POST("/deleteFile", api.DeleteFile) // 删除指定文件
|
||||
FileUploadAndDownloadGroup.POST("/breakpointContinue", api.BreakpointContinue) // 断点续传
|
||||
FileUploadAndDownloadGroup.GET("/findFile", api.FindFile) // 查询当前文件成功的切片
|
||||
FileUploadAndDownloadGroup.POST("/breakpointContinueFinish", api.BreakpointContinueFinish) // 查询当前文件成功的切片
|
||||
FileUploadAndDownloadGroup.POST("/removeChunk", api.RemoveChunk) // 查询当前文件成功的切片
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitApiRouter(Router *gin.RouterGroup) {
|
||||
ApiRouter := Router.Group("api").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
ApiRouter.POST("createApi", api.CreateApi) //创建Api
|
||||
ApiRouter.POST("deleteApi", api.DeleteApi) //删除Api
|
||||
ApiRouter.POST("getApiList", api.GetApiList) //获取Api列表
|
||||
ApiRouter.POST("getApiById", api.GetApiById) //获取单条Api消息
|
||||
ApiRouter.POST("updataApi", api.UpdataApi) //更新api
|
||||
ApiRouter.POST("getAllApis", api.GetAllApis) // 获取所有api
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitAuthorityRouter(Router *gin.RouterGroup) {
|
||||
AuthorityRouter := Router.Group("authority").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
AuthorityRouter.POST("createAuthority", api.CreateAuthority) //创建角色
|
||||
AuthorityRouter.POST("deleteAuthority", api.DeleteAuthority) //删除角色
|
||||
AuthorityRouter.POST("getAuthorityList", api.GetAuthorityList) //获取角色列表
|
||||
AuthorityRouter.POST("setDataAuthority", api.SetDataAuthority) //设置角色资源权限
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitAutoCodeRouter(Router *gin.RouterGroup) {
|
||||
AutoCodeRouter := Router.Group("autoCode").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
AutoCodeRouter.POST("createTemp", api.CreateTemp) //创建自动化代码
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitBaseRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
|
||||
BaseRouter := Router.Group("base")
|
||||
{
|
||||
BaseRouter.POST("regist", api.Regist)
|
||||
BaseRouter.POST("login", api.Login)
|
||||
BaseRouter.POST("captcha",api.Captcha)
|
||||
BaseRouter.GET("captcha/:captchaId",api.CaptchaImg)
|
||||
}
|
||||
return BaseRouter
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitCasbinRouter(Router *gin.RouterGroup) {
|
||||
CasbinRouter := Router.Group("casbin").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
CasbinRouter.POST("casbinPUpdata", api.CasbinPUpdata)
|
||||
CasbinRouter.POST("getPolicyPathByAuthorityId", api.GetPolicyPathByAuthorityId)
|
||||
CasbinRouter.GET("casbinTest/:pathParam", api.CasbinTest)
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitMenuRouter(Router *gin.RouterGroup) (R gin.IRoutes) {
|
||||
MenuRouter := Router.Group("menu").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
MenuRouter.POST("getMenu", api.GetMenu) //获取菜单树
|
||||
MenuRouter.POST("getMenuList", api.GetMenuList) // 分页获取基础menu列表
|
||||
MenuRouter.POST("addBaseMenu", api.AddBaseMenu) // 新增菜单
|
||||
MenuRouter.POST("getBaseMenuTree", api.GetBaseMenuTree) // 获取用户动态路由
|
||||
MenuRouter.POST("addMenuAuthority", api.AddMenuAuthority) // 增加menu和角色关联关系
|
||||
MenuRouter.POST("getMenuAuthority", api.GetMenuAuthority) // 获取指定角色menu
|
||||
MenuRouter.POST("deleteBaseMenu", api.DeleteBaseMenu) // 删除菜单
|
||||
MenuRouter.POST("updataBaseMenu", api.UpdataBaseMenu) // 更新菜单
|
||||
MenuRouter.POST("getBaseMenuById", api.GetBaseMenuById) //根据id获取菜单
|
||||
}
|
||||
return MenuRouter
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitSystemRouter(Router *gin.RouterGroup) {
|
||||
UserRouter := Router.Group("system").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
UserRouter.POST("getSystemConfig", api.GetSystemConfig) // 获取配置文件内容
|
||||
UserRouter.POST("setSystemConfig", api.SetSystemConfig) // 设置配置文件内容
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitUserRouter(Router *gin.RouterGroup) {
|
||||
UserRouter := Router.Group("user").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
UserRouter.POST("changePassword", api.ChangePassword) // 修改密码
|
||||
UserRouter.POST("uploadHeaderImg", api.UploadHeaderImg) //上传头像
|
||||
UserRouter.POST("getUserList", api.GetUserList) // 分页获取用户列表
|
||||
UserRouter.POST("setUserAuthority", api.SetUserAuthority) //设置用户权限
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"casbinconfig": {
|
||||
"modelPath": "./static/rbacmodel/rbac_model.conf"
|
||||
},
|
||||
"jwt": {
|
||||
"signingKey": "qmPlus"
|
||||
},
|
||||
"mysqladmin": {
|
||||
"username": "root",
|
||||
"password": "Aa@6447985",
|
||||
"path": "127.0.0.1:3306",
|
||||
"dbname": "qmPlus",
|
||||
"config": "charset=utf8\u0026parseTime=True\u0026loc=Local",
|
||||
"maxIdleConns": 10,
|
||||
"maxOpenConns": 100,
|
||||
"logMode": true
|
||||
},
|
||||
"qiniu": {
|
||||
"accessKey": "25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ",
|
||||
"secretKey": "pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY"
|
||||
},
|
||||
"redisadmin": {
|
||||
"addr": "127.0.0.1:6379",
|
||||
"password": "",
|
||||
"db": 0
|
||||
},
|
||||
"system": {
|
||||
"useMultipoint": false,
|
||||
"env": "develop",
|
||||
"addr": 8888
|
||||
},
|
||||
"captcha": {
|
||||
"keyLong": 6,
|
||||
"imgWidth": 120,
|
||||
"imgHeight": 40
|
||||
},
|
||||
"log": {
|
||||
"prefix": "[GIN-VUE-ADMIN]",
|
||||
"logFile": false,
|
||||
"stdout": ["DEBUG"],
|
||||
"file": ["WARNING"]
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ArrayToString(array []interface{}) string {
|
||||
return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
)
|
||||
|
||||
func padding(src []byte, blocksize int) []byte {
|
||||
n := len(src)
|
||||
padnum := blocksize - n%blocksize
|
||||
pad := bytes.Repeat([]byte{byte(padnum)}, padnum)
|
||||
dst := append(src, pad...)
|
||||
return dst
|
||||
}
|
||||
|
||||
func unpadding(src []byte) []byte {
|
||||
n := len(src)
|
||||
unpadnum := int(src[n-1])
|
||||
dst := src[:n-unpadnum]
|
||||
return dst
|
||||
}
|
||||
|
||||
func EncryptDES(src []byte) []byte {
|
||||
key := []byte("qimiao66")
|
||||
block, _ := des.NewCipher(key)
|
||||
src = padding(src, block.BlockSize())
|
||||
blockmode := cipher.NewCBCEncrypter(block, key)
|
||||
blockmode.CryptBlocks(src, src)
|
||||
return src
|
||||
}
|
||||
|
||||
func DecryptDES(src []byte) []byte {
|
||||
key := []byte("qimiao66")
|
||||
block, _ := des.NewCipher(key)
|
||||
blockmode := cipher.NewCBCDecrypter(block, key)
|
||||
blockmode.CryptBlocks(src, src)
|
||||
src = unpadding(src)
|
||||
return src
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package tools
|
||||
|
||||
import "os"
|
||||
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// 空值校验工具 仅用于检验空字符串 其余类型请勿使用
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func HasGap(input interface{}) error {
|
||||
getType := reflect.TypeOf(input)
|
||||
getValue := reflect.ValueOf(input)
|
||||
// 获取方法字段
|
||||
for i := 0; i < getType.NumField(); i++ {
|
||||
field := getType.Field(i)
|
||||
value := getValue.Field(i).Interface()
|
||||
switch value.(type) {
|
||||
case string:
|
||||
if value == "" {
|
||||
fmt.Printf("%s为空", field.Name)
|
||||
return errors.New(fmt.Sprintf("%s为空", field.Name))
|
||||
}
|
||||
default:
|
||||
if value == nil {
|
||||
fmt.Printf("%s为空", field.Name)
|
||||
return errors.New(fmt.Sprintf("%s为空", field.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取方法
|
||||
// 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历
|
||||
//for i := 0; i < getType.NumMethod(); i++ {
|
||||
// m := getType.Method(i)
|
||||
// fmt.Printf("%s: %v\n", m.Name, m.Type)
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package tools
|
||||
|
||||
import "reflect"
|
||||
|
||||
// 利用反射将结构体转化为map
|
||||
func StructToMap(obj interface{}) map[string]interface{}{
|
||||
obj1 := reflect.TypeOf(obj)
|
||||
obj2 := reflect.ValueOf(obj)
|
||||
|
||||
var data = make(map[string]interface{})
|
||||
for i := 0; i < obj1.NumField(); i++ {
|
||||
data[obj1.Field(i).Name] = obj2.Field(i).Interface()
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
// 请自行引入model路径
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
||||
// @Tags {{.StructName}}
|
||||
// @Summary 创建{{.StructName}}
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body {{.PackageName}}.{{.StructName}} true "创建{{.StructName}}"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /{{.Abbreviation}}/create{{.StructName}} [post]
|
||||
func Create{{.StructName}}(c *gin.Context) {
|
||||
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
|
||||
_ = c.ShouldBindJSON(&{{.Abbreviation}})
|
||||
err := {{.Abbreviation}}.Create{{.StructName}}()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("创建失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Tags {{.StructName}}
|
||||
// @Summary 删除{{.StructName}}
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body {{.PackageName}}.{{.StructName}} true "删除{{.StructName}}"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
|
||||
// @Router /{{.Abbreviation}}/delete{{.StructName}} [post]
|
||||
func Delete{{.StructName}}(c *gin.Context) {
|
||||
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
|
||||
_ = c.ShouldBindJSON(&{{.Abbreviation}})
|
||||
err := {{.Abbreviation}}.Delete{{.StructName}}()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("删除失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "创建成功", gin.H{})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Tags {{.StructName}}
|
||||
// @Summary 更新{{.StructName}}
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body {{.PackageName}}.{{.StructName}} true "更新{{.StructName}}"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
|
||||
// @Router /{{.Abbreviation}}/update{{.StructName}} [post]
|
||||
func Update{{.StructName}}(c *gin.Context) {
|
||||
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
|
||||
_ = c.ShouldBindJSON(&{{.Abbreviation}})
|
||||
err,re{{.Abbreviation}} := {{.Abbreviation}}.Update{{.StructName}}()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("更新失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "更新成功", gin.H{
|
||||
"re{{.Abbreviation}}":re{{.Abbreviation}},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Tags {{.StructName}}
|
||||
// @Summary 用id查询{{.StructName}}
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body {{.PackageName}}.{{.StructName}} true "用id查询{{.StructName}}"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
|
||||
// @Router /{{.Abbreviation}}/find{{.StructName}} [post]
|
||||
func Find{{.StructName}}(c *gin.Context) {
|
||||
var {{.Abbreviation}} {{.PackageName}}.{{.StructName}}
|
||||
_ = c.ShouldBindJSON(&{{.Abbreviation}})
|
||||
err,re{{.Abbreviation}} := {{.Abbreviation}}.FindById()
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("查询失败:%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "查询成功", gin.H{
|
||||
"re{{.Abbreviation}}":re{{.Abbreviation}},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Tags {{.StructName}}
|
||||
// @Summary 分页获取{{.StructName}}列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取{{.StructName}}列表"
|
||||
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /{{.Abbreviation}}/get{{.StructName}}List [post]
|
||||
func Get{{.StructName}}List(c *gin.Context) {
|
||||
var pageInfo modelInterface.PageInfo
|
||||
_ = c.ShouldBindJSON(&pageInfo)
|
||||
err, list, total := new({{.PackageName}}.{{.StructName}}).GetInfoList(pageInfo)
|
||||
if err != nil {
|
||||
servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
|
||||
} else {
|
||||
servers.ReportFormat(c, true, "获取数据成功", gin.H{
|
||||
"{{.PackageName}}List": list,
|
||||
"total": total,
|
||||
"page": pageInfo.Page,
|
||||
"pageSize": pageInfo.PageSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// 自动生成模板{{.StructName}}
|
||||
package {{.PackageName}}
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/servers"
|
||||
"gin-vue-admin/init/qmsql"
|
||||
"gin-vue-admin/model/modelInterface"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type {{.StructName}} struct {
|
||||
gorm.Model {{range .Fields}}
|
||||
{{.FieldName}} {{.FieldType}} `json:"{{.FieldJson}}"{{if .ColumnName}} gorm:"column:{{.ColumnName}}"{{end}}`{{ end }}
|
||||
}
|
||||
|
||||
// 创建{{.StructName}}
|
||||
func ({{.Abbreviation}} *{{.StructName}})Create{{.StructName}}()(err error){
|
||||
err = qmsql.DEFAULTDB.Create({{.Abbreviation}}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
// 删除{{.StructName}}
|
||||
func ({{.Abbreviation}} *{{.StructName}})Delete{{.StructName}}()(err error){
|
||||
err = qmsql.DEFAULTDB.Delete({{.Abbreviation}}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新{{.StructName}}
|
||||
func ({{.Abbreviation}} *{{.StructName}})Update{{.StructName}}()(err error, re{{.Abbreviation}} {{.StructName}}){
|
||||
err = qmsql.DEFAULTDB.Save({{.Abbreviation}}).Error
|
||||
return err, *{{.Abbreviation}}
|
||||
}
|
||||
|
||||
// 根据ID查看单条{{.StructName}}
|
||||
func ({{.Abbreviation}} *{{.StructName}})FindById()(err error,re{{.Abbreviation}} {{.StructName}}){
|
||||
err = qmsql.DEFAULTDB.Where("id = ?",{{.Abbreviation}}.ID).First(&re{{.Abbreviation}}).Error
|
||||
return err,re{{.Abbreviation}}
|
||||
}
|
||||
|
||||
// 分页获取{{.StructName}}
|
||||
func ({{.Abbreviation}} *{{.StructName}})GetInfoList(info modelInterface.PageInfo)(err error, list interface{}, total int){
|
||||
// 封装分页方法 调用即可 传入 当前的结构体和分页信息
|
||||
err, db, total := servers.PagingServer({{.Abbreviation}}, info)
|
||||
if err != nil {
|
||||
return
|
||||
} else {
|
||||
var re{{.StructName}}List []{{.StructName}}
|
||||
err = db.Find(&re{{.StructName}}List).Error
|
||||
return err, re{{.StructName}}List, total
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-vue-admin/controller/api"
|
||||
"gin-vue-admin/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Init{{.StructName}}Router(Router *gin.RouterGroup) {
|
||||
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
|
||||
{
|
||||
{{.StructName}}Router.POST("create{{.StructName}}", api.Create{{.StructName}}) // 新建{{.StructName}}
|
||||
{{.StructName}}Router.POST("delete{{.StructName}}", api.Delete{{.StructName}}) //删除{{.StructName}}
|
||||
{{.StructName}}Router.POST("update{{.StructName}}", api.Update{{.StructName}}) //更新{{.StructName}}
|
||||
{{.StructName}}Router.POST("find{{.StructName}} ", api.Find{{.StructName}}) // 根据ID获取{{.StructName}}
|
||||
{{.StructName}}Router.POST("get{{.StructName}}List", api.Get{{.StructName}}List) //获取{{.StructName}}列表
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
ENV = 'production'
|
||||
VUE_APP_BASE_API = '/v1'
|
||||
@@ -1,21 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
Generated
-12384
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 6.5 KiB |
@@ -1,21 +0,0 @@
|
||||
import service from '@/utils/request'
|
||||
// @Tags api
|
||||
// @Summary 分页获取角色列表
|
||||
// @Security ApiKeyAuth
|
||||
// @accept application/json
|
||||
// @Produce application/json
|
||||
// @Param data body modelInterface.PageInfo true "分页获取用户列表"
|
||||
// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
|
||||
// @Router /api/getApiList [post]
|
||||
// {
|
||||
// page int
|
||||
// pageSize int
|
||||
// }
|
||||
export const createTemp = (data) => {
|
||||
return service({
|
||||
url: "/autoCode/createTemp",
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,32 +0,0 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
page: 1,
|
||||
total: 10,
|
||||
pageSize: 10,
|
||||
tableData: [],
|
||||
searchInfo: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(val) {
|
||||
this.pageSize = val
|
||||
this.getTableData()
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.page = val
|
||||
this.getTableData()
|
||||
},
|
||||
async getTableData(page = this.page, pageSize = this.pageSize) {
|
||||
const table = await this.listApi({ page, pageSize, ...this.searchInfo })
|
||||
this.tableData = table.data[this.listKey]
|
||||
this.total = table.data.total
|
||||
this.page = table.data.page
|
||||
this.pageSize = table.data.pageSize
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getTableData()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,850 +0,0 @@
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
/* 1 */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
/* 1 */
|
||||
height: 0;
|
||||
/* 1 */
|
||||
overflow: visible;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace;
|
||||
/* 1 */
|
||||
font-size: 1em;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none;
|
||||
/* 1 */
|
||||
text-decoration: underline;
|
||||
/* 2 */
|
||||
text-decoration: underline dotted;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
/* 1 */
|
||||
font-size: 1em;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
/* 1 */
|
||||
font-size: 100%;
|
||||
/* 1 */
|
||||
line-height: 1.15;
|
||||
/* 1 */
|
||||
margin: 0;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
/* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
/* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
color: inherit;
|
||||
/* 2 */
|
||||
display: table;
|
||||
/* 1 */
|
||||
max-width: 100%;
|
||||
/* 1 */
|
||||
padding: 0;
|
||||
/* 3 */
|
||||
white-space: normal;
|
||||
/* 1 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
padding: 0;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
font: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
HTML,
|
||||
body,
|
||||
div,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
ul,
|
||||
ol,
|
||||
dl,
|
||||
li,
|
||||
dt,
|
||||
dd,
|
||||
p,
|
||||
blockquote,
|
||||
pre,
|
||||
form,
|
||||
fieldset,
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: none;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
address,
|
||||
caption,
|
||||
cite,
|
||||
code,
|
||||
dfn,
|
||||
em,
|
||||
strong,
|
||||
th,
|
||||
var {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a:active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
input::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input::-webkit-input-placeholder {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input::-ms-input-placeholder {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input::-moz-placeholder {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type=submit],
|
||||
input[type=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button[disabled],
|
||||
input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol,
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
.el-table__body-wrapper{
|
||||
tr{
|
||||
td{
|
||||
.cell{
|
||||
.el-button+.el-button{
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// navbar
|
||||
.aside{
|
||||
.el-scrollbar {
|
||||
.el-scrollbar__view {
|
||||
.el-menu-vertical{
|
||||
background-color: #001529;
|
||||
}
|
||||
.el-menu-item:hover i,
|
||||
.el-menu-item:hover span{
|
||||
color:#fff;
|
||||
}
|
||||
li{
|
||||
background-color: #001529;
|
||||
|
||||
ul{
|
||||
.el-menu-item{
|
||||
background-color: #000408;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.is-active{
|
||||
background-color:#1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-submenu__title:hover{
|
||||
background-color: #001529;
|
||||
}
|
||||
.el-submenu__title:hover i,
|
||||
.el-submenu__title:hover span{
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.el-menu--inline{
|
||||
border-left: 5px solid #2c3b41;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// layout
|
||||
.layout-cont{
|
||||
.main-cont{
|
||||
position: relative;
|
||||
&.el-main {
|
||||
background-color: #ecf0f5;
|
||||
padding: 0;
|
||||
}
|
||||
.breadcrumb{
|
||||
background-color: #fff;
|
||||
padding: 0 0 15px 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-box {
|
||||
padding: 15px 20px;
|
||||
.el-button{
|
||||
padding: 7px 10px;
|
||||
}
|
||||
.el-input__inner{
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.el-input__icon{
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
.button-box{
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
border-bottom: none;
|
||||
|
||||
}
|
||||
|
||||
.search-term{
|
||||
background: #fff;
|
||||
padding: 0 15px;
|
||||
border-left: 1px solid #ebeef5;
|
||||
border-right: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// table
|
||||
.has-gutter{
|
||||
tr{
|
||||
th{
|
||||
background-color: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-table--striped{
|
||||
.el-table__body{
|
||||
tr.el-table__row--striped{
|
||||
td{
|
||||
background: #fff!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-table th, .el-table tr{
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.el-pagination{
|
||||
.btn-prev,
|
||||
.btn-next{
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.el-pager{
|
||||
|
||||
|
||||
li{
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
margin: 0 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// el-form
|
||||
.el-form{
|
||||
background-color: #fff;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.el-row{
|
||||
padding: 10px 0;
|
||||
.el-col>label{
|
||||
|
||||
line-height: 30px;
|
||||
text-align: right;
|
||||
width: 80%;
|
||||
padding-right: 15px;
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
|
||||
.line{
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
// edit_container
|
||||
.edit_container{
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
.el-button {
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
.edit{
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
.el-button {
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
// upload-demo
|
||||
.upload-demo,
|
||||
.upload{
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
.el-upload-list__item-status-label{
|
||||
right: 0;
|
||||
left: 120px;
|
||||
}
|
||||
.el-upload__tip{
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
// system
|
||||
.system{
|
||||
padding: 15px;
|
||||
.el-input__inner{
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
// 导航
|
||||
#app {
|
||||
.el-container{
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
.el-container.mobile.openside {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
.hideside{
|
||||
.aside{
|
||||
width: 54px!important;
|
||||
}
|
||||
}
|
||||
.el-aside{
|
||||
-webkit-transition: width .2s;
|
||||
transition: width .2s;
|
||||
width: 220px;
|
||||
background-color: #304156;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
font-size: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mobile.hideside{
|
||||
.el-aside{
|
||||
// pointer-events: none;
|
||||
-webkit-transition-duration: .2s;
|
||||
transition-duration: .2s;
|
||||
-webkit-transform: translate3d(-210px,0,0);
|
||||
transform: translate3d(-220px,0,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.mobile{
|
||||
.el-aside{
|
||||
-webkit-transition: -webkit-transform .28s;
|
||||
transition: -webkit-transform .28s;
|
||||
transition: transform .28s;
|
||||
transition: transform .28s,-webkit-transform .28s;
|
||||
width: 210px!important
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.el-container{
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.el-aside{
|
||||
// transition: none;
|
||||
.aside {
|
||||
background: #000;
|
||||
.el-menu{
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-cont.el-main{
|
||||
min-height: 100%;
|
||||
-webkit-transition: margin-left .28s;
|
||||
transition: margin-left .28s;
|
||||
margin-left: 220px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.hideside{
|
||||
.main-cont.el-main{
|
||||
margin-left: 54px;
|
||||
}
|
||||
}
|
||||
.mobile {
|
||||
.main-cont.el-main{
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
}
|
||||
.openside.mobile{
|
||||
.shadowBg{
|
||||
background: #000;
|
||||
opacity: .3;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.el-menu--vertical{
|
||||
.el-menu{
|
||||
margin-left: -8px;
|
||||
background-color:rgb(48,65,86);
|
||||
.el-menu-item{
|
||||
background-color:rgb(48,65,86);
|
||||
}
|
||||
.el-menu-item:focus,
|
||||
.el-menu-item:hover{
|
||||
background-color: #263445;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 导航*****
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export const toUpperCase = (str) => {
|
||||
if (str[0]) {
|
||||
return str.replace(str[0], str[0].toUpperCase())
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<ul class="moon">
|
||||
<li class="crater"></li>
|
||||
<li class="crater"></li>
|
||||
<li class="crater"></li>
|
||||
</ul>
|
||||
<ul class="mountain-range">
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
</ul>
|
||||
<div class="mountain-range-mask"></div>
|
||||
<ul class="forest">
|
||||
<li class="hill"></li>
|
||||
<li class="hill"></li>
|
||||
<li class="hill"></li>
|
||||
</ul>
|
||||
<ul class="sparkles">
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
</ul>
|
||||
<div class="grass">
|
||||
<div class="pokemon">
|
||||
<div class="poke" id="bulbasaur">
|
||||
<div class="ear"></div>
|
||||
<div class="ear"></div>
|
||||
<div class="head"></div>
|
||||
<div class="leg"></div>
|
||||
<div class="bulba-body"></div>
|
||||
<div class="bulbs">
|
||||
<div class="bulb"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="poke" id="pikachu">
|
||||
<div class="ear"></div>
|
||||
<div class="ear"></div>
|
||||
<div class="hand"></div>
|
||||
<div class="pika-body"></div>
|
||||
<div class="head"></div>
|
||||
<div class="pika-tail"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'Animition'
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@/style/animition.scss';
|
||||
|
||||
</style>
|
||||
@@ -1,48 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 style="text-align:center">gin-vue-admin by 奇淼 And krank666</h2>
|
||||
<h2 style="text-align:center;margin:15px">点击动画获取联系方式</h2>
|
||||
|
||||
<el-drawer
|
||||
:visible.sync="drawer"
|
||||
title="联系方式"
|
||||
>
|
||||
<div style="text-align:center;margin-top:30px;">
|
||||
<img src="http://qmplusimg.henrongyi.top/yx.jpg" width="180" />
|
||||
<H3>krank666微信</H3>
|
||||
</div>
|
||||
<div style="text-align:center;margin-top:30px;">
|
||||
<img src="http://qmplusimg.henrongyi.top/jjz.jpg" width="180" />
|
||||
<H3>Mr.奇淼微信</H3>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<div @click="drawer = true">
|
||||
<Animition />
|
||||
</div>
|
||||
<h2 style="text-align:right;margin:40px;">
|
||||
当前版本号:v0.1.0
|
||||
</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Animition from '@/view/dashbord/component/animition.vue'
|
||||
export default {
|
||||
name: 'Dashbord',
|
||||
data() {
|
||||
return {
|
||||
drawer: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo'])
|
||||
},
|
||||
components: {
|
||||
Animition
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -1,163 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="search-term">
|
||||
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
|
||||
<el-form-item>
|
||||
<el-button @click="openDialog" type="primary">新增客户</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
ref="multipleTable"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
tooltip-effect="dark"
|
||||
>
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column label="接入日期" width="180">
|
||||
<template slot-scope="scope">{{ scope.row.CreatedAt|formatDate }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="姓名" prop="customerName" width="120"></el-table-column>
|
||||
<el-table-column label="电话" prop="customerPhoneData" width="120"></el-table-column>
|
||||
<el-table-column label="接入人ID" prop="sysUserId" width="120"></el-table-column>
|
||||
<el-table-column label="按钮组">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="updataCustomer(scope.row)" size="small" type="text">变更</el-button>
|
||||
<el-popover
|
||||
placement="top"
|
||||
width="160"
|
||||
v-model="visible">
|
||||
<p>确定要删除吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" @click="deleteCustomer(scope.row)">确定</el-button>
|
||||
</div>
|
||||
<el-button type="text" size="mini" slot="reference">删除</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
|
||||
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="新增Api">
|
||||
<el-form :inline="true" :model="form" label-width="80px">
|
||||
<el-form-item label="客户名">
|
||||
<el-input autocomplete="off" v-model="form.customerName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户电话">
|
||||
<el-input autocomplete="off" v-model="form.customerPhoneData"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
createExaCustomer,
|
||||
updataExaCustomer,
|
||||
deleteExaCustomer,
|
||||
getExaCustomer,
|
||||
getExaCustomerList
|
||||
} from '@/api/customer'
|
||||
import { formatTimeToStr } from '@/utils/data'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Customer',
|
||||
mixins: [infoList],
|
||||
data(){
|
||||
return{
|
||||
listApi: getExaCustomerList,
|
||||
listKey: 'customer',
|
||||
dialogFormVisible:false,
|
||||
visible:false,
|
||||
type:"",
|
||||
form:{
|
||||
customerName:"",
|
||||
customerPhoneData:""
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapGetters('user', ['token'])
|
||||
},
|
||||
filters: {
|
||||
formatDate: function(time) {
|
||||
if (time != null && time != '') {
|
||||
var date = new Date(time)
|
||||
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async updataCustomer(row){
|
||||
const res = await getExaCustomer(row)
|
||||
this.type = "update"
|
||||
if(res.success){
|
||||
this.form = res.data.customer
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
},
|
||||
closeDialog(){
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
async deleteCustomer(row){
|
||||
this.visible = false
|
||||
const res = await deleteExaCustomer(row)
|
||||
if (res.success){
|
||||
this.getTableData()
|
||||
}
|
||||
},
|
||||
async enterDialog(){
|
||||
let res
|
||||
switch (this.type) {
|
||||
case "create":
|
||||
res =await createExaCustomer(this.form)
|
||||
break;
|
||||
case "update":
|
||||
res =await updataExaCustomer(this.form)
|
||||
break;
|
||||
default:
|
||||
res =await createExaCustomer(this.form)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(res.success){
|
||||
this.dialogFormVisible = false
|
||||
this.getTableData()
|
||||
}
|
||||
},
|
||||
openDialog() {
|
||||
this.type = "create"
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,164 +0,0 @@
|
||||
<template>
|
||||
<div v-loading.fullscreen.lock="fullscreenLoading">
|
||||
<div class="upload">
|
||||
<el-upload
|
||||
:action="`${path}/fileUploadAndDownload/upload`"
|
||||
:before-upload="checkFile"
|
||||
:headers="{'x-token':token}"
|
||||
:on-error="uploadError"
|
||||
:on-success="uploadSuccess"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||
</el-upload>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column label="预览" width="100">
|
||||
<template slot-scope="scope">
|
||||
<img :alt="scope.row.alt" :src="scope.row.url" height="80" width="80" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="日期" prop="UpdatedAt" width="180">
|
||||
<template slot-scope="scope">
|
||||
<div>{{scope.row.UpdatedAt|formatDate}}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名" prop="name" width="180"></el-table-column>
|
||||
<el-table-column label="链接" prop="url"></el-table-column>
|
||||
<el-table-column label="标签" prop="tag" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
:type="scope.row.tag === 'jpg' ? 'primary' : 'success'"
|
||||
disable-transitions
|
||||
>{{scope.row.tag}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="downloadFile(scope.row)" size="small" type="text">下载</el-button>
|
||||
<el-button @click="deleteFile(scope.row)" size="small" type="text">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
import { mapGetters } from 'vuex'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { getFileList, deleteFile } from '@/api/fileUploadAndDownload'
|
||||
import { downloadImage } from '@/utils/downloadImg'
|
||||
import { formatTimeToStr } from '@/utils/data'
|
||||
export default {
|
||||
name: 'Upload',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
fullscreenLoading:false,
|
||||
listApi: getFileList,
|
||||
listKey: 'list',
|
||||
path: path,
|
||||
tableData: [
|
||||
{
|
||||
UpdatedAt: '2019-10-25',
|
||||
name: '文件名.jpg',
|
||||
url: 'http://qmplusimg.henrongyi.top/1571321688timg.jpg',
|
||||
tag: 'jpg'
|
||||
},
|
||||
{
|
||||
UpdatedAt: '2019-10-25',
|
||||
name: '文件名.jpg',
|
||||
url: 'http://qmplusimg.henrongyi.top/157162774820191015140921496.gif',
|
||||
tag: 'gif'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo', 'token'])
|
||||
},
|
||||
filters: {
|
||||
formatDate: function(time) {
|
||||
if (time != null && time != '') {
|
||||
var date = new Date(time)
|
||||
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async deleteFile(row) {
|
||||
this.$confirm('此操作将永久文件, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteFile(row)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
checkFile(file) {
|
||||
this.fullscreenLoading = true
|
||||
const isJPG = file.type === 'image/jpeg'
|
||||
const isPng = file.type === 'image/png'
|
||||
const isLt2M = file.size / 1024 / 1024 < 2
|
||||
if (!isJPG && !isPng) {
|
||||
this.$message.error('上传头像图片只能是 JPG或png 格式!')
|
||||
this.fullscreenLoading = false
|
||||
}
|
||||
if (!isLt2M) {
|
||||
this.$message.error('上传头像图片大小不能超过 2MB!')
|
||||
this.fullscreenLoading = false
|
||||
}
|
||||
return (isPng || isJPG) && isLt2M
|
||||
},
|
||||
uploadSuccess(res) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '上传成功'
|
||||
})
|
||||
if (res.success) {
|
||||
this.getTableData()
|
||||
}
|
||||
this.fullscreenLoading = false
|
||||
},
|
||||
uploadError() {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传失败'
|
||||
})
|
||||
this.fullscreenLoading = false
|
||||
|
||||
},
|
||||
downloadFile(row) {
|
||||
downloadImage(row.url, row.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-scrollbar style="height:calc(100vh)">
|
||||
<el-menu
|
||||
:class="['el-menu-vertical',!isCollapse&&'noCollapse']"
|
||||
:collapse="isCollapse"
|
||||
:collapse-transition="true"
|
||||
:default-active="active"
|
||||
@select="selectMenuItem"
|
||||
active-text-color="#fff"
|
||||
text-color="rgb(191, 203, 217)"
|
||||
unique-opened
|
||||
>
|
||||
<template v-for="item in asyncRouters[0].children">
|
||||
<aside-component :key="item.name" :routerInfo="item" v-if="!item.hidden" />
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import AsideComponent from '@/view/layout/aside/asideComponent'
|
||||
export default {
|
||||
name: 'Aside',
|
||||
data() {
|
||||
return {
|
||||
active: '',
|
||||
isCollapse: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectMenuItem(index) {
|
||||
if (index === this.$route.name) return
|
||||
this.$router.push({ name: index })
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('router', ['asyncRouters'])
|
||||
|
||||
},
|
||||
components: {
|
||||
AsideComponent
|
||||
},
|
||||
created() {
|
||||
this.active = this.$route.name
|
||||
let screenWidth = document.body.clientWidth
|
||||
if(screenWidth<1000){
|
||||
this.isCollapse = !this.isCollapse
|
||||
}
|
||||
this.$bus.on('totalCollapse', () => {
|
||||
this.isCollapse = !this.isCollapse
|
||||
})
|
||||
this.$bus.on('collapse', (item) => {
|
||||
this.isCollapse = item
|
||||
})
|
||||
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.off('totalCollapse')
|
||||
this.$bus.off('collapse')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-scrollbar {
|
||||
.el-scrollbar__view {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.menu-info {
|
||||
.menu-contorl {
|
||||
line-height: 52px;
|
||||
font-size: 20px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,309 +0,0 @@
|
||||
<template>
|
||||
<el-container class="layout-cont">
|
||||
<el-container :class="[isSider?'openside':'hideside',isMobile ? 'mobile': '']">
|
||||
<el-row :class="[isShadowBg?'shadowBg':'']" @click.native="changeShadow()"></el-row>
|
||||
<el-aside class="main-cont main-left">
|
||||
<Aside class="aside" />
|
||||
</el-aside>
|
||||
<!-- 分块滑动功能 -->
|
||||
<el-main class="main-cont main-right">
|
||||
<el-header class="header-cont">
|
||||
<div @click="totalCollapse" class="menu-total">
|
||||
<i class="el-icon-s-unfold" v-if="isCollapse"></i>
|
||||
<i class="el-icon-s-fold" v-else></i>
|
||||
</div>
|
||||
<h1 class="admin-title">Gin-Vue-Admin</h1>
|
||||
<div class="fl-right right-box">
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
<img :src="userInfo.headerImg" height="30" width="30" />
|
||||
{{userInfo.nickName}}
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</span>
|
||||
<el-dropdown-menu class="dropdown-group" slot="dropdown">
|
||||
<el-dropdown-item>
|
||||
<span>
|
||||
更多信息
|
||||
<el-badge is-dot />
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="showPassword=true" icon="el-icon-s-custom">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="toPerson" icon="el-icon-s-custom">个人信息</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="LoginOut" icon="el-icon-table-lamp">登 出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-dialog
|
||||
title="修改密码"
|
||||
:visible.sync="showPassword"
|
||||
@close="clearPassword"
|
||||
width="360px"
|
||||
>
|
||||
<el-form ref="modifyPwdForm" :model="pwdModify" :rules="rules" label-width="80px">
|
||||
<el-form-item prop="password" :minlength="6" label="原密码">
|
||||
<el-input v-model="pwdModify.password" show-password></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="newPassword" :minlength="6" label="新密码">
|
||||
<el-input v-model="pwdModify.newPassword" show-password></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="confirmPassword" :minlength="6" label="确认密码">
|
||||
<el-input v-model="pwdModify.confirmPassword" show-password></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPassword=false">取 消</el-button>
|
||||
<el-button type="primary" @click="savePassword">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</el-header>
|
||||
<!-- 当前面包屑用路由自动生成可根据需求修改 -->
|
||||
<!--
|
||||
:to="{ path: item.path }" 暂时注释不用-->
|
||||
<el-breadcrumb class="breadcrumb" separator-class="el-icon-arrow-right">
|
||||
<el-breadcrumb-item
|
||||
:key="item.path"
|
||||
v-for="item in matched.slice(1,matched.length)"
|
||||
>{{item.meta.title}}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
<transition mode="out-in" name="el-fade-in-linear">
|
||||
<router-view class="admin-box"></router-view>
|
||||
</transition>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Aside from '@/view/layout/aside'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import { changePassword } from '@/api/user'
|
||||
export default {
|
||||
name: 'Layout',
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
isSider: true,
|
||||
isMobile: false,
|
||||
isShadowBg: false,
|
||||
showPassword: false,
|
||||
pwdModify: {},
|
||||
rules: {
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' }
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: '请输入新密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: '请输入确认密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value !== this.pwdModify.newPassword) {
|
||||
callback(new Error('两次密码不一致'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Aside
|
||||
},
|
||||
created() {
|
||||
let screenWidth = document.body.clientWidth
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = !this.isCollapse
|
||||
} else {
|
||||
this.isMobile = false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginOut']),
|
||||
totalCollapse() {
|
||||
this.isCollapse = !this.isCollapse
|
||||
this.isSider = !this.isCollapse
|
||||
this.isShadowBg = !this.isCollapse
|
||||
this.$bus.emit('totalCollapse')
|
||||
},
|
||||
toPerson() {
|
||||
this.$router.push({ name: 'person' })
|
||||
},
|
||||
changeShadow() {
|
||||
this.isShadowBg = !this.isShadowBg
|
||||
this.isSider = !!this.isCollapse
|
||||
this.totalCollapse()
|
||||
},
|
||||
savePassword() {
|
||||
this.$refs.modifyPwdForm.validate(valid => {
|
||||
if (valid) {
|
||||
changePassword({
|
||||
username: this.userInfo.userName,
|
||||
password: this.pwdModify.password,
|
||||
newPassword: this.pwdModify.newPassword
|
||||
}).then(() => {
|
||||
this.$message.success('修改密码成功!')
|
||||
this.showPassword = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
clearPassword() {
|
||||
this.pwdModify = {
|
||||
password: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
}
|
||||
this.$refs.modifyPwdForm.clearValidate()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo']),
|
||||
title() {
|
||||
return this.$route.meta.title || '当前页面'
|
||||
},
|
||||
matched() {
|
||||
return this.$route.matched
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.onresize = () => {
|
||||
return (() => {
|
||||
let screenWidth = document.body.clientWidth
|
||||
if (!this.screenWidth && this.isSider) {
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = true
|
||||
this.$bus.emit('collapse', this.isCollapse)
|
||||
}
|
||||
} else {
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = true
|
||||
} else {
|
||||
this.isMobile = false
|
||||
}
|
||||
}
|
||||
})()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$headerHigh: 52px;
|
||||
$mainHight: 100vh;
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown-group {
|
||||
min-width: 100px;
|
||||
}
|
||||
.el-scrollbar__wrap {
|
||||
padding-bottom: 17px;
|
||||
}
|
||||
.layout-cont {
|
||||
.right-box {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
.menu-contorl {
|
||||
line-height: 52px;
|
||||
font-size: 20px;
|
||||
color: #eee;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.header-cont {
|
||||
height: $headerHigh !important;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
line-height: $headerHigh;
|
||||
}
|
||||
.main-cont {
|
||||
.breadcrumb {
|
||||
line-height: 24px;
|
||||
// padding: 6px;
|
||||
// border-bottom: 1px solid #eee;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
&.el-main {
|
||||
overflow: auto;
|
||||
// padding: 0px 10px;
|
||||
// background: #fff;
|
||||
}
|
||||
height: $mainHight !important;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
.menu-total {
|
||||
// z-index: 5;
|
||||
// position: absolute;
|
||||
// top: 10px;
|
||||
// right: -35px;
|
||||
margin-left: -10px;
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-size: 30px;
|
||||
// border: 0 solid #ffffff;
|
||||
// border-radius: 50%;
|
||||
// background: #fff;
|
||||
}
|
||||
.aside {
|
||||
overflow: auto;
|
||||
// background: #fff;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu-vertical {
|
||||
height: 100vh !important;
|
||||
visibility: auto;
|
||||
&:not(.el-menu--collapse) {
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
&.main-left {
|
||||
width: auto !important;
|
||||
}
|
||||
&.main-right {
|
||||
.admin-title {
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
vertical-align: middle;
|
||||
margin-left: 20px;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
&.collapse {
|
||||
width: 53px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,128 +0,0 @@
|
||||
<template>
|
||||
<el-container class="login-regist-box">
|
||||
<vue-particle-line></vue-particle-line>
|
||||
<el-main class="login-box">
|
||||
<h1 class="title-1">GIN-VUE-ADMIN</h1>
|
||||
<el-form :model="loginForm" :rules="rules" ref="loginForm">
|
||||
<el-form-item prop="username">
|
||||
<el-input placeholder="请输入用户名" v-model="loginForm.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请输入密码"
|
||||
v-model="loginForm.password"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item style="position:relative">
|
||||
<el-input
|
||||
v-model="loginForm.captcha"
|
||||
name="logVerify"
|
||||
placeholder="请输入验证码"
|
||||
maxlength="10"
|
||||
/>
|
||||
<img :src="path + picPath" alt="请输入验证码" @click="loginVefify()" class="vPic">
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="submitForm" style="width:100%">登 录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<h3 class="title-3 fl-right">测试用户:admin 密码:123456</h3>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { captcha } from '@/api/user'
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
const checkUsername = (rule, value, callback) => {
|
||||
if (value.length < 5 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的用户名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkPassword = (rule, value, callback) => {
|
||||
if (value.length < 6 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的密码'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lock: 'lock',
|
||||
loginForm: {
|
||||
username: '',
|
||||
password: '',
|
||||
captcha:'',
|
||||
captchaId: '',
|
||||
},
|
||||
rules: {
|
||||
username: [{ validator: checkUsername, trigger: 'blur' }],
|
||||
password: [{ validator: checkPassword, trigger: 'blur' }]
|
||||
},
|
||||
path:path,
|
||||
logVerify:'',
|
||||
picPath:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loginVefify()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginIn']),
|
||||
async login() {
|
||||
await this.LoginIn(this.loginForm)
|
||||
},
|
||||
async submitForm() {
|
||||
this.$refs.loginForm.validate(async v => {
|
||||
if (v) {
|
||||
await this.login()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请正确填写登录信息',
|
||||
showClose: true
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
changeLock() {
|
||||
this.lock === 'lock' ? (this.lock = 'unlock') : (this.lock = 'lock')
|
||||
},
|
||||
loginVefify() {
|
||||
captcha({}).then(ele=>{
|
||||
this.picPath = ele.data.picPath
|
||||
this.loginForm.captchaId = ele.data.captchaId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-regist-box {
|
||||
background: #fff;
|
||||
height: 100vh;
|
||||
.login-box {
|
||||
width: 40vw;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -22vw;
|
||||
top: 25vh;
|
||||
}
|
||||
.vPic{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 0px; // 适配ie
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,121 +0,0 @@
|
||||
<template>
|
||||
<el-container class="login-regist-box">
|
||||
<vue-particle-line></vue-particle-line>
|
||||
<el-main class="login-box">
|
||||
<h1 class="title-1">GIN-VUE-ADMIN</h1>
|
||||
<el-form :model="registForm" :rules="rules" ref="registForm">
|
||||
<el-form-item prop="username">
|
||||
<el-input placeholder="请输入用户名" v-model="registForm.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请输入密码"
|
||||
v-model="registForm.password"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="rePassword">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请再次输入密码"
|
||||
v-model="registForm.rePassword"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="submitForm" style="width:100%">注 册</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { regist } from '@/api/user'
|
||||
export default {
|
||||
name: 'Regist',
|
||||
data() {
|
||||
const ratioPassword = (rule, value, callback) => {
|
||||
if (value != this.registForm.password) {
|
||||
return callback(new Error('两次密码不同'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkUsername = (rule, value, callback) => {
|
||||
if (value.length < 5 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的用户名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkPassword = (rule, value, callback) => {
|
||||
if (value.length < 6 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的密码'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lock: 'lock',
|
||||
registForm: {
|
||||
username: '',
|
||||
password: '',
|
||||
rePassword: ''
|
||||
},
|
||||
rules: {
|
||||
username: [{ validator: checkUsername, trigger: 'blur' }],
|
||||
password: [{ validator: checkPassword, trigger: 'blur' }],
|
||||
rePassword: [{ validator: ratioPassword, trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginIn']),
|
||||
async submitForm() {
|
||||
this.$refs.registForm.validate(async v => {
|
||||
if (v) {
|
||||
const res = await regist(this.registForm)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '注册成功',
|
||||
showClose: true
|
||||
})
|
||||
await this.LoginIn(this.registForm)
|
||||
}
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请正确填写注册信息',
|
||||
showClose: true
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
changeLock() {
|
||||
this.lock === 'lock' ? (this.lock = 'unlock') : (this.lock = 'lock')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-regist-box {
|
||||
background: #fff;
|
||||
height: 100vh;
|
||||
.login-box {
|
||||
width: 40vw;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -22vw;
|
||||
top: 25vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,70 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="fl-left left-mg-xs">
|
||||
<el-upload
|
||||
:headers="{'x-token':token}"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:show-file-list="false"
|
||||
:action="`${path}/user/uploadHeaderImg`"
|
||||
class="avatar-uploader"
|
||||
name="headerImg"
|
||||
>
|
||||
<img :src="userInfo.headerImg" class="avatar" v-if="userInfo.headerImg" />
|
||||
<i class="el-icon-plus avatar-uploader-icon" v-else></i>
|
||||
</el-upload>
|
||||
|
||||
<!-- <el-avatar :size="120" :src="userInfo.headerImg" shape="square"></el-avatar> -->
|
||||
</div>
|
||||
<div class="fl-left left-mg-lg">
|
||||
<div>用户ID:{{userInfo.uuid}}</div>
|
||||
<div>用户昵称:{{userInfo.nickName}}</div>
|
||||
<div>用户组:{{userInfo.authority&&userInfo.authority.authorityName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
export default {
|
||||
name: 'Person',
|
||||
data(){
|
||||
return {
|
||||
path:path
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo', 'token'])
|
||||
},
|
||||
methods:{
|
||||
...mapMutations('user',['ResetUserInfo']),
|
||||
handleAvatarSuccess(res){
|
||||
this.ResetUserInfo({headerImg:res.data.user.headerImg})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -1,203 +0,0 @@
|
||||
<template>
|
||||
<div class="authority">
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addAuthority('0')" type="primary">新增角色</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||
border
|
||||
row-key="ID"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="id" min-width="180" prop="ID"></el-table-column>
|
||||
|
||||
<el-table-column label="角色id" min-width="180" prop="authorityId"></el-table-column>
|
||||
<el-table-column label="角色名称" min-width="180" prop="authorityName"></el-table-column>
|
||||
<el-table-column fixed="right" label="操作" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="opdendrawer(scope.row)" size="small" type="text">设置权限</el-button>
|
||||
<el-button @click="deleteAuth(scope.row)" size="small" type="text">删除角色</el-button>
|
||||
<el-button @click="addAuthority(scope.row.authorityId)" size="small" type="text">新增子角色</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 新增角色弹窗 -->
|
||||
<el-dialog :visible.sync="dialogFormVisible" title="新增角色">
|
||||
<el-form :model="form" :rules="rules" ref="authorityForm">
|
||||
<el-form-item label="父级角色ID" prop="parentId">
|
||||
<el-input autocomplete="off" disabled v-model="form.parentId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色ID" prop="authorityId">
|
||||
<el-input autocomplete="off" v-model="form.authorityId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色姓名" prop="authorityName">
|
||||
<el-input autocomplete="off" v-model="form.authorityName"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer :visible.sync="drawer" :with-header="false" size="40%" title="角色配置" v-if="drawer">
|
||||
<el-tabs class="role-box" type="border-card">
|
||||
<el-tab-pane label="角色菜单">
|
||||
<Menus :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="角色api">
|
||||
<apis :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="资源权限">
|
||||
<Datas :authority="tableData" :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
|
||||
import {
|
||||
getAuthorityList,
|
||||
deleteAuthority,
|
||||
createAuthority
|
||||
} from '@/api/authority'
|
||||
|
||||
import Menus from '@/view/superAdmin/authority/components/menus'
|
||||
import Apis from '@/view/superAdmin/authority/components/apis'
|
||||
import Datas from '@/view/superAdmin/authority/components/datas'
|
||||
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
export default {
|
||||
name: 'Authority',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getAuthorityList,
|
||||
listKey: 'list',
|
||||
drawer: false,
|
||||
activeRow: {},
|
||||
activeUserId: 0,
|
||||
dialogFormVisible: false,
|
||||
apiDialogFlag: false,
|
||||
form: {
|
||||
authorityId: '',
|
||||
authorityName: '',
|
||||
parentId: '0'
|
||||
},
|
||||
rules: {
|
||||
authorityId: [
|
||||
{ required: true, message: '请输入角色ID', trigger: 'blur' }
|
||||
],
|
||||
authorityName: [
|
||||
{ required: true, message: '请输入角色名', trigger: 'blur' }
|
||||
],
|
||||
parentId: [
|
||||
{ required: true, message: '请选择请求方式', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Menus,
|
||||
Apis,
|
||||
Datas
|
||||
},
|
||||
methods: {
|
||||
opdendrawer(row) {
|
||||
this.drawer = true
|
||||
this.activeRow = row
|
||||
},
|
||||
// 删除角色
|
||||
deleteAuth(row) {
|
||||
this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteAuthority({ authorityId: row.authorityId })
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 初始化表单
|
||||
initForm() {
|
||||
for (const key in this.form) {
|
||||
this.form[key] = ''
|
||||
}
|
||||
},
|
||||
// 关闭窗口
|
||||
closeDialog() {
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
this.apiDialogFlag = false
|
||||
},
|
||||
// 确定弹窗
|
||||
|
||||
async enterDialog() {
|
||||
if (this.form.authorityId == '0') {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '角色id不能为0'
|
||||
})
|
||||
return false
|
||||
}
|
||||
this.$refs.authorityForm.validate(async valid => {
|
||||
if (valid) {
|
||||
const res = await createAuthority(this.form)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
this.closeDialog()
|
||||
}
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 增加角色
|
||||
addAuthority(parentId) {
|
||||
this.form.parentId = parentId
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageSize = 999
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.authority {
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.role-box {
|
||||
.el-tabs__content {
|
||||
height: calc(100vh - 150px);
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,238 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addMenu('0')" type="primary">新增根菜单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
|
||||
<el-table :data="tableData" border row-key="ID" stripe>
|
||||
<el-table-column label="ID" min-width="100" prop="ID"></el-table-column>
|
||||
<el-table-column label="路由Name" min-width="160" prop="name"></el-table-column>
|
||||
<el-table-column label="是否隐藏" min-width="100" prop="hidden">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.hidden?"隐藏":"显示"}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="父节点" min-width="90" prop="parentId"></el-table-column>
|
||||
<el-table-column label="排序" min-width="70" prop="sort"></el-table-column>
|
||||
<el-table-column label="文件路径" min-width="360" prop="component"></el-table-column>
|
||||
<el-table-column label="展示名称" min-width="120" prop="authorityName">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.meta.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图标" min-width="140" prop="authorityName">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.meta.icon}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="300">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="deleteMenu(scope.row.ID)" size="small" type="text">删除菜单</el-button>
|
||||
<el-button @click="editMenu(scope.row.ID)" size="small" type="text">编辑菜单</el-button>
|
||||
<el-button @click="addMenu(scope.row.ID)" size="small" type="text">添加子菜单</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog :before-close="handleClose" :visible.sync="dialogFormVisible" title="新增菜单">
|
||||
<el-form :inline="true" :model="form" :rules="rules" label-width="85px" ref="menuForm">
|
||||
<el-form-item label="路由name" prop="path">
|
||||
<el-input autocomplete="off" placeholder="唯一英文字符串" v-model="form.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否隐藏">
|
||||
<el-select placeholder="是否在列表隐藏" v-model="form.hidden">
|
||||
<el-option :value="false" label="否"></el-option>
|
||||
<el-option :value="true" label="是"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="父节点Id">
|
||||
<el-input autocomplete="off" disabled v-model="form.parentId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件路径" prop="component">
|
||||
<el-input autocomplete="off" v-model="form.component"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="展示名称" prop="meta.title">
|
||||
<el-input autocomplete="off" v-model="form.meta.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图标">
|
||||
<el-input autocomplete="off" v-model="form.meta.icon"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序标记">
|
||||
<el-input autocomplete="off" v-model="form.sort"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="warning">新增菜单需要在角色管理内配置权限才可使用</div>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
|
||||
import {
|
||||
updataBaseMenu,
|
||||
getMenuList,
|
||||
addBaseMenu,
|
||||
deleteBaseMenu,
|
||||
getBaseMenuById
|
||||
} from '@/api/menu'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
export default {
|
||||
name: 'Menus',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getMenuList,
|
||||
listKey: 'list',
|
||||
dialogFormVisible: false,
|
||||
form: {
|
||||
ID: 0,
|
||||
path: '',
|
||||
name: '',
|
||||
hidden: '',
|
||||
parentId: '',
|
||||
component: '',
|
||||
meta: {
|
||||
title: '',
|
||||
icon: ''
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
|
||||
component: [
|
||||
{ required: true, message: '请输入文件路径', trigger: 'blur' }
|
||||
],
|
||||
'meta.title': [
|
||||
{ required: true, message: '请输入菜单展示名称', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
isEdit: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
this.initForm()
|
||||
done()
|
||||
},
|
||||
// 懒加载子菜单
|
||||
load(tree, treeNode, resolve) {
|
||||
resolve([
|
||||
{
|
||||
id: 31,
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
}
|
||||
])
|
||||
},
|
||||
// 删除菜单
|
||||
deleteMenu(ID) {
|
||||
this.$confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteBaseMenu({ ID })
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 初始化弹窗内表格方法
|
||||
initForm() {
|
||||
this.form = {
|
||||
path: '',
|
||||
name: '',
|
||||
hidden: '',
|
||||
parentId: '',
|
||||
component: '',
|
||||
meta: {
|
||||
title: '',
|
||||
icon: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
// 关闭弹窗
|
||||
closeDialog() {
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
// 添加menu
|
||||
async enterDialog() {
|
||||
this.$refs.menuForm.validate(async valid => {
|
||||
if (valid) {
|
||||
let res
|
||||
this.form.name = this.form.path
|
||||
if (this.isEdit) {
|
||||
res = await updataBaseMenu(this.form)
|
||||
} else {
|
||||
res = await addBaseMenu(this.form)
|
||||
}
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '添加失败!'
|
||||
})
|
||||
}
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 添加菜单方法,id为 0则为添加根菜单
|
||||
addMenu(id) {
|
||||
this.form.parentId = String(id)
|
||||
this.isEdit = false
|
||||
this.dialogFormVisible = true
|
||||
},
|
||||
// 修改菜单方法
|
||||
async editMenu(id) {
|
||||
const res = await getBaseMenuById({ id })
|
||||
this.form = res.data.menu
|
||||
this.dialogFormVisible = true
|
||||
this.isEdit = true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageSize = 999
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.warning {
|
||||
color: #dc143c;
|
||||
}
|
||||
</style>
|
||||
@@ -1,203 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addUser" type="primary">新增用户</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column label="头像" min-width="50">
|
||||
<template slot-scope="scope">
|
||||
<div :style="{'textAlign':'center'}">
|
||||
<img :src="scope.row.headerImg" height="50" width="50" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="uuid" min-width="250" prop="uuid"></el-table-column>
|
||||
<el-table-column label="用户名" min-width="150" prop="userName"></el-table-column>
|
||||
<el-table-column label="昵称" min-width="150" prop="nickName"></el-table-column>
|
||||
<el-table-column label="用户角色" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-select
|
||||
@change="changeAuthority(scope.row)"
|
||||
placeholder="请选择"
|
||||
v-model="scope.row.authority.authorityId"
|
||||
>
|
||||
<el-option
|
||||
:key="item.authorityId"
|
||||
:label="item.authorityName"
|
||||
:value="item.authorityId"
|
||||
v-for="item in authOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
|
||||
<el-dialog :visible.sync="addUserDialog" custom-class="user-dialog" title="新增用户">
|
||||
<el-form :rules="rules" ref="userForm" :model="userInfo" >
|
||||
<el-form-item label="用户名" label-width="80px" prop="username">
|
||||
<el-input v-model="userInfo.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" label-width="80px" prop="password">
|
||||
<el-input v-model="userInfo.password"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="别名" label-width="80px" prop="nickName">
|
||||
<el-input v-model="userInfo.nickName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" label-width="80px">
|
||||
<el-upload
|
||||
:headers="{'x-token':token}"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:show-file-list="false"
|
||||
:action="`${path}/fileUploadAndDownload/upload?noSave=1`"
|
||||
class="avatar-uploader"
|
||||
name="file"
|
||||
>
|
||||
<img :src="userInfo.headerImg" class="avatar" v-if="userInfo.headerImg" />
|
||||
<i class="el-icon-plus avatar-uploader-icon" v-else></i>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户角色" label-width="80px" prop="authorityId">
|
||||
<el-select placeholder="请选择" v-model="userInfo.authorityId">
|
||||
<el-option
|
||||
:key="item.authorityId"
|
||||
:label="item.authorityName"
|
||||
:value="item.authorityId"
|
||||
v-for="item in authOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeAddUserDialog">取 消</el-button>
|
||||
<el-button @click="enterAddUserDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
import { getUserList, setUserAuthority, regist } from '@/api/user'
|
||||
import { getAuthorityList } from '@/api/authority'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'Api',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getUserList,
|
||||
listKey: 'userList',
|
||||
path:path,
|
||||
authOptions: [],
|
||||
addUserDialog: false,
|
||||
userInfo: {
|
||||
username: '',
|
||||
password: '',
|
||||
nickName: '',
|
||||
headerImg: '',
|
||||
authorityId: ''
|
||||
},
|
||||
rules: {
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [
|
||||
{ required: true, message: '请输入用户密码', trigger: 'blur' }
|
||||
],
|
||||
nickName: [
|
||||
{ required: true, message: '请输入用户昵称', trigger: 'blur' }
|
||||
],
|
||||
authorityId: [
|
||||
{ required: true, message: '请选择用户角色', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['token'])
|
||||
},
|
||||
methods: {
|
||||
async enterAddUserDialog() {
|
||||
this.$refs.userForm.validate(async valid => {
|
||||
if (valid) {
|
||||
const res = await regist(this.userInfo)
|
||||
if (res.success) {
|
||||
this.$message({ type: 'success', message: '创建成功' })
|
||||
}
|
||||
await this.getTableData()
|
||||
this.closeAddUserDialog()
|
||||
}
|
||||
})
|
||||
},
|
||||
closeAddUserDialog() {
|
||||
this.userInfo = {
|
||||
username: '',
|
||||
password: '',
|
||||
nickName: '',
|
||||
headerImg: '',
|
||||
authorityId: ''
|
||||
}
|
||||
this.addUserDialog = false
|
||||
},
|
||||
handleAvatarSuccess(res) {
|
||||
this.userInfo.headerImg = res.data.file.url
|
||||
},
|
||||
addUser() {
|
||||
this.addUserDialog = true
|
||||
},
|
||||
async changeAuthority(row) {
|
||||
const res = await setUserAuthority({
|
||||
uuid: row.uuid,
|
||||
authorityId: row.authority.authorityId
|
||||
})
|
||||
if (res.success) {
|
||||
this.$message({ type: 'success', message: '角色设置成功' })
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const res = await getAuthorityList({ page: 1, pageSize: 999 })
|
||||
this.authOptions = res.data.list
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.user-dialog {
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px dashed #d9d9d9 !important;
|
||||
border-radius: 6px;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="dialogMiddle" ref="fieldDialogFrom" label-width="120px" label-position="left" :rules="rules">
|
||||
<el-form-item label="Field名称" prop="fieldName">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.fieldName" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="FieldJSON" prop="fieldJson">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.fieldJson" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库字段名" prop="columnName">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.columnName" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="Field数据类型" prop="fieldType">
|
||||
<el-col :span="8">
|
||||
<el-select v-model="dialogMiddle.fieldType" placeholder="请选择field数据类型">
|
||||
<el-option
|
||||
v-for="item in typeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:"FieldDialog",
|
||||
props:{
|
||||
dialogMiddle:{
|
||||
type:Object,
|
||||
default:function(){
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
visible:false,
|
||||
typeOptions:[
|
||||
{
|
||||
label:"字符串",
|
||||
value:"string"
|
||||
},
|
||||
{
|
||||
label:"整型",
|
||||
value:"int"
|
||||
},
|
||||
{
|
||||
label:"布尔值",
|
||||
value:"bool"
|
||||
},
|
||||
{
|
||||
label:"浮点型",
|
||||
value:"float64"
|
||||
},
|
||||
{
|
||||
label:"时间",
|
||||
value:"time.Time"
|
||||
},
|
||||
],
|
||||
rules:{
|
||||
fieldName:[ { required: true, message: '请输入field英文名', trigger: 'blur' }],
|
||||
fieldJson:[ { required: true, message: '请输入field格式化json', trigger: 'blur' }],
|
||||
fieldType:[ { required: true, message: '请选择field数据类型', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,186 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 初始版本自动化代码工具 -->
|
||||
<el-form ref="autoCodeForm" :rules="rules" :model="form" label-width="120px" :inline="true">
|
||||
<el-form-item label="Struct名称" prop="structName">
|
||||
<el-input v-model="form.structName" placeholder="首字母自动转换大写"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Struct简称" prop="abbreviation">
|
||||
<el-input v-model="form.abbreviation"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Package名称" prop="packageName">
|
||||
<el-input v-model="form.packageName"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 组件列表 -->
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="editAndAddField()" type="primary">新增Field</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="form.fields"
|
||||
border stripe>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序列"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldName"
|
||||
label="Field名"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldJson"
|
||||
label="FieldJson"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldType"
|
||||
label="Field数据类型"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" @click="editAndAddField(scope.row)">编辑</el-button>
|
||||
<el-popover
|
||||
placement="top"
|
||||
width="280"
|
||||
v-model="scope.row.visible">
|
||||
<p>这是一段内容这是一段内容确定删除吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" @click="deleteField(scope.$index)">确定</el-button>
|
||||
</div>
|
||||
<el-button type="danger" slot="reference">删除</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 组件列表 -->
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="enterForm" type="primary">生成代码包</el-button>
|
||||
</div>
|
||||
<!-- 组件弹窗 -->
|
||||
<el-dialog title="组件内容" :visible.sync="dialogFlag">
|
||||
<FieldDialog :dialogMiddle="dialogMiddle" ref="fieldDialog"/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button type="primary" @click="enterDialog">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const fieldTemplate={
|
||||
fieldName:"",
|
||||
fieldType:"",
|
||||
fieldJson:"",
|
||||
columnName:"",
|
||||
}
|
||||
|
||||
import FieldDialog from "@/view/systemTools/autoCode/component/fieldDialog.vue"
|
||||
import {toUpperCase} from "@/utils/toUpperCase.js"
|
||||
import {createTemp} from "@/api/autoCode.js"
|
||||
export default {
|
||||
name:"autoCode",
|
||||
data(){
|
||||
return{
|
||||
addFlag:"",
|
||||
form:{
|
||||
structName:"",
|
||||
packageName:"",
|
||||
abbreviation:"",
|
||||
fields:[]
|
||||
},
|
||||
rules:{
|
||||
structName:[{required: true, message: '请输入结构体名称', trigger: 'blur'}],
|
||||
abbreviation:[{required: true, message: '请输入结构体简称', trigger: 'blur'}],
|
||||
packageName:[{required: true, message: '请输入包名称', trigger: 'blur'}]
|
||||
},
|
||||
dialogMiddle:{},
|
||||
bk:{},
|
||||
dialogFlag:false
|
||||
}
|
||||
},
|
||||
components:{
|
||||
FieldDialog
|
||||
},
|
||||
methods:{
|
||||
editAndAddField(item){
|
||||
this.dialogFlag = true
|
||||
if(item){
|
||||
this.addFlag="edit"
|
||||
this.bk=JSON.parse(JSON.stringify(item))
|
||||
this.dialogMiddle = item
|
||||
}else{
|
||||
this.addFlag="add"
|
||||
this.dialogMiddle = JSON.parse(JSON.stringify(fieldTemplate))
|
||||
}
|
||||
},
|
||||
enterDialog(){
|
||||
this.$refs.fieldDialog.$refs.fieldDialogFrom.validate((valid) => {
|
||||
if (valid) {
|
||||
this.dialogMiddle.fieldName = toUpperCase(this.dialogMiddle.fieldName)
|
||||
if(this.addFlag=="add"){
|
||||
this.form.fields.push(this.dialogMiddle)
|
||||
}
|
||||
this.dialogFlag = false
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
closeDialog(){
|
||||
if(this.addFlag=="edit"){
|
||||
this.dialogMiddle = this.bk
|
||||
}
|
||||
this.dialogFlag = false
|
||||
},
|
||||
deleteField(index){
|
||||
this.form.fields.splice(index,1)
|
||||
},
|
||||
async enterForm(){
|
||||
if(this.form.fields.length<=0){
|
||||
this.$message({
|
||||
type:"error",
|
||||
message:"请填写至少一个field"
|
||||
})
|
||||
return false
|
||||
}
|
||||
this.$refs.autoCodeForm.validate(async (valid) => {
|
||||
if (valid) {
|
||||
this.form.structName = toUpperCase(this.form.structName)
|
||||
const data = await createTemp(this.form)
|
||||
const blob = new Blob([data])
|
||||
const fileName = 'ginvueadmin.zip'
|
||||
if ('download' in document.createElement('a')) { // 不是IE浏览器
|
||||
let url = window.URL.createObjectURL(blob)
|
||||
let link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
link.setAttribute('download', fileName)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link) // 下载完成移除元素
|
||||
window.URL.revokeObjectURL(url) // 释放掉blob对象
|
||||
} else { // IE 10+
|
||||
window.navigator.msSaveBlob(blob, fileName)
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scope lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div style="height:80vh">
|
||||
<iframe width="100%" height="100%" src="http://localhost:8888/form-generator/#/" frameborder="0"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"FormGenerator"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user