Compare commits
624 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30ce9f6eca | ||
|
|
1e32aaa77e | ||
|
|
9832947dfa | ||
|
|
ec5007c3b9 | ||
|
|
f1330bf4e8 | ||
|
|
ca9656a40f | ||
|
|
c5b6a2a53d | ||
|
|
f5dcdfeea4 | ||
|
|
b56c3b0e00 | ||
|
|
7f20cdecac | ||
|
|
4d11b76b39 | ||
|
|
32ea8f5278 | ||
|
|
83d2e79f96 | ||
|
|
79228bd947 | ||
|
|
f106afc0f9 | ||
|
|
95aeee54e7 | ||
|
|
251c217a40 | ||
|
|
1dbcf4ad7b | ||
|
|
9f6d8d2139 | ||
|
|
61394e577f | ||
|
|
9c78758cd6 | ||
|
|
c0fa6311ce | ||
|
|
984e9e7d27 | ||
|
|
4e0bb86b68 | ||
|
|
d965d5e30f | ||
|
|
13a3e8ec7a | ||
|
|
dbf9591b3b | ||
|
|
d06d27eef3 | ||
|
|
cdc52f32ea | ||
|
|
d3461f58bc | ||
|
|
b2e9637587 | ||
|
|
e618f8e404 | ||
|
|
803e3eda71 | ||
|
|
527b217557 | ||
|
|
6d5f833c29 | ||
|
|
f5846b0a6c | ||
|
|
4b0e64f817 | ||
|
|
ffd4e0672a | ||
|
|
237455f853 | ||
|
|
853fb4b210 | ||
|
|
6d28124299 | ||
|
|
5f96b50bad | ||
|
|
4d14bdffad | ||
|
|
00064607b8 | ||
|
|
d21dcba1ee | ||
|
|
25c5291338 | ||
|
|
e1bef1ce8a | ||
|
|
f1a1bb7838 | ||
|
|
00c95e33b3 | ||
|
|
f180b8d7d3 | ||
|
|
5016b76b04 | ||
|
|
27592b4f4a | ||
|
|
8048ba92c2 | ||
|
|
6f7df7e53e | ||
|
|
ec280224a8 | ||
|
|
59c6963f7c | ||
|
|
c2d70ce831 | ||
|
|
2d63b50989 | ||
|
|
0190984262 | ||
|
|
220d727605 | ||
|
|
f34f61cc25 | ||
|
|
06b5589d1f | ||
|
|
384d96d79d | ||
|
|
a3ec21cb0f | ||
|
|
7b74c28148 | ||
|
|
a58dc7b543 | ||
|
|
90224975fc | ||
|
|
e28d73a76c | ||
|
|
cca9807a4e | ||
|
|
708d7db320 | ||
|
|
b0409fc779 | ||
|
|
a81f5de321 | ||
|
|
e24d9dec01 | ||
|
|
e76a5bdb68 | ||
|
|
65ee76a79f | ||
|
|
8986299fea | ||
|
|
7ef6209c13 | ||
|
|
d5bd499899 | ||
|
|
dd1ed7b81e | ||
|
|
ee7cb5055c | ||
|
|
ac661150d7 | ||
|
|
f620bc3fec | ||
|
|
df65b88fe9 | ||
|
|
f6d259b620 | ||
|
|
6f3e026f4c | ||
|
|
d5fe4a3c89 | ||
|
|
85aae8587e | ||
|
|
bd5706bfa1 | ||
|
|
4d42b8834b | ||
|
|
5619441f61 | ||
|
|
695014a6d1 | ||
|
|
6474fba923 | ||
|
|
9c216e5b7d | ||
|
|
ac25dbe286 | ||
|
|
5a18223bc3 | ||
|
|
0d81431541 | ||
|
|
36c8448ed5 | ||
|
|
458a042701 | ||
|
|
9185e5d2a0 | ||
|
|
71550a3c0e | ||
|
|
eadad75590 | ||
|
|
dfffbe3823 | ||
|
|
608f177200 | ||
|
|
d60ff1688e | ||
|
|
589aaab298 | ||
|
|
0a2fbae9d8 | ||
|
|
30f097ed26 | ||
|
|
6d770bba17 | ||
|
|
7f6d64e921 | ||
|
|
2edf53a403 | ||
|
|
c107095d22 | ||
|
|
aaf84aae03 | ||
|
|
c44ecf08ff | ||
|
|
cb111fd9ba | ||
|
|
41bb7c6f29 | ||
|
|
aa36a5c690 | ||
|
|
d2d2b5cd89 | ||
|
|
b43813ab96 | ||
|
|
d5e54288c1 | ||
|
|
fb577ca7c1 | ||
|
|
a464c8058f | ||
|
|
f05a4e0cad | ||
|
|
bf7c22e0fa | ||
|
|
6aaceb27b4 | ||
|
|
4347bc793c | ||
|
|
4a7b5df1b7 | ||
|
|
b0b24a19d9 | ||
|
|
ace19f5da4 | ||
|
|
3449882a70 | ||
|
|
4f43bc2d63 | ||
|
|
67dd42dd16 | ||
|
|
c98e1c14a3 | ||
|
|
9af01c9842 | ||
|
|
682efbe3c3 | ||
|
|
90c727ee69 | ||
|
|
76bed8028a | ||
|
|
8433c3ad71 | ||
|
|
56c13b888e | ||
|
|
362059420d | ||
|
|
cd5fc4db19 | ||
|
|
25bd30b28c | ||
|
|
ae525435b0 | ||
|
|
bb4bce8389 | ||
|
|
380ef717d7 | ||
|
|
31bbcecb36 | ||
|
|
510de0c6d0 | ||
|
|
8719348c84 | ||
|
|
a38206f574 | ||
|
|
3e8e2b1421 | ||
|
|
2203d8bdb9 | ||
|
|
7902fe5c39 | ||
|
|
e03f485591 | ||
|
|
3e686bb2db | ||
|
|
3a9a0215b0 | ||
|
|
6f8ca56e16 | ||
|
|
81340a636b | ||
|
|
5f513bff9f | ||
|
|
0f83d0177a | ||
|
|
80db91ea97 | ||
|
|
79df30d0f8 | ||
|
|
f06e508c9d | ||
|
|
5f8c569a70 | ||
|
|
583cb9388a | ||
|
|
3c244fd44d | ||
|
|
c528a5344f | ||
|
|
7a08c293dc | ||
|
|
bb2303e789 | ||
|
|
d87343d70c | ||
|
|
cdfa049cc6 | ||
|
|
35f35bb1ee | ||
|
|
c33db3e60c | ||
|
|
4b92663b5e | ||
|
|
95d1c82c82 | ||
|
|
3c4af5210c | ||
|
|
b8e907ba62 | ||
|
|
61e03b8141 | ||
|
|
5b538c6596 | ||
|
|
2d602914ac | ||
|
|
e73311d074 | ||
|
|
3c5eff5603 | ||
|
|
b4e68fa018 | ||
|
|
9399f36232 | ||
|
|
4d3fb9db18 | ||
|
|
0f66390a2a | ||
|
|
9dfe6d273c | ||
|
|
fc113b640b | ||
|
|
48b8a5dc78 | ||
|
|
cb136fe143 | ||
|
|
41db81d0ac | ||
|
|
b7226f8b12 | ||
|
|
8071a552f7 | ||
|
|
57b3897eb3 | ||
|
|
8c4332f47d | ||
|
|
6ed88db8a4 | ||
|
|
de09f992bf | ||
|
|
40d3324266 | ||
|
|
efd42c81e0 | ||
|
|
c6b8a09356 | ||
|
|
19d9d66a38 | ||
|
|
2460e492cf | ||
|
|
46d16c45e6 | ||
|
|
26dee4026b | ||
|
|
488458b631 | ||
|
|
479a05b5d7 | ||
|
|
fcea893ec9 | ||
|
|
c82274821a | ||
|
|
0e6d94876d | ||
|
|
5b73366ffa | ||
|
|
6005c4839b | ||
|
|
c54b330cdf | ||
|
|
b5474d1d84 | ||
|
|
239c38cf64 | ||
|
|
a347d2a1d3 | ||
|
|
a912dc32f4 | ||
|
|
98ad02744b | ||
|
|
3e8b2d7d58 | ||
|
|
6b4bc47d08 | ||
|
|
e99138493b | ||
|
|
16fd9dc425 | ||
|
|
e5c4c747a4 | ||
|
|
29fff03f93 | ||
|
|
193110e456 | ||
|
|
2923ae216d | ||
|
|
2c28e11631 | ||
|
|
0f886b0446 | ||
|
|
6343627c2c | ||
|
|
3d07628050 | ||
|
|
03c4f65081 | ||
|
|
7755c6a77b | ||
|
|
38270be962 | ||
|
|
03d3c8b5a8 | ||
|
|
27588467a2 | ||
|
|
da13b91b66 | ||
|
|
ab4ad6c2b7 | ||
|
|
9b785369ab | ||
|
|
1b84f3f1ea | ||
|
|
f1cf5f9f88 | ||
|
|
55adb8efa9 | ||
|
|
34ea1db585 | ||
|
|
fec84f2682 | ||
|
|
33e5c2a7f9 | ||
|
|
30e323dc9a | ||
|
|
b37e593ada | ||
|
|
51c6ad1fd9 | ||
|
|
ff055e5a2c | ||
|
|
441330e455 | ||
|
|
9ce0814e2b | ||
|
|
0ed12d1615 | ||
|
|
ecd5d607a8 | ||
|
|
ef1096f56a | ||
|
|
d79514d821 | ||
|
|
97b931f782 | ||
|
|
b8fb106aaf | ||
|
|
917746a1a7 | ||
|
|
2faaa65325 | ||
|
|
d0ce24a2f6 | ||
|
|
f879c4aa2b | ||
|
|
fcfa66100c | ||
|
|
3012ff84a2 | ||
|
|
b47e5d4c5d | ||
|
|
383ff130b9 | ||
|
|
3774afe553 | ||
|
|
4381d938be | ||
|
|
4807547d73 | ||
|
|
9945b5fcd0 | ||
|
|
6dd514b84a | ||
|
|
7b36eca609 | ||
|
|
6471c4641d | ||
|
|
d150a8333d | ||
|
|
d35fc522bc | ||
|
|
89848cebf3 | ||
|
|
2bd40cfb3b | ||
|
|
ca28d791aa | ||
|
|
ff18d2f30a | ||
|
|
e20600f0c2 | ||
|
|
31c24cd340 | ||
|
|
0045602e6b | ||
|
|
5c04c9eeaf | ||
|
|
5598f62456 | ||
|
|
71930d492e | ||
|
|
64c478a45b | ||
|
|
97bcee429b | ||
|
|
cca4c9fceb | ||
|
|
b52a38d297 | ||
|
|
84744938be | ||
|
|
2f1234cda8 | ||
|
|
9b3092b3fd | ||
|
|
4c6e915def | ||
|
|
284ee5000a | ||
|
|
8174916c92 | ||
|
|
b1149279c0 | ||
|
|
f08fe24174 | ||
|
|
ca6e7a4528 | ||
|
|
0cf1738c0a | ||
|
|
ea7ad4b1ca | ||
|
|
0745ad9254 | ||
|
|
6d5d72999b | ||
|
|
213ec8bd72 | ||
|
|
b2fc171609 | ||
|
|
88352fe065 | ||
|
|
f4c83c0168 | ||
|
|
f32e43863b | ||
|
|
78c200ca61 | ||
|
|
93f4334eb6 | ||
|
|
bfb15aea09 | ||
|
|
e5fed46ae1 | ||
|
|
6d9195ac83 | ||
|
|
13936b39aa | ||
|
|
0fcd30bbfd | ||
|
|
e89ef5496c | ||
|
|
94d62b8d79 | ||
|
|
9bb0422c1c | ||
|
|
5b2616fac1 | ||
|
|
12e2ce99e1 | ||
|
|
fcc5180ebf | ||
|
|
48bd0c1b3c | ||
|
|
db27985036 | ||
|
|
341404eafa | ||
|
|
af8f9745e9 | ||
|
|
001892824c | ||
|
|
b5480816ef | ||
|
|
53a33e4999 | ||
|
|
50d8aac20f | ||
|
|
b5b102d13f | ||
|
|
a01d66a318 | ||
|
|
4f50845b66 | ||
|
|
c50f99e7b3 | ||
|
|
30e2d08784 | ||
|
|
4e926d8d1a | ||
|
|
0eeb4b3add | ||
|
|
9fb182e21a | ||
|
|
03fde3699b | ||
|
|
49250ebf45 | ||
|
|
efaeb5b39d | ||
|
|
04f53da686 | ||
|
|
63b4c27c8f | ||
|
|
0285bf50fb | ||
|
|
9345166422 | ||
|
|
c60f9c71bf | ||
|
|
d1b6118052 | ||
|
|
0a14b530b6 | ||
|
|
fdc83d4550 | ||
|
|
db4ee1ed7e | ||
|
|
8f8f4d72b5 | ||
|
|
e0d7731626 | ||
|
|
c208456bc2 | ||
|
|
671d4ad246 | ||
|
|
e0ab6b8462 | ||
|
|
54325da259 | ||
|
|
709b85e453 | ||
|
|
f0999eac46 | ||
|
|
c94fae173e | ||
|
|
42c6389023 | ||
|
|
60b0043a78 | ||
|
|
6fd899bca2 | ||
|
|
cb0c7744ac | ||
|
|
b5e939fdb4 | ||
|
|
5b3c464faf | ||
|
|
2c6331eb75 | ||
|
|
274352613a | ||
|
|
4bfb7c2e04 | ||
|
|
9fb421360f | ||
|
|
8818b350d6 | ||
|
|
5122b68aca | ||
|
|
ed71f5e9c8 | ||
|
|
84cc2728bd | ||
|
|
5714ddcbe8 | ||
|
|
b57b2bc931 | ||
|
|
3914b32637 | ||
|
|
81fef80c51 | ||
|
|
d06e51ba21 | ||
|
|
dfd25c1516 | ||
|
|
11b2f67ed1 | ||
|
|
7697c8b0c0 | ||
|
|
b83262af5f | ||
|
|
f3316d14c7 | ||
|
|
5acf1ae3d4 | ||
|
|
e7a7f4293f | ||
|
|
cb28f67b8d | ||
|
|
973a923bf8 | ||
|
|
128b9dc21a | ||
|
|
72ed490334 | ||
|
|
d970591a78 | ||
|
|
27a5dd3555 | ||
|
|
d739c34e6c | ||
|
|
c71defa8fb | ||
|
|
777133bd49 | ||
|
|
cbbd2ea017 | ||
|
|
1daf0dd8cc | ||
|
|
c6c838d759 | ||
|
|
da826a21c9 | ||
|
|
d0ce6090ad | ||
|
|
8646d0a69e | ||
|
|
0252bd0f0b | ||
|
|
981b3d87e2 | ||
|
|
d88da8229f | ||
|
|
72347c8149 | ||
|
|
495bf2ed58 | ||
|
|
90047c10d7 | ||
|
|
7dbbd412d8 | ||
|
|
75876682fb | ||
|
|
e107b42f53 | ||
|
|
be4b34c884 | ||
|
|
9a9407641c | ||
|
|
67f8b61f47 | ||
|
|
ac5ab0b70b | ||
|
|
d503d8b2fc | ||
|
|
e87cb91332 | ||
|
|
7aa25e8342 | ||
|
|
ef015d9e4c | ||
|
|
de81e5f5ae | ||
|
|
24f3e697b8 | ||
|
|
2b8459680b | ||
|
|
b1313bf52e | ||
|
|
a61613aca4 | ||
|
|
41996876ca | ||
|
|
a99afdc833 | ||
|
|
305eed408c | ||
|
|
b209505f99 | ||
|
|
4198c154aa | ||
|
|
e0edc2d2d9 | ||
|
|
6465e5e30a | ||
|
|
84d4e604b1 | ||
|
|
6ae48b6543 | ||
|
|
25047e081c | ||
|
|
ef1354478e | ||
|
|
8edc49f4e7 | ||
|
|
92c2d79dc1 | ||
|
|
1dadf93449 | ||
|
|
e6201b00c1 | ||
|
|
187b17ed01 | ||
|
|
0df486a677 | ||
|
|
e04c9584e3 | ||
|
|
c0407267b9 | ||
|
|
32c1cfb3a7 | ||
|
|
4397cbe643 | ||
|
|
c5596919f5 | ||
|
|
e3f2e15c43 | ||
|
|
26ea8dd907 | ||
|
|
d619f0fae8 | ||
|
|
3b5199b60b | ||
|
|
02dda60e60 | ||
|
|
42e30bf380 | ||
|
|
4ed8d5fcf2 | ||
|
|
e1e42c0ce0 | ||
|
|
ac9d5f32f7 | ||
|
|
f8cfb32b13 | ||
|
|
846510c309 | ||
|
|
244f248ad5 | ||
|
|
61e5cfe617 | ||
|
|
99c591d6f9 | ||
|
|
d34e555aa0 | ||
|
|
2daea0060d | ||
|
|
74d05557e1 | ||
|
|
6d1a47afea | ||
|
|
40fe027753 | ||
|
|
3a23ca72e6 | ||
|
|
6bddebafff | ||
|
|
e4d3254869 | ||
|
|
eee0444e81 | ||
|
|
4c4708cc8f | ||
|
|
8af7b252aa | ||
|
|
cf7cedbd06 | ||
|
|
3be27d0648 | ||
|
|
51a5e5b750 | ||
|
|
6a4b6fe67f | ||
|
|
93c646890d | ||
|
|
d89e5bad98 | ||
|
|
41514100e0 | ||
|
|
301e2c5720 | ||
|
|
61564c7798 | ||
|
|
c1ca5f7dc5 | ||
|
|
bedaaf0999 | ||
|
|
ee6fa2b805 | ||
|
|
20d8db6ce8 | ||
|
|
dfd1360b28 | ||
|
|
3cbd872497 | ||
|
|
3d6bd5e4ee | ||
|
|
ee7cf3e871 | ||
|
|
8121aee460 | ||
|
|
1e4ef483a7 | ||
|
|
25c3b3cb89 | ||
|
|
3803170b34 | ||
|
|
ca0b887c60 | ||
|
|
76c19d7a75 | ||
|
|
4293fde5ad | ||
|
|
ffd4fd82a8 | ||
|
|
1e8057b04e | ||
|
|
c8a7e35731 | ||
|
|
e47029cff2 | ||
|
|
c34c501fb8 | ||
|
|
16a39255f9 | ||
|
|
0c198e8f08 | ||
|
|
20e65bf2f7 | ||
|
|
7dbe420d8d | ||
|
|
4f095309fd | ||
|
|
230ace1959 | ||
|
|
7fcf954649 | ||
|
|
e629319d8b | ||
|
|
963dffb862 | ||
|
|
83ccd6729f | ||
|
|
5733a56e68 | ||
|
|
e013cbcdbc | ||
|
|
bc507a4754 | ||
|
|
211164d4d1 | ||
|
|
4580f61489 | ||
|
|
03857426aa | ||
|
|
a29fb12b8a | ||
|
|
6d86e349ef | ||
|
|
333f0707bb | ||
|
|
34623fd775 | ||
|
|
6956489862 | ||
|
|
e04798d48a | ||
|
|
bea0228357 | ||
|
|
966375beda | ||
|
|
ee735c0ec4 | ||
|
|
cce62c43f4 | ||
|
|
23251cb187 | ||
|
|
a8bc6754c2 | ||
|
|
b45739d151 | ||
|
|
b227928135 | ||
|
|
08f3d35573 | ||
|
|
055d204ded | ||
|
|
b996ddfa1e | ||
|
|
a4ca27d68c | ||
|
|
a00c4eb054 | ||
|
|
96858fae21 | ||
|
|
e21d19502f | ||
|
|
382a4e8d6e | ||
|
|
88a3cd8d02 | ||
|
|
413f75f402 | ||
|
|
b24e45947b | ||
|
|
58d9b76d2d | ||
|
|
249dc086c6 | ||
|
|
845911f412 | ||
|
|
eb7c52b7b4 | ||
|
|
ecd75df0d4 | ||
|
|
956bdb5396 | ||
|
|
f6c0a8a8aa | ||
|
|
104e33f5f9 | ||
|
|
b6498b4483 | ||
|
|
0c328605b7 | ||
|
|
a3cbccecd6 | ||
|
|
43935d3e1e | ||
|
|
748fe31cfe | ||
|
|
739afb86e3 | ||
|
|
09eba0d21d | ||
|
|
c4474b6ced | ||
|
|
311fa087c6 | ||
|
|
cf4c3ad66d | ||
|
|
6b2213d580 | ||
|
|
4ec0864626 | ||
|
|
fffdd4466b | ||
|
|
80c8dd3553 | ||
|
|
016600ab2e | ||
|
|
20f2ad7416 | ||
|
|
9da9a50b92 | ||
|
|
4669e81645 | ||
|
|
9f3dc3c087 | ||
|
|
fb75521bc6 | ||
|
|
174b19723a | ||
|
|
3c5486c80a | ||
|
|
83d9afd3d0 | ||
|
|
157b166435 | ||
|
|
2543d95d0e | ||
|
|
7c8393292e | ||
|
|
00e958266b | ||
|
|
f605775ba7 | ||
|
|
47d4d3f2dc | ||
|
|
16d5bc3cf7 | ||
|
|
84f94459e1 | ||
|
|
c40b43eda4 | ||
|
|
4e6d3ff382 | ||
|
|
952fdf08a7 | ||
|
|
5513b767dc | ||
|
|
cf77478fb5 | ||
|
|
35b50f79aa | ||
|
|
b7ed9e116c | ||
|
|
6e5254e737 | ||
|
|
e4048f8716 | ||
|
|
0763551d6d | ||
|
|
4e5b6ff2cf | ||
|
|
4e38bf75ca | ||
|
|
a279495936 | ||
|
|
f7157d283c | ||
|
|
caf605063c | ||
|
|
983c01d709 | ||
|
|
18180b3a01 | ||
|
|
eb86ae7cbc | ||
|
|
a545d673ab | ||
|
|
6f37500f62 | ||
|
|
eec8f0860e | ||
|
|
6bcad5d53f | ||
|
|
cc9696938a | ||
|
|
bdff67b7b3 | ||
|
|
e36b32a97d | ||
|
|
ac86ca2a13 | ||
|
|
0c987989fd | ||
|
|
e431f169fb | ||
|
|
57145d426e | ||
|
|
220984c45b | ||
|
|
f4a698bc57 | ||
|
|
4ffc2cb815 | ||
|
|
233a441579 | ||
|
|
ff6b6e667f | ||
|
|
3734f141c6 | ||
|
|
6c3c025bfc | ||
|
|
954979b586 | ||
|
|
059dbc6c79 | ||
|
|
90391664cc | ||
|
|
4dc0e6aead | ||
|
|
0761607bef | ||
|
|
3dd7f2d0af | ||
|
|
d0ae7e61b3 | ||
|
|
3b49aff5a4 | ||
|
|
60db9b9a77 | ||
|
|
4a2870e8e5 | ||
|
|
ac2ee0a1e9 | ||
|
|
a0e9687f1b | ||
|
|
8aedbbc5b4 | ||
|
|
a248a4b3b4 | ||
|
|
363f6b208d | ||
|
|
eda5facc53 | ||
|
|
31b0bd081e |
@@ -1,11 +1,10 @@
|
||||
root=true
|
||||
|
||||
[*.java]
|
||||
[*.{adoc,bat,groovy,html,java,js,jsp,kt,kts,md,properties,py,rb,sh,sql,svg,txt,xml,xsd}]
|
||||
charset = utf-8
|
||||
|
||||
[*.{groovy,java,kt,kts,xml,xsd}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
continuation_indent_size = 8
|
||||
|
||||
[*.xml]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
continuation_indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
25
.gitee/ISSUE_TEMPLATE.zh-CN.md
Normal file
@@ -0,0 +1,25 @@
|
||||
碰到问题,请在 <https://gitee.com/zhijiantianya/yudao-cloud/issues> 搜索是否存在相似的 issue。
|
||||
|
||||
不按照模板提交的 issue,会被系统自动删除。
|
||||
|
||||
### 基本信息
|
||||
|
||||
- ruoyi-vue-pro 版本:
|
||||
- 操作系统:
|
||||
- 数据库:
|
||||
|
||||
### 你猜测可能的原因
|
||||
|
||||
(必填)我花费了 2-4 小时自查,发现可能的原因是:xxxxxx
|
||||
|
||||
### 复现步骤
|
||||
|
||||
第一步,
|
||||
|
||||
第二步,
|
||||
|
||||
第三步,
|
||||
|
||||
### 报错信息
|
||||
|
||||
带上必要的截图
|
||||
34
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: 问题反馈
|
||||
about: 请详细描述,以便更高快的获得到解决
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
碰到问题,请在 <https://github.com/YunaiV/yudao-cloud/issues> 搜索是否存在相似的 issue。
|
||||
|
||||
不按照模板提交的 issue,会被系统自动删除。
|
||||
|
||||
### 基本信息
|
||||
|
||||
- ruoyi-vue-pro 版本:
|
||||
- 操作系统:
|
||||
- 数据库:
|
||||
|
||||
### 你猜测可能的原因
|
||||
|
||||
(必填)我花费了 2-4 小时自查,发现可能的原因是:xxxxxx
|
||||
|
||||
### 复现步骤
|
||||
|
||||
第一步,
|
||||
|
||||
第二步,
|
||||
|
||||
第三步,
|
||||
|
||||
### 报错信息
|
||||
|
||||
带上必要的截图
|
||||
30
.github/workflows/maven.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Java CI with Maven
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
# pull_request:
|
||||
# branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
java: [ '8', '11', '17' ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK ${{ matrix.Java }}
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml -Dmaven.test.skip=true
|
||||
20
LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 yudao-cloud
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
456
README.md
@@ -1,214 +1,322 @@
|
||||
[toc]
|
||||
**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!**
|
||||
|
||||
# 前言
|
||||
**「我喜欢写代码,乐此不疲」**
|
||||
**「我喜欢做开源,以此为乐」**
|
||||
|
||||
基于微服务的思想,构建在 B2C 电商场景下的项目实战。
|
||||
我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
|
||||
|
||||
* 「Talk is cheap. Show me the code」(屁话少说,放码过来)
|
||||
> 我们看过很多技术文章,却依然不知道微服务该咋整。
|
||||
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
|
||||
|
||||
* 这会是一个认真做的业务开源项目,目前 Java 代码 2w+ 行,不包括注释的情况下。
|
||||
## 🐶 新手必读
|
||||
|
||||
* 整体的功能如下图:
|
||||
> 功能图,和实际后端模块拆分,并不是绝对对应。
|
||||
* [功能列表 - H5 商城](https://gitee.com/zhijiantianya/onemall/blob/master/docs/guides/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8-H5%20%E5%95%86%E5%9F%8E.md)
|
||||
* [功能列表 - 管理后台](https://gitee.com/zhijiantianya/onemall/blob/master/docs/guides/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8/%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8-%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0.md)
|
||||
* 演示地址:<http://dashboard.yudao.iocoder.cn>
|
||||
* 启动文档:<https://cloud.iocoder.cn/quick-start/>
|
||||
* 视频教程:<https://cloud.iocoder.cn/video/>
|
||||
|
||||
* 交流群:[传送门](http://www.iocoder.cn/mall-user-group/?vip&gitee)
|
||||
> 一起交流,Get 知识。
|
||||
## 🐯 平台简介
|
||||
|
||||
* 我们迫切希望更多的参与进来,可以加入「交流群」,一起骚聊。
|
||||
* [《Onemall 电商开源项目 —— 应用分层》](http://www.iocoder.cn/Onemall/Application-layer/?vip&onemall)
|
||||
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
||||
|
||||
# 近期计划
|
||||
|
||||
近期准备开发如下功能:
|
||||
|
||||
> 🔥 :近期会更新新的项目分层结构。
|
||||
|
||||
1. 微信 H5 网页登陆 @To0R𓃰
|
||||
2. 订单评价 @wang171776704
|
||||
3. 商品品牌 @黑子
|
||||
4. 短信接入 @小范
|
||||
5. 访问日志、错误日志接入
|
||||
6. 会员资料 @nengjie
|
||||
7. 拼团购买 @大太阳
|
||||
8. 部门管理 @Tprotect曦
|
||||
9. 商品收藏 @笑笑生
|
||||
|
||||
# 演示
|
||||
|
||||
> 艿艿:目前的开发者,都是后端出身。所以,一帮没有审美自觉的人,撸出来的前端界面,可能是东半球倒数第二难看。
|
||||
> 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。
|
||||
>
|
||||
> 迫切希望,有前端能力不错的小伙伴,加入我们,一起来完善「一个商城」。
|
||||
> 😜 给项目点点 Star 吧,这对我们真的很重要!
|
||||
|
||||

|
||||
|
||||
* 管理后台的 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) ,Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
|
||||
* 管理后台的移动端采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5!
|
||||
* 后端采用 Spring Cloud Alibaba 微服务架构,注册中心 + 配置中心 Nacos,消息队列 RocketMQ,定时任务 XXL-Job,服务保障 Sentinel,服务网关 Gateway,分布式事务 Seata
|
||||
* 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等,基于 MyBatis Plus、Redis + Redisson 操作
|
||||
* 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录
|
||||
* 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能
|
||||
* 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装
|
||||
* 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式
|
||||
* 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验
|
||||
* 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款
|
||||
* 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务
|
||||
* 集成报表设计器、大屏设计器,通过拖拽即可生成酷炫的报表与大屏
|
||||
|
||||
## 🐳 项目关系
|
||||
|
||||

|
||||
|
||||
三个项目的功能对比,可见社区共同整理的 [国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn) 表格。
|
||||
|
||||
### 后端项目
|
||||
|
||||
|
||||
| 项目 | Star | 简介 |
|
||||
|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
|
||||
| [ruoyi-vue-pro](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro) [](https://github.com/YunaiV/ruoyi-vue-pro) | 基于 Spring Boot 多模块架构 |
|
||||
| [yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [](https://gitee.com/zhijiantianya/yudao-cloud) [](https://github.com/YunaiV/yudao-cloud) | 基于 Spring Cloud 微服务架构 |
|
||||
| [Spring-Boot-Labs](https://gitee.com/yudaocode/SpringBoot-Labs) | [](https://gitee.com/zhijiantianya/yudao-cloud) [](https://github.com/yudaocode/SpringBoot-Labs) | 系统学习 Spring Boot & Cloud 专栏 |
|
||||
|
||||
### 前端项目
|
||||
|
||||
| 项目 | Star | 简介 |
|
||||
|----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|
|
||||
| [yudao-ui-admin-vue3](https://gitee.com/yudaocode/yudao-ui-admin-vue3) | [](https://gitee.com/yudaocode/yudao-ui-admin-vue3) [](https://github.com/yudaocode/yudao-ui-admin-vue3) | 基于 Vue3 + element-plus 实现的管理后台 |
|
||||
| [yudao-ui-admin-vben](https://gitee.com/yudaocode/yudao-ui-admin-vben) | [](https://gitee.com/yudaocode/yudao-ui-admin-vben) [](https://github.com/yudaocode/yudao-ui-admin-vben) | 基于 Vue3 + vben(ant-design-vue) 实现的管理后台 |
|
||||
| [yudao-ui-admin](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) [](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin) | 基于 Vue2 + element-ui 实现的管理后台 |
|
||||
| [yudao-ui-admin-uniapp](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) [](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-admin-uniapp) | 基于 uni-app + uni-ui 实现的管理后台的小程序 |
|
||||
| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [](https://gitee.com/yudaocode/yudao-ui-go-view) [](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
|
||||
| [yudao-ui-app](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-app) [](https://github.com/YunaiV/ruoyi-vue-pro/tree/master/yudao-ui-app) | 基于 uni-app + uview 实现的用户 App |
|
||||
|
||||
## 😎 开源协议
|
||||
|
||||
**为什么推荐使用本项目?**
|
||||
|
||||
① 本项目采用比 Apache 2.0 更宽松的 [MIT License](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE) 开源协议,个人与企业可 100% 免费使用,不用保留类作者、Copyright 信息。
|
||||
|
||||
② 代码全部开源,不会像其他项目一样,只开源部分代码,让你无法了解整个项目的架构设计。[国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn)
|
||||
|
||||

|
||||
|
||||
③ 代码整洁、架构整洁,遵循《阿里巴巴 Java 开发手册》规范,代码注释详细,57000 行 Java 代码,22000 行代码注释。
|
||||
|
||||
## 🤝 项目外包
|
||||
|
||||
我们也是接外包滴,如果你有项目想要外包,可以微信联系【**Aix9975**】。
|
||||
|
||||
团队包含专业的项目经理、架构师、前端工程师、后端工程师、测试工程师、运维工程师,可以提供全流程的外包服务。
|
||||
|
||||
项目可以是商城、SCRM 系统、OA 系统、物流系统、ERP 系统、CMS 系统、HIS 系统、支付系统、IM 聊天、微信公众号、微信小程序等等。
|
||||
|
||||
## 🐼 内置功能
|
||||
|
||||
系统内置多种多种业务功能,可以用于快速你的业务系统:
|
||||
|
||||

|
||||
|
||||
* 系统功能
|
||||
* 基础设施
|
||||
* 工作流程
|
||||
* 支付系统
|
||||
* 会员中心
|
||||
* 数据报表
|
||||
* 商城系统
|
||||
* 微信公众号
|
||||
|
||||
> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
|
||||
>
|
||||
> 啊啊啊!我好像做店铺装修功能。
|
||||
> * 额外新增的功能,我们使用 🚀 标记。
|
||||
> * 重新实现的功能,我们使用 ⭐️ 标记。
|
||||
|
||||
## H5 商城
|
||||
🙂 所有功能,都通过 **单元测试** 保证高质量。
|
||||
|
||||
[体验传送门](http://h5.shop.iocoder.cn:18099)
|
||||
### 系统功能
|
||||
|
||||

|
||||
| | 功能 | 描述 |
|
||||
|-----|-------|---------------------------------|
|
||||
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
|
||||
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
|
||||
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
|
||||
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
|
||||
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
|
||||
| | 岗位管理 | 配置系统用户所属担任职务 |
|
||||
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
|
||||
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
|
||||
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
|
||||
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
|
||||
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
|
||||
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
|
||||
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
|
||||
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
|
||||
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
|
||||
| | 通知公告 | 系统通知公告信息发布维护 |
|
||||
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
|
||||
## 管理后台
|
||||
### 工作流程
|
||||
|
||||
[体验传送门](http://admin.shop.iocoder.cn:18099)
|
||||
| | 功能 | 描述 |
|
||||
|-----|-------|----------------------------------------|
|
||||
| 🚀 | 流程模型 | 配置工作流的流程模型,支持文件导入与在线设计流程图,提供 7 种任务分配规则 |
|
||||
| 🚀 | 流程表单 | 拖动表单元素生成相应的工作流表单,覆盖 Element UI 所有的表单组件 |
|
||||
| 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 |
|
||||
| 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 |
|
||||
| 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 |
|
||||
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 |
|
||||
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
|
||||
|
||||
* 账号:yudaoyuanma
|
||||
* 密码:yudaoyuanma
|
||||
### 支付系统
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|------|---------------------------|
|
||||
| 🚀 | 商户信息 | 管理商户信息,支持 Saas 场景下的多商户功能 |
|
||||
| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 |
|
||||
| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 |
|
||||
| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 |
|
||||
|
||||
ps:核心功能已经实现,正在对接微信小程序中...
|
||||
|
||||
### 基础设施
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 |
|
||||
| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 |
|
||||
| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
|
||||
### 数据报表
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|----------|----------------------------------------------|
|
||||
| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 |
|
||||
| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 |
|
||||
|
||||
### 微信公众号
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|--------|-------------------------------|
|
||||
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
|
||||
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
|
||||
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
|
||||
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
|
||||
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
|
||||
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
|
||||
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
|
||||
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
|
||||
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
|
||||
|
||||
### 商城系统
|
||||
|
||||
建设中...
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 其它演示
|
||||

|
||||
|
||||
下面,我们会提供目前用到的中间件的管理平台。
|
||||
### 会员中心
|
||||
|
||||
> 艿艿:考虑到大家可以看到更全的功能,所以一般提供 admin 账号。所以,大家素质使用哟。
|
||||
和「商城系统」一起开发
|
||||
|
||||
**SkyWalking UI**
|
||||
## 🐨 技术栈
|
||||
|
||||
* 地址:http://skywalking-ui.shop.iocoder.cn:18099
|
||||
* 管理员账号:admin / admin
|
||||
### 微服务
|
||||
|
||||
**Grafana UI**
|
||||
| 项目 | 说明 |
|
||||
|--------------------------------------------------------------------------|--------------------|
|
||||
| `yudao-dependencies` | Maven 依赖版本管理 |
|
||||
| `yudao-framework` | Java 框架拓展 |
|
||||
| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
|
||||
| `yudao-module-system` | 系统功能的 Module 模块 |
|
||||
| `yudao-module-member` | 会员中心的 Module 模块 |
|
||||
| `yudao-module-infra` | 基础设施的 Module 模块 |
|
||||
| `yudao-module-bpm` | 工作流程的 Module 模块 |
|
||||
| `yudao-module-pay` | 支付系统的 Module 模块 |
|
||||
| `yudao-module-mall` | 商城系统的 Module 模块 |
|
||||
| `yudao-module-mp` | 微信公众号的 Module 模块 |
|
||||
| `yudao-module-report` | 大屏报表 Module 模块 |
|
||||
|
||||
* 地址:http://grafana.shop.iocoder.cn:18099
|
||||
* 演示账号:yudaoyuanma / yudaoyuanma
|
||||
* 用于展示 Prometheus 收集的 Metrics 指标数据。
|
||||
### 框架
|
||||
|
||||
**Dubbo Admin**
|
||||
| 框架 | 说明 | 版本 | 学习指南 |
|
||||
|---------------------------------------------------------------------------------------------|------------------|-------------|---------------------------------------------------------------------|
|
||||
| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2021.0.4.0 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||
| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.0.4 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) |
|
||||
| [RocketMQ](https://github.com/apache/rocketmq) | 消息队列 | 4.9.4 | [文档](https://www.iocoder.cn/categories/RocketMQ/?yudao) |
|
||||
| [Sentinel](https://github.com/alibaba/sentinel) | 服务保障 | 1.8.6 | [文档](https://www.iocoder.cn/categories/Sentinel/?yudao) |
|
||||
| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.3.1 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) |
|
||||
| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 3.4.1 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) |
|
||||
| [Seata](https://github.com/seata/seata) | 分布式事务 | 1.6.1 | [文档](https://www.iocoder.cn/categories/Seata/?yudao) |
|
||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.16 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.3.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.26 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
||||
|
||||
* 地址:http://dubbo-admin.shop.iocoder.cn:18099
|
||||
* 管理员账号:无需登陆
|
||||
## 🐷 演示图
|
||||
|
||||
**RocketMQ Console**
|
||||
### 系统功能
|
||||
|
||||
* 地址:http://rocketmq-console.shop.iocoder.cn:18099
|
||||
* 管理员账号:admin / RPsa2GHjTNs8pxEU
|
||||
| 模块 | biu | biu | biu |
|
||||
|------------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|
|
||||
| 登录 & 首页 |  |  |  |
|
||||
| 用户 & 应用 |  |  |  |
|
||||
| 租户 & 套餐 |  |  | - |
|
||||
| 部门 & 岗位 |  |  | - |
|
||||
| 菜单 & 角色 |  |  | - |
|
||||
| 审计日志 |  |  | - |
|
||||
| 短信 |  |  |  |
|
||||
| 字典 & 敏感词 |  |  |  |
|
||||
| 错误码 & 通知 |  |  | - |
|
||||
|
||||
**Sentinel Console**
|
||||
### 工作流程
|
||||
|
||||
* 地址:http://sentinel.shop.iocoder.cn:18099
|
||||
* 账号:sentinel / sentinel
|
||||
| 模块 | biu | biu | biu |
|
||||
|---------|------------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||
| 流程模型 |  |  |  |
|
||||
| 表单 & 分组 |  |  | - |
|
||||
| 我的流程 |  |  |  |
|
||||
| 待办 & 已办 |  |  |  |
|
||||
| OA 请假 |  |  |  |
|
||||
|
||||
**XXL-Job Console**
|
||||
### 基础设施
|
||||
|
||||
* 地址:http://job-console.shop.iocoder.cn:18099
|
||||
* 管理员账号:admin / 233666
|
||||
| 模块 | biu | biu | biu |
|
||||
|---------------|----------------------------------------------------------------------|--------------------------------------------------------------------|------------------------------------------------------------------|
|
||||
| 代码生成 |  |  | - |
|
||||
| 文档 |  |  | - |
|
||||
| 文件 & 配置 |  |  |  |
|
||||
| 定时任务 |  |  | - |
|
||||
| API 日志 |  |  | - |
|
||||
| MySQL & Redis |  |  | - |
|
||||
| 监控平台 |  |  |  |
|
||||
|
||||
# 技术
|
||||
### 支付系统
|
||||
|
||||
## 搭建环境
|
||||
| 模块 | biu | biu | biu |
|
||||
|---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||
| 商家 & 应用 |  |  |  |
|
||||
| 支付 & 退款 |  |  | --- |
|
||||
|
||||
[搭建调试环境](https://gitee.com/zhijiantianya/onemall/blob/master/docs/setup/quick-start.md)
|
||||
### 数据报表
|
||||
|
||||
## 架构图
|
||||
| 模块 | biu | biu | biu |
|
||||
|---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||
| 报表设计器 |  |  |  |
|
||||
| 大屏设计器 |  |  |  |
|
||||
|
||||
TODO 此处应有一个架构图的装逼 JPG 图。
|
||||
### 移动端(管理后台)
|
||||
|
||||
## 项目结构
|
||||
| biu | biu | biu |
|
||||
|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||
|  |  |  |
|
||||
|  |  |  |
|
||||
|  |  |  |
|
||||
|
||||
| 模块 | 名称 | 端口 | |
|
||||
| --- | --- | --- | --- |
|
||||
| `admin-web` | 【前端】管理后台 | HTTP 8080 | |
|
||||
| `mobile-web` | 【前端】商城 H5 | HTTP 8000 | |
|
||||
| `system-application` | 管理员 HTTP 服务 | HTTP 18083 | [接口文档](http://api.shop.iocoder.cn:18099/admin-api/doc.html) |
|
||||
| `user-application` | 用户 HTTP 服务 | HTTP 18082 | [接口文档](http://api.shop.iocoder.cn:18099/user-api/doc.html) |
|
||||
| `product-application` | 商品 HTTP 服务 | HTTP 18081 | [接口文档](http://api.shop.iocoder.cn:18099/product-api/doc.html) |
|
||||
| `pay-application` | 支付 HTTP 服务 | HTTP 18084 | [接口文档](http://api.shop.iocoder.cn:18099/pay-api/doc.html) |
|
||||
| `promotion-application` | 促销 HTTP 服务 | HTTP 18085 | [接口文档](http://api.shop.iocoder.cn:18099/promotion-api/doc.html) |
|
||||
| `search-application` | 搜索 HTTP 服务 | HTTP 18086 | [接口文档](http://api.shop.iocoder.cn:18099/search-api/doc.html) |
|
||||
| `order-application` | 订单 HTTP 服务 | HTTP 18088 | [接口文档](http://api.shop.iocoder.cn:18099/order-api/doc.html) |
|
||||
|
||||
-------
|
||||
|
||||
后端项目,目前的项目结构如下:
|
||||
|
||||
```Java
|
||||
[-] xxx
|
||||
├──[-] xxx-application // 提供对外 HTTP API 。
|
||||
├──[-] xxx-service-api // 提供 Dubbo 服务 API 。
|
||||
├──[-] xxx-service-impl // 提供 Dubbo 服务 Service 实现。
|
||||
```
|
||||
|
||||
考虑到大多数公司,无需拆分的特别细,并且过多 JVM 带来的服务器成本。所以目前的设定是:
|
||||
|
||||
* `xxx-service-impl` 内嵌在 `xxx-application` 中运行。
|
||||
* MQ 消费者、定时器执行器,内嵌在 `xxx-service-impl` 中运行。
|
||||
|
||||
也就是说,一个 `xxx-application` 启动后,该模块就完整启动了。
|
||||
|
||||
## 技术栈
|
||||
|
||||
### 后端
|
||||
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.1.4 |
|
||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.6 |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.1.16 |
|
||||
| [MyBatis](http://www.mybatis.org/mybatis-3/zh/index.html) | 数据持久层框架 | 3.5.1 |
|
||||
| [MyBatis-Plus](https://mp.baomidou.com/) | Mybatis 增强工具包 | 3.1.1 |
|
||||
| [Redis](https://redis.io/) | key-value 数据库 | 暂未引入,等压测后,部分模块 |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 暂未引入,等压测后,部分模块 |
|
||||
| [Elasticsearch](https://www.elastic.co/cn/) | 分布式搜索引擎 | 6.7.1 |
|
||||
| [Dubbo](http://dubbo.apache.org/) | 分布式 RPC 服务框架 | 2.7.1 |
|
||||
| [RocketMQ](http://dubbo.apache.org/) | 消息中间件 | 4.3.2 |
|
||||
| [Seata](https://github.com/seata/seata) | 分布式事务中间件 | 0.5.1 |
|
||||
| [Zookeeper](http://zookeeper.apache.org/) | 分布式系统协调 | 3.4.9 作为注册中心 |
|
||||
| [XXL-Job](http://www.xuxueli.com/xxl-job/) | 分布式任务调度平台 | 2.0.1 |
|
||||
| [springfox-swagger2](https://github.com/springfox/springfox/tree/master/springfox-swagger2) | API 文档 | 2.9.2 |
|
||||
| [swagger-bootstrap-ui](https://gitee.com/xiaoym/swagger-bootstrap-ui) | Swagger 增强 UI 实现 | 1.9.3 |
|
||||
|
||||
未来考虑引入
|
||||
|
||||
* [ ] 配置中心 Apollo
|
||||
* [ ] 服务保障 Sentinel
|
||||
* [ ] 网关 Soul
|
||||
|
||||
### 前端
|
||||
|
||||
商城 H5 和管理后台,分别采用了 Vue 和 React ,基于其适合的场景考虑。具体的,可以看看 [《为什么 React 比 Vue 更适合大型应用?》](https://www.zhihu.com/question/314761485/answer/615318460) 的讨论。
|
||||
|
||||
**商城 H5**
|
||||
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.5.17 |
|
||||
| [Vant](https://youzan.github.io/vant/#/zh-CN/intro) | Vue UI 组件库 | 3.13.0 |
|
||||
|
||||
**管理后台**
|
||||
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [React](https://reactjs.org/) | JavaScript 框架 | 16.7.0 |
|
||||
| [Ant Design](https://ant.design/docs/react/introduce-cn) | React UI 组件库 | 3.13.0 |
|
||||
|
||||
### 监控
|
||||
|
||||
一般来说,监控会有三种方式:
|
||||
|
||||
* 1、Tracing ,我们采用 Apache SkyWalking
|
||||
* 2、Logging ,我们采用 ELK
|
||||
* 3、Metrics ,我们采用 Prometheus
|
||||
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [SkyWalking](http://skywalking.apache.org/) | 分布式应用追踪系统 | 6.0.0 |
|
||||
| [Prometheus](https://prometheus.io/) | 服务监控体系 | 2.9.2 |
|
||||
| [Alertmanager](https://prometheus.io/docs/alerting/alertmanager/) | 告警管理器 | 0.17.0 |
|
||||
| [Grafana](https://grafana.com/) | 仪表盘和图形编辑器 | 0.17.0 |
|
||||
|
||||
### 其它
|
||||
|
||||
* Jenkins 持续集成
|
||||
* Nginx 服务器
|
||||
* [ ] Docker 容器
|
||||
* [ ] Nginx
|
||||
|
||||
# 某种结尾
|
||||
|
||||
目前成员
|
||||
|
||||
* 小范
|
||||
* 芋艿
|
||||
目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
**/node_modules
|
||||
/src/utils/request-temp.js
|
||||
|
||||
# production
|
||||
/.vscode
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
npm-debug.log*
|
||||
yarn-error.log
|
||||
|
||||
/coverage
|
||||
.idea
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
*bak
|
||||
.vscode
|
||||
|
||||
# visual studio code
|
||||
.history
|
||||
*.log
|
||||
|
||||
functions/mock
|
||||
.temp/**
|
||||
|
||||
# umi
|
||||
.umi
|
||||
.umi-production
|
||||
|
||||
# screenshot
|
||||
screenshot
|
||||
.firebase
|
||||
@@ -1,16 +0,0 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -1,3 +0,0 @@
|
||||
/functions/mock/**
|
||||
/scripts
|
||||
/config
|
||||
@@ -1,39 +0,0 @@
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
extends: ['airbnb', 'prettier', 'plugin:compat/recommended'],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
mocha: true,
|
||||
jest: true,
|
||||
jasmine: true,
|
||||
},
|
||||
globals: {
|
||||
APP_TYPE: true,
|
||||
page: true,
|
||||
},
|
||||
rules: {
|
||||
'react/jsx-filename-extension': [1, { extensions: ['.js'] }],
|
||||
'react/jsx-wrap-multilines': 0,
|
||||
'react/prop-types': 0,
|
||||
'react/forbid-prop-types': 0,
|
||||
'react/jsx-one-expression-per-line': 0,
|
||||
'import/no-unresolved': [2, { ignore: ['^@/', '^umi/'] }],
|
||||
'import/no-extraneous-dependencies': [
|
||||
2,
|
||||
{
|
||||
optionalDependencies: true,
|
||||
devDependencies: ['**/tests/**.js', '/mock/**/**.js', '**/**.test.js'],
|
||||
},
|
||||
],
|
||||
'jsx-a11y/no-noninteractive-element-interactions': 0,
|
||||
'jsx-a11y/click-events-have-key-events': 0,
|
||||
'jsx-a11y/no-static-element-interactions': 0,
|
||||
'jsx-a11y/anchor-is-valid': 0,
|
||||
'linebreak-style': 0,
|
||||
},
|
||||
settings: {
|
||||
polyfills: ['fetch', 'promises', 'url'],
|
||||
},
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"projects": {
|
||||
"default": "antd-pro"
|
||||
}
|
||||
}
|
||||
38
admin-web/.gitignore
vendored
@@ -1,38 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
**/node_modules
|
||||
# roadhog-api-doc ignore
|
||||
/src/utils/request-temp.js
|
||||
_roadhog-api-doc
|
||||
|
||||
# production
|
||||
/dist
|
||||
/.vscode
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
npm-debug.log*
|
||||
yarn-error.log
|
||||
|
||||
/coverage
|
||||
.idea
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
*bak
|
||||
.vscode
|
||||
|
||||
# visual studio code
|
||||
.history
|
||||
*.log
|
||||
|
||||
functions/mock
|
||||
.temp/**
|
||||
|
||||
# umi
|
||||
.umi
|
||||
.umi-production
|
||||
|
||||
# screenshot
|
||||
screenshot
|
||||
.firebase
|
||||
@@ -1,6 +0,0 @@
|
||||
ports:
|
||||
- port: 8000
|
||||
onOpen: open-preview
|
||||
tasks:
|
||||
- init: npm install
|
||||
command: npm start
|
||||
@@ -1,5 +0,0 @@
|
||||
**/*.md
|
||||
**/*.svg
|
||||
package.json
|
||||
.umi
|
||||
.umi-production
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"overrides": [
|
||||
{
|
||||
"files": ".prettierrc",
|
||||
"options": { "parser": "json" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"stylelint-config-standard",
|
||||
"stylelint-config-css-modules",
|
||||
"stylelint-config-rational-order",
|
||||
"stylelint-config-prettier"
|
||||
],
|
||||
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
|
||||
"rules": {
|
||||
"no-descending-specificity": null,
|
||||
"plugin/declaration-block-no-ignored-properties": true
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at afc163@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM circleci/node:latest-browsers
|
||||
|
||||
WORKDIR /usr/src/app/
|
||||
USER root
|
||||
COPY package.json ./
|
||||
RUN yarn
|
||||
|
||||
COPY ./ ./
|
||||
|
||||
RUN npm run test:all
|
||||
|
||||
CMD ["npm", "run", "build"]
|
||||
@@ -1,11 +0,0 @@
|
||||
FROM node:latest
|
||||
|
||||
WORKDIR /usr/src/app/
|
||||
|
||||
COPY package.json ./
|
||||
RUN npm install --silent --no-cache
|
||||
|
||||
COPY ./ ./
|
||||
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
@@ -1,11 +0,0 @@
|
||||
FROM nginx
|
||||
|
||||
WORKDIR /usr/src/app/
|
||||
|
||||
COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
COPY ./dist /usr/share/nginx/html/
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Alipay.inc
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,38 +0,0 @@
|
||||
# 后台管理页面
|
||||
|
||||
> 采用 antd pro 快速开发
|
||||
|
||||
> TODO
|
||||
|
||||
## 命名规范
|
||||
|
||||
#### 1.文件夹命名
|
||||
|
||||
文件夹命名全部小写,单词之间以中划线隔离 例如: node-modules
|
||||
|
||||
|
||||
#### 2.文件命名
|
||||
|
||||
文件以小写开头,以驼峰格式连接单词 例如: dashBoard.js
|
||||
component目录下的文件 以大写开头
|
||||
route目录下的文件以大写开头
|
||||
model目录下的文件大写开头
|
||||
|
||||
|
||||
#### 3.标点符号
|
||||
|
||||
对于字符串统一用单引号 例如: 'hello world'
|
||||
|
||||
#### 4.语法规范
|
||||
|
||||
JS语法规范遵守ES6规范
|
||||
http://www.tuicool.com/articles/YrQ7j2a
|
||||
|
||||
#### 5.注释
|
||||
|
||||
1.route目录下的文件需要加上文件头部注释(写清楚文件是什么功能)
|
||||
2.component文件需要加上头部注释 (写清楚改控件的用处)
|
||||
|
||||
## 补充规范
|
||||
|
||||
1. services 目录中,每个 api 文件,对应后端一个 api 服务。主要考虑是
|
||||
@@ -1,74 +0,0 @@
|
||||
# Node.js
|
||||
# Build a general Node.js project with npm.
|
||||
# Add steps that analyze code, save build artifacts, deploy, and more:
|
||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript
|
||||
name: ant design pro
|
||||
|
||||
trigger:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
- job: lintAndBuild
|
||||
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: false
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run build
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
|
||||
- job: test
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
|
||||
container:
|
||||
image: circleci/node:latest-browsers
|
||||
options: '-u root'
|
||||
|
||||
steps:
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run test:all
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: test
|
||||
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '11.x'
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run build
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
|
||||
- job: MacOS
|
||||
pool:
|
||||
vmImage: 'macOS-10.13'
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '11.x'
|
||||
- script: yarn install
|
||||
displayName: install
|
||||
- script: npm run lint
|
||||
displayName: lint
|
||||
- script: npm run
|
||||
env:
|
||||
PROGRESS: none
|
||||
displayName: build
|
||||
@@ -1,121 +0,0 @@
|
||||
// https://umijs.org/config/
|
||||
import os from 'os';
|
||||
import pageRoutes from './router.config';
|
||||
import webpackPlugin from './plugin.config';
|
||||
import defaultSettings from '../src/defaultSettings';
|
||||
import slash from 'slash2';
|
||||
import proxy from './proxy';
|
||||
|
||||
const { pwa, primaryColor } = defaultSettings;
|
||||
const { NODE_ENV, APP_TYPE, TEST, BASE_PATH } = process.env;
|
||||
|
||||
// 用于控制,部署非跟目录下
|
||||
const basePath = BASE_PATH ? BASE_PATH : '';
|
||||
|
||||
const plugins = [
|
||||
[
|
||||
'umi-plugin-react',
|
||||
{
|
||||
antd: true,
|
||||
dva: {
|
||||
hmr: true,
|
||||
},
|
||||
locale: {
|
||||
enable: true, // default false
|
||||
default: 'zh-CN', // default zh-CN
|
||||
baseNavigator: true, // default true, when it is true, will use `navigator.language` overwrite default
|
||||
},
|
||||
dynamicImport: {
|
||||
loadingComponent: './components/PageLoading/index',
|
||||
webpackChunkName: true,
|
||||
level: 3,
|
||||
},
|
||||
pwa: pwa
|
||||
? {
|
||||
workboxPluginMode: 'InjectManifest',
|
||||
workboxOptions: {
|
||||
importWorkboxFrom: 'local',
|
||||
},
|
||||
}
|
||||
: {},
|
||||
...(!TEST && os.platform() === 'darwin'
|
||||
? {
|
||||
dll: {
|
||||
include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'],
|
||||
exclude: ['@babel/runtime'],
|
||||
},
|
||||
hardSource: false,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
// 针对 preview.pro.ant.design 的 GA 统计代码
|
||||
// 业务上不需要这个
|
||||
if (APP_TYPE === 'site') {
|
||||
plugins.push([
|
||||
'umi-plugin-ga',
|
||||
{
|
||||
code: 'UA-72788897-6',
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
export default {
|
||||
// add for transfer to umi
|
||||
base: basePath,
|
||||
publicPath: basePath,
|
||||
plugins,
|
||||
define: {
|
||||
APP_TYPE: APP_TYPE || '',
|
||||
},
|
||||
treeShaking: true,
|
||||
targets: {
|
||||
ie: 11,
|
||||
},
|
||||
// 路由配置
|
||||
routes: pageRoutes,
|
||||
// Theme for antd
|
||||
// https://ant.design/docs/react/customize-theme-cn
|
||||
theme: {
|
||||
'primary-color': primaryColor,
|
||||
},
|
||||
externals: {
|
||||
'@antv/data-set': 'DataSet',
|
||||
bizcharts: 'BizCharts',
|
||||
},
|
||||
proxy: proxy(NODE_ENV, basePath),
|
||||
ignoreMomentLocale: true,
|
||||
lessLoaderOptions: {
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
disableRedirectHoist: true,
|
||||
cssLoaderOptions: {
|
||||
modules: true,
|
||||
getLocalIdent: (context, localIdentName, localName) => {
|
||||
if (
|
||||
context.resourcePath.includes('node_modules') ||
|
||||
context.resourcePath.includes('ant.design.pro.less') ||
|
||||
context.resourcePath.includes('global.less')
|
||||
) {
|
||||
return localName;
|
||||
}
|
||||
const match = context.resourcePath.match(/src(.*)/);
|
||||
if (match && match[1]) {
|
||||
const antdProPath = match[1].replace('.less', '');
|
||||
const arr = slash(antdProPath)
|
||||
.split('/')
|
||||
.map(a => a.replace(/([A-Z])/g, '-$1'))
|
||||
.map(a => a.toLowerCase());
|
||||
return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
|
||||
}
|
||||
return localName;
|
||||
},
|
||||
},
|
||||
manifest: {
|
||||
basePath: '/',
|
||||
},
|
||||
|
||||
chainWebpack: webpackPlugin,
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
// Change theme plugin
|
||||
|
||||
import MergeLessPlugin from 'antd-pro-merge-less';
|
||||
import AntDesignThemePlugin from 'antd-theme-webpack-plugin';
|
||||
import path from 'path';
|
||||
|
||||
export default config => {
|
||||
// pro 和 开发环境再添加这个插件
|
||||
if (process.env.APP_TYPE === 'site' || process.env.NODE_ENV !== 'production') {
|
||||
// 将所有 less 合并为一个供 themePlugin使用
|
||||
const outFile = path.join(__dirname, '../.temp/ant-design-pro.less');
|
||||
const stylesDir = path.join(__dirname, '../src/');
|
||||
|
||||
config.plugin('merge-less').use(MergeLessPlugin, [
|
||||
{
|
||||
stylesDir,
|
||||
outFile,
|
||||
},
|
||||
]);
|
||||
|
||||
config.plugin('ant-design-theme').use(AntDesignThemePlugin, [
|
||||
{
|
||||
antDir: path.join(__dirname, '../node_modules/antd'),
|
||||
stylesDir,
|
||||
varFile: path.join(__dirname, '../node_modules/antd/lib/style/themes/default.less'),
|
||||
mainLessFile: outFile, // themeVariables: ['@primary-color'],
|
||||
indexFileName: 'index.html',
|
||||
generateOne: true,
|
||||
lessUrl: 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js',
|
||||
},
|
||||
]);
|
||||
}
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
// development 和 production
|
||||
|
||||
import path from 'path';
|
||||
import proxyDev from './proxy.dev';
|
||||
import proxyProd from './proxy.prod';
|
||||
|
||||
function basePathBuilder(proxys, basePath) {
|
||||
for (const key in proxys) {
|
||||
const proxy = proxys[key];
|
||||
const pathRewrite = proxy.pathRewrite;
|
||||
const newPathRewrite = {};
|
||||
for (const key2 in pathRewrite) {
|
||||
const item = pathRewrite[key2];
|
||||
newPathRewrite[key2] = path.join(basePath, item);
|
||||
}
|
||||
proxy.pathRewrite = newPathRewrite;
|
||||
}
|
||||
return proxys;
|
||||
}
|
||||
|
||||
export default function(NODE_ENV, basePath) {
|
||||
let proxys = NODE_ENV === 'development' || NODE_ENV === 'undefined' ? proxyDev : proxyProd;
|
||||
if (basePath) {
|
||||
proxys = basePathBuilder(proxys, basePath);
|
||||
}
|
||||
return proxys;
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// 开发环境,的代理配置
|
||||
|
||||
module.exports = {
|
||||
'/admin-api/': {
|
||||
target: 'http://127.0.0.1:18083/',
|
||||
// target: 'http://180.167.213.26:18083/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/product-api/': {
|
||||
// target: 'http://180.167.213.26:18083/',
|
||||
target: 'http://127.0.0.1:18081/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/order-api/': {
|
||||
// target: 'http://180.167.213.26:18084/',
|
||||
target: 'http://127.0.0.1:18088/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/promotion-api/': {
|
||||
// target: 'http://180.167.213.26:18085/',
|
||||
target: 'http://127.0.0.1:18085/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/user-api/': {
|
||||
// target: 'http://180.167.213.26:18085/',
|
||||
target: 'http://127.0.0.1:18082/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/pay-api/': {
|
||||
// target: 'http://180.167.213.26:18085/',
|
||||
target: 'http://127.0.0.1:18084/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
// production 配置文件
|
||||
|
||||
module.exports = {
|
||||
'/admin-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/product-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/order-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/promotion-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/pay-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/user-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/server/api/': {
|
||||
target: 'https://preview.pro.ant.design/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: { '^/server': '' },
|
||||
},
|
||||
};
|
||||
@@ -1,456 +0,0 @@
|
||||
export default [
|
||||
// user
|
||||
{
|
||||
path: '/user',
|
||||
component: '../layouts/UserLayout',
|
||||
routes: [
|
||||
{ path: '/user', redirect: '/user/login' },
|
||||
{ path: '/user/login', name: 'login', component: './User/Login' },
|
||||
{ path: '/user/register', name: 'register', component: './User/Register' },
|
||||
{
|
||||
path: '/user/register-result',
|
||||
name: 'register.result',
|
||||
component: './User/RegisterResult',
|
||||
},
|
||||
],
|
||||
},
|
||||
// app
|
||||
{
|
||||
path: '/',
|
||||
component: '../layouts/BasicLayout',
|
||||
Routes: ['src/pages/Authorized'],
|
||||
authority: ['admin', 'user'],
|
||||
routes: [
|
||||
// redirect
|
||||
{ path: '/', redirect: '/home' },
|
||||
// home
|
||||
{
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
icon: 'user',
|
||||
component: './Home/Home',
|
||||
},
|
||||
// admin
|
||||
{
|
||||
path: '/admin',
|
||||
name: 'admin',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/admin/admin-list',
|
||||
name: 'admin-list',
|
||||
component: './Admin/AdminList',
|
||||
},
|
||||
{
|
||||
path: '/admin/resource-list',
|
||||
name: 'resource-list',
|
||||
component: './Admin/ResourceList',
|
||||
},
|
||||
{
|
||||
path: '/admin/role-list',
|
||||
name: 'role-list',
|
||||
component: './Admin/RoleList',
|
||||
},
|
||||
{
|
||||
path: '/admin/dept-list',
|
||||
name: 'deptment-list',
|
||||
component: './Admin/DeptmentList',
|
||||
},
|
||||
{
|
||||
path: '/admin/dictionary-list',
|
||||
name: 'dictionary-list',
|
||||
component: './Admin/DictionaryList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// user
|
||||
{
|
||||
path: '/member', // TODO 芋艿,后面调整
|
||||
name: 'user',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/member/user-list',
|
||||
name: 'user-list',
|
||||
component: './User/UserList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// order
|
||||
{
|
||||
path: 'order',
|
||||
name: 'order',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/order/order-list',
|
||||
name: 'order-list',
|
||||
component: './Order/OrderList',
|
||||
},
|
||||
{
|
||||
path: '/order/order-refunds',
|
||||
name: 'order-refunds',
|
||||
component: './OrderRefunds/OrderRefundsList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// product
|
||||
{
|
||||
path: '/product',
|
||||
name: 'product',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/product/product-spu-list',
|
||||
name: 'product-spu-list',
|
||||
component: './Product/ProductSpuList',
|
||||
},
|
||||
{
|
||||
path: '/product/product-spu-add',
|
||||
name: 'product-spu-add',
|
||||
component: './Product/ProductSpuAddOrUpdate',
|
||||
},
|
||||
{
|
||||
path: '/product/product-spu-update',
|
||||
name: 'product-spu-update',
|
||||
component: './Product/ProductSpuAddOrUpdate',
|
||||
},
|
||||
{
|
||||
path: '/product/product-category-list',
|
||||
name: 'product-category-list',
|
||||
component: './Product/ProductCategoryList',
|
||||
},
|
||||
{
|
||||
path: '/product/product-brand-list',
|
||||
name: 'product-brand-list',
|
||||
component: './Product/ProductBrandList',
|
||||
},
|
||||
{
|
||||
path: '/product/product-attr-list',
|
||||
name: 'product-attr-list',
|
||||
component: './Product/ProductAttrList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// promotion
|
||||
{
|
||||
path: '/promotion',
|
||||
name: 'promotion',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/promotion/banner-list',
|
||||
name: 'promotion-banner-list',
|
||||
component: './Promotion/BannerList',
|
||||
},
|
||||
{
|
||||
path: '/promotion/product-recommend-list',
|
||||
name: 'product-recommend-list',
|
||||
component: './Promotion/ProductRecommendList',
|
||||
},
|
||||
// {
|
||||
// path: '/product/product-category-list',
|
||||
// name: 'product-category-list',
|
||||
// component: './Product/ProductCategoryList',
|
||||
// },
|
||||
{
|
||||
path: '/promotion/coupon-card-template-list',
|
||||
name: 'coupon-card-template-list',
|
||||
component: './Promotion/CouponCardTemplateList',
|
||||
},
|
||||
{
|
||||
path: '/promotion/time-limit-discount-list',
|
||||
name: 'time-limit-discount-list',
|
||||
component: './Promotion/TimeLimitedDiscountList',
|
||||
},
|
||||
{
|
||||
path: '/promotion/full-privilege-list',
|
||||
name: 'full-privilege-list',
|
||||
component: './Promotion/FullPrivilegeList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// pay
|
||||
{
|
||||
path: '/pay',
|
||||
name: 'pay',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/pay/transaction-list',
|
||||
name: 'pay-transaction-list',
|
||||
component: './Pay/PayTransactionList',
|
||||
},
|
||||
{
|
||||
path: '/pay/refund-list',
|
||||
name: 'pay-refund-list',
|
||||
component: './Pay/PayRefundList',
|
||||
},
|
||||
],
|
||||
},
|
||||
// sms
|
||||
{
|
||||
path: '/sms',
|
||||
name: 'sms',
|
||||
icon: 'user',
|
||||
routes: [
|
||||
{
|
||||
path: '/sms/sign-list',
|
||||
name: 'sign-list',
|
||||
component: './Sms/SignList',
|
||||
},
|
||||
{
|
||||
path: '/sms/template-list',
|
||||
name: 'template-list',
|
||||
component: './Sms/TemplateList',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
icon: 'dashboard',
|
||||
routes: [
|
||||
{
|
||||
path: '/dashboard/analysis',
|
||||
name: 'analysis',
|
||||
component: './Dashboard/Analysis',
|
||||
},
|
||||
{
|
||||
path: '/dashboard/monitor',
|
||||
name: 'monitor',
|
||||
component: './Dashboard/Monitor',
|
||||
},
|
||||
{
|
||||
path: '/dashboard/workplace',
|
||||
name: 'workplace',
|
||||
component: './Dashboard/Workplace',
|
||||
},
|
||||
],
|
||||
},
|
||||
// forms
|
||||
{
|
||||
path: '/form',
|
||||
icon: 'form',
|
||||
name: 'form',
|
||||
routes: [
|
||||
{
|
||||
path: '/form/basic-form',
|
||||
name: 'basicform',
|
||||
component: './Forms/BasicForm',
|
||||
},
|
||||
{
|
||||
path: '/form/step-form',
|
||||
name: 'stepform',
|
||||
component: './Forms/StepForm',
|
||||
hideChildrenInMenu: true,
|
||||
routes: [
|
||||
{
|
||||
path: '/form/step-form',
|
||||
redirect: '/form/step-form/info',
|
||||
},
|
||||
{
|
||||
path: '/form/step-form/info',
|
||||
name: 'info',
|
||||
component: './Forms/StepForm/Step1',
|
||||
},
|
||||
{
|
||||
path: '/form/step-form/confirm',
|
||||
name: 'confirm',
|
||||
component: './Forms/StepForm/Step2',
|
||||
},
|
||||
{
|
||||
path: '/form/step-form/result',
|
||||
name: 'result',
|
||||
component: './Forms/StepForm/Step3',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/form/advanced-form',
|
||||
name: 'advancedform',
|
||||
authority: ['admin'],
|
||||
component: './Forms/AdvancedForm',
|
||||
},
|
||||
],
|
||||
},
|
||||
// list
|
||||
{
|
||||
path: '/list',
|
||||
icon: 'table',
|
||||
name: 'list',
|
||||
routes: [
|
||||
{
|
||||
path: '/list/table-list',
|
||||
name: 'searchtable',
|
||||
component: './List/TableList',
|
||||
},
|
||||
{
|
||||
path: '/list/basic-list',
|
||||
name: 'basiclist',
|
||||
component: './List/BasicList',
|
||||
},
|
||||
{
|
||||
path: '/list/card-list',
|
||||
name: 'cardlist',
|
||||
component: './List/CardList',
|
||||
},
|
||||
{
|
||||
path: '/list/search',
|
||||
name: 'searchlist',
|
||||
component: './List/List',
|
||||
routes: [
|
||||
{
|
||||
path: '/list/search',
|
||||
redirect: '/list/search/articles',
|
||||
},
|
||||
{
|
||||
path: '/list/search/articles',
|
||||
name: 'articles',
|
||||
component: './List/Articles',
|
||||
},
|
||||
{
|
||||
path: '/list/search/projects',
|
||||
name: 'projects',
|
||||
component: './List/Projects',
|
||||
},
|
||||
{
|
||||
path: '/list/search/applications',
|
||||
name: 'applications',
|
||||
component: './List/Applications',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/profile',
|
||||
name: 'profile',
|
||||
icon: 'profile',
|
||||
routes: [
|
||||
// profile
|
||||
{
|
||||
path: '/profile/basic',
|
||||
name: 'basic',
|
||||
component: './Profile/BasicProfile',
|
||||
},
|
||||
{
|
||||
path: '/profile/basic/:id',
|
||||
name: 'basic',
|
||||
hideInMenu: true,
|
||||
component: './Profile/BasicProfile',
|
||||
},
|
||||
{
|
||||
path: '/profile/advanced',
|
||||
name: 'advanced',
|
||||
authority: ['admin'],
|
||||
component: './Profile/AdvancedProfile',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'result',
|
||||
icon: 'check-circle-o',
|
||||
path: '/result',
|
||||
routes: [
|
||||
// result
|
||||
{
|
||||
path: '/result/success',
|
||||
name: 'success',
|
||||
component: './Result/Success',
|
||||
},
|
||||
{ path: '/result/fail', name: 'fail', component: './Result/Error' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'exception',
|
||||
icon: 'warning',
|
||||
path: '/exception',
|
||||
routes: [
|
||||
// exception
|
||||
{
|
||||
path: '/exception/403',
|
||||
name: 'not-permission',
|
||||
component: './Exception/403',
|
||||
},
|
||||
{
|
||||
path: '/exception/404',
|
||||
name: 'not-find',
|
||||
component: './Exception/404',
|
||||
},
|
||||
{
|
||||
path: '/exception/500',
|
||||
name: 'server-error',
|
||||
component: './Exception/500',
|
||||
},
|
||||
{
|
||||
path: '/exception/trigger',
|
||||
name: 'trigger',
|
||||
hideInMenu: true,
|
||||
component: './Exception/TriggerException',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'account',
|
||||
icon: 'user',
|
||||
path: '/account',
|
||||
routes: [
|
||||
{
|
||||
path: '/account/center',
|
||||
name: 'center',
|
||||
component: './Account/Center/Center',
|
||||
routes: [
|
||||
{
|
||||
path: '/account/center',
|
||||
redirect: '/account/center/articles',
|
||||
},
|
||||
{
|
||||
path: '/account/center/articles',
|
||||
component: './Account/Center/Articles',
|
||||
},
|
||||
{
|
||||
path: '/account/center/applications',
|
||||
component: './Account/Center/Applications',
|
||||
},
|
||||
{
|
||||
path: '/account/center/projects',
|
||||
component: './Account/Center/Projects',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/account/settings',
|
||||
name: 'settings',
|
||||
component: './Account/Settings/Info',
|
||||
routes: [
|
||||
{
|
||||
path: '/account/settings',
|
||||
redirect: '/account/settings/base',
|
||||
},
|
||||
{
|
||||
path: '/account/settings/base',
|
||||
component: './Account/Settings/BaseView',
|
||||
},
|
||||
{
|
||||
path: '/account/settings/security',
|
||||
component: './Account/Settings/SecurityView',
|
||||
},
|
||||
{
|
||||
path: '/account/settings/binding',
|
||||
component: './Account/Settings/BindingView',
|
||||
},
|
||||
{
|
||||
path: '/account/settings/notification',
|
||||
component: './Account/Settings/NotificationView',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: '404',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
# 使用说明
|
||||
|
||||
|
||||
### 第一步
|
||||
|
||||
```
|
||||
npm install
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 第二步
|
||||
复制文件到 server 目录
|
||||
|
||||
```
|
||||
cp -rf dist server
|
||||
```
|
||||
|
||||
### 第三步
|
||||
|
||||
```
|
||||
node server.prod
|
||||
```
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// 粉笔:
|
||||
// 输出不同颜色的提示信息
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
module.exports = {
|
||||
chalkError: chalk.red,
|
||||
chalkSuccess: chalk.green,
|
||||
chalkWarning: chalk.yellow,
|
||||
chalkProcessing: chalk.blue,
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
// production 配置文件
|
||||
|
||||
module.exports = {
|
||||
'/admin-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/product-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/order-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/promotion-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/pay-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/user-api/': {
|
||||
target: 'http://api.shop.iocoder.cn',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {},
|
||||
},
|
||||
'/server/api/': {
|
||||
target: 'https://preview.pro.ant.design/',
|
||||
changeOrigin: true,
|
||||
pathRewrite: { '^/server': '' },
|
||||
},
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "browser-work-server",
|
||||
"description": "node server",
|
||||
"dependencies": {
|
||||
"express": "^4.16.3",
|
||||
"object-assign": "4.1.1",
|
||||
"chalk": "2.4.1",
|
||||
"http-proxy-middleware": "^0.18.0"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "admin-web",
|
||||
"script": "./server.prod.js",
|
||||
"instances": "1",
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"env_production": {
|
||||
"NODE_ENV": "production"
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
const path = require('path');
|
||||
const express = require('express');
|
||||
|
||||
const { chalkSuccess } = require('./config/chalk.config');
|
||||
const proxyConfig = require('./config/proxy.prod.config');
|
||||
const proxyBuild = require('./utils/proxy.build');
|
||||
|
||||
// create app server
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
// host proxy
|
||||
app.use(proxyBuild(proxyConfig));
|
||||
|
||||
// use index.html
|
||||
app.use(express.static(path.join(__dirname, 'dist/static')));
|
||||
app.use(express.static(path.join(__dirname, 'dist')));
|
||||
|
||||
app.use((req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
|
||||
});
|
||||
|
||||
app.listen(port, error => {
|
||||
if (error) {
|
||||
console.error(error);
|
||||
} else {
|
||||
console.info(
|
||||
chalkSuccess(
|
||||
'==> 🌎 Listening on port %s. ' + 'Open up http://localhost:%s/ in your browser.'
|
||||
),
|
||||
port,
|
||||
port
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
# 安装依赖包
|
||||
|
||||
cd admin-web
|
||||
|
||||
cnpm install
|
||||
|
||||
# 开始构建
|
||||
|
||||
#npm run build
|
||||
|
||||
# 创建 app 运行目录
|
||||
|
||||
rm -rf app
|
||||
|
||||
mkdir app
|
||||
|
||||
# 复制配置文件
|
||||
|
||||
cp -rf config/server app/
|
||||
|
||||
# npm 构建项目
|
||||
|
||||
npm run build
|
||||
|
||||
# 复制文件到 server 努力
|
||||
|
||||
cp -rf dist app/server
|
||||
|
||||
# 复制文件到 project 目录执行
|
||||
if [ ! -d "/work2/project/admin-web/server/dist" ]; then
|
||||
mkdir -pv /work2/project/admin-web/server/dist
|
||||
else
|
||||
rm -rf /work2/project/admin-web/server/dist
|
||||
fi
|
||||
|
||||
|
||||
cp -rf app/server /work2/project/admin-web
|
||||
|
||||
# 安装 server 依赖项
|
||||
cd /work2/project/admin-web/server
|
||||
|
||||
npm install
|
||||
|
||||
# 启动服务
|
||||
pm2 restart pm2.json
|
||||
@@ -1,50 +0,0 @@
|
||||
const proxy = require('http-proxy-middleware');
|
||||
const ObjectAssign = require('object-assign');
|
||||
const { chalkError, chalkSuccess } = require('../config/chalk.config');
|
||||
|
||||
/**
|
||||
*
|
||||
* key :
|
||||
* [0]: /api
|
||||
* [1]: target url
|
||||
*
|
||||
* 预计写法:
|
||||
* 1、 /api -> baidu.com : { }
|
||||
* 2、 /user : function() { return {} }
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
module.exports = function(config) {
|
||||
console.info(chalkSuccess('build proxy.%s.config 配置!'), process.env.NODE_ENV);
|
||||
|
||||
const proxys = [];
|
||||
if (!config) {
|
||||
console.log(chalkError('proxy.%s.config 没有配置!'), process.env.NODE_ENV);
|
||||
}
|
||||
|
||||
for (const key in config) {
|
||||
let source;
|
||||
let target;
|
||||
if (/->/.test(key)) {
|
||||
const keys = key.toString().split('->');
|
||||
source = keys[0].trim();
|
||||
target = keys[1].trim();
|
||||
} else {
|
||||
source = key;
|
||||
target = config[key].target;
|
||||
}
|
||||
|
||||
if (typeof config !== 'object') {
|
||||
console.log(
|
||||
chalkError('%s: proxy.%s.config 初始化失败 config 类型为 object!'),
|
||||
key,
|
||||
process.env.NODE_ENV
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
proxys.push(proxy(source, ObjectAssign({ target }, config[key])));
|
||||
}
|
||||
|
||||
return proxys;
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
ant-design-pro_dev:
|
||||
ports:
|
||||
- 8000:8000
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: Dockerfile.dev
|
||||
container_name: "ant-design-pro_dev"
|
||||
volumes:
|
||||
- ../src:/usr/src/app/src
|
||||
- ../config:/usr/src/app/config
|
||||
- ../mock:/usr/src/app/mock
|
||||
@@ -1,21 +0,0 @@
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
ant-design-pro_build:
|
||||
build: ../
|
||||
container_name: "ant-design-pro_build"
|
||||
volumes:
|
||||
- dist:/usr/src/app/dist
|
||||
|
||||
ant-design-pro_web:
|
||||
image: nginx
|
||||
ports:
|
||||
- 80:80
|
||||
container_name: "ant-design-pro_web"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- dist:/usr/share/nginx/html:ro
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
volumes:
|
||||
dist:
|
||||
@@ -1,22 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
# gzip config
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_comp_level 9;
|
||||
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
|
||||
gzip_vary on;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
location /api {
|
||||
proxy_pass https://preview.pro.ant.design;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"hosting": {
|
||||
"public": "dist",
|
||||
"rewrites": [
|
||||
{ "source": "/api/**", "function": "api" },
|
||||
{
|
||||
"source": "**",
|
||||
"destination": "/index.html"
|
||||
}
|
||||
],
|
||||
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// [START functionsimport]
|
||||
const functions = require('firebase-functions');
|
||||
const express = require('express');
|
||||
|
||||
const matchMock = require('./matchMock');
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(matchMock);
|
||||
exports.api = functions.https.onRequest(app);
|
||||
@@ -1,115 +0,0 @@
|
||||
const pathToRegexp = require('path-to-regexp');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
const mockFile = require('./mock/index');
|
||||
|
||||
const BODY_PARSED_METHODS = ['post', 'put', 'patch'];
|
||||
|
||||
const debug = console.log;
|
||||
function parseKey(key) {
|
||||
let method = 'get';
|
||||
let path = key;
|
||||
if (key.indexOf(' ') > -1) {
|
||||
const splited = key.split(' ');
|
||||
method = splited[0].toLowerCase();
|
||||
path = splited[1]; // eslint-disable-line
|
||||
}
|
||||
return {
|
||||
method,
|
||||
path,
|
||||
};
|
||||
}
|
||||
|
||||
function createHandler(method, path, handler) {
|
||||
return (req, res, next) => {
|
||||
function sendData() {
|
||||
if (typeof handler === 'function') {
|
||||
handler(req, res, next);
|
||||
} else {
|
||||
res.json(handler);
|
||||
}
|
||||
}
|
||||
if (BODY_PARSED_METHODS.includes(method)) {
|
||||
bodyParser.json({ limit: '5mb', strict: false })(req, res, () => {
|
||||
bodyParser.urlencoded({ limit: '5mb', extended: true })(req, res, () => {
|
||||
sendData();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
sendData();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeConfig(config) {
|
||||
return Object.keys(config).reduce((memo, key) => {
|
||||
const handler = config[key];
|
||||
const { method, path } = parseKey(key);
|
||||
const keys = [];
|
||||
const re = pathToRegexp(path, keys);
|
||||
memo.push({
|
||||
method,
|
||||
path,
|
||||
re,
|
||||
keys,
|
||||
handler: createHandler(method, path, handler),
|
||||
});
|
||||
return memo;
|
||||
}, []);
|
||||
}
|
||||
|
||||
const mockData = normalizeConfig(mockFile);
|
||||
|
||||
function matchMock(req) {
|
||||
const { path: exceptPath } = req;
|
||||
const exceptMethod = req.method.toLowerCase();
|
||||
function decodeParam(val) {
|
||||
if (typeof val !== 'string' || val.length === 0) {
|
||||
return val;
|
||||
}
|
||||
|
||||
try {
|
||||
return decodeURIComponent(val);
|
||||
} catch (err) {
|
||||
if (err instanceof URIError) {
|
||||
err.message = `Failed to decode param ' ${val} '`;
|
||||
err.statusCode = 400;
|
||||
err.status = 400;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const mock of mockData) {
|
||||
const { method, re, keys } = mock;
|
||||
if (method === exceptMethod) {
|
||||
const match = re.exec(req.path);
|
||||
if (match) {
|
||||
const params = {};
|
||||
|
||||
for (let i = 1; i < match.length; i += 1) {
|
||||
const key = keys[i - 1];
|
||||
const prop = key.name;
|
||||
const val = decodeParam(match[i]);
|
||||
|
||||
if (val !== undefined || !hasOwnProperty.call(params, prop)) {
|
||||
params[prop] = val;
|
||||
}
|
||||
}
|
||||
req.params = params;
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mockData.filter(({ method, re }) => method === exceptMethod && re.test(exceptPath))[0];
|
||||
}
|
||||
module.exports = (req, res, next) => {
|
||||
const match = matchMock(req);
|
||||
if (match) {
|
||||
debug(`mock matched: [${match.method}] ${match.path}`);
|
||||
return match.handler(req, res, next);
|
||||
}
|
||||
return next();
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "functions",
|
||||
"description": "Cloud Functions for Firebase",
|
||||
"scripts": {
|
||||
"serve": "firebase serve --only functions",
|
||||
"shell": "firebase functions:shell",
|
||||
"start": "npm run shell",
|
||||
"deploy": "npm run mock && firebase deploy --only functions",
|
||||
"logs": "firebase functions:log",
|
||||
"mock": "node ../scripts/generateMock.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"body-parser": "^1.18.3",
|
||||
"express": "^4.16.4",
|
||||
"firebase-admin": "^6.4.0",
|
||||
"firebase-functions": "^2.1.0",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"moment": "^2.22.2",
|
||||
"path-to-regexp": "^3.0.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
const DEFAULT_PAGE_NO = 1;
|
||||
const DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
class PaginationHelper {
|
||||
|
||||
static defaultPaginationConfig = {
|
||||
defaultCurrent: DEFAULT_PAGE_NO,
|
||||
defaultPageSize: DEFAULT_PAGE_SIZE,
|
||||
current: DEFAULT_PAGE_NO,
|
||||
total: 0,
|
||||
pageSize: DEFAULT_PAGE_SIZE,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: total => `共 ${total} 条`
|
||||
};
|
||||
|
||||
static formatPagination(data) {
|
||||
return {
|
||||
defaultCurrent: DEFAULT_PAGE_NO,
|
||||
defaultPageSize: DEFAULT_PAGE_SIZE,
|
||||
current: data.current,
|
||||
total: data.total,
|
||||
pageSize: data.size,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: total => `共 ${total} 条`,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* data.total 数据总数
|
||||
* payload.pageNo 页码
|
||||
* payload.pageSize 每页总数
|
||||
*/
|
||||
static formatPagination(data, payload) {
|
||||
return {
|
||||
defaultCurrent: DEFAULT_PAGE_NO,
|
||||
defaultPageSize: DEFAULT_PAGE_SIZE,
|
||||
current: payload.pageNo,
|
||||
pageSize: payload.pageSize,
|
||||
total: data.total,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: total => `共 ${total} 条`,
|
||||
};
|
||||
};
|
||||
|
||||
//获取初始页码
|
||||
static defaultPayload = {
|
||||
pageNo: DEFAULT_PAGE_NO,
|
||||
pageSize: DEFAULT_PAGE_SIZE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PaginationHelper;
|
||||
export {PaginationHelper};
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
// 校验必须是英文或者数字
|
||||
export function checkTypeWithEnglishAndNumbers (rule, value, callback, text) {
|
||||
let char = /^[a-zA-Z0-9]+$/
|
||||
if (char.test(value)) {
|
||||
callback()
|
||||
} else {
|
||||
callback(text)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// ps https://github.com/GoogleChrome/puppeteer/issues/3120
|
||||
module.exports = {
|
||||
launch: {
|
||||
args: [
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--no-first-run',
|
||||
'--no-zygote',
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = {
|
||||
testURL: 'http://localhost:8000',
|
||||
preset: 'jest-puppeteer',
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/* eslint-disable */
|
||||
import mockjs from 'mockjs';
|
||||
import { resultBody } from './mock-comment';
|
||||
import adminMenu from './geographic/admin-menu.json';
|
||||
import adminMenuAll from './geographic/admin-menu-all.json';
|
||||
import adminUrls from './geographic/admin-urls';
|
||||
import resourceTree from './geographic/resource-tree.json';
|
||||
import roleQuery from './geographic/role-query.json';
|
||||
import dictionaryList from './geographic/dictionary-list.json';
|
||||
|
||||
function getAdminMenu(req, res) {
|
||||
return res.json(adminMenu);
|
||||
}
|
||||
|
||||
function getAdminMenuAll(req, res) {
|
||||
return res.json(adminMenuAll);
|
||||
}
|
||||
|
||||
function getAdminUrls(req, res) {
|
||||
return res.json(adminUrls);
|
||||
}
|
||||
|
||||
function getResourceTree(req, res) {
|
||||
return res.json(resourceTree);
|
||||
}
|
||||
|
||||
function getQueryRole(req, res) {
|
||||
return res.json(roleQuery);
|
||||
}
|
||||
|
||||
function getDictionaryKeys(req, res) {
|
||||
const values = mockjs.mock({
|
||||
'list|5': [{ 'value|+1': 0, text: '@city' }],
|
||||
});
|
||||
|
||||
return res.json(resultBody(values));
|
||||
}
|
||||
|
||||
function getDictionaryText(req, res) {
|
||||
const values = mockjs.mock({
|
||||
text: '@city',
|
||||
});
|
||||
|
||||
return res.json(resultBody(values));
|
||||
}
|
||||
|
||||
function getDictionaryTree(req, res) {
|
||||
return res.json(dictionaryList);
|
||||
}
|
||||
|
||||
export default {
|
||||
// 'GET /admin-api/admins/admin/menu_resource_tree': getAdminMenuAll,
|
||||
// 'GET /admin-api/admins/admin/url_resource_list': getAdminUrls,
|
||||
// 'GET /admin-api/admins/resource/tree': getResourceTree,
|
||||
// 'GET /admin-api/admins/role/page': getQueryRole,
|
||||
// 'GET /admin-api/admins/admin/page': getQueryRole,
|
||||
// 'GET /admin-api/admins/data_dict/tree': getDictionaryTree,
|
||||
};
|
||||
@@ -1,336 +0,0 @@
|
||||
import mockjs from 'mockjs';
|
||||
|
||||
const titles = [
|
||||
'Alipay',
|
||||
'Angular',
|
||||
'Ant Design',
|
||||
'Ant Design Pro',
|
||||
'Bootstrap',
|
||||
'React',
|
||||
'Vue',
|
||||
'Webpack',
|
||||
];
|
||||
const avatars = [
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png', // Alipay
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png', // Angular
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png', // Ant Design
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png', // Ant Design Pro
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png', // Bootstrap
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png', // React
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png', // Vue
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png', // Webpack
|
||||
];
|
||||
|
||||
const avatars2 = [
|
||||
'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/cnrhVkzwxjPwAaCfPbdc.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/gaOngJwsRYRaVAuXXcmB.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/ubnKSIfAJTxIgXOKlciN.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/WhxKECPNujWoWEFNdnJE.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/psOgztMplJMGpVEqfcgF.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/ZpBqSxLxVEXfcUNoPKrz.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/laiEnJdGHVOhJrUShBaJ.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/UrQsqscbKEpNuJcvBZBu.png',
|
||||
];
|
||||
|
||||
const covers = [
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/iXjVmWVHbCJAyqvDxdtx.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/gLaIAoVWTtLbBWZNYEMg.png',
|
||||
];
|
||||
const desc = [
|
||||
'那是一种内在的东西, 他们到达不了,也无法触及的',
|
||||
'希望是一个好东西,也许是最好的,好东西是不会消亡的',
|
||||
'生命就像一盒巧克力,结果往往出人意料',
|
||||
'城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
|
||||
'那时候我只会想自己想要什么,从不想自己拥有什么',
|
||||
];
|
||||
|
||||
const user = [
|
||||
'付小小',
|
||||
'曲丽丽',
|
||||
'林东东',
|
||||
'周星星',
|
||||
'吴加好',
|
||||
'朱偏右',
|
||||
'鱼酱',
|
||||
'乐哥',
|
||||
'谭小仪',
|
||||
'仲尼',
|
||||
];
|
||||
|
||||
function fakeList(count) {
|
||||
const list = [];
|
||||
for (let i = 0; i < count; i += 1) {
|
||||
list.push({
|
||||
id: `fake-list-${i}`,
|
||||
owner: user[i % 10],
|
||||
title: titles[i % 8],
|
||||
avatar: avatars[i % 8],
|
||||
cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)],
|
||||
status: ['active', 'exception', 'normal'][i % 3],
|
||||
percent: Math.ceil(Math.random() * 50) + 50,
|
||||
logo: avatars[i % 8],
|
||||
href: 'https://ant.design',
|
||||
updatedAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
|
||||
createdAt: new Date(new Date().getTime() - 1000 * 60 * 60 * 2 * i),
|
||||
subDescription: desc[i % 5],
|
||||
description:
|
||||
'在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。',
|
||||
activeUser: Math.ceil(Math.random() * 100000) + 100000,
|
||||
newUser: Math.ceil(Math.random() * 1000) + 1000,
|
||||
star: Math.ceil(Math.random() * 100) + 100,
|
||||
like: Math.ceil(Math.random() * 100) + 100,
|
||||
message: Math.ceil(Math.random() * 10) + 10,
|
||||
content:
|
||||
'段落示意:蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。蚂蚁金服设计平台 ant.design,用最小的工作量,无缝接入蚂蚁金服生态,提供跨越设计与开发的体验解决方案。',
|
||||
members: [
|
||||
{
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ZiESqWwCXBRQoaPONSJe.png',
|
||||
name: '曲丽丽',
|
||||
id: 'member1',
|
||||
},
|
||||
{
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/tBOxZPlITHqwlGjsJWaF.png',
|
||||
name: '王昭君',
|
||||
id: 'member2',
|
||||
},
|
||||
{
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/sBxjgqiuHMGRkIjqlQCd.png',
|
||||
name: '董娜娜',
|
||||
id: 'member3',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
let sourceData;
|
||||
|
||||
function getFakeList(req, res) {
|
||||
const params = req.query;
|
||||
|
||||
const count = params.count * 1 || 20;
|
||||
|
||||
const result = fakeList(count);
|
||||
sourceData = result;
|
||||
return res.json(result);
|
||||
}
|
||||
|
||||
function postFakeList(req, res) {
|
||||
const { /* url = '', */ body } = req;
|
||||
// const params = getUrlParams(url);
|
||||
const { method, id } = body;
|
||||
// const count = (params.count * 1) || 20;
|
||||
let result = sourceData;
|
||||
|
||||
switch (method) {
|
||||
case 'delete':
|
||||
result = result.filter(item => item.id !== id);
|
||||
break;
|
||||
case 'update':
|
||||
result.forEach((item, i) => {
|
||||
if (item.id === id) {
|
||||
result[i] = Object.assign(item, body);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'post':
|
||||
result.unshift({
|
||||
body,
|
||||
id: `fake-list-${result.length}`,
|
||||
createdAt: new Date().getTime(),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return res.json(result);
|
||||
}
|
||||
|
||||
const getNotice = [
|
||||
{
|
||||
id: 'xxx1',
|
||||
title: titles[0],
|
||||
logo: avatars[0],
|
||||
description: '那是一种内在的东西,他们到达不了,也无法触及的',
|
||||
updatedAt: new Date(),
|
||||
member: '科学搬砖组',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
{
|
||||
id: 'xxx2',
|
||||
title: titles[1],
|
||||
logo: avatars[1],
|
||||
description: '希望是一个好东西,也许是最好的,好东西是不会消亡的',
|
||||
updatedAt: new Date('2017-07-24'),
|
||||
member: '全组都是吴彦祖',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
{
|
||||
id: 'xxx3',
|
||||
title: titles[2],
|
||||
logo: avatars[2],
|
||||
description: '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
|
||||
updatedAt: new Date(),
|
||||
member: '中二少女团',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
{
|
||||
id: 'xxx4',
|
||||
title: titles[3],
|
||||
logo: avatars[3],
|
||||
description: '那时候我只会想自己想要什么,从不想自己拥有什么',
|
||||
updatedAt: new Date('2017-07-23'),
|
||||
member: '程序员日常',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
{
|
||||
id: 'xxx5',
|
||||
title: titles[4],
|
||||
logo: avatars[4],
|
||||
description: '凛冬将至',
|
||||
updatedAt: new Date('2017-07-23'),
|
||||
member: '高逼格设计天团',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
{
|
||||
id: 'xxx6',
|
||||
title: titles[5],
|
||||
logo: avatars[5],
|
||||
description: '生命就像一盒巧克力,结果往往出人意料',
|
||||
updatedAt: new Date('2017-07-23'),
|
||||
member: '骗你来学计算机',
|
||||
href: '',
|
||||
memberLink: '',
|
||||
},
|
||||
];
|
||||
|
||||
const getActivities = [
|
||||
{
|
||||
id: 'trend-1',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '曲丽丽',
|
||||
avatar: avatars2[0],
|
||||
},
|
||||
group: {
|
||||
name: '高逼格设计天团',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
project: {
|
||||
name: '六月迭代',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '在 @{group} 新建项目 @{project}',
|
||||
},
|
||||
{
|
||||
id: 'trend-2',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '付小小',
|
||||
avatar: avatars2[1],
|
||||
},
|
||||
group: {
|
||||
name: '高逼格设计天团',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
project: {
|
||||
name: '六月迭代',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '在 @{group} 新建项目 @{project}',
|
||||
},
|
||||
{
|
||||
id: 'trend-3',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '林东东',
|
||||
avatar: avatars2[2],
|
||||
},
|
||||
group: {
|
||||
name: '中二少女团',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
project: {
|
||||
name: '六月迭代',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '在 @{group} 新建项目 @{project}',
|
||||
},
|
||||
{
|
||||
id: 'trend-4',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '周星星',
|
||||
avatar: avatars2[4],
|
||||
},
|
||||
project: {
|
||||
name: '5 月日常迭代',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '将 @{project} 更新至已发布状态',
|
||||
},
|
||||
{
|
||||
id: 'trend-5',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '朱偏右',
|
||||
avatar: avatars2[3],
|
||||
},
|
||||
project: {
|
||||
name: '工程效能',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
comment: {
|
||||
name: '留言',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '在 @{project} 发布了 @{comment}',
|
||||
},
|
||||
{
|
||||
id: 'trend-6',
|
||||
updatedAt: new Date(),
|
||||
user: {
|
||||
name: '乐哥',
|
||||
avatar: avatars2[5],
|
||||
},
|
||||
group: {
|
||||
name: '程序员日常',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
project: {
|
||||
name: '品牌迭代',
|
||||
link: 'http://github.com/',
|
||||
},
|
||||
template: '在 @{group} 新建项目 @{project}',
|
||||
},
|
||||
];
|
||||
|
||||
function getFakeCaptcha(req, res) {
|
||||
return res.json('captcha-xxx');
|
||||
}
|
||||
|
||||
export default {
|
||||
'GET /api/project/notice': getNotice,
|
||||
'GET /api/activities': getActivities,
|
||||
'POST /api/forms': (req, res) => {
|
||||
res.send({ message: 'Ok' });
|
||||
},
|
||||
'GET /api/tags': mockjs.mock({
|
||||
'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }],
|
||||
}),
|
||||
'GET /api/fake_list': getFakeList,
|
||||
'POST /api/fake_list': postFakeList,
|
||||
'GET /api/captcha': getFakeCaptcha,
|
||||
};
|
||||
@@ -1,196 +0,0 @@
|
||||
import moment from 'moment';
|
||||
|
||||
// mock data
|
||||
const visitData = [];
|
||||
const beginDay = new Date().getTime();
|
||||
|
||||
const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
|
||||
for (let i = 0; i < fakeY.length; i += 1) {
|
||||
visitData.push({
|
||||
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||
y: fakeY[i],
|
||||
});
|
||||
}
|
||||
|
||||
const visitData2 = [];
|
||||
const fakeY2 = [1, 6, 4, 8, 3, 7, 2];
|
||||
for (let i = 0; i < fakeY2.length; i += 1) {
|
||||
visitData2.push({
|
||||
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||
y: fakeY2[i],
|
||||
});
|
||||
}
|
||||
|
||||
const salesData = [];
|
||||
for (let i = 0; i < 12; i += 1) {
|
||||
salesData.push({
|
||||
x: `${i + 1}月`,
|
||||
y: Math.floor(Math.random() * 1000) + 200,
|
||||
});
|
||||
}
|
||||
const searchData = [];
|
||||
for (let i = 0; i < 50; i += 1) {
|
||||
searchData.push({
|
||||
index: i + 1,
|
||||
keyword: `搜索关键词-${i}`,
|
||||
count: Math.floor(Math.random() * 1000),
|
||||
range: Math.floor(Math.random() * 100),
|
||||
status: Math.floor((Math.random() * 10) % 2),
|
||||
});
|
||||
}
|
||||
const salesTypeData = [
|
||||
{
|
||||
x: '家用电器',
|
||||
y: 4544,
|
||||
},
|
||||
{
|
||||
x: '食用酒水',
|
||||
y: 3321,
|
||||
},
|
||||
{
|
||||
x: '个护健康',
|
||||
y: 3113,
|
||||
},
|
||||
{
|
||||
x: '服饰箱包',
|
||||
y: 2341,
|
||||
},
|
||||
{
|
||||
x: '母婴产品',
|
||||
y: 1231,
|
||||
},
|
||||
{
|
||||
x: '其他',
|
||||
y: 1231,
|
||||
},
|
||||
];
|
||||
|
||||
const salesTypeDataOnline = [
|
||||
{
|
||||
x: '家用电器',
|
||||
y: 244,
|
||||
},
|
||||
{
|
||||
x: '食用酒水',
|
||||
y: 321,
|
||||
},
|
||||
{
|
||||
x: '个护健康',
|
||||
y: 311,
|
||||
},
|
||||
{
|
||||
x: '服饰箱包',
|
||||
y: 41,
|
||||
},
|
||||
{
|
||||
x: '母婴产品',
|
||||
y: 121,
|
||||
},
|
||||
{
|
||||
x: '其他',
|
||||
y: 111,
|
||||
},
|
||||
];
|
||||
|
||||
const salesTypeDataOffline = [
|
||||
{
|
||||
x: '家用电器',
|
||||
y: 99,
|
||||
},
|
||||
{
|
||||
x: '食用酒水',
|
||||
y: 188,
|
||||
},
|
||||
{
|
||||
x: '个护健康',
|
||||
y: 344,
|
||||
},
|
||||
{
|
||||
x: '服饰箱包',
|
||||
y: 255,
|
||||
},
|
||||
{
|
||||
x: '其他',
|
||||
y: 65,
|
||||
},
|
||||
];
|
||||
|
||||
const offlineData = [];
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
offlineData.push({
|
||||
name: `Stores ${i}`,
|
||||
cvr: Math.ceil(Math.random() * 9) / 10,
|
||||
});
|
||||
}
|
||||
const offlineChartData = [];
|
||||
for (let i = 0; i < 20; i += 1) {
|
||||
offlineChartData.push({
|
||||
x: new Date().getTime() + 1000 * 60 * 30 * i,
|
||||
y1: Math.floor(Math.random() * 100) + 10,
|
||||
y2: Math.floor(Math.random() * 100) + 10,
|
||||
});
|
||||
}
|
||||
|
||||
const radarOriginData = [
|
||||
{
|
||||
name: '个人',
|
||||
ref: 10,
|
||||
koubei: 8,
|
||||
output: 4,
|
||||
contribute: 5,
|
||||
hot: 7,
|
||||
},
|
||||
{
|
||||
name: '团队',
|
||||
ref: 3,
|
||||
koubei: 9,
|
||||
output: 6,
|
||||
contribute: 3,
|
||||
hot: 1,
|
||||
},
|
||||
{
|
||||
name: '部门',
|
||||
ref: 4,
|
||||
koubei: 1,
|
||||
output: 6,
|
||||
contribute: 5,
|
||||
hot: 7,
|
||||
},
|
||||
];
|
||||
|
||||
const radarData = [];
|
||||
const radarTitleMap = {
|
||||
ref: '引用',
|
||||
koubei: '口碑',
|
||||
output: '产量',
|
||||
contribute: '贡献',
|
||||
hot: '热度',
|
||||
};
|
||||
radarOriginData.forEach(item => {
|
||||
Object.keys(item).forEach(key => {
|
||||
if (key !== 'name') {
|
||||
radarData.push({
|
||||
name: item.name,
|
||||
label: radarTitleMap[key],
|
||||
value: item[key],
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const getFakeChartData = {
|
||||
visitData,
|
||||
visitData2,
|
||||
salesData,
|
||||
searchData,
|
||||
offlineData,
|
||||
offlineChartData,
|
||||
salesTypeData,
|
||||
salesTypeDataOnline,
|
||||
salesTypeDataOffline,
|
||||
radarData,
|
||||
};
|
||||
|
||||
export default {
|
||||
'GET /api/fake_chart_data': getFakeChartData,
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import city from './geographic/city.json';
|
||||
import province from './geographic/province.json';
|
||||
|
||||
function getProvince(req, res) {
|
||||
return res.json(province);
|
||||
}
|
||||
|
||||
function getCity(req, res) {
|
||||
return res.json(city[req.params.province]);
|
||||
}
|
||||
|
||||
export default {
|
||||
'GET /api/geographic/province': getProvince,
|
||||
'GET /api/geographic/city/:province': getCity,
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": "all"
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": [
|
||||
{
|
||||
"id": 20,
|
||||
"handler": null,
|
||||
"pid": 0,
|
||||
"sort": 0,
|
||||
"displayName": "商品管理",
|
||||
"children": [
|
||||
{
|
||||
"id": 21,
|
||||
"handler": "/product/product-spu-list",
|
||||
"pid": 20,
|
||||
"sort": 1,
|
||||
"displayName": "商品管理",
|
||||
"children": null
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"handler": "/product/product-category-list",
|
||||
"pid": 20,
|
||||
"sort": 2,
|
||||
"displayName": "商品分类",
|
||||
"children": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"handler": null,
|
||||
"pid": 0,
|
||||
"sort": 2,
|
||||
"displayName": "系统管理",
|
||||
"children": [
|
||||
{
|
||||
"id": 14,
|
||||
"handler": "/admin/admin-list",
|
||||
"pid": 13,
|
||||
"sort": 0,
|
||||
"displayName": "管理员列表",
|
||||
"children": null
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"handler": "/admin/role-list",
|
||||
"pid": 13,
|
||||
"sort": 1,
|
||||
"displayName": "角色列表",
|
||||
"children": null
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"handler": "/admin/resource-list",
|
||||
"pid": 13,
|
||||
"sort": 2,
|
||||
"displayName": "资源列表",
|
||||
"children": null
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"handler": "/admin/dictionary-list",
|
||||
"pid": 13,
|
||||
"sort": 4,
|
||||
"displayName": "数据字典",
|
||||
"children": null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"data": ["/admin/source/add", "/admin/source/delete"],
|
||||
"message": "string"
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": [
|
||||
{
|
||||
"enumValue": "gender",
|
||||
"values": [
|
||||
{
|
||||
"value": "1",
|
||||
"displayName": "男"
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"displayName": "女"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enumValue": "gender",
|
||||
"values": [
|
||||
{
|
||||
"value": "1",
|
||||
"displayName": "男"
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"displayName": "女"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": [
|
||||
{
|
||||
"enumValue": "gender",
|
||||
"values": [
|
||||
{
|
||||
"displayName": "男",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"displayName": "女",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "北京市",
|
||||
"id": "110000"
|
||||
},
|
||||
{
|
||||
"name": "天津市",
|
||||
"id": "120000"
|
||||
},
|
||||
{
|
||||
"name": "河北省",
|
||||
"id": "130000"
|
||||
},
|
||||
{
|
||||
"name": "山西省",
|
||||
"id": "140000"
|
||||
},
|
||||
{
|
||||
"name": "内蒙古自治区",
|
||||
"id": "150000"
|
||||
},
|
||||
{
|
||||
"name": "辽宁省",
|
||||
"id": "210000"
|
||||
},
|
||||
{
|
||||
"name": "吉林省",
|
||||
"id": "220000"
|
||||
},
|
||||
{
|
||||
"name": "黑龙江省",
|
||||
"id": "230000"
|
||||
},
|
||||
{
|
||||
"name": "上海市",
|
||||
"id": "310000"
|
||||
},
|
||||
{
|
||||
"name": "江苏省",
|
||||
"id": "320000"
|
||||
},
|
||||
{
|
||||
"name": "浙江省",
|
||||
"id": "330000"
|
||||
},
|
||||
{
|
||||
"name": "安徽省",
|
||||
"id": "340000"
|
||||
},
|
||||
{
|
||||
"name": "福建省",
|
||||
"id": "350000"
|
||||
},
|
||||
{
|
||||
"name": "江西省",
|
||||
"id": "360000"
|
||||
},
|
||||
{
|
||||
"name": "山东省",
|
||||
"id": "370000"
|
||||
},
|
||||
{
|
||||
"name": "河南省",
|
||||
"id": "410000"
|
||||
},
|
||||
{
|
||||
"name": "湖北省",
|
||||
"id": "420000"
|
||||
},
|
||||
{
|
||||
"name": "湖南省",
|
||||
"id": "430000"
|
||||
},
|
||||
{
|
||||
"name": "广东省",
|
||||
"id": "440000"
|
||||
},
|
||||
{
|
||||
"name": "广西壮族自治区",
|
||||
"id": "450000"
|
||||
},
|
||||
{
|
||||
"name": "海南省",
|
||||
"id": "460000"
|
||||
},
|
||||
{
|
||||
"name": "重庆市",
|
||||
"id": "500000"
|
||||
},
|
||||
{
|
||||
"name": "四川省",
|
||||
"id": "510000"
|
||||
},
|
||||
{
|
||||
"name": "贵州省",
|
||||
"id": "520000"
|
||||
},
|
||||
{
|
||||
"name": "云南省",
|
||||
"id": "530000"
|
||||
},
|
||||
{
|
||||
"name": "西藏自治区",
|
||||
"id": "540000"
|
||||
},
|
||||
{
|
||||
"name": "陕西省",
|
||||
"id": "610000"
|
||||
},
|
||||
{
|
||||
"name": "甘肃省",
|
||||
"id": "620000"
|
||||
},
|
||||
{
|
||||
"name": "青海省",
|
||||
"id": "630000"
|
||||
},
|
||||
{
|
||||
"name": "宁夏回族自治区",
|
||||
"id": "640000"
|
||||
},
|
||||
{
|
||||
"name": "新疆维吾尔自治区",
|
||||
"id": "650000"
|
||||
},
|
||||
{
|
||||
"name": "台湾省",
|
||||
"id": "710000"
|
||||
},
|
||||
{
|
||||
"name": "香港特别行政区",
|
||||
"id": "810000"
|
||||
},
|
||||
{
|
||||
"name": "澳门特别行政区",
|
||||
"id": "820000"
|
||||
}
|
||||
]
|
||||
@@ -1,63 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "admin_info",
|
||||
"type": 2,
|
||||
"sort": -1,
|
||||
"displayName": "管理员信息(The mock data)",
|
||||
"createTime": 1551020863000,
|
||||
"pid": 0,
|
||||
"handler": "/admin/admin/info",
|
||||
"children": null
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "product",
|
||||
"type": 1,
|
||||
"sort": 1,
|
||||
"displayName": "商品",
|
||||
"createTime": 1551062423000,
|
||||
"pid": 0,
|
||||
"handler": "",
|
||||
"children": [
|
||||
{
|
||||
"id": 3,
|
||||
"name": "product_manager",
|
||||
"type": 1,
|
||||
"sort": 1,
|
||||
"displayName": "商品管理",
|
||||
"createTime": 1551332076000,
|
||||
"pid": 2,
|
||||
"handler": "/product/list",
|
||||
"children": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "测试菜单1",
|
||||
"type": 1,
|
||||
"sort": 1,
|
||||
"displayName": "测试说明",
|
||||
"createTime": 1551371637000,
|
||||
"pid": 0,
|
||||
"handler": null,
|
||||
"children": [
|
||||
{
|
||||
"id": 11,
|
||||
"name": "测试",
|
||||
"type": 1,
|
||||
"sort": 1,
|
||||
"displayName": "测试",
|
||||
"createTime": 1551791053000,
|
||||
"pid": 9,
|
||||
"handler": "/admin/test",
|
||||
"children": null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"code": 0,
|
||||
"data": {
|
||||
"count": 2,
|
||||
"roles": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "系统管理员",
|
||||
"createTime": 1551332076000
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "系统管理员",
|
||||
"createTime": 1551332076000
|
||||
}
|
||||
]
|
||||
},
|
||||
"message": "string"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// 常用,公共 mock
|
||||
|
||||
export function resultBody(result, code, message) {
|
||||
return {
|
||||
code: code || 0,
|
||||
message: message || '',
|
||||
...(result || null),
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
resultBody,
|
||||
};
|
||||
@@ -1,115 +0,0 @@
|
||||
const fakeNotices = [
|
||||
{
|
||||
id: '000000001',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '你收到了 14 份新周报',
|
||||
datetime: '2017-08-09',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000002',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png',
|
||||
title: '你推荐的 曲妮妮 已通过第三轮面试',
|
||||
datetime: '2017-08-08',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000003',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png',
|
||||
title: '这种模板可以区分多种通知类型',
|
||||
datetime: '2017-08-07',
|
||||
read: true,
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000004',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
|
||||
title: '左侧图标用于区分不同的类型',
|
||||
datetime: '2017-08-07',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000005',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '内容不要超过两行字,超出时自动截断',
|
||||
datetime: '2017-08-07',
|
||||
type: 'notification',
|
||||
},
|
||||
{
|
||||
id: '000000006',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
|
||||
title: '曲丽丽 评论了你',
|
||||
description: '描述信息描述信息描述信息',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000007',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
|
||||
title: '朱偏右 回复了你',
|
||||
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000008',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg',
|
||||
title: '标题',
|
||||
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像',
|
||||
datetime: '2017-08-07',
|
||||
type: 'message',
|
||||
clickClose: true,
|
||||
},
|
||||
{
|
||||
id: '000000009',
|
||||
title: '任务名称',
|
||||
description: '任务需要在 2017-01-12 20:00 前启动',
|
||||
extra: '未开始',
|
||||
status: 'todo',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000010',
|
||||
title: '第三方紧急代码变更',
|
||||
description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
|
||||
extra: '马上到期',
|
||||
status: 'urgent',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000011',
|
||||
title: '信息安全考试',
|
||||
description: '指派竹尔于 2017-01-09 前完成更新并发布',
|
||||
extra: '已耗时 8 天',
|
||||
status: 'doing',
|
||||
type: 'event',
|
||||
},
|
||||
{
|
||||
id: '000000012',
|
||||
title: 'ABCD 版本发布',
|
||||
description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
|
||||
extra: '进行中',
|
||||
status: 'processing',
|
||||
type: 'event',
|
||||
},
|
||||
];
|
||||
|
||||
const getNotices = (req, res) => {
|
||||
if (req.query && req.query.type) {
|
||||
const startFrom = parseInt(req.query.lastItemId, 10) + 1;
|
||||
const result = fakeNotices
|
||||
.filter(({ type }) => type === req.query.type)
|
||||
.map((notice, index) => ({
|
||||
...notice,
|
||||
id: `0000000${startFrom + index}`,
|
||||
}));
|
||||
return res.json(startFrom > 24 ? result.concat(null) : result);
|
||||
}
|
||||
return res.json(fakeNotices);
|
||||
};
|
||||
|
||||
export default {
|
||||
'GET /api/notices': getNotices,
|
||||
};
|
||||
@@ -1,177 +0,0 @@
|
||||
import mockjs from 'mockjs';
|
||||
|
||||
const basicGoods = [
|
||||
{
|
||||
id: '1234561',
|
||||
name: '矿泉水 550ml',
|
||||
barcode: '12421432143214321',
|
||||
price: '2.00',
|
||||
num: '1',
|
||||
amount: '2.00',
|
||||
},
|
||||
{
|
||||
id: '1234562',
|
||||
name: '凉茶 300ml',
|
||||
barcode: '12421432143214322',
|
||||
price: '3.00',
|
||||
num: '2',
|
||||
amount: '6.00',
|
||||
},
|
||||
{
|
||||
id: '1234563',
|
||||
name: '好吃的薯片',
|
||||
barcode: '12421432143214323',
|
||||
price: '7.00',
|
||||
num: '4',
|
||||
amount: '28.00',
|
||||
},
|
||||
{
|
||||
id: '1234564',
|
||||
name: '特别好吃的蛋卷',
|
||||
barcode: '12421432143214324',
|
||||
price: '8.50',
|
||||
num: '3',
|
||||
amount: '25.50',
|
||||
},
|
||||
];
|
||||
|
||||
const basicProgress = [
|
||||
{
|
||||
key: '1',
|
||||
time: '2017-10-01 14:10',
|
||||
rate: '联系客户',
|
||||
status: 'processing',
|
||||
operator: '取货员 ID1234',
|
||||
cost: '5mins',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
time: '2017-10-01 14:05',
|
||||
rate: '取货员出发',
|
||||
status: 'success',
|
||||
operator: '取货员 ID1234',
|
||||
cost: '1h',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
time: '2017-10-01 13:05',
|
||||
rate: '取货员接单',
|
||||
status: 'success',
|
||||
operator: '取货员 ID1234',
|
||||
cost: '5mins',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
time: '2017-10-01 13:00',
|
||||
rate: '申请审批通过',
|
||||
status: 'success',
|
||||
operator: '系统',
|
||||
cost: '1h',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
time: '2017-10-01 12:00',
|
||||
rate: '发起退货申请',
|
||||
status: 'success',
|
||||
operator: '用户',
|
||||
cost: '5mins',
|
||||
},
|
||||
];
|
||||
|
||||
const advancedOperation1 = [
|
||||
{
|
||||
key: 'op1',
|
||||
type: '订购关系生效',
|
||||
name: '曲丽丽',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '-',
|
||||
},
|
||||
{
|
||||
key: 'op2',
|
||||
type: '财务复审',
|
||||
name: '付小小',
|
||||
status: 'reject',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '不通过原因',
|
||||
},
|
||||
{
|
||||
key: 'op3',
|
||||
type: '部门初审',
|
||||
name: '周毛毛',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '-',
|
||||
},
|
||||
{
|
||||
key: 'op4',
|
||||
type: '提交订单',
|
||||
name: '林东东',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '很棒',
|
||||
},
|
||||
{
|
||||
key: 'op5',
|
||||
type: '创建订单',
|
||||
name: '汗牙牙',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '-',
|
||||
},
|
||||
];
|
||||
|
||||
const advancedOperation2 = [
|
||||
{
|
||||
key: 'op1',
|
||||
type: '订购关系生效',
|
||||
name: '曲丽丽',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '-',
|
||||
},
|
||||
];
|
||||
|
||||
const advancedOperation3 = [
|
||||
{
|
||||
key: 'op1',
|
||||
type: '创建订单',
|
||||
name: '汗牙牙',
|
||||
status: 'agree',
|
||||
updatedAt: '2017-10-03 19:23:12',
|
||||
memo: '-',
|
||||
},
|
||||
];
|
||||
const getProfileAdvancedData = {
|
||||
advancedOperation1,
|
||||
advancedOperation2,
|
||||
advancedOperation3,
|
||||
};
|
||||
|
||||
const { Random } = mockjs;
|
||||
|
||||
export default {
|
||||
'GET /api/profile/advanced': getProfileAdvancedData,
|
||||
'GET /api/profile/basic': (req, res) => {
|
||||
const { id } = req.query;
|
||||
const application = {
|
||||
id,
|
||||
status: '已取货',
|
||||
orderNo: Random.id(),
|
||||
childOrderNo: Random.id(),
|
||||
};
|
||||
const userInfo = {
|
||||
name: Random.cname(),
|
||||
tel: '18100000000',
|
||||
delivery: '菜鸟物流',
|
||||
addr: '浙江省杭州市西湖区万塘路18号',
|
||||
remark: '备注',
|
||||
};
|
||||
res.json({
|
||||
userInfo,
|
||||
application,
|
||||
basicGoods,
|
||||
basicProgress,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
export default {
|
||||
'/api/auth_routes': {
|
||||
'/form/advanced-form': { authority: ['admin', 'user'] },
|
||||
},
|
||||
};
|
||||
@@ -1,131 +0,0 @@
|
||||
import { parse } from 'url';
|
||||
|
||||
// mock tableListDataSource
|
||||
let tableListDataSource = [];
|
||||
for (let i = 0; i < 46; i += 1) {
|
||||
tableListDataSource.push({
|
||||
key: i,
|
||||
disabled: i % 6 === 0,
|
||||
href: 'https://ant.design',
|
||||
avatar: [
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
|
||||
][i % 2],
|
||||
name: `TradeCode ${i}`,
|
||||
title: `一个任务名称 ${i}`,
|
||||
owner: '曲丽丽',
|
||||
desc: '这是一段描述',
|
||||
callNo: Math.floor(Math.random() * 1000),
|
||||
status: Math.floor(Math.random() * 10) % 4,
|
||||
updatedAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
|
||||
createdAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
|
||||
progress: Math.ceil(Math.random() * 100),
|
||||
});
|
||||
}
|
||||
|
||||
function getRule(req, res, u) {
|
||||
let url = u;
|
||||
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
|
||||
url = req.url; // eslint-disable-line
|
||||
}
|
||||
|
||||
const params = parse(url, true).query;
|
||||
|
||||
let dataSource = tableListDataSource;
|
||||
|
||||
if (params.sorter) {
|
||||
const s = params.sorter.split('_');
|
||||
dataSource = dataSource.sort((prev, next) => {
|
||||
if (s[1] === 'descend') {
|
||||
return next[s[0]] - prev[s[0]];
|
||||
}
|
||||
return prev[s[0]] - next[s[0]];
|
||||
});
|
||||
}
|
||||
|
||||
if (params.status) {
|
||||
const status = params.status.split(',');
|
||||
let filterDataSource = [];
|
||||
status.forEach(s => {
|
||||
filterDataSource = filterDataSource.concat(
|
||||
dataSource.filter(data => parseInt(data.status, 10) === parseInt(s[0], 10))
|
||||
);
|
||||
});
|
||||
dataSource = filterDataSource;
|
||||
}
|
||||
|
||||
if (params.name) {
|
||||
dataSource = dataSource.filter(data => data.name.indexOf(params.name) > -1);
|
||||
}
|
||||
|
||||
let pageSize = 10;
|
||||
if (params.pageSize) {
|
||||
pageSize = params.pageSize * 1;
|
||||
}
|
||||
|
||||
const result = {
|
||||
list: dataSource,
|
||||
pagination: {
|
||||
total: dataSource.length,
|
||||
pageSize,
|
||||
current: parseInt(params.currentPage, 10) || 1,
|
||||
},
|
||||
};
|
||||
|
||||
return res.json(result);
|
||||
}
|
||||
|
||||
function postRule(req, res, u, b) {
|
||||
let url = u;
|
||||
if (!url || Object.prototype.toString.call(url) !== '[object String]') {
|
||||
url = req.url; // eslint-disable-line
|
||||
}
|
||||
|
||||
const body = (b && b.body) || req.body;
|
||||
const { method, name, desc, key } = body;
|
||||
|
||||
switch (method) {
|
||||
/* eslint no-case-declarations:0 */
|
||||
case 'delete':
|
||||
tableListDataSource = tableListDataSource.filter(item => key.indexOf(item.key) === -1);
|
||||
break;
|
||||
case 'post':
|
||||
const i = Math.ceil(Math.random() * 10000);
|
||||
tableListDataSource.unshift({
|
||||
key: i,
|
||||
href: 'https://ant.design',
|
||||
avatar: [
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png',
|
||||
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png',
|
||||
][i % 2],
|
||||
name: `TradeCode ${i}`,
|
||||
title: `一个任务名称 ${i}`,
|
||||
owner: '曲丽丽',
|
||||
desc,
|
||||
callNo: Math.floor(Math.random() * 1000),
|
||||
status: Math.floor(Math.random() * 10) % 2,
|
||||
updatedAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
progress: Math.ceil(Math.random() * 100),
|
||||
});
|
||||
break;
|
||||
case 'update':
|
||||
tableListDataSource = tableListDataSource.map(item => {
|
||||
if (item.key === key) {
|
||||
Object.assign(item, { desc, name });
|
||||
return item;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return getRule(req, res, u);
|
||||
}
|
||||
|
||||
export default {
|
||||
'GET /api/rule': getRule,
|
||||
'POST /api/rule': postRule,
|
||||
};
|
||||
@@ -1,136 +0,0 @@
|
||||
// 代码中会兼容本地 service mock 以及部署站点的静态数据
|
||||
// import { stringify } from 'qs';
|
||||
|
||||
export default {
|
||||
// 支持值为 Object 和 Array
|
||||
'GET /api/currentUser': {
|
||||
name: 'Serati Ma',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
|
||||
userid: '00000001',
|
||||
email: 'antdesign@alipay.com',
|
||||
signature: '海纳百川,有容乃大',
|
||||
title: '交互专家',
|
||||
group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED',
|
||||
tags: [
|
||||
{
|
||||
key: '0',
|
||||
label: '很有想法的',
|
||||
},
|
||||
{
|
||||
key: '1',
|
||||
label: '专注设计',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: '辣~',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: '大长腿',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: '川妹子',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
label: '海纳百川',
|
||||
},
|
||||
],
|
||||
notifyCount: 12,
|
||||
unreadCount: 11,
|
||||
country: 'China',
|
||||
geographic: {
|
||||
province: {
|
||||
label: '浙江省',
|
||||
key: '330000',
|
||||
},
|
||||
city: {
|
||||
label: '杭州市',
|
||||
key: '330100',
|
||||
},
|
||||
},
|
||||
address: '西湖区工专路 77 号',
|
||||
phone: '0752-268888888',
|
||||
},
|
||||
// GET POST 可省略
|
||||
'GET /api/users': [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: 'Jim Green',
|
||||
age: 42,
|
||||
address: 'London No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: 'Joe Black',
|
||||
age: 32,
|
||||
address: 'Sidney No. 1 Lake Park',
|
||||
},
|
||||
],
|
||||
'POST /admin-api/admins/passport/login': (req, res) => {
|
||||
const { username } = req.body;
|
||||
if (username === 'admin') {
|
||||
res.send({
|
||||
code: 0,
|
||||
data: {
|
||||
accessToken: '2e3d7635c15e47e997611707a237859f',
|
||||
expiresIn: 2879,
|
||||
refreshToken: 'd091e7c35bbb4313b0f557a6ef23d033',
|
||||
},
|
||||
message: 'string',
|
||||
});
|
||||
return;
|
||||
}
|
||||
res.send({
|
||||
code: 1000,
|
||||
data: {},
|
||||
message: '账号或密码错误-mock!',
|
||||
});
|
||||
},
|
||||
'POST /api/register': (req, res) => {
|
||||
res.send({ status: 'ok', currentAuthority: 'user' });
|
||||
},
|
||||
'GET /api/500': (req, res) => {
|
||||
res.status(500).send({
|
||||
timestamp: 1513932555104,
|
||||
status: 500,
|
||||
error: 'error',
|
||||
message: 'error',
|
||||
path: '/base/category/list',
|
||||
});
|
||||
},
|
||||
'GET /api/404': (req, res) => {
|
||||
res.status(404).send({
|
||||
timestamp: 1513932643431,
|
||||
status: 404,
|
||||
error: 'Not Found',
|
||||
message: 'No message available',
|
||||
path: '/base/category/list/2121212',
|
||||
});
|
||||
},
|
||||
'GET /api/403': (req, res) => {
|
||||
res.status(403).send({
|
||||
timestamp: 1513932555104,
|
||||
status: 403,
|
||||
error: 'Unauthorized',
|
||||
message: 'Unauthorized',
|
||||
path: '/base/category/list',
|
||||
});
|
||||
},
|
||||
'GET /api/401': (req, res) => {
|
||||
res.status(401).send({
|
||||
timestamp: 1513932555104,
|
||||
status: 401,
|
||||
error: 'Unauthorized',
|
||||
message: 'Unauthorized',
|
||||
path: '/base/category/list',
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
[[redirects]]
|
||||
from = "/api/*"
|
||||
to = "https://us-central1-antd-pro.cloudfunctions.net/api/api/:splat"
|
||||
status = 200
|
||||
force = true
|
||||
[redirects.headers]
|
||||
X-From = "Netlify"
|
||||
X-Api-Key = "some-api-key-string"
|
||||
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -1,144 +0,0 @@
|
||||
{
|
||||
"name": "ant-design-pro",
|
||||
"version": "2.2.1",
|
||||
"description": "An out-of-box UI solution for enterprise applications",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"presite": "cd functions && npm install",
|
||||
"start": "cross-env APP_TYPE=site umi dev",
|
||||
"start:no-mock": "cross-env MOCK=none umi dev",
|
||||
"start:admin-web": "cross-env BASE_PATH='/admin-web/' NODE_ENV=development APP_TYPE=site umi dev",
|
||||
"start:admin-web:no-mock": "cross-env BASE_PATH='/admin-web/' NODE_ENV=development MOCK=none APP_TYPE=site umi dev",
|
||||
"build": "cross-env BASE_PATH='/' NODE_ENV=production umi build",
|
||||
"build:admin-web": "cross-env BASE_PATH='/admin-web/' NODE_ENV=production umi build",
|
||||
"site": "npm run presite && cross-env APP_TYPE=site npm run build && firebase deploy && npm run docker:push",
|
||||
"analyze": "cross-env ANALYZE=1 umi build",
|
||||
"lint:style": "stylelint 'src/**/*.less' --syntax less",
|
||||
"lint:prettier": "check-prettier lint",
|
||||
"lint": "eslint --ext .js src mock tests && npm run lint:style && npm run lint:prettier",
|
||||
"lint:fix": "eslint --fix --ext .js src mock tests && stylelint --fix 'src/**/*.less' --syntax less",
|
||||
"lint-staged": "lint-staged",
|
||||
"lint-staged:js": "eslint --ext .js",
|
||||
"tslint": "npm run tslint:fix",
|
||||
"tslint:fix": "tslint --fix 'src/**/*.ts*'",
|
||||
"test": "umi test",
|
||||
"test:component": "umi test ./src/components",
|
||||
"test:all": "node ./tests/run-tests.js",
|
||||
"prettier": "node ./scripts/prettier.js",
|
||||
"docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up",
|
||||
"docker:build": "docker-compose -f ./docker/docker-compose.dev.yml build",
|
||||
"docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up",
|
||||
"docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build",
|
||||
"docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./",
|
||||
"docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro",
|
||||
"docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/data-set": "^0.10.1",
|
||||
"@babel/runtime": "^7.3.1",
|
||||
"antd": "^3.13.0",
|
||||
"bizcharts": "^3.4.3",
|
||||
"bizcharts-plugin-slider": "^2.1.1-beta.1",
|
||||
"braft-editor": "^2.2.10",
|
||||
"classnames": "^2.2.6",
|
||||
"crypto": "^1.0.1",
|
||||
"dva": "^2.4.1",
|
||||
"enquire-js": "^0.2.1",
|
||||
"hash.js": "^1.1.7",
|
||||
"js-uuid": "0.0.6",
|
||||
"lodash": "^4.17.11",
|
||||
"lodash-decorators": "^6.0.1",
|
||||
"memoize-one": "^5.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"numeral": "^2.0.6",
|
||||
"nzh": "^1.0.4",
|
||||
"omit.js": "^1.0.0",
|
||||
"path-to-regexp": "^3.0.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"qiniu-js": "^2.5.4",
|
||||
"qs": "^6.6.0",
|
||||
"rc-animate": "^2.6.0",
|
||||
"react": "^16.7.0",
|
||||
"react-container-query": "^0.11.0",
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"react-document-title": "^2.0.3",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-fittext": "^1.0.0",
|
||||
"react-media": "^1.9.2",
|
||||
"react-router-dom": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.8.1",
|
||||
"@types/react-dom": "^16.0.11",
|
||||
"antd-pro-merge-less": "^1.0.0",
|
||||
"antd-theme-webpack-plugin": "^1.2.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"check-prettier": "^1.0.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"cross-port-killer": "^1.0.1",
|
||||
"enzyme": "3.8.0",
|
||||
"eslint": "^5.13.0",
|
||||
"eslint-config-airbnb": "^17.1.0",
|
||||
"eslint-config-prettier": "^4.0.0",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-compat": "^2.6.3",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.0",
|
||||
"eslint-plugin-markdown": "^1.0.0",
|
||||
"eslint-plugin-react": "^7.12.4",
|
||||
"gh-pages": "^2.0.1",
|
||||
"husky": "^1.3.1",
|
||||
"jest-puppeteer": "^3.9.0",
|
||||
"less": "^3.9.0",
|
||||
"lint-staged": "^8.1.1",
|
||||
"merge-umi-mock-data": "^1.0.4",
|
||||
"mockjs": "^1.0.1-beta3",
|
||||
"prettier": "1.16.3",
|
||||
"slash2": "^2.0.0",
|
||||
"stylelint": "^9.10.1",
|
||||
"stylelint-config-css-modules": "^1.3.0",
|
||||
"stylelint-config-prettier": "^4.0.0",
|
||||
"stylelint-config-rational-order": "^0.0.4",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "^1.1.0",
|
||||
"stylelint-order": "^2.0.0",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-config-prettier": "^1.17.0",
|
||||
"tslint-react": "^3.6.0",
|
||||
"umi": "^2.4.4",
|
||||
"umi-plugin-ga": "^1.1.3",
|
||||
"umi-plugin-react": "^1.4.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"puppeteer": "^1.12.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{js,ts,tsx,json,jsx,less}": [
|
||||
"node ./scripts/lint-prettier.js",
|
||||
"git add"
|
||||
],
|
||||
"**/*.{js}": "npm run lint-staged:js",
|
||||
"**/*.less": "stylelint --syntax less"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10"
|
||||
],
|
||||
"checkFiles": [
|
||||
"src/**/*.js*",
|
||||
"src/**/*.ts*",
|
||||
"src/**/*.less",
|
||||
"config/**/*.js*",
|
||||
"scripts/**/*.js"
|
||||
],
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint-staged"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -1,3 +0,0 @@
|
||||
const generateMock = require('merge-umi-mock-data');
|
||||
const path = require('path');
|
||||
generateMock(path.join(__dirname, '../mock'), path.join(__dirname, '../functions/mock/index.js'));
|
||||
@@ -1,21 +0,0 @@
|
||||
const glob = require('glob');
|
||||
|
||||
const getPrettierFiles = () => {
|
||||
let files = [];
|
||||
const jsFiles = glob.sync('src/**/*.js*', { ignore: ['**/node_modules/**', 'build/**'] });
|
||||
const tsFiles = glob.sync('src/**/*.ts*', { ignore: ['**/node_modules/**', 'build/**'] });
|
||||
const configFiles = glob.sync('config/**/*.js*', { ignore: ['**/node_modules/**', 'build/**'] });
|
||||
const scriptFiles = glob.sync('scripts/**/*.js');
|
||||
const lessFiles = glob.sync('src/**/*.less*', { ignore: ['**/node_modules/**', 'build/**'] });
|
||||
files = files.concat(jsFiles);
|
||||
files = files.concat(tsFiles);
|
||||
files = files.concat(configFiles);
|
||||
files = files.concat(scriptFiles);
|
||||
files = files.concat(lessFiles);
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
module.exports = getPrettierFiles;
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* copy to https://github.com/facebook/react/blob/master/scripts/prettier/index.js
|
||||
* prettier api doc https://prettier.io/docs/en/api.html
|
||||
*----------*****--------------
|
||||
* lint file is prettier
|
||||
*----------*****--------------
|
||||
*/
|
||||
|
||||
const prettier = require('prettier');
|
||||
const fs = require('fs');
|
||||
const chalk = require('chalk');
|
||||
const prettierConfigPath = require.resolve('../.prettierrc');
|
||||
|
||||
const files = process.argv.slice(2);
|
||||
|
||||
let didError = false;
|
||||
|
||||
files.forEach(file => {
|
||||
Promise.all([
|
||||
prettier.resolveConfig(file, {
|
||||
config: prettierConfigPath,
|
||||
}),
|
||||
prettier.getFileInfo(file),
|
||||
])
|
||||
.then(resolves => {
|
||||
const [options, fileInfo] = resolves;
|
||||
if (fileInfo.ignored) {
|
||||
return;
|
||||
}
|
||||
const input = fs.readFileSync(file, 'utf8');
|
||||
const withParserOptions = {
|
||||
...options,
|
||||
parser: fileInfo.inferredParser,
|
||||
};
|
||||
const output = prettier.format(input, withParserOptions);
|
||||
if (output !== input) {
|
||||
fs.writeFileSync(file, output, 'utf8');
|
||||
console.log(chalk.green(`${file} is prettier`));
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
didError = true;
|
||||
})
|
||||
.finally(() => {
|
||||
if (didError) {
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(chalk.hex('#1890FF')('prettier success!'));
|
||||
});
|
||||
});
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* copy to https://github.com/facebook/react/blob/master/scripts/prettier/index.js
|
||||
* prettier api doc https://prettier.io/docs/en/api.html
|
||||
*----------*****--------------
|
||||
* prettier all js and all ts.
|
||||
*----------*****--------------
|
||||
*/
|
||||
|
||||
const prettier = require('prettier');
|
||||
const fs = require('fs');
|
||||
const getPrettierFiles = require('./getPrettierFiles');
|
||||
const prettierConfigPath = require.resolve('../.prettierrc');
|
||||
const chalk = require('chalk');
|
||||
|
||||
let didError = false;
|
||||
|
||||
const files = getPrettierFiles();
|
||||
|
||||
files.forEach(file => {
|
||||
const options = prettier.resolveConfig.sync(file, {
|
||||
config: prettierConfigPath,
|
||||
});
|
||||
const fileInfo = prettier.getFileInfo.sync(file);
|
||||
if (fileInfo.ignored) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const input = fs.readFileSync(file, 'utf8');
|
||||
const withParserOptions = {
|
||||
...options,
|
||||
parser: fileInfo.inferredParser,
|
||||
};
|
||||
const output = prettier.format(input, withParserOptions);
|
||||
if (output !== input) {
|
||||
fs.writeFileSync(file, output, 'utf8');
|
||||
console.log(chalk.green(`${file} is prettier`));
|
||||
}
|
||||
} catch (e) {
|
||||
didError = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (didError) {
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(chalk.hex('#1890FF')('prettier success!'));
|
||||
@@ -1,48 +0,0 @@
|
||||
// import fetch from 'dva/fetch';
|
||||
import getAuthRoutesData from './mock-data/authRoutesData';
|
||||
|
||||
export const dva = {
|
||||
config: {
|
||||
onError(err) {
|
||||
err.preventDefault();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let authRoutes = {};
|
||||
|
||||
function ergodicRoutes(routes, authKey, authority) {
|
||||
routes.forEach(element => {
|
||||
if (element.path === authKey) {
|
||||
if (!element.authority) element.authority = []; // eslint-disable-line
|
||||
Object.assign(element.authority, authority || []);
|
||||
} else if (element.routes) {
|
||||
ergodicRoutes(element.routes, authKey, authority);
|
||||
}
|
||||
return element;
|
||||
});
|
||||
}
|
||||
|
||||
export function patchRoutes(routes) {
|
||||
Object.keys(authRoutes).map(authKey =>
|
||||
ergodicRoutes(routes, authKey, authRoutes[authKey].authority)
|
||||
);
|
||||
window.g_routes = routes;
|
||||
}
|
||||
|
||||
export function render(oldRender) {
|
||||
// fetch('/api/auth_routes')
|
||||
// .then(res => res.json())
|
||||
// .then(
|
||||
// ret => {
|
||||
// authRoutes = ret;
|
||||
// oldRender();
|
||||
// },
|
||||
// () => {
|
||||
// oldRender();
|
||||
// }
|
||||
// );
|
||||
|
||||
authRoutes = getAuthRoutesData;
|
||||
oldRender();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Group 28 Copy 5</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<linearGradient x1="62.1023273%" y1="0%" x2="108.19718%" y2="37.8635764%" id="linearGradient-1">
|
||||
<stop stop-color="#4285EB" offset="0%"></stop>
|
||||
<stop stop-color="#2EC7FF" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="69.644116%" y1="0%" x2="54.0428975%" y2="108.456714%" id="linearGradient-2">
|
||||
<stop stop-color="#29CDFF" offset="0%"></stop>
|
||||
<stop stop-color="#148EFF" offset="37.8600687%"></stop>
|
||||
<stop stop-color="#0A60FF" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="69.6908165%" y1="-12.9743587%" x2="16.7228981%" y2="117.391248%" id="linearGradient-3">
|
||||
<stop stop-color="#FA816E" offset="0%"></stop>
|
||||
<stop stop-color="#F74A5C" offset="41.472606%"></stop>
|
||||
<stop stop-color="#F51D2C" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="68.1279872%" y1="-35.6905737%" x2="30.4400914%" y2="114.942679%" id="linearGradient-4">
|
||||
<stop stop-color="#FA8E7D" offset="0%"></stop>
|
||||
<stop stop-color="#F74A5C" offset="51.2635191%"></stop>
|
||||
<stop stop-color="#F51D2C" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="logo" transform="translate(-20.000000, -20.000000)">
|
||||
<g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)">
|
||||
<g id="Group-27-Copy-3">
|
||||
<g id="Group-25" fill-rule="nonzero">
|
||||
<g id="2">
|
||||
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-1)"></path>
|
||||
<path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-2)"></path>
|
||||
</g>
|
||||
<path d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z" id="Shape" fill="url(#linearGradient-3)"></path>
|
||||
</g>
|
||||
<ellipse id="Combined-Shape" fill="url(#linearGradient-4)" cx="100.519339" cy="100.436681" rx="23.6001926" ry="23.580786"></ellipse>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,98 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { MiniArea } from '../Charts';
|
||||
import NumberInfo from '../NumberInfo';
|
||||
import styles from './index.less';
|
||||
|
||||
function fixedZero(val) {
|
||||
return val * 1 < 10 ? `0${val}` : val;
|
||||
}
|
||||
|
||||
function getActiveData() {
|
||||
const activeData = [];
|
||||
for (let i = 0; i < 24; i += 1) {
|
||||
activeData.push({
|
||||
x: `${fixedZero(i)}:00`,
|
||||
y: Math.floor(Math.random() * 200) + i * 50,
|
||||
});
|
||||
}
|
||||
return activeData;
|
||||
}
|
||||
|
||||
export default class ActiveChart extends Component {
|
||||
state = {
|
||||
activeData: getActiveData(),
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.loopData();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timer);
|
||||
cancelAnimationFrame(this.requestRef);
|
||||
}
|
||||
|
||||
loopData = () => {
|
||||
this.timer = setTimeout(() => {
|
||||
this.setState(
|
||||
{
|
||||
activeData: getActiveData(),
|
||||
},
|
||||
() => {
|
||||
this.loopData();
|
||||
}
|
||||
);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { activeData = [] } = this.state;
|
||||
|
||||
return (
|
||||
<div className={styles.activeChart}>
|
||||
<NumberInfo subTitle="目标评估" total="有望达到预期" />
|
||||
<div style={{ marginTop: 32 }}>
|
||||
<MiniArea
|
||||
animate={false}
|
||||
line
|
||||
borderWidth={2}
|
||||
height={84}
|
||||
scale={{
|
||||
y: {
|
||||
tickCount: 3,
|
||||
},
|
||||
}}
|
||||
yAxis={{
|
||||
tickLine: false,
|
||||
label: false,
|
||||
title: false,
|
||||
line: false,
|
||||
}}
|
||||
data={activeData}
|
||||
/>
|
||||
</div>
|
||||
{activeData && (
|
||||
<div>
|
||||
<div className={styles.activeChartGrid}>
|
||||
<p>{[...activeData].sort()[activeData.length - 1].y + 200} 亿元</p>
|
||||
<p>{[...activeData].sort()[Math.floor(activeData.length / 2)].y} 亿元</p>
|
||||
</div>
|
||||
<div className={styles.dashedLine}>
|
||||
<div className={styles.line} />
|
||||
</div>
|
||||
<div className={styles.dashedLine}>
|
||||
<div className={styles.line} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeData && (
|
||||
<div className={styles.activeChartLegend}>
|
||||
<span>00:00</span>
|
||||
<span>{activeData[Math.floor(activeData.length / 2)].x}</span>
|
||||
<span>{activeData[activeData.length - 1].x}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
.activeChart {
|
||||
position: relative;
|
||||
}
|
||||
.activeChartGrid {
|
||||
p {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
}
|
||||
p:last-child {
|
||||
top: 115px;
|
||||
}
|
||||
}
|
||||
.activeChartLegend {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
margin-top: 8px;
|
||||
font-size: 0;
|
||||
line-height: 20px;
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 33.33%;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
span:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
span:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.dashedLine {
|
||||
position: relative;
|
||||
top: -70px;
|
||||
left: -3px;
|
||||
height: 1px;
|
||||
|
||||
.line {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(to right, transparent 50%, #e9e9e9 50%);
|
||||
background-size: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashedLine:last-child {
|
||||
top: -36px;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import { Avatar } from 'antd';
|
||||
import styles from './index.less';
|
||||
|
||||
const ArticleListContent = ({ data: { content, updatedAt, avatar, owner, href } }) => (
|
||||
<div className={styles.listContent}>
|
||||
<div className={styles.description}>{content}</div>
|
||||
<div className={styles.extra}>
|
||||
<Avatar src={avatar} size="small" />
|
||||
<a href={href}>{owner}</a> 发布在 <a href={href}>{href}</a>
|
||||
<em>{moment(updatedAt).format('YYYY-MM-DD HH:mm')}</em>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ArticleListContent;
|
||||
@@ -1,38 +0,0 @@
|
||||
@import '~antd/lib/style/themes/default.less';
|
||||
|
||||
.listContent {
|
||||
.description {
|
||||
max-width: 720px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.extra {
|
||||
margin-top: 16px;
|
||||
color: @text-color-secondary;
|
||||
line-height: 22px;
|
||||
& > :global(.ant-avatar) {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 8px;
|
||||
vertical-align: top;
|
||||
}
|
||||
& > em {
|
||||
margin-left: 16px;
|
||||
color: @disabled-color;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs) {
|
||||
.listContent {
|
||||
.extra {
|
||||
& > em {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
---
|
||||
|
||||
使用 demo
|
||||
|
||||
|
||||
authKey: 代表key的权限
|
||||
|
||||
---
|
||||
|
||||
```jsx harmony
|
||||
<AuthorityControl authKey="home.button">
|
||||
<Button type="primary">按钮 控制</Button>
|
||||
</AuthorityControl>
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface AuthorityControlProps {
|
||||
authKey: string;
|
||||
}
|
||||
|
||||
export default class LoginItem extends React.Component<AuthorityControlProps, any> {}
|
||||
@@ -1,19 +0,0 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import UrlsContext from '../../layouts/UrlsContext';
|
||||
|
||||
// 用于控制权限
|
||||
class AuthorityControl extends PureComponent {
|
||||
render() {
|
||||
const { authKey, children } = this.props;
|
||||
return (
|
||||
<UrlsContext.Consumer>
|
||||
{context => {
|
||||
const { authList } = context;
|
||||
return <div>{authList[authKey] ? children : '无权限'}</div>;
|
||||
}}
|
||||
</UrlsContext.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AuthorityControl;
|
||||
@@ -1,8 +0,0 @@
|
||||
import CheckPermissions from './CheckPermissions';
|
||||
|
||||
const Authorized = ({ children, authority, noMatch = null }) => {
|
||||
const childrenRender = typeof children === 'undefined' ? null : children;
|
||||
return CheckPermissions(authority, childrenRender, noMatch);
|
||||
};
|
||||
|
||||
export default Authorized;
|
||||
@@ -1,13 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { RouteProps } from 'react-router';
|
||||
|
||||
type authorityFN = (currentAuthority?: string) => boolean;
|
||||
|
||||
type authority = string | string[] | authorityFN | Promise<any>;
|
||||
|
||||
export interface IAuthorizedRouteProps extends RouteProps {
|
||||
authority: authority;
|
||||
}
|
||||
export { authority };
|
||||
|
||||
export default class AuthorizedRoute extends React.Component<IAuthorizedRouteProps, any> {}
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Route, Redirect } from 'react-router-dom';
|
||||
import Authorized from './Authorized';
|
||||
|
||||
// TODO: umi只会返回render和rest
|
||||
const AuthorizedRoute = ({ component: Component, render, authority, redirectPath, ...rest }) => (
|
||||
<Authorized
|
||||
authority={authority}
|
||||
noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
|
||||
>
|
||||
<Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} />
|
||||
</Authorized>
|
||||
);
|
||||
|
||||
export default AuthorizedRoute;
|
||||
@@ -1,88 +0,0 @@
|
||||
import React from 'react';
|
||||
import PromiseRender from './PromiseRender';
|
||||
import { CURRENT } from './renderAuthorize';
|
||||
|
||||
function isPromise(obj) {
|
||||
return (
|
||||
!!obj &&
|
||||
(typeof obj === 'object' || typeof obj === 'function') &&
|
||||
typeof obj.then === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用权限检查方法
|
||||
* Common check permissions method
|
||||
* @param { 权限判定 Permission judgment type string |array | Promise | Function } authority
|
||||
* @param { 你的权限 Your permission description type:string} currentAuthority
|
||||
* @param { 通过的组件 Passing components } target
|
||||
* @param { 未通过的组件 no pass components } Exception
|
||||
*/
|
||||
const checkPermissions = (authority, currentAuthority, target, Exception) => {
|
||||
// 没有判定权限.默认查看所有
|
||||
// Retirement authority, return target;
|
||||
if (!authority) {
|
||||
return target;
|
||||
}
|
||||
// 数组处理
|
||||
if (Array.isArray(authority)) {
|
||||
if (authority.indexOf(currentAuthority) >= 0) {
|
||||
return target;
|
||||
}
|
||||
if (Array.isArray(currentAuthority)) {
|
||||
for (let i = 0; i < currentAuthority.length; i += 1) {
|
||||
const element = currentAuthority[i];
|
||||
if (authority.indexOf(element) >= 0) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Exception;
|
||||
}
|
||||
|
||||
// string 处理
|
||||
if (typeof authority === 'string') {
|
||||
if (authority === currentAuthority) {
|
||||
return target;
|
||||
}
|
||||
if (Array.isArray(currentAuthority)) {
|
||||
for (let i = 0; i < currentAuthority.length; i += 1) {
|
||||
const element = currentAuthority[i];
|
||||
if (authority === element) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Exception;
|
||||
}
|
||||
|
||||
// Promise 处理
|
||||
if (isPromise(authority)) {
|
||||
return <PromiseRender ok={target} error={Exception} promise={authority} />;
|
||||
}
|
||||
|
||||
// Function 处理
|
||||
if (typeof authority === 'function') {
|
||||
try {
|
||||
const bool = authority(currentAuthority);
|
||||
// 函数执行后返回值是 Promise
|
||||
if (isPromise(bool)) {
|
||||
return <PromiseRender ok={target} error={Exception} promise={bool} />;
|
||||
}
|
||||
if (bool) {
|
||||
return target;
|
||||
}
|
||||
return Exception;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
throw new Error('unsupported parameters');
|
||||
};
|
||||
|
||||
export { checkPermissions };
|
||||
|
||||
const check = (authority, target, Exception) =>
|
||||
checkPermissions(authority, CURRENT, target, Exception);
|
||||
|
||||
export default check;
|
||||
@@ -1,55 +0,0 @@
|
||||
import { checkPermissions } from './CheckPermissions';
|
||||
|
||||
const target = 'ok';
|
||||
const error = 'error';
|
||||
|
||||
describe('test CheckPermissions', () => {
|
||||
it('Correct string permission authentication', () => {
|
||||
expect(checkPermissions('user', 'user', target, error)).toEqual('ok');
|
||||
});
|
||||
it('Correct string permission authentication', () => {
|
||||
expect(checkPermissions('user', 'NULL', target, error)).toEqual('error');
|
||||
});
|
||||
it('authority is undefined , return ok', () => {
|
||||
expect(checkPermissions(null, 'NULL', target, error)).toEqual('ok');
|
||||
});
|
||||
it('currentAuthority is undefined , return error', () => {
|
||||
expect(checkPermissions('admin', null, target, error)).toEqual('error');
|
||||
});
|
||||
it('Wrong string permission authentication', () => {
|
||||
expect(checkPermissions('admin', 'user', target, error)).toEqual('error');
|
||||
});
|
||||
it('Correct Array permission authentication', () => {
|
||||
expect(checkPermissions(['user', 'admin'], 'user', target, error)).toEqual('ok');
|
||||
});
|
||||
it('Wrong Array permission authentication,currentAuthority error', () => {
|
||||
expect(checkPermissions(['user', 'admin'], 'user,admin', target, error)).toEqual('error');
|
||||
});
|
||||
it('Wrong Array permission authentication', () => {
|
||||
expect(checkPermissions(['user', 'admin'], 'guest', target, error)).toEqual('error');
|
||||
});
|
||||
it('Wrong Function permission authentication', () => {
|
||||
expect(checkPermissions(() => false, 'guest', target, error)).toEqual('error');
|
||||
});
|
||||
it('Correct Function permission authentication', () => {
|
||||
expect(checkPermissions(() => true, 'guest', target, error)).toEqual('ok');
|
||||
});
|
||||
it('authority is string, currentAuthority is array, return ok', () => {
|
||||
expect(checkPermissions('user', ['user'], target, error)).toEqual('ok');
|
||||
});
|
||||
it('authority is string, currentAuthority is array, return ok', () => {
|
||||
expect(checkPermissions('user', ['user', 'admin'], target, error)).toEqual('ok');
|
||||
});
|
||||
it('authority is array, currentAuthority is array, return ok', () => {
|
||||
expect(checkPermissions(['user', 'admin'], ['user', 'admin'], target, error)).toEqual('ok');
|
||||
});
|
||||
it('Wrong Function permission authentication', () => {
|
||||
expect(checkPermissions(() => false, ['user'], target, error)).toEqual('error');
|
||||
});
|
||||
it('Correct Function permission authentication', () => {
|
||||
expect(checkPermissions(() => true, ['user'], target, error)).toEqual('ok');
|
||||
});
|
||||
it('authority is undefined , return ok', () => {
|
||||
expect(checkPermissions(null, ['user'], target, error)).toEqual('ok');
|
||||
});
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
export default class PromiseRender extends React.PureComponent {
|
||||
state = {
|
||||
component: null,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.setRenderComponent(this.props);
|
||||
}
|
||||
|
||||
componentDidUpdate(nextProps) {
|
||||
// new Props enter
|
||||
this.setRenderComponent(nextProps);
|
||||
}
|
||||
|
||||
// set render Component : ok or error
|
||||
setRenderComponent(props) {
|
||||
const ok = this.checkIsInstantiation(props.ok);
|
||||
const error = this.checkIsInstantiation(props.error);
|
||||
props.promise
|
||||
.then(() => {
|
||||
this.setState({
|
||||
component: ok,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
component: error,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Determine whether the incoming component has been instantiated
|
||||
// AuthorizedRoute is already instantiated
|
||||
// Authorized render is already instantiated, children is no instantiated
|
||||
// Secured is not instantiated
|
||||
checkIsInstantiation = target => {
|
||||
if (!React.isValidElement(target)) {
|
||||
return target;
|
||||
}
|
||||
return () => target;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { component: Component } = this.state;
|
||||
const { ok, error, promise, ...rest } = this.props;
|
||||
return Component ? (
|
||||
<Component {...rest} />
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
margin: 'auto',
|
||||
paddingTop: 50,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
<Spin size="large" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import React from 'react';
|
||||
import Exception from '../Exception';
|
||||
import CheckPermissions from './CheckPermissions';
|
||||
/**
|
||||
* 默认不能访问任何页面
|
||||
* default is "NULL"
|
||||
*/
|
||||
const Exception403 = () => <Exception type="403" />;
|
||||
|
||||
// Determine whether the incoming component has been instantiated
|
||||
// AuthorizedRoute is already instantiated
|
||||
// Authorized render is already instantiated, children is no instantiated
|
||||
// Secured is not instantiated
|
||||
const checkIsInstantiation = target => {
|
||||
if (!React.isValidElement(target)) {
|
||||
return target;
|
||||
}
|
||||
return () => target;
|
||||
};
|
||||
|
||||
/**
|
||||
* 用于判断是否拥有权限访问此view权限
|
||||
* authority 支持传入 string, function:()=>boolean|Promise
|
||||
* e.g. 'user' 只有user用户能访问
|
||||
* e.g. 'user,admin' user和 admin 都能访问
|
||||
* e.g. ()=>boolean 返回true能访问,返回false不能访问
|
||||
* e.g. Promise then 能访问 catch不能访问
|
||||
* e.g. authority support incoming string, function: () => boolean | Promise
|
||||
* e.g. 'user' only user user can access
|
||||
* e.g. 'user, admin' user and admin can access
|
||||
* e.g. () => boolean true to be able to visit, return false can not be accessed
|
||||
* e.g. Promise then can not access the visit to catch
|
||||
* @param {string | function | Promise} authority
|
||||
* @param {ReactNode} error 非必需参数
|
||||
*/
|
||||
const authorize = (authority, error) => {
|
||||
/**
|
||||
* conversion into a class
|
||||
* 防止传入字符串时找不到staticContext造成报错
|
||||
* String parameters can cause staticContext not found error
|
||||
*/
|
||||
let classError = false;
|
||||
if (error) {
|
||||
classError = () => error;
|
||||
}
|
||||
if (!authority) {
|
||||
throw new Error('authority is required');
|
||||
}
|
||||
return function decideAuthority(target) {
|
||||
const component = CheckPermissions(authority, target, classError || Exception403);
|
||||
return checkIsInstantiation(component);
|
||||
};
|
||||
};
|
||||
|
||||
export default authorize;
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 使用数组作为参数
|
||||
en-US: Use Array as a parameter
|
||||
---
|
||||
|
||||
Use Array as a parameter
|
||||
|
||||
```jsx
|
||||
import RenderAuthorized from 'ant-design-pro/lib/Authorized';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
const Authorized = RenderAuthorized('user');
|
||||
const noMatch = <Alert message="No permission." type="error" showIcon />;
|
||||
|
||||
ReactDOM.render(
|
||||
<Authorized authority={['user', 'admin']} noMatch={noMatch}>
|
||||
<Alert message="Use Array as a parameter passed!" type="success" showIcon />
|
||||
</Authorized>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 使用方法作为参数
|
||||
en-US: Use function as a parameter
|
||||
---
|
||||
|
||||
Use Function as a parameter
|
||||
|
||||
```jsx
|
||||
import RenderAuthorized from 'ant-design-pro/lib/Authorized';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
const Authorized = RenderAuthorized('user');
|
||||
const noMatch = <Alert message="No permission." type="error" showIcon />;
|
||||
|
||||
const havePermission = () => {
|
||||
return false;
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<Authorized authority={havePermission} noMatch={noMatch}>
|
||||
<Alert
|
||||
message="Use Function as a parameter passed!"
|
||||
type="success"
|
||||
showIcon
|
||||
/>
|
||||
</Authorized>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基本使用
|
||||
en-US: Basic use
|
||||
---
|
||||
|
||||
Basic use
|
||||
|
||||
```jsx
|
||||
import RenderAuthorized from 'ant-design-pro/lib/Authorized';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
const Authorized = RenderAuthorized('user');
|
||||
const noMatch = <Alert message="No permission." type="error" showIcon />;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Authorized authority="admin" noMatch={noMatch}>
|
||||
<Alert message="user Passed!" type="success" showIcon />
|
||||
</Authorized>
|
||||
</div>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 注解基本使用
|
||||
en-US: Basic use secured
|
||||
---
|
||||
|
||||
secured demo used
|
||||
|
||||
```jsx
|
||||
import RenderAuthorized from 'ant-design-pro/lib/Authorized';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
const { Secured } = RenderAuthorized('user');
|
||||
|
||||
@Secured('admin')
|
||||
class TestSecuredString extends React.Component {
|
||||
render() {
|
||||
<Alert message="user Passed!" type="success" showIcon />;
|
||||
}
|
||||
}
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<TestSecuredString />
|
||||
</div>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
||||