Compare commits
951 Commits
feat-unify
...
v1.1.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
672f7a0a7c | ||
|
|
32762aa8a7 | ||
|
|
c35dd6fad9 | ||
|
|
de78fb2149 | ||
|
|
8d05953b8b | ||
|
|
afed1cb6b3 | ||
|
|
f6a4e87e05 | ||
|
|
e36265a2f4 | ||
|
|
4a59e69bbe | ||
|
|
a442e13a7b | ||
|
|
4d093a4a80 | ||
|
|
3dd94fb408 | ||
|
|
7e59d8d36c | ||
|
|
bb46050bb3 | ||
|
|
b50620ec2c | ||
|
|
7bef69af92 | ||
|
|
8241077495 | ||
|
|
82b29a2f8b | ||
|
|
b789d80f98 | ||
|
|
a8c80e2366 | ||
|
|
ae8fcd640b | ||
|
|
455f3ff09a | ||
|
|
e4afaded36 | ||
|
|
a10409f829 | ||
|
|
112138fdc5 | ||
|
|
73e5ca59df | ||
|
|
38f92febb7 | ||
|
|
cd6f1e0438 | ||
|
|
1d73f71aaf | ||
|
|
e4e77cd141 | ||
|
|
e0e7270623 | ||
|
|
885c376e2a | ||
|
|
2845e9829d | ||
|
|
36b82de301 | ||
|
|
a2ac99e7cb | ||
|
|
d037e1ff36 | ||
|
|
9d4424356d | ||
|
|
f087a0766b | ||
|
|
0bb7400755 | ||
|
|
6460c475b6 | ||
|
|
f8b645f867 | ||
|
|
834b330bc8 | ||
|
|
a4b4ce57bd | ||
|
|
ff7a0830d0 | ||
|
|
ff43d0c2d8 | ||
|
|
bad4b5d7b3 | ||
|
|
adaf30dd3b | ||
|
|
c0fc84061e | ||
|
|
b84ad0f598 | ||
|
|
aa0569ef4b | ||
|
|
b88d90cb80 | ||
|
|
c055129309 | ||
|
|
30351cecb5 | ||
|
|
4f6757fff2 | ||
|
|
284fdb8e05 | ||
|
|
738bcae563 | ||
|
|
987a68a6d1 | ||
|
|
bdbdd37789 | ||
|
|
c8fb5b9152 | ||
|
|
59cb5d609d | ||
|
|
4add9ce4c6 | ||
|
|
c75d9f7a59 | ||
|
|
2d94085c54 | ||
|
|
2a6e5915f5 | ||
|
|
656532e43d | ||
|
|
d835a904c9 | ||
|
|
a5bf0e9f6a | ||
|
|
7e3efa46ee | ||
|
|
ce68910e48 | ||
|
|
6dce639a0e | ||
|
|
c738103fec | ||
|
|
801f298448 | ||
|
|
e08a7723b6 | ||
|
|
166b5b98e8 | ||
|
|
07e56631da | ||
|
|
1435789a6c | ||
|
|
7c5fa7610d | ||
|
|
084e680e12 | ||
|
|
380a6b95b7 | ||
|
|
9467feff23 | ||
|
|
a6f4267915 | ||
|
|
cfe9efd4dd | ||
|
|
971b03620a | ||
|
|
92339dae28 | ||
|
|
c84f6d9c33 | ||
|
|
e187c012cc | ||
|
|
af1c280f28 | ||
|
|
aef155e039 | ||
|
|
016e48cc69 | ||
|
|
6dcd39983f | ||
|
|
b055b6c511 | ||
|
|
293259a97d | ||
|
|
7584c79519 | ||
|
|
d9bb0bf61d | ||
|
|
cbb401840c | ||
|
|
1d18c86dc7 | ||
|
|
f8b8624244 | ||
|
|
443573455b | ||
|
|
785a4d97f7 | ||
|
|
d811ab7dfa | ||
|
|
5f79ab6e6d | ||
|
|
502edbca5d | ||
|
|
9da073e838 | ||
|
|
1a04267cb7 | ||
|
|
9c2c1bdfa1 | ||
|
|
1764c0de08 | ||
|
|
79fd809993 | ||
|
|
d3a0d36c92 | ||
|
|
0841e632c2 | ||
|
|
d8f8ef032d | ||
|
|
b7f84dbb0d | ||
|
|
17f1a7ce9d | ||
|
|
ca69331286 | ||
|
|
8258ad21d7 | ||
|
|
2a129d0ee3 | ||
|
|
e391520ce3 | ||
|
|
3e8329c31f | ||
|
|
19d7b1be77 | ||
|
|
ee8a05b6e6 | ||
|
|
111f5bdcfb | ||
|
|
4c1b955bd5 | ||
|
|
ad6614e338 | ||
|
|
57c730a7eb | ||
|
|
e1ec5d15ee | ||
|
|
4496e17d45 | ||
|
|
28668f2acb | ||
|
|
87440362ac | ||
|
|
f470817c01 | ||
|
|
4d9330983a | ||
|
|
edecfc7116 | ||
|
|
d4f3b97b3d | ||
|
|
48d17f9244 | ||
|
|
a96fa8f4b7 | ||
|
|
a81c6e1756 | ||
|
|
b3255ab28b | ||
|
|
75b5103637 | ||
|
|
ddee71fc0d | ||
|
|
18ea1a575c | ||
|
|
3e4cc376f9 | ||
|
|
f17c22793b | ||
|
|
965f734618 | ||
|
|
fc1258319e | ||
|
|
7d17e2b332 | ||
|
|
5a79fc4f2d | ||
|
|
db8fd7582b | ||
|
|
daa6458a26 | ||
|
|
b6ac93ae63 | ||
|
|
87e7c4bee2 | ||
|
|
4adc46dd79 | ||
|
|
73f6d6a622 | ||
|
|
b98c3166f2 | ||
|
|
b7503a841a | ||
|
|
0eb3123848 | ||
|
|
a637cd783c | ||
|
|
8530e9bc5e | ||
|
|
f18c05519d | ||
|
|
cbeddb2460 | ||
|
|
be84e64f00 | ||
|
|
34210104d4 | ||
|
|
035586c9ef | ||
|
|
7f52ef9843 | ||
|
|
ca9b33da88 | ||
|
|
c7f64ceb00 | ||
|
|
11d4f86551 | ||
|
|
00aaf3427a | ||
|
|
3e72a0e440 | ||
|
|
72e93f3768 | ||
|
|
0a1023f795 | ||
|
|
71471bac27 | ||
|
|
972c92519c | ||
|
|
617b940d64 | ||
|
|
8d36a857eb | ||
|
|
59ff14aec4 | ||
|
|
3c39d5db9d | ||
|
|
3980cc584f | ||
|
|
2167525312 | ||
|
|
e724822198 | ||
|
|
0d1abd00a1 | ||
|
|
62aec195ea | ||
|
|
9692945716 | ||
|
|
b8dab8c87d | ||
|
|
a6646be66b | ||
|
|
8cfb54aab1 | ||
|
|
960f3aa3cf | ||
|
|
43f35de27a | ||
|
|
d39ce294b8 | ||
|
|
e7349bfae9 | ||
|
|
ad1ff249aa | ||
|
|
3fed2bb5e0 | ||
|
|
67995ac461 | ||
|
|
39d9aa1896 | ||
|
|
895fd25627 | ||
|
|
7582cac69a | ||
|
|
790917eaf2 | ||
|
|
18d83f161e | ||
|
|
42e9e5edce | ||
|
|
31450e0eac | ||
|
|
34d799049d | ||
|
|
92bf26ced5 | ||
|
|
6214c17903 | ||
|
|
f1e801340f | ||
|
|
4105883ab6 | ||
|
|
feb39bde44 | ||
|
|
ae4ae074d8 | ||
|
|
2ed1b4bf23 | ||
|
|
e6f2066d42 | ||
|
|
e4ed2392bb | ||
|
|
ae32b9838b | ||
|
|
f126fc3d04 | ||
|
|
3ac03973fb | ||
|
|
96384d7b39 | ||
|
|
20f720bf27 | ||
|
|
2812c39524 | ||
|
|
642de9a78c | ||
|
|
b8a1fd904b | ||
|
|
31c63130d6 | ||
|
|
6a7c2bca9a | ||
|
|
491485856e | ||
|
|
369a8ade42 | ||
|
|
6e19ed2dce | ||
|
|
abde7e176d | ||
|
|
bab8faadee | ||
|
|
ed5dd5e122 | ||
|
|
854ff4b888 | ||
|
|
9bdf42a057 | ||
|
|
ad60b7b44c | ||
|
|
58033530c1 | ||
|
|
fa0c570f90 | ||
|
|
73bb93f166 | ||
|
|
427d72fb8b | ||
|
|
696a363591 | ||
|
|
dc5b20a329 | ||
|
|
4cb934eef3 | ||
|
|
45737c8f7a | ||
|
|
25077b91ca | ||
|
|
35e8cea0b5 | ||
|
|
8487a1b159 | ||
|
|
4141d00409 | ||
|
|
924a173d6b | ||
|
|
368ae13db6 | ||
|
|
5c5c0b02df | ||
|
|
888ad61cf2 | ||
|
|
cfa7f59b0b | ||
|
|
3fc6012145 | ||
|
|
463b14736f | ||
|
|
d37034cb52 | ||
|
|
c9d61128bf | ||
|
|
810f4d8e6d | ||
|
|
1bd0f516e2 | ||
|
|
336ef369cc | ||
|
|
efcb25153e | ||
|
|
f8aafd0e0b | ||
|
|
fdb19fb310 | ||
|
|
d497e17a7d | ||
|
|
287097ceed | ||
|
|
789f24d89d | ||
|
|
8c370c550e | ||
|
|
d8fa5784bf | ||
|
|
1baa18888f | ||
|
|
9644b22896 | ||
|
|
5312ba5a45 | ||
|
|
545e9f6571 | ||
|
|
42093e2a32 | ||
|
|
f7d23ff830 | ||
|
|
049d3fb911 | ||
|
|
18947db22b | ||
|
|
dbd49a05bd | ||
|
|
df07169005 | ||
|
|
21fe89adf6 | ||
|
|
49956d32cc | ||
|
|
b75667d92c | ||
|
|
c9848e7b01 | ||
|
|
e2cda9140b | ||
|
|
e091eb7b64 | ||
|
|
aa3a5fbf84 | ||
|
|
f1ed9c848a | ||
|
|
c2bcc51797 | ||
|
|
2c7192b40c | ||
|
|
6b81559d4c | ||
|
|
15e9a0c0f5 | ||
|
|
8085640ea6 | ||
|
|
5eb851fc82 | ||
|
|
24ede6ac4f | ||
|
|
d39a8c293f | ||
|
|
c44dd111db | ||
|
|
5763ff0d57 | ||
|
|
76f4a73525 | ||
|
|
bf45cd607d | ||
|
|
9c0f1f793f | ||
|
|
674131a0ae | ||
|
|
43438594d2 | ||
|
|
5af0b60644 | ||
|
|
35313f2ce8 | ||
|
|
d01b8b2b15 | ||
|
|
8f061e5c3b | ||
|
|
0c596c69cf | ||
|
|
390eec99a2 | ||
|
|
fe77d88936 | ||
|
|
e4bc388faa | ||
|
|
255c47a8e1 | ||
|
|
03f8dee9d4 | ||
|
|
2b34a01845 | ||
|
|
4e435d4f29 | ||
|
|
89a6e5db20 | ||
|
|
f43f744c3e | ||
|
|
7b9ca460a6 | ||
|
|
1c0a923771 | ||
|
|
76112345f2 | ||
|
|
7985db16f1 | ||
|
|
bec5868068 | ||
|
|
ac8d77a53f | ||
|
|
826d294690 | ||
|
|
23075b7bdd | ||
|
|
096d63cbac | ||
|
|
acc9dc7751 | ||
|
|
4eca4c607a | ||
|
|
fe22e1d330 | ||
|
|
085c393767 | ||
|
|
df10ae58f4 | ||
|
|
714dac93bc | ||
|
|
2589cad06e | ||
|
|
2ae3461a9c | ||
|
|
bb16fa51d0 | ||
|
|
36bfbf900a | ||
|
|
d89b22a8f7 | ||
|
|
159a165457 | ||
|
|
199c6abcb1 | ||
|
|
96a41f8ebc | ||
|
|
ac3f5567c5 | ||
|
|
9fd85761d7 | ||
|
|
130e4a3659 | ||
|
|
0107643e7e | ||
|
|
9fea20cb79 | ||
|
|
a1233aa1fe | ||
|
|
558512220e | ||
|
|
177fa6bfbe | ||
|
|
a6d1baec3e | ||
|
|
8ddc85738a | ||
|
|
52c1eabf1e | ||
|
|
6cd30283e7 | ||
|
|
2380c6ec60 | ||
|
|
f02e92a58e | ||
|
|
a54a007c5a | ||
|
|
2ad3677fdc | ||
|
|
d09d1b96be | ||
|
|
e4e1fee8b4 | ||
|
|
e348caaa0c | ||
|
|
1ee76efeb8 | ||
|
|
716379fc9f | ||
|
|
01c2a20a0f | ||
|
|
4c353136d5 | ||
|
|
c293c43862 | ||
|
|
45dcd1885d | ||
|
|
a4690c21cf | ||
|
|
0ca908c8d5 | ||
|
|
e40a1f87f9 | ||
|
|
09ebd67c37 | ||
|
|
bad7e37f5a | ||
|
|
99b344bdef | ||
|
|
3b7f9e5dec | ||
|
|
2928eaa4ae | ||
|
|
77ef4c05b9 | ||
|
|
f55a2b94e7 | ||
|
|
5fba293245 | ||
|
|
e380ead651 | ||
|
|
57798b9000 | ||
|
|
eb774f9d41 | ||
|
|
e2a0478357 | ||
|
|
0bd5587e65 | ||
|
|
96d8cb0006 | ||
|
|
b0e4383a43 | ||
|
|
5cadcc8259 | ||
|
|
fbc689b235 | ||
|
|
0779aeca6a | ||
|
|
9aca371e9c | ||
|
|
9ea4858770 | ||
|
|
d7b74ed90d | ||
|
|
ffb6b2f68c | ||
|
|
4d560ab937 | ||
|
|
857f811685 | ||
|
|
0bce64c867 | ||
|
|
0998fc5376 | ||
|
|
ba52c55158 | ||
|
|
27d78c6b4d | ||
|
|
1b68c39d5d | ||
|
|
8c01974494 | ||
|
|
c74322e783 | ||
|
|
b7d8225dbd | ||
|
|
48e9165483 | ||
|
|
b37c8114d8 | ||
|
|
997790e653 | ||
|
|
3b12503e77 | ||
|
|
f6d605da62 | ||
|
|
35fda2b9a9 | ||
|
|
2d76991d27 | ||
|
|
c9b2fc2674 | ||
|
|
6c65e419e2 | ||
|
|
288bb264e0 | ||
|
|
33a741ca0e | ||
|
|
5f80fa8aa4 | ||
|
|
506412175e | ||
|
|
06c3765d9d | ||
|
|
66f22551c4 | ||
|
|
d30f60a972 | ||
|
|
bf69ba91d5 | ||
|
|
15ff1d2912 | ||
|
|
740f471ff4 | ||
|
|
d1de5f0c4c | ||
|
|
f178b0e0ca | ||
|
|
d4bfdd1e91 | ||
|
|
539db3c56b | ||
|
|
2ac2d79966 | ||
|
|
4db0ba4714 | ||
|
|
6b0df75357 | ||
|
|
e9c2ca0989 | ||
|
|
bb32edf264 | ||
|
|
db00fcf372 | ||
|
|
801f6e8d18 | ||
|
|
88abcf8a4a | ||
|
|
410dc4fc58 | ||
|
|
ddee396cea | ||
|
|
2cb65c623e | ||
|
|
f612b62b0a | ||
|
|
84fd1b2181 | ||
|
|
ce925e0f45 | ||
|
|
67da33931a | ||
|
|
a58eb4a53c | ||
|
|
3f3caae4fc | ||
|
|
417821b72d | ||
|
|
b1ae4c3712 | ||
|
|
0705fb8b0f | ||
|
|
6a90d1a043 | ||
|
|
74e30390cf | ||
|
|
4ba3d8803a | ||
|
|
f53f4d57f2 | ||
|
|
33d78ffcda | ||
|
|
9e6873e1da | ||
|
|
47f6fc87c7 | ||
|
|
2ee2783a9c | ||
|
|
3a066fc9bb | ||
|
|
16b703f317 | ||
|
|
3537427846 | ||
|
|
8693a11a32 | ||
|
|
2259545094 | ||
|
|
e09d014fa6 | ||
|
|
8c74b8e8df | ||
|
|
c3b6bcec65 | ||
|
|
633bf987ab | ||
|
|
bf1b81e554 | ||
|
|
729021f37c | ||
|
|
bde2634ef3 | ||
|
|
d6da6f759d | ||
|
|
32f851e57b | ||
|
|
30e7e7ab7c | ||
|
|
cfa69baaa3 | ||
|
|
78626b3c04 | ||
|
|
340492f784 | ||
|
|
6cecbb6ec2 | ||
|
|
665ebd7b17 | ||
|
|
c07d7c7c28 | ||
|
|
a0c8bc7fe5 | ||
|
|
0f73536ce0 | ||
|
|
455e387a62 | ||
|
|
99467f87ff | ||
|
|
f7d3a0b499 | ||
|
|
1c54b81212 | ||
|
|
6d6fa04a4b | ||
|
|
954de6d58b | ||
|
|
a0ecfa7264 | ||
|
|
54f9c065c8 | ||
|
|
b8705c4f31 | ||
|
|
588cc380cd | ||
|
|
5eca551271 | ||
|
|
5522837b00 | ||
|
|
29fd85254b | ||
|
|
61af1674b9 | ||
|
|
d8ccff8de5 | ||
|
|
e29c427f8d | ||
|
|
b8d0d1a2ff | ||
|
|
ffa127593a | ||
|
|
f9c17c732a | ||
|
|
427c5589b2 | ||
|
|
b618f9e865 | ||
|
|
2182c7d34a | ||
|
|
9482e9aba3 | ||
|
|
6d5651fd1d | ||
|
|
c195b69003 | ||
|
|
8216cd7604 | ||
|
|
8d691f2d69 | ||
|
|
09d8c58e73 | ||
|
|
0823bf1d9c | ||
|
|
43e8b9939b | ||
|
|
c792482c60 | ||
|
|
e48ca421d8 | ||
|
|
ac23d4c8dc | ||
|
|
68b49ea710 | ||
|
|
99287497cc | ||
|
|
70f9df7650 | ||
|
|
8b39ec2773 | ||
|
|
eafbcb2cde | ||
|
|
f8f5bc7688 | ||
|
|
0335b379ea | ||
|
|
3c221345dd | ||
|
|
13bcf3c649 | ||
|
|
58fee4a86f | ||
|
|
a22e4b814b | ||
|
|
c249c120c1 | ||
|
|
c8d016e1b4 | ||
|
|
2e6d87ab80 | ||
|
|
5c07885a4e | ||
|
|
5f8db36888 | ||
|
|
ce34a7ed2a | ||
|
|
b3422eaede | ||
|
|
8b57ffa124 | ||
|
|
dcbaf37a69 | ||
|
|
741ba1a039 | ||
|
|
80176e5737 | ||
|
|
04ed5d354d | ||
|
|
fa678e1089 | ||
|
|
8575d27504 | ||
|
|
fa6ef30cd8 | ||
|
|
14402e6674 | ||
|
|
0915e162fd | ||
|
|
fffe49cd0f | ||
|
|
94fc6138a0 | ||
|
|
4f248e57c8 | ||
|
|
e5bf08f709 | ||
|
|
d61769f9b8 | ||
|
|
0ec9fd8534 | ||
|
|
fcf8d9d99d | ||
|
|
6c91fca4e7 | ||
|
|
e01292376f | ||
|
|
1c5c867a19 | ||
|
|
dde5ae796e | ||
|
|
64992c59b7 | ||
|
|
c3aae6e5fa | ||
|
|
2a44fd3ca4 | ||
|
|
68512206f7 | ||
|
|
88073e97af | ||
|
|
e8642d0301 | ||
|
|
aafafdd0aa | ||
|
|
198b839dab | ||
|
|
597b8fb5af | ||
|
|
a4cb4cb0ad | ||
|
|
1bc51a51c2 | ||
|
|
8857059da8 | ||
|
|
7939d37fa3 | ||
|
|
df83385cb0 | ||
|
|
5d69fc4b24 | ||
|
|
4f1b550fa9 | ||
|
|
782c12d91d | ||
|
|
4b97d98b3a | ||
|
|
8e3e9b5f50 | ||
|
|
ceed66b7ea | ||
|
|
a8399be4a3 | ||
|
|
19f73d7066 | ||
|
|
36d46d0a45 | ||
|
|
323e5505f5 | ||
|
|
12a2ace498 | ||
|
|
c5eefec24d | ||
|
|
c4c4572885 | ||
|
|
8fcd2a9141 | ||
|
|
f0fad0dba7 | ||
|
|
71c7116493 | ||
|
|
e797879e0d | ||
|
|
2e460ea32a | ||
|
|
ef3b1dce7c | ||
|
|
22e01a80c1 | ||
|
|
770373c48c | ||
|
|
77ff376e75 | ||
|
|
d5fb56f571 | ||
|
|
b37ba41694 | ||
|
|
f7084ba3a3 | ||
|
|
f89a64f10e | ||
|
|
f6fe7816c9 | ||
|
|
ca8e08f3db | ||
|
|
1e188dd26b | ||
|
|
59fb22cd0c | ||
|
|
ede7bcce80 | ||
|
|
07e3f227be | ||
|
|
d0070319a9 | ||
|
|
60ec01eb32 | ||
|
|
47e04ba6e3 | ||
|
|
c7a2a01f12 | ||
|
|
45e5ca0722 | ||
|
|
8ca9a3be05 | ||
|
|
c89b92c2d3 | ||
|
|
38685e9b49 | ||
|
|
65f0c87149 | ||
|
|
71a7247f71 | ||
|
|
27dac34c2b | ||
|
|
99fec48458 | ||
|
|
1c093e5243 | ||
|
|
96d1b79cf5 | ||
|
|
bd4879e88a | ||
|
|
6a5d746703 | ||
|
|
b5271b07fa | ||
|
|
e3fa62a3f8 | ||
|
|
b129123fa0 | ||
|
|
e9a1606f00 | ||
|
|
6cc321b997 | ||
|
|
f668a2b892 | ||
|
|
cf50e77daf | ||
|
|
ef9e4c8ea4 | ||
|
|
ab96d0919f | ||
|
|
dee6aa6754 | ||
|
|
55f59f9f2d | ||
|
|
8f5bc134f2 | ||
|
|
8ca08a5600 | ||
|
|
621a302451 | ||
|
|
bf4254719d | ||
|
|
3bcef87d6c | ||
|
|
bacdcd1760 | ||
|
|
871b61acf5 | ||
|
|
e0b0d5747b | ||
|
|
b61215d540 | ||
|
|
43cc7d8a95 | ||
|
|
d5656ea07c | ||
|
|
880f9d535c | ||
|
|
30bd83b032 | ||
|
|
5d73a5fdd3 | ||
|
|
9f95a4c83e | ||
|
|
8c3c483894 | ||
|
|
8486e08615 | ||
|
|
798a7eb49a | ||
|
|
17f29d3773 | ||
|
|
43c46c873c | ||
|
|
96581511f8 | ||
|
|
be81a8c731 | ||
|
|
74338c06f0 | ||
|
|
9fbe2500e0 | ||
|
|
4f16531016 | ||
|
|
98bebbc796 | ||
|
|
3c85322450 | ||
|
|
9e9410533c | ||
|
|
b5d420c9bf | ||
|
|
9c8fab832e | ||
|
|
f304a4f27a | ||
|
|
0b674fb0ae | ||
|
|
9cd18c9086 | ||
|
|
98d3962f87 | ||
|
|
b4ebf8cde3 | ||
|
|
828497bd08 | ||
|
|
3d0611cfdf | ||
|
|
33b7d990e3 | ||
|
|
24dbc21cfc | ||
|
|
ee9a93b353 | ||
|
|
991b134e23 | ||
|
|
553d9d7519 | ||
|
|
1bcace8d5e | ||
|
|
8d9f503867 | ||
|
|
d1f84cded9 | ||
|
|
533af6b2f9 | ||
|
|
10a21c9f6b | ||
|
|
16bf72ac24 | ||
|
|
aef57f13f0 | ||
|
|
4b3acfca74 | ||
|
|
33b2f67df8 | ||
|
|
4c28df1602 | ||
|
|
9c04f51548 | ||
|
|
d0752b0b26 | ||
|
|
77137990a6 | ||
|
|
7bb0b1a463 | ||
|
|
c8d8698b19 | ||
|
|
97da2a6ec1 | ||
|
|
ce42f5c294 | ||
|
|
80f81c1870 | ||
|
|
4aff485816 | ||
|
|
bb9ea4ca32 | ||
|
|
64cad02b62 | ||
|
|
be0c0566df | ||
|
|
b5ea97e239 | ||
|
|
9c2f70b68c | ||
|
|
8b7606f893 | ||
|
|
c0a654fa63 | ||
|
|
e8ce806082 | ||
|
|
cc0ecedd4e | ||
|
|
4aa303b51f | ||
|
|
496c097e5f | ||
|
|
f95d940ff0 | ||
|
|
78879c56cc | ||
|
|
7d2c4e6431 | ||
|
|
f12d3148aa | ||
|
|
6ae0cd55e6 | ||
|
|
2c2aaaac67 | ||
|
|
97df02c07e | ||
|
|
2b0f8a817c | ||
|
|
089bb8945a | ||
|
|
819ad34481 | ||
|
|
aca79071b9 | ||
|
|
a573cd2391 | ||
|
|
0d54716e59 | ||
|
|
d1ea05c2c0 | ||
|
|
bb78d89037 | ||
|
|
e6ff73c252 | ||
|
|
f00bd16aaf | ||
|
|
7002e64b8f | ||
|
|
ab05a6f384 | ||
|
|
d60e6effa1 | ||
|
|
bd430aab32 | ||
|
|
214995fb23 | ||
|
|
0b71c43e89 | ||
|
|
f29299fde5 | ||
|
|
ecaf8e8970 | ||
|
|
cb5f558c62 | ||
|
|
7db9bc85f8 | ||
|
|
91220d31a7 | ||
|
|
e146018f7d | ||
|
|
09e402357a | ||
|
|
2b2b46a990 | ||
|
|
7a8a57a078 | ||
|
|
f3ef1a4022 | ||
|
|
a6c750f877 | ||
|
|
cf92ed55a4 | ||
|
|
caa403a8dc | ||
|
|
822fbbcd24 | ||
|
|
71972f0d8c | ||
|
|
9326c9a59c | ||
|
|
c46c6d30e7 | ||
|
|
a43f0791ea | ||
|
|
19ed2fec19 | ||
|
|
66373a427b | ||
|
|
0d1c24c536 | ||
|
|
a7b2d5a24b | ||
|
|
4d55e5a57b | ||
|
|
890dd88b5f | ||
|
|
2d36600e3b | ||
|
|
2e038ad7db | ||
|
|
27fcec9846 | ||
|
|
62ed00e31c | ||
|
|
c937555020 | ||
|
|
593a48eea4 | ||
|
|
7ea078dbf3 | ||
|
|
6d4be943d7 | ||
|
|
8ee18819c5 | ||
|
|
e672b75453 | ||
|
|
c4e3c34842 | ||
|
|
c4ff0d24b7 | ||
|
|
501dfdc223 | ||
|
|
c399277350 | ||
|
|
b101b2b857 | ||
|
|
7e8d30382f | ||
|
|
0fdbeb1e7a | ||
|
|
9aec36b201 | ||
|
|
0933486e6f | ||
|
|
33b0c94159 | ||
|
|
6c402b3a17 | ||
|
|
3a9f68384f | ||
|
|
3747771078 | ||
|
|
67dc58e08e | ||
|
|
987f4f73a2 | ||
|
|
dd0bf5611d | ||
|
|
58d20b7c8d | ||
|
|
a4c14c39b3 | ||
|
|
ddc005ec10 | ||
|
|
4d54a3029b | ||
|
|
07cb0a7d3a | ||
|
|
0ee76c1579 | ||
|
|
3560effe2c | ||
|
|
0abcbbae53 | ||
|
|
43844c834e | ||
|
|
d15e551743 | ||
|
|
d1c0cae68e | ||
|
|
a1a2e260f6 | ||
|
|
aebed94140 | ||
|
|
96740a6841 | ||
|
|
c29ecc8b0b | ||
|
|
790cc7b878 | ||
|
|
b71b7bfd0e | ||
|
|
06b1e40930 | ||
|
|
159ffb4af2 | ||
|
|
e69fd0cdc4 | ||
|
|
a467283618 | ||
|
|
a6e5dec2c0 | ||
|
|
b96c2f0d3e | ||
|
|
f8785a4505 | ||
|
|
5b14e3a70f | ||
|
|
e6a99302d6 | ||
|
|
8aa4490ea9 | ||
|
|
a451faad77 | ||
|
|
e3816524da | ||
|
|
75232ee902 | ||
|
|
4405ebd30d | ||
|
|
0946d170d7 | ||
|
|
30361aa7ca | ||
|
|
76b22ce05c | ||
|
|
00f2359b9d | ||
|
|
40b8dbc4d5 | ||
|
|
1c67e06138 | ||
|
|
a2e91bac1e | ||
|
|
19b7429215 | ||
|
|
7412c777ee | ||
|
|
499f36bc62 | ||
|
|
862753d35e | ||
|
|
b691003187 | ||
|
|
a63efa5d26 | ||
|
|
013edc4f11 | ||
|
|
504b3a762f | ||
|
|
f26d7e394d | ||
|
|
56bf44e4b0 | ||
|
|
1d6ab1ae5b | ||
|
|
4e1069ec1d | ||
|
|
63ed00bd28 | ||
|
|
5675ea0720 | ||
|
|
c29a70f90b | ||
|
|
3fe2fbfc08 | ||
|
|
8d97bdc976 | ||
|
|
0bf38c032c | ||
|
|
4a76e419be | ||
|
|
0c2da460a3 | ||
|
|
d9a3b358e7 | ||
|
|
632c09bf01 | ||
|
|
2b0008ffc7 | ||
|
|
c6beee08df | ||
|
|
6c2692bb96 | ||
|
|
d690f4277f | ||
|
|
e874ca1e8c | ||
|
|
7918918a69 | ||
|
|
a4198bf75a | ||
|
|
89ac30438a | ||
|
|
d7ebf0e173 | ||
|
|
d1d27a740f | ||
|
|
148297766c | ||
|
|
144980e45d | ||
|
|
116de1a70a | ||
|
|
bc8b0a5226 | ||
|
|
3f828d4208 | ||
|
|
a3b26ff247 | ||
|
|
f06aafd14e | ||
|
|
8f9e45e660 | ||
|
|
8b890fb5e3 | ||
|
|
133c6bea6b | ||
|
|
c107c8c440 | ||
|
|
825d21a3a9 | ||
|
|
383d419f84 | ||
|
|
b20e842af9 | ||
|
|
d13ba5ff78 | ||
|
|
29ce548662 | ||
|
|
a3ec971be2 | ||
|
|
7747ac07ed | ||
|
|
902145df71 | ||
|
|
31194bd4d6 | ||
|
|
9e1a9bf6c3 | ||
|
|
fb136b0918 | ||
|
|
0cf898bd57 | ||
|
|
60b18a20fa | ||
|
|
62f8e389a8 | ||
|
|
b258b0f651 | ||
|
|
1b7bcd3e32 | ||
|
|
88b03a416c | ||
|
|
8fb8b9328d | ||
|
|
688ce50c58 | ||
|
|
314daede24 | ||
|
|
7b24b90fbc | ||
|
|
7d5985f743 | ||
|
|
5590a3024f | ||
|
|
71e13c83e6 | ||
|
|
ad8cc8a003 | ||
|
|
0cda041315 | ||
|
|
8ef13b6325 | ||
|
|
ccf78c6dd2 | ||
|
|
ded1f8ae4b | ||
|
|
917772cce0 | ||
|
|
6f93de7ad4 | ||
|
|
25368419a3 | ||
|
|
c0392e7370 | ||
|
|
31d1983958 | ||
|
|
50e62dbed7 | ||
|
|
25f5d91e87 | ||
|
|
c8d7cca4ed | ||
|
|
727a0c8e8e | ||
|
|
ef40a6347a | ||
|
|
825731edcc | ||
|
|
d820cce6d4 | ||
|
|
3acf2fe732 | ||
|
|
a2a3a31df5 | ||
|
|
929bc4da9f | ||
|
|
56a36cf306 | ||
|
|
dc7db58a8e | ||
|
|
e8999a7fdf | ||
|
|
b93509a6bb | ||
|
|
a606039976 | ||
|
|
37ee9de02b | ||
|
|
2f2a395406 | ||
|
|
01e2ba6db9 | ||
|
|
62f012f2e9 | ||
|
|
49fb0e1113 | ||
|
|
663ef6f2a6 | ||
|
|
bb7aa78738 | ||
|
|
08a24b9e3c | ||
|
|
151ec13904 | ||
|
|
d7965c5857 | ||
|
|
0033b42008 | ||
|
|
f9d533972f | ||
|
|
c57a4850b6 | ||
|
|
ceb8cd5158 | ||
|
|
825b3bf2ea | ||
|
|
a7905b6a60 | ||
|
|
95f5d725ac | ||
|
|
c1bbc83acd | ||
|
|
e1bb655bf1 | ||
|
|
c63637360f | ||
|
|
f626d8a157 | ||
|
|
26b698097d | ||
|
|
9f2ebba293 | ||
|
|
cb7a8298ec | ||
|
|
551a1f2d01 | ||
|
|
3758db4cb6 | ||
|
|
f6860c3fa6 | ||
|
|
ae71e13c6d | ||
|
|
2b83ea6452 | ||
|
|
3e511069b5 | ||
|
|
02c3f7478d | ||
|
|
0a75035339 | ||
|
|
75fb327d7e | ||
|
|
f243dbdd55 | ||
|
|
24c649d19f | ||
|
|
c2369dd733 | ||
|
|
9577bd9de7 | ||
|
|
6a23fd2d72 | ||
|
|
2e1c143d9b | ||
|
|
caadad501f | ||
|
|
39ab04e051 | ||
|
|
7332dd1e98 | ||
|
|
3d8519519b | ||
|
|
58261fd3a3 | ||
|
|
1298abd9e6 | ||
|
|
5b7da15bdd | ||
|
|
1b878b0016 | ||
|
|
05ed82b091 | ||
|
|
34722916b0 | ||
|
|
4333b58938 | ||
|
|
97a0a60754 | ||
|
|
df1fccffa7 | ||
|
|
1afc06b079 | ||
|
|
ef008adf51 | ||
|
|
f00935d795 | ||
|
|
1031d3e248 | ||
|
|
cc5d6ae5d7 | ||
|
|
60183b6a60 | ||
|
|
a02877e38f | ||
|
|
5b98d5703f | ||
|
|
4303e79e6f | ||
|
|
c606102a29 | ||
|
|
3440da72d6 | ||
|
|
f9d0547fc3 | ||
|
|
35a05c046b | ||
|
|
72c7bb3ecc | ||
|
|
8a57a7f3b9 | ||
|
|
54dd1a0dbe | ||
|
|
0f71961d0c |
12
.env
@@ -1,8 +1,14 @@
|
||||
# port
|
||||
VITE_DEV_PORT = '8080'
|
||||
VITE_DEV_PORT = '8001'
|
||||
|
||||
# development path
|
||||
VITE_DEV_PATH = 'http://1.117.240.165:8080'
|
||||
VITE_DEV_PATH = '/'
|
||||
|
||||
# production path
|
||||
VITE_PRO_PATH = 'http://1.117.240.165:8080'
|
||||
VITE_PRO_PATH = '/'
|
||||
|
||||
# spa-title
|
||||
VITE_GLOB_APP_TITLE = GoView
|
||||
|
||||
# spa shortname
|
||||
VITE_GLOB_APP_SHORT_NAME = GoView
|
||||
|
||||
51
.workflow/branch-pipeline.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
version: '1.0'
|
||||
name: branch-pipeline
|
||||
displayName: BranchPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
exclude:
|
||||
- master
|
||||
include:
|
||||
- .*
|
||||
49
.workflow/master-pipeline.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
version: '1.0'
|
||||
name: master-pipeline
|
||||
displayName: MasterPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
- stage:
|
||||
name: release
|
||||
displayName: 发布
|
||||
steps:
|
||||
- step: publish@release_artifacts
|
||||
name: publish_release_artifacts
|
||||
displayName: '发布'
|
||||
# 上游上传制品任务的产出
|
||||
dependArtifact: output
|
||||
# 发布制品版本号
|
||||
version: '1.0.0.0'
|
||||
# 是否开启版本号自增,默认开启
|
||||
autoIncrement: true
|
||||
triggers:
|
||||
push:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
36
.workflow/pr-pipeline.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: '1.0'
|
||||
name: pr-pipeline
|
||||
displayName: PRPipeline
|
||||
stages:
|
||||
- stage:
|
||||
name: compile
|
||||
displayName: 编译
|
||||
steps:
|
||||
- step: build@nodejs
|
||||
name: build_nodejs
|
||||
displayName: Nodejs 构建
|
||||
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
|
||||
nodeVersion: 14.16.0
|
||||
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
|
||||
commands:
|
||||
- npm install && rm -rf ./dist && npm run build
|
||||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
|
||||
artifacts:
|
||||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
|
||||
- name: BUILD_ARTIFACT
|
||||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
|
||||
path:
|
||||
- ./dist
|
||||
- step: publish@general_artifacts
|
||||
name: publish_general_artifacts
|
||||
displayName: 上传制品
|
||||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
|
||||
dependArtifact: BUILD_ARTIFACT
|
||||
# 上传到制品库时的制品命名,默认output
|
||||
artifactName: output
|
||||
dependsOn: build_nodejs
|
||||
triggers:
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
218
README.md
@@ -1,74 +1,166 @@
|
||||
## 总览
|
||||
|
||||

|
||||
<p align="center">
|
||||
<img src="readme/logo-t-y.png" alt="go-view" />
|
||||
</p>
|
||||
|
||||
**`master-fetch` 分支是带有后端接口请求的分支**
|
||||
<h4 align="center">开源、精美、便捷的「数据可视化」低代码开发平台</h4>
|
||||
|
||||
#### 😶 **纯前端** 分支: **`master`**
|
||||
|
||||
### feat-unify-test 分支目标
|
||||
+ 实现 backend 后端工厂
|
||||
将后端业务逻辑集中到 backend 了,控制 BackEndFactory 就可以适配不同的后端。
|
||||
伪代码如下:
|
||||
export const BackEndFactory = ():IBackend=>{
|
||||
switch(项目后端配置){
|
||||
case "无数据库":
|
||||
return new MockBackend() // 等同: -master ,没有存储
|
||||
case "indexdb":
|
||||
return new IndexDbBackend() // 这次开发的,用 indexdb 做测试
|
||||
case "java":
|
||||
return new JavaBackend() // 等同: -fetch, 没 java 环境,还没做
|
||||
case "python":
|
||||
return new PythonBackend() // 自定义开发的后端
|
||||
。。。 其他 oss 、云平台的后端 。。。
|
||||
}}
|
||||
意义:
|
||||
1 unify 统一 -fetch 和 master 分支,消除分支之间的差异。
|
||||
2 方便接入不同的自定义后端平台。
|
||||
3 前端存储功能让测试工作更加方便
|
||||
#### 👻 携带 **后端** 请求分支: **`master-fetch`**
|
||||
|
||||
+ 完善事件处理机制
|
||||
在事件中修改图表配置
|
||||
在事件中修改图表数据
|
||||
在事件中调用图表 exposed 函数
|
||||
数据驱动界面
|
||||
#### 📚 GoView **文档** 地址:[https://www.mtruning.club/](https://www.mtruning.club/)
|
||||
|
||||
### 试验功能1:Backend 后端工厂
|
||||
+ 对比 -fetch 分支,梳理后端逻辑到 backend 目录的 ibackend 接口
|
||||
+ 登录 - login
|
||||
+ 登出 - logout
|
||||
+ 预览,token 注入或单点登陆 - checkToken
|
||||
+ 显示项目列表和分页 - projectList
|
||||
+ 保存、发布、修改名称 - updateProject
|
||||
+ 复制项目 - copyProject
|
||||
+ 图表内的图片上传 - uploadFile
|
||||
+ 上传图片显示处理 - getFileUrl
|
||||
+ IndexDbBackend 用indexdb浏览器数据库实现了 project 相关所有功能。
|
||||
+ Todo: 统一后端错误处理
|
||||
+ Todo:开发 javabackend,适配现有的后端
|
||||
项目纯前端-Demo 地址:[https://vue.mtruning.club/](https://vue.mtruning.club/)
|
||||
|
||||
### 试验功能2:事件处理机制
|
||||
+ 实现最常用的互动:找到图表元素、显示或隐藏、修改数据
|
||||
+ 核心代码:useLifeHandler.hook.ts
|
||||
+ 在事件代码中通过 runtime 实现运行时刻的图表管理,提供基础函数:
|
||||
+ selectComponents 选择多个图表
|
||||
+ selectOneComponent 选择一个图表
|
||||
+ getChartConfig 读取图表
|
||||
+ setChartConfig 设置图表
|
||||
+ callExposed 调用图表 exposed 的函数
|
||||
+ 以下例子可以在点击事件中加入代码并预览,测试效果。
|
||||
项目带后端-Demo 地址:[https://demo.mtruning.club/](https://demo.mtruning.club/)
|
||||
|
||||
+ 例子1 切换显示名称为 饼图 和 柱状图 的图表:
|
||||
const range = runtime.fn.selectComponents("饼图 柱状图")
|
||||
const h = runtime.fn.getChartConfig(range, "hide")
|
||||
runtime.fn.setChartConfig(range, "hide", !h)
|
||||
文档-源码地址:[https://gitee.com/MTrun/go-view-doc](https://gitee.com/MTrun/go-view-doc)
|
||||
|
||||
+ 例子2 修改一个名称 柱状图001 组件id 2wolqibrx3c000 的图表数据,以下两句等效
|
||||
runtime.fn.setChartConfig("柱状图001", "dataset", {"dimensions":["product","data1","data2"],"source":[{"product":"Mon","data1":120,"data2":130}]})
|
||||
runtime.fn.setChartConfig("#2wolqibrx3c000", "dataset", {"dimensions":["product","data1","data2"],"source":[{"product":"Mon","data1":120,"data2":230}]})
|
||||
#### 🤯 后端项目看这里!
|
||||
|
||||
+ 例子3 找到一个组并隐藏
|
||||
const c = runtime.fn.selectOneComponent("分组")
|
||||
if(c){
|
||||
console.log(runtime.fn.getChartConfig(c, "isGroup" ))
|
||||
runtime.fn.setChartConfig(c, "hide", true)
|
||||
}
|
||||
后端项目 gitee 地址:[https://gitee.com/MTrun/go-view-serve](https://gitee.com/MTrun/go-view-serve)
|
||||
|
||||
接口说明地址:[https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb](https://docs.apipost.cn/preview/5aa85d10a59d66ce/ddb813732007ad2b?target_id=84dbc5b0-158f-4bcb-8f74-793ac604ada3#3e053622-1e76-43f9-a039-756aee822dbb)
|
||||
|
||||
技术点:
|
||||
|
||||
- 框架:基于 `Vue3` 框架编写,使用 `hooks` 写法抽离部分逻辑,使代码结构更加清晰;
|
||||
|
||||
- 类型:使用 `TypeScript` 进行类型约束,减少未知错误发生概率,可以大胆修改逻辑内容;
|
||||
|
||||
- 性能:多处性能优化,使用页面懒加载、组件动态注册、数据滚动加载等方式,提升页面渲染速度;
|
||||
|
||||
- 存储:拥有本地记忆,部分配置项采用 `storage` 存储本地,提升使用体验;
|
||||
|
||||
- 封装:项目进行了详细的工具类封装如:路由、存储、加/解密、文件处理、主题、NaiveUI 全局方法、组件等
|
||||
|
||||
说明文档:
|
||||

|
||||
|
||||
工作台:
|
||||

|
||||
|
||||
请求配置:
|
||||

|
||||
|
||||
数据过滤:
|
||||

|
||||
|
||||
高级事件编辑:
|
||||

|
||||
|
||||
快捷主页:
|
||||

|
||||
|
||||
主题色:
|
||||

|
||||
|
||||
亮白主题:
|
||||

|
||||
|
||||
主要技术栈为:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ------------------- | ----- | ----------- | ------ |
|
||||
| Vue | 3.2.x | TypeScript4 | 4.6.x |
|
||||
| Vite | 2.9.x | NaiveUI | 2.27.x |
|
||||
| ECharts | 5.3.x | Pinia | 2.0.x |
|
||||
| 详见 `package.json` | 😁 | 🥰 | 🤗 |
|
||||
|
||||
开发环境:
|
||||
|
||||
| 名称 | 版本 | 名称 | 版本 |
|
||||
| ---- | ------- | ------- | ----- |
|
||||
| node | 16.14.x | npm | 8.5.x |
|
||||
| pnpm | 7.1.x | windows | 11 |
|
||||
|
||||
已完成图表:
|
||||
|
||||
| 分类 | 名称 | 名称 | 名称 | 名称 |
|
||||
| ------ | ---------------- | ---------- | -------------- | ------------------------ |
|
||||
| 图表 | 柱状图 | 横向柱状图 | 折线图 | 单/多 折线面积图(渐变色) |
|
||||
| \* | 饼图 | 环形图 | 水球图 | 雷达图 |
|
||||
| \* | NaiveUI 多种进度 | 散点图 | 对数回归散点图 | 热力图 |
|
||||
| \* | 漏斗图 | 中国地图 | 高德地图 | 🦊 |
|
||||
| 信息 | 文字 | 渐变文字 | 词云 | 嵌套网页 |
|
||||
| \* | 图片 | 视频 | 😺 | 🐯 |
|
||||
| 列表 | 滚动排名列表 | 滚动表格 | 🐮 | 🐐 |
|
||||
| 小组件 | 边框-01~13 | 装饰-01~05 | 数字翻牌 | 通用时间 |
|
||||
| \* | 数字计数 | 倒计时 | 时钟 | 🦁 |
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
开发和测试平台均在 `Google` 和最新版 `EDGE` 上完成,暂未测试 `IE11` 等其它浏览器,如有需求请自行测试与兼容。
|
||||
|
||||
## 安装
|
||||
|
||||
本项目采用` pnpm` 进行包管理
|
||||
|
||||
```shell
|
||||
#建议使用 nrm 切换到淘宝源 https://registry.npmmirror.com/
|
||||
#pnpm
|
||||
pnpm install
|
||||
|
||||
#yarn
|
||||
yarn install
|
||||
|
||||
#npm
|
||||
npm install
|
||||
```
|
||||
|
||||
## 启动
|
||||
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm dev
|
||||
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
#yarn
|
||||
yarn dev
|
||||
|
||||
#Makefile
|
||||
make dev
|
||||
```
|
||||
|
||||
## 编译
|
||||
|
||||
```shell
|
||||
#pnpm
|
||||
pnpm run build
|
||||
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
#yarn
|
||||
yarn run build
|
||||
|
||||
#Makefile
|
||||
make dist
|
||||
|
||||
```
|
||||
|
||||
## 代码提交
|
||||
|
||||
- feat: 新功能
|
||||
- fix: 修复 Bug
|
||||
- docs: 文档修改
|
||||
- perf: 性能优化
|
||||
- revert: 版本回退
|
||||
- ci: CICD 集成相关
|
||||
- test: 添加测试代码
|
||||
- refactor: 代码重构
|
||||
- build: 影响项目构建或依赖修改
|
||||
- style: 不影响程序逻辑的代码修改
|
||||
- chore: 不属于以上类型的其他类型(日常事务)
|
||||
|
||||
## 交流
|
||||
|
||||
QQ 群:1030129384
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
9
build/getConfigFileName.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Get the configuration file variable name
|
||||
* @param env
|
||||
*/
|
||||
export const getConfigFileName = (env: Record<string, any>) => {
|
||||
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`
|
||||
.toUpperCase()
|
||||
.replace(/\s/g, '');
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "go-view",
|
||||
"version": "2.1.0",
|
||||
"version": "1.1.4",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
@@ -11,6 +11,8 @@
|
||||
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx,.vue src --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@amap/amap-jsapi-types": "^0.0.8",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/keymaster": "^1.6.30",
|
||||
@@ -33,7 +35,7 @@
|
||||
"three": "^0.145.0",
|
||||
"vue": "^3.2.31",
|
||||
"vue-demi": "^0.13.1",
|
||||
"vue-i18n": "9.1.10",
|
||||
"vue-i18n": "9.1.9",
|
||||
"vue-router": "4.0.12",
|
||||
"vue3-lazyload": "^0.2.5-beta",
|
||||
"vue3-sketch-ruler": "^1.3.3",
|
||||
|
||||
84
pnpm-lock.yaml
generated
@@ -1,6 +1,8 @@
|
||||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@amap/amap-jsapi-loader': ^1.0.1
|
||||
'@amap/amap-jsapi-types': ^0.0.8
|
||||
'@commitlint/cli': ^17.0.2
|
||||
'@commitlint/config-conventional': ^17.0.2
|
||||
'@types/color': ^3.0.3
|
||||
@@ -57,7 +59,7 @@ specifiers:
|
||||
vue: ^3.2.31
|
||||
vue-demi: ^0.13.1
|
||||
vue-echarts: ^6.0.2
|
||||
vue-i18n: 9.1.10
|
||||
vue-i18n: 9.1.9
|
||||
vue-router: 4.0.12
|
||||
vue-tsc: ^0.28.10
|
||||
vue3-lazyload: ^0.2.5-beta
|
||||
@@ -65,6 +67,8 @@ specifiers:
|
||||
vuedraggable: ^4.1.0
|
||||
|
||||
dependencies:
|
||||
'@amap/amap-jsapi-loader': 1.0.1
|
||||
'@amap/amap-jsapi-types': 0.0.8
|
||||
'@types/color': 3.0.3
|
||||
'@types/crypto-js': 4.1.1
|
||||
'@types/keymaster': 1.6.30
|
||||
@@ -87,7 +91,7 @@ dependencies:
|
||||
three: 0.145.0
|
||||
vue: 3.2.37
|
||||
vue-demi: 0.13.1_vue@3.2.37
|
||||
vue-i18n: 9.1.10_vue@3.2.37
|
||||
vue-i18n: 9.1.9_vue@3.2.37
|
||||
vue-router: 4.0.12_vue@3.2.37
|
||||
vue3-lazyload: 0.2.5-beta_2yymnzrok6eda47acnj2yjm3ae
|
||||
vue3-sketch-ruler: 1.3.4_vue@3.2.37
|
||||
@@ -132,6 +136,14 @@ devDependencies:
|
||||
|
||||
packages:
|
||||
|
||||
/@amap/amap-jsapi-loader/1.0.1:
|
||||
resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==}
|
||||
dev: false
|
||||
|
||||
/@amap/amap-jsapi-types/0.0.8:
|
||||
resolution: {integrity: sha512-q0FyZDIJcXjsMLGc3oS9rjfJsErOvt9rcp6AgzY4k14vo7bBhdq4eKwoSdVp/pYjR/rfaKBns5v10ycZOFwf/A==}
|
||||
dev: false
|
||||
|
||||
/@ampproject/remapping/2.2.0:
|
||||
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -659,60 +671,60 @@ packages:
|
||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||
dev: true
|
||||
|
||||
/@intlify/core-base/9.1.10:
|
||||
resolution: {integrity: sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==}
|
||||
/@intlify/core-base/9.1.9:
|
||||
resolution: {integrity: sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/devtools-if': 9.1.10
|
||||
'@intlify/message-compiler': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/runtime': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/vue-devtools': 9.1.10
|
||||
'@intlify/devtools-if': 9.1.9
|
||||
'@intlify/message-compiler': 9.1.9
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/runtime': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
'@intlify/vue-devtools': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/devtools-if/9.1.10:
|
||||
resolution: {integrity: sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==}
|
||||
/@intlify/devtools-if/9.1.9:
|
||||
resolution: {integrity: sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/message-compiler/9.1.10:
|
||||
resolution: {integrity: sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==}
|
||||
/@intlify/message-compiler/9.1.9:
|
||||
resolution: {integrity: sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
source-map: 0.6.1
|
||||
dev: false
|
||||
|
||||
/@intlify/message-resolver/9.1.10:
|
||||
resolution: {integrity: sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==}
|
||||
/@intlify/message-resolver/9.1.9:
|
||||
resolution: {integrity: sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: false
|
||||
|
||||
/@intlify/runtime/9.1.10:
|
||||
resolution: {integrity: sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==}
|
||||
/@intlify/runtime/9.1.9:
|
||||
resolution: {integrity: sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-compiler': 9.1.9
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@intlify/shared/9.1.10:
|
||||
resolution: {integrity: sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==}
|
||||
/@intlify/shared/9.1.9:
|
||||
resolution: {integrity: sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==}
|
||||
engines: {node: '>= 10'}
|
||||
dev: false
|
||||
|
||||
/@intlify/vue-devtools/9.1.10:
|
||||
resolution: {integrity: sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==}
|
||||
/@intlify/vue-devtools/9.1.9:
|
||||
resolution: {integrity: sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==}
|
||||
engines: {node: '>= 10'}
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.10
|
||||
'@intlify/runtime': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/runtime': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
dev: false
|
||||
|
||||
/@jridgewell/gen-mapping/0.1.1:
|
||||
@@ -5373,15 +5385,15 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-i18n/9.1.10_vue@3.2.37:
|
||||
resolution: {integrity: sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==}
|
||||
/vue-i18n/9.1.9_vue@3.2.37:
|
||||
resolution: {integrity: sha512-JeRdNVxS2OGp1E+pye5XB6+M6BBkHwAv9C80Q7+kzoMdUDGRna06tjC0vCB/jDX9aWrl5swxOMFcyAr7or8XTA==}
|
||||
engines: {node: '>= 10'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.1.10
|
||||
'@intlify/shared': 9.1.10
|
||||
'@intlify/vue-devtools': 9.1.10
|
||||
'@intlify/core-base': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
'@intlify/vue-devtools': 9.1.9
|
||||
'@vue/devtools-api': 6.1.4
|
||||
vue: 3.2.37
|
||||
dev: false
|
||||
|
||||
BIN
readme/go-view-doc.png
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
readme/go-view-indexpage.png
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
readme/go-view-theme.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
14
src/App.vue
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<n-config-provider
|
||||
:locale="zhCN"
|
||||
:theme="darkTheme"
|
||||
:hljs="hljsTheme"
|
||||
:date-locale="dateZhCN"
|
||||
:locale="locale"
|
||||
:date-locale="dateLocale"
|
||||
:theme-overrides="overridesTheme"
|
||||
>
|
||||
<go-app-provider>
|
||||
@@ -14,11 +14,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { zhCN, dateZhCN, NConfigProvider } from 'naive-ui'
|
||||
import { NConfigProvider } from 'naive-ui'
|
||||
import { GoAppProvider } from '@/components/GoAppProvider'
|
||||
import { I18n } from '@/components/I18n'
|
||||
|
||||
import { useSystemInit, useDarkThemeHook, useThemeOverridesHook, useCode } from '@/hooks'
|
||||
import { useDarkThemeHook, useThemeOverridesHook, useCode, useLang } from '@/hooks'
|
||||
|
||||
// 暗黑主题
|
||||
const darkTheme = useDarkThemeHook()
|
||||
@@ -29,6 +28,7 @@ const overridesTheme = useThemeOverridesHook()
|
||||
// 代码主题
|
||||
const hljsTheme = useCode()
|
||||
|
||||
// 系统全局数据初始化
|
||||
useSystemInit()
|
||||
// 全局语言
|
||||
const { locale, dateLocale } = useLang()
|
||||
|
||||
</script>
|
||||
|
||||
@@ -21,7 +21,7 @@ axiosInstance.interceptors.request.use(
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
const { code } = res.data as { code: number }
|
||||
if (code === ResultEnum.SUCCESS) return Promise.resolve(res.data)
|
||||
if (code === ResultEnum.DATA_SUCCESS) return Promise.resolve(res.data)
|
||||
// 重定向
|
||||
if (ErrorPageNameMap.get(code)) redirectErrorPage(code)
|
||||
return Promise.resolve(res.data)
|
||||
|
||||
@@ -15,6 +15,7 @@ export const radarUrl = '/mock/radarData'
|
||||
export const heatMapUrl = '/mock/heatMapData'
|
||||
export const scatterBasicUrl = '/mock/scatterBasic'
|
||||
export const mapUrl = '/mock/map'
|
||||
export const capsuleUrl = '/mock/capsule'
|
||||
export const wordCloudUrl = '/mock/wordCloud'
|
||||
export const treemapUrl = '/mock/treemap'
|
||||
export const threeEarth01Url = '/mock/threeEarth01Data'
|
||||
@@ -82,6 +83,11 @@ const mockObject: MockMethod[] = [
|
||||
method: RequestHttpEnum.GET,
|
||||
response: () => test.fetchMap
|
||||
},
|
||||
{
|
||||
url: capsuleUrl,
|
||||
method: RequestHttpEnum.GET,
|
||||
response: () => test.fetchCapsule
|
||||
},
|
||||
{
|
||||
url: wordCloudUrl,
|
||||
method: RequestHttpEnum.GET,
|
||||
|
||||
@@ -1,79 +1,9 @@
|
||||
{
|
||||
"point": [
|
||||
"markers|50": [
|
||||
{
|
||||
"name": "北京",
|
||||
"value": [116.405285, 39.904989, 200]
|
||||
},
|
||||
{
|
||||
"name": "郑州",
|
||||
"value": [113.665412, 34.757975, 888]
|
||||
},
|
||||
{
|
||||
"name": "青海",
|
||||
"value": [101.778916, 36.623178, 666]
|
||||
},
|
||||
{
|
||||
"name": "宁夏回族自治区",
|
||||
"value": [106.278179, 38.46637, 66]
|
||||
},
|
||||
{
|
||||
"name": "哈尔滨市",
|
||||
"value": [126.642464, 45.756967, 101]
|
||||
"name": "某某地市",
|
||||
"value": "@integer(2, 20)",
|
||||
"position": ["@float(115, 117, 1, 6)", "@float(38, 40, 1, 6)"]
|
||||
}
|
||||
],
|
||||
"map": [
|
||||
{
|
||||
"name": "北京市",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "河北省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "江苏省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "福建省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "山东省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "河南省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "湖北省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "广西壮族自治区",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "海南省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "青海省",
|
||||
"value": "@integer(0, 1000)"
|
||||
},
|
||||
{
|
||||
"name": "新疆维吾尔自治区",
|
||||
"value": "@integer(0, 1000)"
|
||||
}
|
||||
],
|
||||
"pieces": [
|
||||
{ "gte": 1000, "label": ">1000" },
|
||||
{ "gte": 600, "lte": 999, "label": "600-999" },
|
||||
{ "gte": 200, "lte": 599, "label": "200-599" },
|
||||
{ "gte": 50, "lte": 199, "label": "49-199" },
|
||||
{ "gte": 10, "lte": 49, "label": "10-49" },
|
||||
{ "lte": 9, "label": "<9" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -11,27 +11,7 @@ export default {
|
||||
msg: '请求成功',
|
||||
data: {
|
||||
dimensions: ['product', 'dataOne'],
|
||||
source: [
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
},
|
||||
'source|50': [
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|0-900': 3
|
||||
@@ -39,6 +19,22 @@ export default {
|
||||
]
|
||||
}
|
||||
},
|
||||
// 胶囊图
|
||||
fetchCapsule: {
|
||||
code: 0,
|
||||
status: 200,
|
||||
msg: '请求成功',
|
||||
data: {
|
||||
dimensions: ['name', 'value'],
|
||||
source: [
|
||||
{ name: '厦门', 'value|0-40': 20 },
|
||||
{ name: '南阳', 'value|20-60': 40 },
|
||||
{ name: '北京', 'value|40-80': 60 },
|
||||
{ name: '上海', 'value|60-100': 80 },
|
||||
{ name: '新疆', value: 100 }
|
||||
]
|
||||
}
|
||||
},
|
||||
// 图表
|
||||
fetchMockData: {
|
||||
code: 0,
|
||||
@@ -46,32 +42,7 @@ export default {
|
||||
msg: '请求成功',
|
||||
data: {
|
||||
dimensions: ['product', 'dataOne', 'dataTwo'],
|
||||
source: [
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
'dataTwo|100-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
'dataTwo|100-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
'dataTwo|100-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
'dataTwo|100-900': 3
|
||||
},
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
'dataTwo|100-900': 3
|
||||
},
|
||||
'source|50': [
|
||||
{
|
||||
product: '@name',
|
||||
'dataOne|100-900': 3,
|
||||
@@ -85,21 +56,7 @@ export default {
|
||||
code: 0,
|
||||
status: 200,
|
||||
msg: '请求成功',
|
||||
data: [
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 },
|
||||
{ name: '@name', 'value|100-900': 5 }
|
||||
]
|
||||
'data|50': [{ name: '@name', 'value|100-900': 5 }]
|
||||
},
|
||||
// 轮播表格
|
||||
fetchScrollBoard: {
|
||||
@@ -262,12 +219,7 @@ export default {
|
||||
data: [
|
||||
{
|
||||
startArray: { name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
|
||||
endArray: [
|
||||
{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
|
||||
{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
|
||||
{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' },
|
||||
{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }
|
||||
]
|
||||
'endArray|10': [{ name: '@name', N: '@integer(10, 100)', E: '@integer(10, 100)' }]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from '@/api/path/project.api'
|
||||
export * from '@/api/path/system.api'
|
||||
@@ -1,84 +0,0 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { ContentTypeEnum, RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
// * 项目列表
|
||||
export const projectListApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/list`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 新增项目
|
||||
export const createProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/create`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 获取项目
|
||||
export const fetchProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.PROJECT}/getData`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 保存项目
|
||||
export const saveProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/save/data`, data, ContentTypeEnum.FORM_URLENCODED);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 修改项目基础信息
|
||||
export const updateProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.PROJECT}/edit`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * 删除项目
|
||||
export const deleteProjectApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.DELETE)(`${ModuleTypeEnum.PROJECT}/delete`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 修改发布状态 [-1未发布,1发布]
|
||||
export const changeProjectReleaseApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.PUT)(`${ModuleTypeEnum.PROJECT}/publish`, data);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 上传文件
|
||||
export const uploadFile = async (url:string, data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(url, data, ContentTypeEnum.FORM_DATA);
|
||||
return res;
|
||||
} catch {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { http } from '@/api/http'
|
||||
import { httpErrorHandle } from '@/utils'
|
||||
import { RequestHttpEnum, ModuleTypeEnum } from '@/enums/httpEnum'
|
||||
|
||||
// * 登录
|
||||
export const loginApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.POST)(`${ModuleTypeEnum.SYSTEM}/login`, data);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 登出
|
||||
export const logoutApi = async () => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/logout`);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
|
||||
// * 获取 oss 上传接口
|
||||
export const ossUrlApi = async (data: object) => {
|
||||
try {
|
||||
const res = await http(RequestHttpEnum.GET)(`${ModuleTypeEnum.SYSTEM}/getOssInfo`, data);
|
||||
return res;
|
||||
} catch(err) {
|
||||
httpErrorHandle();
|
||||
}
|
||||
}
|
||||
BIN
src/assets/images/chart/charts/capsule.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
src/assets/images/chart/charts/map_amap.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/images/chart/informations/iframe.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
@@ -1,146 +0,0 @@
|
||||
|
||||
/**
|
||||
* 后端接口,相关功能对应表:
|
||||
* 登录 - login
|
||||
* 登出 - logout
|
||||
* 预览,token 注入或单点登陆 - checkToken
|
||||
* 显示项目列表和分页 - projectList
|
||||
* 保存、发布、修改名称 - updateProject
|
||||
* 复制项目 - copyProject
|
||||
* 图表内的图片上传 - uploadFile
|
||||
* 上传图片显示处理 - getFileUrl
|
||||
* 所有接口返回格式:MyResponseType
|
||||
*/
|
||||
import { IndexDbBackend } from "./indexdb/indexdbbackend";
|
||||
// import { PythonBackend } from "./python/pythonbackend";
|
||||
|
||||
export interface MyResponseType {
|
||||
code: number; // 状态:200 表示接口调用成功,参考:HttpEnum
|
||||
msg: string; // 提示信息,配合 data 和 code
|
||||
data: any; // data = null 表示接口结果错误,错误原因放在 msg
|
||||
}
|
||||
|
||||
export class MyResponse implements MyResponseType {
|
||||
code: number = 200;
|
||||
msg: string = "";
|
||||
data: any = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现 IBackend 后端接口
|
||||
* 错误处理:
|
||||
*/
|
||||
export interface IBackend {
|
||||
/**
|
||||
* 初始化后端系统,测试后端连接,oss地址等
|
||||
* @param data 可选,备用
|
||||
*/
|
||||
init(data:any):any
|
||||
|
||||
/**
|
||||
* 登陆
|
||||
* @param data {} .username .password
|
||||
* @return MyResponseType
|
||||
* .data 须包含:
|
||||
* token:{tokenValue:"", tokenName:""},
|
||||
* userinfo:{nickname:"", username: "", id: 用户ID}
|
||||
* 错误处理:
|
||||
* 1 接口错误 .code 不为 200 .msg 可选,后端反馈错误信息
|
||||
* 2 登陆错误 .code=200 .data = null, msg 可选,反馈不能登陆的原因
|
||||
* 登陆信息.data 记录:
|
||||
* setLocalStorage(GO_LOGIN_INFO_STORE, res.data)
|
||||
*/
|
||||
login(data:any):any
|
||||
|
||||
/**
|
||||
* 通知后端登出
|
||||
*/
|
||||
logout():any
|
||||
|
||||
/**
|
||||
* 检查Token是否有效,配合预览页面和单点登陆,备用
|
||||
* @param data {tokenValue, tokenName}
|
||||
* @return 同 login()
|
||||
*/
|
||||
checkToken(data:any):any
|
||||
|
||||
/**
|
||||
* 项目列表
|
||||
* @param data {} .page, .limit
|
||||
* @return [项目],字段名称需要进行 map
|
||||
* id: projectId
|
||||
* title:projectName
|
||||
* release,
|
||||
* label:remarks
|
||||
* image:indexImage 如果需要挂刷新,在这里处理。如果需要拼接 url(getFileUrl),也在这里处理好。
|
||||
*/
|
||||
projectList(data:any):any
|
||||
|
||||
/**
|
||||
* 新增项目
|
||||
* @param data
|
||||
* .projectName
|
||||
* @return id 新项目 ID
|
||||
*/
|
||||
createProject(data: any):any
|
||||
|
||||
/**
|
||||
* 获取项目
|
||||
* @param data .projectId
|
||||
* @return
|
||||
id:projectId
|
||||
projectName,
|
||||
state: release,
|
||||
remarks,
|
||||
content
|
||||
*/
|
||||
fetchProject(data: any):any
|
||||
|
||||
/**
|
||||
* 修改项目
|
||||
* @param data
|
||||
* .projectId 必须
|
||||
* .projectName 可选
|
||||
* .release 可选
|
||||
* .content 可选
|
||||
* .object File 可选 对象
|
||||
* .remarks 可选
|
||||
* @return
|
||||
*/
|
||||
updateProject(data: any):any
|
||||
|
||||
/**
|
||||
* 复制项目
|
||||
* @param data
|
||||
* .copyId 需要复制的项目ID
|
||||
* .projectName
|
||||
* @return id 新项目ID
|
||||
*/
|
||||
copyProject(data: any):any
|
||||
|
||||
/**
|
||||
* 删除项目
|
||||
* @param data
|
||||
* .projectId
|
||||
* @return
|
||||
*/
|
||||
deleteProject(data: any):any
|
||||
|
||||
/**
|
||||
* 文件上传
|
||||
* @param file File 图片对象
|
||||
* @param params 备用 Todo: 上传文件可带上项目ID和其他附加信息,以便后端文件管理
|
||||
* @return .uri 文件对象 uri。建议在图表中保存相对地址,通过 getFileUrl 得到完整地址
|
||||
*/
|
||||
uploadFile(file: File, params: any):any
|
||||
/**
|
||||
* 文件地址转换,处理 uploadFile 的返回地址。如果是绝对地址,可以不处理
|
||||
* @param uploadUri 上传返回的 uri
|
||||
* @return 供 image.src 使用的地址信息
|
||||
*/
|
||||
getFileUrl(uploadUri:string):string
|
||||
}
|
||||
|
||||
export const BackEndFactory = new IndexDbBackend();
|
||||
// export const BackEndFactory = new MockBackend();
|
||||
// export const BackEndFactory = new PythonBackend();
|
||||
@@ -1,147 +0,0 @@
|
||||
/**
|
||||
* IndexDb 帮助类
|
||||
*/
|
||||
|
||||
const win: { [k: string]: any } = window || globalThis;
|
||||
const indexedDB =
|
||||
win.indexedDB || win.mozIndexedDB || win.webkitIndexedDB || win.msIndexedDB;
|
||||
const dbs: { [k: string]: IDBDatabase } = {};
|
||||
let databaseName: string;
|
||||
let request: IDBOpenDBRequest;
|
||||
interface AnyEvent {
|
||||
[k: string]: any;
|
||||
}
|
||||
|
||||
export interface TableOption {
|
||||
storeName: string;
|
||||
option: { [K: string]: any };
|
||||
index: { [K: string]: any }[];
|
||||
}
|
||||
|
||||
export const createDB = (
|
||||
name: string,
|
||||
version?: string,
|
||||
options?: TableOption[],
|
||||
) =>
|
||||
new Promise<IDBDatabase>((resolve, reject) => {
|
||||
if (!indexedDB) reject('浏览器不支持indexedDB');
|
||||
databaseName = name;
|
||||
if (dbs?.[name]) {
|
||||
resolve(dbs[name]);
|
||||
return;
|
||||
}
|
||||
request = indexedDB.open(name, version);
|
||||
createTable(options)?.then((db: IDBDatabase) => resolve(db));
|
||||
request.onsuccess = (event: AnyEvent) => {
|
||||
// IDBDatabase
|
||||
const db = event.target.result;
|
||||
// 缓存起来
|
||||
dbs[name] = db;
|
||||
resolve(db);
|
||||
};
|
||||
request.onerror = (event: AnyEvent) => reject(event);
|
||||
});
|
||||
|
||||
export const createTable = (options?: TableOption[]) => {
|
||||
if (!options) return;
|
||||
return new Promise<IDBDatabase>((resolve) => {
|
||||
request.onupgradeneeded = (event: AnyEvent) => {
|
||||
const db = event.target.result;
|
||||
dbs[databaseName] = db;
|
||||
for (const i in options) {
|
||||
// 判断是否存在表
|
||||
if (!db.objectStoreNames.contains(options[i].storeName)) {
|
||||
const objectStore = db.createObjectStore(
|
||||
options[i].storeName,
|
||||
options[i].option,
|
||||
);
|
||||
for (const j of options[i].index) {
|
||||
objectStore.createIndex(j.name, j.keyPath, {
|
||||
unique: j.unique,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
resolve(db);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const getTransaction = async (name: string, version?: string) => {
|
||||
let db: IDBDatabase;
|
||||
// 先从缓存获取
|
||||
if (dbs[databaseName]) {
|
||||
db = dbs[databaseName];
|
||||
} else {
|
||||
db = await createDB(databaseName, version);
|
||||
}
|
||||
return db.transaction(name, 'readwrite');
|
||||
};
|
||||
|
||||
const getObjectStore = async (
|
||||
name: string,
|
||||
version?: string,
|
||||
): Promise<IDBObjectStore> => {
|
||||
const transaction = await getTransaction(name, version);
|
||||
return transaction.objectStore(name);
|
||||
};
|
||||
|
||||
const getStore = (name: string, type: string, data: any) =>
|
||||
new Promise<IDBDatabase>((resolve) => {
|
||||
getObjectStore(name).then((objectStore: IDBObjectStore | any) => {
|
||||
const request = objectStore[type](data);
|
||||
request.onsuccess = (event: AnyEvent) =>
|
||||
resolve(event.target.result);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const findStore = (
|
||||
name: string,
|
||||
start: any,
|
||||
end: any,
|
||||
startInclude: any,
|
||||
endInclude: any,
|
||||
) =>
|
||||
new Promise<IDBDatabase>((resolve, reject) => {
|
||||
getObjectStore(name).then((objectStore: IDBObjectStore) => {
|
||||
const request = objectStore.openCursor(
|
||||
IDBKeyRange.bound(start, end, startInclude, endInclude),
|
||||
);
|
||||
request.onsuccess = (event: AnyEvent) =>
|
||||
resolve(event.target.result);
|
||||
request.onerror = (event: AnyEvent) => reject(event);
|
||||
});
|
||||
});
|
||||
|
||||
export interface DBSelect {
|
||||
add: (data: any) => Promise<IDBDatabase>;
|
||||
get: (data: any) => Promise<IDBDatabase>;
|
||||
getAll: () => Promise<IDBDatabase>;
|
||||
del: (data: any) => Promise<IDBDatabase>;
|
||||
clear: (data: any) => Promise<IDBDatabase>;
|
||||
put: (data: any) => Promise<IDBDatabase>;
|
||||
find: (
|
||||
start: any,
|
||||
end: any,
|
||||
startInclude: any,
|
||||
endInclude: any,
|
||||
) => Promise<IDBDatabase>;
|
||||
}
|
||||
// 获取一个store
|
||||
export const onDBSelect = async (
|
||||
name: string,
|
||||
version: string
|
||||
): Promise<DBSelect> => {
|
||||
const add = (data: any) => getStore(name, 'add', data);
|
||||
const get = (data: any) => getStore(name, 'get', data);
|
||||
const getAll = () => getStore(name, 'getAll', null);
|
||||
const del = (data: any) => getStore(name, 'delete', data);
|
||||
const clear = (data: any) => getStore(name, 'clear', data);
|
||||
const put = (data: any) => getStore(name, 'put', data);
|
||||
const find = (start: any, end: any, startInclude: any, endInclude: any) =>
|
||||
findStore(name, start, end, startInclude, endInclude);
|
||||
const options: DBSelect = { add, get, getAll, clear, del, put, find };
|
||||
getObjectStore(name, version);
|
||||
return options;
|
||||
};
|
||||
@@ -1,155 +0,0 @@
|
||||
import { MyResponse, IBackend } from '../ibackend'
|
||||
import { createDB, DBSelect, onDBSelect } from '../indexdb/indexdb'
|
||||
import { fileToUrl, fileToBlob } from "@/utils"
|
||||
|
||||
const PROJECT_TABLE = "project"
|
||||
const IMAGE_TABLE = "image" // 保存图片,未实现,Todo
|
||||
const DB_NAME = "goview"
|
||||
const DB_VER = "1"
|
||||
|
||||
export class IndexDbBackend implements IBackend {
|
||||
public async init(data: any) {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:IDBDatabase = await createDB(DB_NAME, DB_VER, [
|
||||
{
|
||||
storeName: PROJECT_TABLE,
|
||||
option: {
|
||||
keyPath: "projectId", autoIncrement:true
|
||||
},
|
||||
index: [
|
||||
{name: 'projectId', keyPath: "projectId", unique: true},
|
||||
{name: 'projectName', keyPath: "projectName", unique: false},
|
||||
{name: 'release', keyPath: "release", unique: false},
|
||||
{name: 'remarks', keyPath: "remarks", unique: false},
|
||||
{name: 'content', keyPath: "content", unique: false},
|
||||
{name: 'indexImage', keyPath: "indexImage", unique: false}
|
||||
]
|
||||
}
|
||||
])
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async login(data:any) {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
if(data.password == "123456" && data.username == "admin"){
|
||||
rtn.data = {
|
||||
token:{tokenValue:"mockToken", tokenName:"name"},
|
||||
userinfo:{nickname:"nickname", username:data.username, id:1}
|
||||
}
|
||||
}else{
|
||||
rtn.data = null
|
||||
rtn.msg = "admin 和 123456"
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async logout() {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async checkToken(data: any) {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
console.log("CheckToken: " + data.token)
|
||||
rtn.data = {
|
||||
token:{tokenValue:"mockToken", tokenName:"name"},
|
||||
userinfo:{nickname:"nickname", username:data.username, id:1}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async projectList(data:any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
const r:any = await db.getAll()
|
||||
rtn.data = []
|
||||
r.map(function (item: any) {
|
||||
let url = ""
|
||||
if(item.indexImage){
|
||||
const Url = URL || window.URL || window.webkitURL
|
||||
url = Url.createObjectURL(item.indexImage)
|
||||
}
|
||||
rtn.data.push({
|
||||
id: item.projectId,
|
||||
title: item.projectName,
|
||||
release: item.release == 1,
|
||||
label:item.remarks,
|
||||
image:url
|
||||
})
|
||||
})
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async createProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
rtn.data.id = await db.add({ projectName:data.projectName })
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async fetchProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
const r:any = await db.get(parseInt(data.projectId))
|
||||
rtn.data = {
|
||||
id:r.projectId,
|
||||
projectName: r.projectName,
|
||||
state: r.release,
|
||||
remarks: r.remarks,
|
||||
content: r.content
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async updateProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
const row:any = await db.get(parseInt(data.projectId))
|
||||
if("content" in data) row.content = data.content
|
||||
if("projectName" in data) row.projectName = data.projectName
|
||||
if("release" in data) row.release = data.release
|
||||
if("remarks" in data) row.remarks = data.remarks
|
||||
if("object" in data) {
|
||||
row.indexImage = await fileToBlob(data.object)
|
||||
}
|
||||
await db.put(row)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async copyProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
const row:any = await db.get(parseInt(data.copyId))
|
||||
rtn.data.id =await db.add({
|
||||
projectName:data.projectName,
|
||||
content:row.content,
|
||||
indexImage:row.indexImage,
|
||||
remarks:row.remarks
|
||||
})
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async deleteProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
const db:DBSelect = await onDBSelect(PROJECT_TABLE, DB_VER)
|
||||
await db.del(parseInt(data.projectId))
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async changeProjectRelease(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async uploadFile(data: File, params:any){
|
||||
// Todo: 图片可以保存在表中
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
rtn.data.uri = fileToUrl(data)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public getFileUrl(uploadUri:string){
|
||||
return uploadUri;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
export enum ModuleTypeEnum {
|
||||
SYSTEM = 'sys',
|
||||
PROJECT = 'project',
|
||||
}
|
||||
|
||||
// 接口白名单(免登录)
|
||||
export const fetchAllowList = [
|
||||
// 登录
|
||||
`${ModuleTypeEnum.SYSTEM}/login`,
|
||||
// 获取 OSS 接口
|
||||
`${ModuleTypeEnum.SYSTEM}/getOssInfo`,
|
||||
// 预览获取数据
|
||||
`${ModuleTypeEnum.PROJECT}/getData`,
|
||||
]
|
||||
|
||||
// 接口黑名单
|
||||
export const fetchBlockList = []
|
||||
@@ -1,71 +0,0 @@
|
||||
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'
|
||||
import { ResultEnum } from "@/enums/httpEnum"
|
||||
import { PageEnum, ErrorPageNameMap } from "@/enums/pageEnum"
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { axiosPre } from '@/settings/httpSetting'
|
||||
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
|
||||
import { redirectErrorPage, getLocalStorage, routerTurnByName, httpErrorHandle } from '@/utils'
|
||||
import { fetchAllowList } from './axios.config'
|
||||
import includes from 'lodash/includes'
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
|
||||
timeout: ResultEnum.TIMEOUT,
|
||||
})
|
||||
|
||||
axiosInstance.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
// 白名单校验
|
||||
if (includes(fetchAllowList, config.url)) return config
|
||||
// 获取 token
|
||||
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
|
||||
// 重新登录
|
||||
if (!info) {
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
return config
|
||||
}
|
||||
const userInfo = info[SystemStoreEnum.USER_INFO]
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token']: userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
|
||||
}
|
||||
return config
|
||||
},
|
||||
(err: AxiosRequestConfig) => {
|
||||
Promise.reject(err)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
const { code } = res.data as { code: number }
|
||||
|
||||
// 成功
|
||||
if (code === ResultEnum.SUCCESS) {
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
|
||||
// 登录过期
|
||||
if (code === ResultEnum.TOKEN_OVERDUE) {
|
||||
window['$message'].error(window['$t']('http.token_overdue_message'))
|
||||
routerTurnByName(PageEnum.BASE_LOGIN_NAME)
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
|
||||
// 固定错误码重定向
|
||||
if (ErrorPageNameMap.get(code)) {
|
||||
redirectErrorPage(code)
|
||||
return Promise.resolve(res.data)
|
||||
}
|
||||
|
||||
// 提示错误
|
||||
window['$message'].error(window['$t']((res.data as any).msg))
|
||||
return Promise.resolve(res.data)
|
||||
},
|
||||
(err: AxiosResponse) => {
|
||||
Promise.reject(err)
|
||||
}
|
||||
)
|
||||
|
||||
export default axiosInstance
|
||||
@@ -1,226 +0,0 @@
|
||||
import axiosInstance from './axios'
|
||||
import {
|
||||
RequestHttpEnum,
|
||||
ContentTypeEnum,
|
||||
RequestBodyEnum,
|
||||
RequestDataTypeEnum,
|
||||
RequestContentTypeEnum,
|
||||
RequestParamsObjType
|
||||
} from '@/enums/httpEnum'
|
||||
import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||
|
||||
export const get = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.GET,
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
|
||||
export const post = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.POST,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const patch = (url: string, data?: object, headersType?: string) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PATCH,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const put = (url: string, data?: object, headersType?: ContentTypeEnum) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.PUT,
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': headersType || ContentTypeEnum.JSON
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const del = (url: string, params?: object) => {
|
||||
return axiosInstance({
|
||||
url: url,
|
||||
method: RequestHttpEnum.DELETE,
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取请求函数,默认get
|
||||
export const http = (type?: RequestHttpEnum) => {
|
||||
switch (type) {
|
||||
case RequestHttpEnum.GET:
|
||||
return get
|
||||
|
||||
case RequestHttpEnum.POST:
|
||||
return post
|
||||
|
||||
case RequestHttpEnum.PATCH:
|
||||
return patch
|
||||
|
||||
case RequestHttpEnum.PUT:
|
||||
return put
|
||||
|
||||
case RequestHttpEnum.DELETE:
|
||||
return del
|
||||
|
||||
default:
|
||||
return get
|
||||
}
|
||||
}
|
||||
const prefix = 'javascript:'
|
||||
// 对输入字符进行转义处理
|
||||
export const translateStr = (target: string | object) => {
|
||||
if (typeof target === 'string') {
|
||||
if (target.startsWith(prefix)) {
|
||||
const funcStr = target.split(prefix)[1]
|
||||
let result;
|
||||
try {
|
||||
result = new Function(`${funcStr}`)()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('js内容解析有误!')
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return target
|
||||
}
|
||||
}
|
||||
for (const key in target) {
|
||||
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
||||
const subTarget = (target as any)[key];
|
||||
(target as any)[key] = translateStr(subTarget)
|
||||
}
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
* * 自定义请求
|
||||
* @param targetParams 当前组件参数
|
||||
* @param globalParams 全局参数
|
||||
*/
|
||||
export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
|
||||
if (!targetParams || !globalParams) {
|
||||
return
|
||||
}
|
||||
|
||||
// 全局
|
||||
const {
|
||||
// 全局请求源地址
|
||||
requestOriginUrl,
|
||||
// 全局请求内容
|
||||
requestParams: globalRequestParams
|
||||
} = globalParams
|
||||
|
||||
// 目标组件(优先级 > 全局组件)
|
||||
const {
|
||||
// 请求地址
|
||||
requestUrl,
|
||||
// 普通 / sql
|
||||
requestContentType,
|
||||
// 获取数据的方式
|
||||
requestDataType,
|
||||
// 请求方式 get/post/del/put/patch
|
||||
requestHttpType,
|
||||
// 请求体类型 none / form-data / x-www-form-urlencoded / json /xml
|
||||
requestParamsBodyType,
|
||||
// SQL 请求对象
|
||||
requestSQLContent,
|
||||
// 请求内容 params / cookie / header / body: 同 requestParamsBodyType
|
||||
requestParams: targetRequestParams
|
||||
} = targetParams
|
||||
|
||||
// 静态排除
|
||||
if (requestDataType === RequestDataTypeEnum.STATIC) return
|
||||
|
||||
if (!requestUrl) {
|
||||
return
|
||||
}
|
||||
|
||||
// 处理头部
|
||||
let headers: RequestParamsObjType = {
|
||||
...globalRequestParams.Header,
|
||||
...targetRequestParams.Header
|
||||
}
|
||||
headers = translateStr(headers)
|
||||
|
||||
// data 参数
|
||||
let data: RequestParamsObjType | FormData | string = {}
|
||||
// params 参数
|
||||
let params: RequestParamsObjType = { ...targetRequestParams.Params }
|
||||
params = translateStr(params)
|
||||
// form 类型处理
|
||||
let formData: FormData = new FormData()
|
||||
formData.set('default', 'defaultData')
|
||||
// 类型处理
|
||||
|
||||
switch (requestParamsBodyType) {
|
||||
case RequestBodyEnum.NONE:
|
||||
break
|
||||
|
||||
case RequestBodyEnum.JSON:
|
||||
headers['Content-Type'] = ContentTypeEnum.JSON
|
||||
data = translateStr(JSON.parse(targetRequestParams.Body['json']))
|
||||
// json 赋值给 data
|
||||
break
|
||||
|
||||
case RequestBodyEnum.XML:
|
||||
headers['Content-Type'] = ContentTypeEnum.XML
|
||||
// xml 字符串赋值给 data
|
||||
data = translateStr(targetRequestParams.Body['xml'])
|
||||
break
|
||||
|
||||
case RequestBodyEnum.X_WWW_FORM_URLENCODED: {
|
||||
headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
|
||||
const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
|
||||
for (const i in bodyFormData) formData.set(i, translateStr(bodyFormData[i]))
|
||||
// FormData 赋值给 data
|
||||
data = formData
|
||||
break
|
||||
}
|
||||
|
||||
case RequestBodyEnum.FORM_DATA: {
|
||||
headers['Content-Type'] = ContentTypeEnum.FORM_DATA
|
||||
const bodyFormUrlencoded = targetRequestParams.Body['form-data']
|
||||
for (const i in bodyFormUrlencoded) {
|
||||
formData.set(i, translateStr(bodyFormUrlencoded[i]))
|
||||
}
|
||||
// FormData 赋值给 data
|
||||
data = formData
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// sql 处理
|
||||
if (requestContentType === RequestContentTypeEnum.SQL) {
|
||||
headers['Content-Type'] = ContentTypeEnum.JSON
|
||||
data = requestSQLContent
|
||||
}
|
||||
|
||||
try {
|
||||
const url = (new Function("return `" + `${requestOriginUrl}${requestUrl}`.trim() + "`"))();
|
||||
return axiosInstance({
|
||||
url,
|
||||
method: requestHttpType,
|
||||
data,
|
||||
params,
|
||||
headers
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
window['$message'].error('URL地址格式有误!')
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
import { MyResponse, IBackend } from './ibackend'
|
||||
import { fileToUrl } from '@/utils'
|
||||
|
||||
|
||||
/**
|
||||
* MockBackend
|
||||
* 模拟纯前端,不会保存,也不报错。
|
||||
*/
|
||||
|
||||
export class MockBackend implements IBackend {
|
||||
public async init(data: any) {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async login(data:any) {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
if(data.password == "123456" && data.username == "admin"){
|
||||
rtn.data = {
|
||||
token:{tokenValue:"mockToken", tokenName:"name"},
|
||||
userinfo:{nickname:"nickname", username:data.username, id:1}
|
||||
}
|
||||
}else{
|
||||
rtn.data = null
|
||||
rtn.msg = "用户名或密码错误!"
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async logout() {
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async checkToken(data:any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async projectList(data:any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
rtn.data =[
|
||||
{
|
||||
id: 1,
|
||||
title: '假数据不可用',
|
||||
release: true,
|
||||
label: '官方案例'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '物料2-假数据不可用',
|
||||
release: false,
|
||||
label: '官方案例'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '物料3-假数据不可用',
|
||||
release: false,
|
||||
label: '官方案例'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '物料4-假数据不可用',
|
||||
release: false,
|
||||
label: '官方案例'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: '物料5-假数据不可用',
|
||||
release: false,
|
||||
label: '官方案例'
|
||||
}
|
||||
];
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async createProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
rtn.data.id = "newId"
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async fetchProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
rtn.data = {
|
||||
id:data.projectId,
|
||||
projectName: '假数据不可用',
|
||||
indexImage:'',
|
||||
state: 0,
|
||||
remarks: '官方案例',
|
||||
content: null
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async saveProject(data: object){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async updateProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async copyProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async deleteProject(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async changeProjectRelease(data: any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public async uploadFile(data: File, params:any){
|
||||
let rtn:MyResponse = new MyResponse;
|
||||
rtn.data.uri = fileToUrl(data)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
public getFileUrl(uploadUri:string){
|
||||
return uploadUri;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
</template>
|
||||
|
||||
<n-list-item>
|
||||
<n-space :size="20">
|
||||
<n-space class="go-my-2" :size="20">
|
||||
<n-text class="item-left">版权声明:</n-text>
|
||||
<n-text>
|
||||
GoView 版权属于
|
||||
@@ -21,8 +21,7 @@
|
||||
</n-list-item>
|
||||
|
||||
<n-list-item>
|
||||
<n-divider style="margin-top: 0" />
|
||||
<n-space :size="20">
|
||||
<n-space class="go-my-2" :size="20">
|
||||
<n-text class="item-left">协议备注:</n-text>
|
||||
<n-text>
|
||||
请遵守开源 MIT 协议,以上声明 <n-text type="error">不可删除</n-text>,否则视作侵权行为,后果自负!
|
||||
@@ -31,8 +30,7 @@
|
||||
</n-list-item>
|
||||
|
||||
<n-list-item>
|
||||
<n-divider style="margin-top: 0" />
|
||||
<n-space :size="20">
|
||||
<n-space class="go-mt-2" :size="20">
|
||||
<n-text class="item-left">商业授权:</n-text>
|
||||
<n-text>
|
||||
若不想保留版权声明,请通过仓库/交流群 联系项目作者,进行授权
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Flipper from './index.vue'
|
||||
|
||||
type FlipType = 'up' | 'down'
|
||||
|
||||
export { Flipper, FlipType }
|
||||
@@ -1,19 +1,13 @@
|
||||
<template>
|
||||
<div class="M-Flipper" :class="[flipType, { go: isFlipping }]">
|
||||
<div class="go-Flipper" :class="[flipType, { go: isFlipping }]">
|
||||
<div class="digital front" :data-front="frontTextFromData"></div>
|
||||
<div class="digital back" :data-back="backTextFromData"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Flipper'
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, PropType, watch } from 'vue'
|
||||
import { FlipType } from '.'
|
||||
import { FlipType } from './index'
|
||||
|
||||
const props = defineProps({
|
||||
flipType: {
|
||||
@@ -131,7 +125,7 @@ $lineColor: #4a9ef8;
|
||||
}
|
||||
// #endregion
|
||||
|
||||
.M-Flipper {
|
||||
.go-Flipper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: $width;
|
||||
@@ -9,6 +9,12 @@ export enum DragKeyEnum {
|
||||
DRAG_KEY = 'ChartData'
|
||||
}
|
||||
|
||||
// 不同页面保存操作
|
||||
export enum SavePageEnum {
|
||||
CHART = 'SaveChart',
|
||||
JSON = 'SaveJSON'
|
||||
}
|
||||
|
||||
// 操作枚举
|
||||
export enum MenuEnum {
|
||||
// 移动
|
||||
@@ -40,6 +46,7 @@ export enum MenuEnum {
|
||||
UN_GROUP = 'unGroup',
|
||||
// 后退
|
||||
BACK = 'back',
|
||||
// 前进
|
||||
FORWORD = 'forward',
|
||||
// 保存
|
||||
SAVE = 'save',
|
||||
@@ -73,15 +80,3 @@ export enum MacKeyboard {
|
||||
SHIFT_SOURCE_KEY = '⇧',
|
||||
ALT_SOURCE_KEY = '⌥'
|
||||
}
|
||||
|
||||
// 同步状态枚举
|
||||
export enum SyncEnum {
|
||||
// 等待
|
||||
PENDING,
|
||||
// 开始
|
||||
START,
|
||||
// 成功
|
||||
SUCCESS,
|
||||
// 失败
|
||||
FAILURE
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ export enum ResultEnum {
|
||||
SERVER_ERROR = 500,
|
||||
SERVER_FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
TOKEN_OVERDUE = 886,
|
||||
TIMEOUT = 60000
|
||||
}
|
||||
|
||||
@@ -27,12 +26,6 @@ export enum RequestContentTypeEnum {
|
||||
SQL = 1
|
||||
}
|
||||
|
||||
// 头部
|
||||
export enum RequestHttpHeaderEnum {
|
||||
TOKEN = 'Token',
|
||||
COOKIE = 'Cookie'
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 请求方法
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,12 @@ export enum PreviewEnum {
|
||||
CHART_PREVIEW_NAME = 'ChartPreview',
|
||||
}
|
||||
|
||||
export enum EditEnum {
|
||||
// 图表JSON编辑
|
||||
CHART_EDIT = '/chart/edit/:id(.*)*',
|
||||
CHART_EDIT_NAME = 'ChartEdit',
|
||||
}
|
||||
|
||||
export enum PageEnum {
|
||||
// 登录
|
||||
BASE_LOGIN = '/login',
|
||||
@@ -20,15 +26,10 @@ export enum PageEnum {
|
||||
//重定向
|
||||
REDIRECT = '/redirect',
|
||||
REDIRECT_NAME = 'Redirect',
|
||||
|
||||
// 未发布
|
||||
REDIRECT_UN_PUBLISH = '/redirect/unPublish',
|
||||
REDIRECT_UN_PUBLISH_NAME = 'redirect-un-publish',
|
||||
|
||||
// 重载
|
||||
RELOAD = '/reload',
|
||||
RELOAD_NAME = 'Reload',
|
||||
|
||||
|
||||
// 首页
|
||||
BASE_HOME = '/project',
|
||||
BASE_HOME_NAME = 'Project',
|
||||
|
||||
@@ -2,4 +2,5 @@ export * from '@/hooks/useTheme.hook'
|
||||
export * from '@/hooks/usePreviewScale.hook'
|
||||
export * from '@/hooks/useCode.hook'
|
||||
export * from '@/hooks/useChartDataFetch.hook'
|
||||
export * from '@/hooks/useLifeHandler.hook'
|
||||
export * from '@/hooks/useLifeHandler.hook'
|
||||
export * from '@/hooks/useLang.hook'
|
||||
24
src/hooks/useLang.hook.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { computed } from 'vue'
|
||||
import { LangEnum } from '@/enums/styleEnum'
|
||||
import { useLangStore } from '@/store/modules/langStore/langStore'
|
||||
import { zhCN, enUS, dateEnUS, dateZhCN } from 'naive-ui'
|
||||
|
||||
type LangStoreType = typeof useLangStore
|
||||
|
||||
// 语言切换
|
||||
export const useLang = () => {
|
||||
const lang = useLangStore()
|
||||
|
||||
const locale = computed(() => {
|
||||
return lang.getLang === LangEnum.ZH ? zhCN : enUS
|
||||
})
|
||||
|
||||
const dateLocale = computed(() => {
|
||||
return lang.getLang === LangEnum.ZH ? dateZhCN : dateEnUS
|
||||
})
|
||||
|
||||
return {
|
||||
locale,
|
||||
dateLocale
|
||||
}
|
||||
}
|
||||
@@ -1,257 +1,25 @@
|
||||
import { CreateComponentType, EventLife } from '@/packages/index.d'
|
||||
import * as echarts from 'echarts'
|
||||
import { BackEndFactory } from '@/backend/ibackend'
|
||||
import { reactive, toRef , watch, computed} from 'vue';
|
||||
|
||||
/**
|
||||
* 事件测试:
|
||||
*
|
||||
切换显示名称为 饼图 和 柱状图 的图标
|
||||
const range = runtime.fn.selectComponents("饼图 柱状图")
|
||||
const h = runtime.fn.getChartConfig(range, "hide")
|
||||
runtime.fn.setChartConfig(range, "hide", !h)
|
||||
|
||||
修改一个名称 柱状图001 组件id 2wolqibrx3c000 的图表数据,以下两句等效
|
||||
runtime.fn.setChartConfig("柱状图001", "dataset", {"dimensions":["product","data1","data2"],"source":[{"product":"Mon","data1":120,"data2":130}]})
|
||||
runtime.fn.setChartConfig("#2wolqibrx3c000", "dataset", {"dimensions":["product","data1","data2"],"source":[{"product":"Mon","data1":120,"data2":230}]})
|
||||
|
||||
找到一个组并隐藏
|
||||
const c = runtime.fn.selectOneComponent("分组")
|
||||
if(c){
|
||||
console.log(runtime.fn.getChartConfig(c, "isGroup" ))
|
||||
runtime.fn.setChartConfig(c, "hide", true)
|
||||
}
|
||||
|
||||
调用组件 exposed 函数的例子
|
||||
组件中增加: defineExpose({ actionTest:actionTest })
|
||||
以下调用名称为 柱状图 组件的 actionTest
|
||||
runtime.fn.callExposed("柱状图", "actionTest")
|
||||
|
||||
|
||||
数据驱动界面:
|
||||
图表A 的 MOUNTED 加入对 status1 的 Watch, = "0" 隐藏
|
||||
watch(()=>runtime.variables.status1, newValue => runtime.fn.setChartConfig(this, "hide", newValue == "0"))
|
||||
图表B 的 MOUNTED 也加入对 status1 的 Watch = "1" 隐藏
|
||||
watch(()=>runtime.variables.status1, newValue => runtime.fn.setChartConfig(this, "hide", newValue == "1"))
|
||||
点击事件代码,实现图表A 和 图表B 的切换显示:
|
||||
if(runtime.variables.status1 == "0"){
|
||||
runtime.variables.status1 = "1"
|
||||
} else{
|
||||
runtime.variables.status1 = "0"
|
||||
}
|
||||
|
||||
图表A 的 MOUNTED 加入对 data1 的 Watch
|
||||
watch(()=>runtime.datasets.data1,
|
||||
newValue => runtime.fn.setChartConfig(this, "dataset", newValue))
|
||||
图表B 的 MOUNTED 加入对 data1 的 Watch
|
||||
watch(()=>runtime.datasets.data1,
|
||||
newValue => runtime.fn.setChartConfig(this, "dataset", newValue))
|
||||
点击事件代码,修改datasets.data1,同时更新图表A 和 图表B 的数据 :
|
||||
runtime.datasets.data1 = {"dimensions":["product","data1","data2"],"source":[{"product":"Mon","data1":120,"data2":230}]}
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// * 初始化
|
||||
export const useSystemInit = async () => {
|
||||
const res = await BackEndFactory.init({}) as any;
|
||||
}
|
||||
|
||||
const getOneChartConfig = (component:any, configName:string, params?:any)=>{
|
||||
let root = null
|
||||
if(component.proxy.chartConfig) root = component.proxy.chartConfig
|
||||
else if (component.proxy.groupData) root = component.proxy.groupData
|
||||
// if(!root) return null
|
||||
switch(configName){
|
||||
case "hide":
|
||||
return root.status.hide
|
||||
break;
|
||||
case "dataset":
|
||||
return root.option.dataset
|
||||
break;
|
||||
case "isGroup":
|
||||
return root.isGroup
|
||||
break;
|
||||
case "key":
|
||||
return root.key
|
||||
break;
|
||||
case "attr":
|
||||
return root.attr
|
||||
break;
|
||||
case "name":
|
||||
return root.chartConfig.title
|
||||
}
|
||||
}
|
||||
|
||||
const setOneChartConfig = (component:any, configName:string, newValue:any, params?:any)=>{
|
||||
let root = null
|
||||
if(component.proxy.chartConfig) root = component.proxy.chartConfig
|
||||
else if (component.proxy.groupData) root = component.proxy.groupData
|
||||
switch(configName){
|
||||
case "hide":
|
||||
root.status.hide = newValue
|
||||
break;
|
||||
case "dataset":
|
||||
root.option.dataset = newValue
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 选择器语法:参考 css selectors
|
||||
* 名称 组件名称,不能有空格和特殊字符(. # 引号等)
|
||||
* [name=名称] Todo
|
||||
* #id 组件编号
|
||||
* .key 组件类型 Todo
|
||||
* @param selectors
|
||||
* @returns []
|
||||
*/
|
||||
const getComponentsBySelectors = (selectors:string):any[]=>{
|
||||
// 返回:数组,可能多个
|
||||
let rtn:any[] = []
|
||||
const ar = selectors.split(" ")
|
||||
for(let a of ar){
|
||||
rtn = rtn.concat(getComponentsBySelector(a))
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
|
||||
const getComponentsBySelector = (selector:string):any[]=>{
|
||||
// 返回:数组,可能多个
|
||||
const rtn:any[] = []
|
||||
if(selector.substring(0,1) == "#")
|
||||
{
|
||||
const key = selector.substring(1)
|
||||
if(key in components){
|
||||
return [components[key]]
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
for (let key in components) {
|
||||
if(getOneChartConfig(components[key], "name") == selector){
|
||||
rtn.push(components[key])
|
||||
}
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
|
||||
|
||||
// 所有图表组件集合对象
|
||||
const components: { [K in string]?: any } = {}
|
||||
|
||||
const runtime = {
|
||||
// 变量,管理各种状态
|
||||
variables:reactive({}),
|
||||
// 数据集
|
||||
datasets:reactive({}),
|
||||
// 组件列表 {}
|
||||
components:components,
|
||||
// 帮助类
|
||||
fn:{
|
||||
/**
|
||||
* 选择一个组件
|
||||
* @param selectors string 选择器语法 | component | [component]
|
||||
* @return 第一个符合要求的 component 或 null
|
||||
*/
|
||||
selectOneComponent:(selectors:any)=>{
|
||||
const cList = runtime.fn.selectComponents(selectors)
|
||||
if(cList.length > 0){
|
||||
return cList[0]
|
||||
}
|
||||
return null
|
||||
},
|
||||
/**
|
||||
* 选择组件
|
||||
* @param selectors string 选择器语法 | component | [component]
|
||||
* @return 要求的 [component] 或 []
|
||||
*/
|
||||
selectComponents:(selectors:any):any[]=>{
|
||||
if(!selectors) return []
|
||||
if(typeof selectors == "string") return getComponentsBySelectors(selectors)
|
||||
if(Array.isArray(selectors)) return selectors
|
||||
return [selectors]
|
||||
},
|
||||
/**
|
||||
* 获取组件的值,如果多个,使用第一个
|
||||
* @param selectors string 选择器语法 | component | [component]
|
||||
* @param configName 配置名称
|
||||
* @param params 备用参数,可选
|
||||
* @returns 配置的值
|
||||
*/
|
||||
getChartConfig:(selectors:any, configName:string, params?:any)=>{
|
||||
const component:any = runtime.fn.selectOneComponent(selectors)
|
||||
if(!component && !component.proxy) return null
|
||||
return getOneChartConfig(component, configName, params)
|
||||
},
|
||||
/**
|
||||
* 设置组件的值,支持多个
|
||||
* @param selectors string 选择器语法 | component | [component]
|
||||
* @param configName 配置名称
|
||||
* @param newValue 新值
|
||||
* @param params 备用参数,可选
|
||||
* @returns 配置的值
|
||||
*/
|
||||
setChartConfig:(selectors:any, configName:string, newValue:any, params?:any)=>{
|
||||
const cList:any[] = runtime.fn.selectComponents(selectors)
|
||||
for(let c of cList){
|
||||
if(!c && !c.proxy) return null
|
||||
setOneChartConfig(c, configName, newValue, params)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 调用组件暴露的函数,组件中使用 defineExpose 进行定义
|
||||
* @param selectors string 选择器语法 | component | [component]
|
||||
* @param action 组件中 defineExpose 的函数名
|
||||
* @param params 调用的参数只支持一个参数或没有参数
|
||||
* @returns 无
|
||||
*/
|
||||
callExposed:(selectors:any, action:string, params?:any)=>{
|
||||
const cList:any[] = runtime.fn.selectComponents(selectors)
|
||||
for(let c of cList){
|
||||
if(!c && !c.exposed) return null
|
||||
if(typeof c.exposed[action] == "function") c.exposed[action](params)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 项目提供的npm 包变量
|
||||
export const npmPkgs = { echarts, toRef , watch, computed, runtime }
|
||||
export const npmPkgs = { echarts }
|
||||
|
||||
export const useLifeHandler = (chartConfig: CreateComponentType) => {
|
||||
const events = chartConfig.events || {}
|
||||
console.log("chartConfig.events")
|
||||
console.log(chartConfig.events)
|
||||
// 生成生命周期事件
|
||||
let lifeEvents = {
|
||||
const lifeEvents = {
|
||||
[EventLife.BEFORE_MOUNT](e: any) {
|
||||
// 存储组件
|
||||
components[chartConfig.id] = e.component
|
||||
const fnStr = (events[EventLife.BEFORE_MOUNT] || '').trim()
|
||||
generateFunc(fnStr, e, e.component)
|
||||
generateFunc(fnStr, e)
|
||||
},
|
||||
[EventLife.MOUNTED](e: any) {
|
||||
const fnStr = (events[EventLife.MOUNTED] || '').trim()
|
||||
generateFunc(fnStr, e, e.component)
|
||||
}
|
||||
}
|
||||
// 遍历,按需侦听
|
||||
for(let key in EventLife)
|
||||
{
|
||||
if(key != "BEFORE_MOUNT" && key != "MOUNTED"){
|
||||
const k = EventLife[key as keyof typeof EventLife]
|
||||
const fnStr = (events[<EventLife>k] || '').trim()
|
||||
if(fnStr){
|
||||
lifeEvents[k as keyof typeof lifeEvents] = (e:any) => {
|
||||
const fnStr = (events[<EventLife>k] || '').trim()
|
||||
generateFunc(fnStr, e, components[chartConfig.id])
|
||||
}
|
||||
}
|
||||
generateFunc(fnStr, e)
|
||||
}
|
||||
}
|
||||
return lifeEvents
|
||||
@@ -262,8 +30,7 @@ export const useLifeHandler = (chartConfig: CreateComponentType) => {
|
||||
* @param fnStr 用户方法体代码
|
||||
* @param e 执行生命周期的动态组件实例
|
||||
*/
|
||||
function generateFunc(fnStr: string, e: any, component:any) {
|
||||
if(fnStr == "") return
|
||||
function generateFunc(fnStr: string, e: any) {
|
||||
try {
|
||||
// npmPkgs 便于拷贝 echarts 示例时设置option 的formatter等相关内容
|
||||
Function(`
|
||||
@@ -273,7 +40,7 @@ function generateFunc(fnStr: string, e: any, component:any) {
|
||||
const {${Object.keys(npmPkgs).join()}} = node_modules;
|
||||
${fnStr}
|
||||
}
|
||||
)`)().bind(component)(e, components, npmPkgs)
|
||||
)`)().bind(e?.component)(e, components, npmPkgs)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ const global = {
|
||||
help: 'Help',
|
||||
contact: 'About Software',
|
||||
logout: 'Logout',
|
||||
logout_success: 'Logout success!',
|
||||
logout_failure: 'Logout Failed!',
|
||||
// system setting
|
||||
sys_set: 'System Setting',
|
||||
lang_set: 'Language Setting',
|
||||
@@ -28,14 +26,8 @@ const global = {
|
||||
r_more: 'More',
|
||||
}
|
||||
|
||||
const http = {
|
||||
error_message: 'The interface is abnormal, please check the interface!',
|
||||
token_overdue_message: 'Login expired, please log in again!'
|
||||
}
|
||||
|
||||
export default {
|
||||
global,
|
||||
http,
|
||||
login,
|
||||
project
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export default {
|
||||
desc: "Login",
|
||||
form_auto: "Sign in automatically",
|
||||
form_button: "Login",
|
||||
login_success: "Login success!",
|
||||
login_message: "Please complete the letter!",
|
||||
login_success: "Login success",
|
||||
login_message: "Please complete the letter",
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
export default {
|
||||
create_btn: 'Creat',
|
||||
create_success: 'Creat Success!',
|
||||
create_failure: 'Failed to create, please try again later!',
|
||||
create_tip: 'Please select a content for development!',
|
||||
create_tip: 'Please select a content for development',
|
||||
project: 'Project',
|
||||
my: 'My',
|
||||
new_project: 'New Project',
|
||||
|
||||
@@ -11,8 +11,6 @@ const global = {
|
||||
help: '帮助中心',
|
||||
contact: '关于软件',
|
||||
logout: '退出登录',
|
||||
logout_success: '退出成功!',
|
||||
logout_failure: '退出失败!',
|
||||
// 系统设置
|
||||
sys_set: '系统设置',
|
||||
lang_set: '语言设置',
|
||||
@@ -20,27 +18,16 @@ const global = {
|
||||
r_edit: '编辑',
|
||||
r_preview: '预览',
|
||||
r_copy: '克隆',
|
||||
r_copy_success: '克隆成功!',
|
||||
r_rename: '重命名',
|
||||
r_rename_success: '重命名成功!',
|
||||
r_publish: '发布',
|
||||
r_publish_success: '成功发布!',
|
||||
r_unpublish: '取消发布',
|
||||
r_unpublish_success: '取消成功!',
|
||||
r_download: '下载',
|
||||
r_delete: '删除',
|
||||
r_delete_success: '删除成功!',
|
||||
r_more: '更多',
|
||||
}
|
||||
|
||||
const http = {
|
||||
error_message: '获取数据失败,请稍后重试!',
|
||||
token_overdue_message: '登录过期,请重新登录!'
|
||||
}
|
||||
|
||||
export default {
|
||||
global,
|
||||
http,
|
||||
login,
|
||||
project
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ export default {
|
||||
desc: "登录",
|
||||
form_auto: "自动登录",
|
||||
form_button: "登录",
|
||||
login_success: "登录成功",
|
||||
login_message: "请填写完整信息",
|
||||
login_success: "登录成功!",
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
export default {
|
||||
// aside
|
||||
create_btn: '新建',
|
||||
create_success: '新建成功!',
|
||||
create_failure: '新建失败,请稍后重试!',
|
||||
create_tip: '从哪里出发好呢?',
|
||||
project: '项目',
|
||||
my: '我的',
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
<global-setting :optionData="optionData"></global-setting>
|
||||
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index + 1}`" :expanded="true">
|
||||
<SettingItemBox name="图形">
|
||||
<SettingItem name="颜色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
|
||||
</SettingItem>
|
||||
<SettingItem>
|
||||
<n-button size="small" @click="item.itemStyle.color = null"> 恢复默认 </n-button>
|
||||
</SettingItem>
|
||||
<SettingItem name="宽度">
|
||||
<n-input-number
|
||||
v-model:value="item.barWidth"
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
<global-setting :optionData="optionData"></global-setting>
|
||||
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-${index+1}`" :expanded="true">
|
||||
<SettingItemBox name="图形">
|
||||
<SettingItem name="颜色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color"></n-color-picker>
|
||||
</SettingItem>
|
||||
<SettingItem>
|
||||
<n-button size="small" @click="item.itemStyle.color = null">恢复默认</n-button>
|
||||
</SettingItem>
|
||||
<SettingItem name="宽度">
|
||||
<n-input-number
|
||||
v-model:value="item.barWidth"
|
||||
|
||||
25
src/packages/components/Charts/Bars/CapsuleChart/config.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { PublicConfigClass } from '@/packages/public'
|
||||
import { CapsuleChartConfig } from './index'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export const option = {
|
||||
dataset: dataJson,
|
||||
colors: ['#c4ebad', '#6be6c1', '#a0a7e6', '#96dee8', '#3fb1e3' ],
|
||||
unit: '',
|
||||
itemHeight: 10,
|
||||
valueFontSize: 16,
|
||||
paddingRight: 50,
|
||||
paddingLeft: 50,
|
||||
showValue: true
|
||||
}
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key: string = CapsuleChartConfig.key
|
||||
public attr = { ...chartInitConfig, zIndex: -1 }
|
||||
public chartConfig = cloneDeep(CapsuleChartConfig)
|
||||
public option = cloneDeep(option)
|
||||
}
|
||||
53
src/packages/components/Charts/Bars/CapsuleChart/config.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<!-- Echarts 全局设置 -->
|
||||
<global-setting :optionData="optionData"> </global-setting>
|
||||
<!-- 胶囊柱图 -->
|
||||
<collapse-item name="胶囊柱图" expanded>
|
||||
<SettingItemBox name="布局">
|
||||
<setting-item name="左侧边距">
|
||||
<n-input-number v-model:value="optionData.paddingLeft" :min="10" :step="1" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="右侧边距">
|
||||
<n-input-number v-model:value="optionData.paddingRight" :min="10" :step="1" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="每块高度(px)">
|
||||
<n-input-number v-model:value="optionData.itemHeight" :min="0" :step="1" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
</SettingItemBox>
|
||||
<SettingItemBox name="文本">
|
||||
<setting-item name="所有文字大小">
|
||||
<n-input-number v-model:value="optionData.valueFontSize" :min="0" :step="1" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="单位">
|
||||
<n-input v-model:value="optionData.unit" size="small"></n-input>
|
||||
</setting-item>
|
||||
|
||||
<SettingItem>
|
||||
<n-space>
|
||||
<n-switch v-model:value="optionData.showValue" size="small"></n-switch>
|
||||
<n-text>显示数值</n-text>
|
||||
</n-space>
|
||||
</SettingItem>
|
||||
</SettingItemBox>
|
||||
<SettingItemBox name="颜色">
|
||||
<setting-item v-for="(item, index) in optionData.colors" :key="index" :name="`颜色${index}`">
|
||||
<n-color-picker v-model:value="optionData.colors[index]" size="small" :modes="['hex']"></n-color-picker>
|
||||
</setting-item>
|
||||
</SettingItemBox>
|
||||
</collapse-item>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType, computed } from 'vue'
|
||||
import { GlobalSetting, CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
import { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||
|
||||
import { option } from './config'
|
||||
|
||||
const props = defineProps({
|
||||
optionData: {
|
||||
type: Object as PropType<typeof option & GlobalThemeJsonType>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
10
src/packages/components/Charts/Bars/CapsuleChart/data.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"dimensions": ["name", "value"],
|
||||
"source": [
|
||||
{ "name": "厦门", "value": 20 },
|
||||
{ "name": "南阳", "value": 40 },
|
||||
{ "name": "北京", "value": 60 },
|
||||
{ "name": "上海", "value": 80 },
|
||||
{ "name": "新疆", "value": 100 }
|
||||
]
|
||||
}
|
||||
15
src/packages/components/Charts/Bars/CapsuleChart/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import image from '@/assets/images/chart/charts/capsule.png'
|
||||
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
|
||||
|
||||
export const CapsuleChartConfig: ConfigType = {
|
||||
key: 'CapsuleChart',
|
||||
chartKey: 'VCapsuleChart',
|
||||
conKey: 'VCCapsuleChart',
|
||||
title: '胶囊柱图',
|
||||
category: ChatCategoryEnum.BAR,
|
||||
categoryName: ChatCategoryEnumName.BAR,
|
||||
package: PackagesCategoryEnum.CHARTS,
|
||||
chartFrame: ChartFrameEnum.COMMON,
|
||||
image
|
||||
}
|
||||
228
src/packages/components/Charts/Bars/CapsuleChart/index.vue
Normal file
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="state.mergedConfig"
|
||||
class="go-dv-capsule-chart"
|
||||
:style="{
|
||||
fontSize: numberSizeHandle(state.mergedConfig.valueFontSize),
|
||||
paddingLeft: numberSizeHandle(state.mergedConfig.paddingLeft),
|
||||
paddingRight: numberSizeHandle(state.mergedConfig.paddingRight)
|
||||
}"
|
||||
>
|
||||
<div class="label-column">
|
||||
<div
|
||||
v-for="item in state.mergedConfig.dataset.source"
|
||||
:key="item[state.mergedConfig.dataset.dimensions[0]]"
|
||||
:style="{ height: state.capsuleItemHeight, lineHeight: state.capsuleItemHeight }"
|
||||
>
|
||||
{{ item[state.mergedConfig.dataset.dimensions[0]] }}
|
||||
</div>
|
||||
<div class="laset"> </div>
|
||||
</div>
|
||||
|
||||
<div class="capsule-container">
|
||||
<div
|
||||
v-for="(capsule, index) in state.capsuleLength"
|
||||
:key="index"
|
||||
class="capsule-item"
|
||||
:style="{ height: state.capsuleItemHeight }"
|
||||
>
|
||||
<div
|
||||
class="capsule-item-column"
|
||||
:style="`width: ${capsule * 100}%; background-color: ${
|
||||
state.mergedConfig.colors[index % state.mergedConfig.colors.length]
|
||||
};height:calc(100% - ${2}px);`"
|
||||
>
|
||||
<div v-if="state.mergedConfig.showValue" class="capsule-item-value">
|
||||
{{ state.capsuleValue[index] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="unit-label">
|
||||
<div v-for="(label, index) in state.labelData" :key="label + index">
|
||||
{{ label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="state.mergedConfig.unit" class="unit-text">
|
||||
{{ state.mergedConfig.unit }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, reactive, PropType } from 'vue'
|
||||
import merge from 'lodash/merge'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import config, { option } from './config'
|
||||
|
||||
type DataProps = {
|
||||
name: string | number
|
||||
value: string | number
|
||||
[key: string]: string | number
|
||||
}
|
||||
|
||||
interface StateProps {
|
||||
defaultConfig: {
|
||||
dataset: {
|
||||
dimensions: Array<string>
|
||||
source: Array<DataProps>
|
||||
}
|
||||
colors: Array<string>
|
||||
unit: string
|
||||
showValue: boolean
|
||||
itemHeight: number
|
||||
valueFontSize: number
|
||||
paddingLeft: number
|
||||
paddingRight: number
|
||||
}
|
||||
mergedConfig: any
|
||||
capsuleLength: Array<number>
|
||||
capsuleValue: Array<string | Object>
|
||||
labelData: Array<number>
|
||||
capsuleItemHeight: string
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
type: Object as PropType<config>,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
|
||||
const state = reactive<StateProps>({
|
||||
defaultConfig: option,
|
||||
mergedConfig: null,
|
||||
capsuleLength: [],
|
||||
capsuleValue: [],
|
||||
labelData: [],
|
||||
capsuleItemHeight: ''
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.chartConfig.option,
|
||||
newVal => {
|
||||
calcData(newVal)
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
const calcData = (data: any) => {
|
||||
mergeConfig(props.chartConfig.option)
|
||||
|
||||
calcCapsuleLengthAndLabelData()
|
||||
}
|
||||
|
||||
const mergeConfig = (data: any) => {
|
||||
state.mergedConfig = merge(cloneDeep(state.defaultConfig), data || {})
|
||||
}
|
||||
|
||||
// 数据解析
|
||||
const calcCapsuleLengthAndLabelData = () => {
|
||||
const { source } = state.mergedConfig.dataset
|
||||
if (!source.length) return
|
||||
|
||||
state.capsuleItemHeight = numberSizeHandle(state.mergedConfig.itemHeight)
|
||||
const capsuleValue = source.map((item: DataProps) => item[state.mergedConfig.dataset.dimensions[1]])
|
||||
|
||||
const maxValue = Math.max(...capsuleValue)
|
||||
|
||||
state.capsuleValue = capsuleValue
|
||||
|
||||
state.capsuleLength = capsuleValue.map((v: any) => (maxValue ? v / maxValue : 0))
|
||||
|
||||
const oneFifth = maxValue / 5
|
||||
|
||||
const labelData = Array.from(new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))))
|
||||
|
||||
state.labelData = labelData
|
||||
}
|
||||
|
||||
const numberSizeHandle = (val: string | number) => {
|
||||
return val + 'px'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
calcData(props.chartConfig.option)
|
||||
})
|
||||
|
||||
// 预览
|
||||
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
|
||||
calcData(newData)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@include go('dv-capsule-chart') {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
padding-right: 50px;
|
||||
color: #b9b8cc;
|
||||
|
||||
.label-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
padding-right: 10px;
|
||||
text-align: right;
|
||||
> div:not(:last-child) {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.capsule-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.capsule-item {
|
||||
box-shadow: 0 0 3px #999;
|
||||
height: 10px;
|
||||
margin: 5px 0px;
|
||||
border-radius: 5px;
|
||||
|
||||
.capsule-item-column {
|
||||
position: relative;
|
||||
height: 8px;
|
||||
margin-top: 1px;
|
||||
border-radius: 5px;
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.capsule-item-value {
|
||||
padding-left: 10px;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unit-label {
|
||||
height: 20px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.unit-text {
|
||||
text-align: right;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
line-height: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BarCommonConfig } from './BarCommon/index'
|
||||
import { BarCrossrangeConfig } from './BarCrossrange/index'
|
||||
import { CapsuleChartConfig } from './CapsuleChart/index'
|
||||
|
||||
export default [BarCommonConfig, BarCrossrangeConfig]
|
||||
export default [BarCommonConfig, BarCrossrangeConfig, CapsuleChartConfig]
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
<global-setting :optionData="optionData"></global-setting>
|
||||
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`折线图-${index + 1}`" :expanded="true">
|
||||
<SettingItemBox name="线条">
|
||||
<setting-item name="颜色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="item.lineStyle.color"></n-color-picker>
|
||||
</setting-item>
|
||||
<SettingItem name="宽度">
|
||||
<n-input-number
|
||||
v-model:value="item.lineStyle.width"
|
||||
|
||||
83
src/packages/components/Charts/Maps/MapAmap/config.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { PublicConfigClass } from '@/packages/public'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { MapAmapConfig } from './index'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import dataJson from './data.json'
|
||||
|
||||
export enum ThemeEnum {
|
||||
NORMAL = 'normal',
|
||||
DARK = 'dark',
|
||||
LIGHT = 'light',
|
||||
WHITES_MOKE = 'whitesmoke',
|
||||
FRESH = 'fresh',
|
||||
GREY = 'grey',
|
||||
GRAFFITI = 'graffiti',
|
||||
MACARON = 'macaron',
|
||||
BLUE = 'blue',
|
||||
DARKBLUE = 'darkblue',
|
||||
WINE = 'wine'
|
||||
}
|
||||
|
||||
export enum LangEnum {
|
||||
ZH_CN = 'zh_cn',
|
||||
EN = 'en',
|
||||
ZH_EN = 'zh_en'
|
||||
}
|
||||
|
||||
export enum ViewModeEnum {
|
||||
PLANE = '2D',
|
||||
STEREOSCOPIC = '3D'
|
||||
}
|
||||
|
||||
export enum FeaturesEnum {
|
||||
BG = 'bg',
|
||||
POINT = 'point',
|
||||
ROAD = 'road',
|
||||
BUILDING = 'building'
|
||||
}
|
||||
|
||||
export enum MarkerEnum {
|
||||
// 圆圈
|
||||
CIRCLE_MARKER = 'CircleMarker',
|
||||
// 定位标点
|
||||
MARKER = 'Marker',
|
||||
// 暂无
|
||||
NONE = 'none'
|
||||
}
|
||||
|
||||
export const option = {
|
||||
dataset: dataJson,
|
||||
mapOptions: {
|
||||
pitch: 60,
|
||||
skyColor: '#53A9DE',
|
||||
amapKey: 'd5f3e16589dbecae64d05fe90e2ba4f2',
|
||||
amapStyleKey: ThemeEnum.DARK,
|
||||
amapStyleKeyCustom: '',
|
||||
amapLon: 116.397428,
|
||||
amapLat: 39.90923,
|
||||
amapZindex: 11,
|
||||
marker: {
|
||||
fillColor: '#E98984FF',
|
||||
fillOpacity: 0.5,
|
||||
strokeColor: 'white',
|
||||
strokeWeight: 2,
|
||||
strokeOpacity: 0.5,
|
||||
zIndex: 10,
|
||||
bubble: true,
|
||||
cursor: 'pointer',
|
||||
clickable: true
|
||||
},
|
||||
mapMarkerType: MarkerEnum.CIRCLE_MARKER,
|
||||
viewMode: ViewModeEnum.PLANE,
|
||||
lang: LangEnum.ZH_CN,
|
||||
features: [FeaturesEnum.BG, FeaturesEnum.POINT, FeaturesEnum.ROAD, FeaturesEnum.BUILDING]
|
||||
}
|
||||
}
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key = MapAmapConfig.key
|
||||
public attr = { ...chartInitConfig, w: 1000, h: 800, zIndex: -1 }
|
||||
public chartConfig = cloneDeep(MapAmapConfig)
|
||||
public option = cloneDeep(option)
|
||||
}
|
||||
199
src/packages/components/Charts/Maps/MapAmap/config.vue
Normal file
@@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<collapse-item name="基础" :expanded="true">
|
||||
<setting-item-box name="语言类型" :alone="true">
|
||||
<setting-item>
|
||||
<n-select size="small" v-model:value="optionData.mapOptions.lang" :options="langOptions" />
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="Key" :alone="true">
|
||||
<setting-item name="请务必使用自己的高德应用 key">
|
||||
<n-input v-model:value="optionData.mapOptions.amapKey" size="small"></n-input>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="自定义地图样式ID" :alone="true">
|
||||
<setting-item>
|
||||
<n-input size="small" v-model:value="optionData.mapOptions.amapStyleKeyCustom" />
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</collapse-item>
|
||||
<collapse-item name="地图" :expanded="true">
|
||||
<setting-item-box name="主题">
|
||||
<setting-item>
|
||||
<n-select size="small" v-model:value="optionData.mapOptions.amapStyleKey" :options="themeOptions" />
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="内容" :alone="true">
|
||||
<n-checkbox-group v-model:value="optionData.mapOptions.features">
|
||||
<n-space item-style="display: flex;">
|
||||
<n-checkbox :value="item.value" :label="item.label" v-for="(item, index) in featuresOptions" :key="index" />
|
||||
</n-space>
|
||||
</n-checkbox-group>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="位置">
|
||||
<setting-item name="经度">
|
||||
<n-input-number v-model:value="optionData.mapOptions.amapLon" :show-button="false" size="small">
|
||||
<template #suffix>°</template>
|
||||
</n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="纬度">
|
||||
<n-input-number v-model:value="optionData.mapOptions.amapLat" :show-button="false" size="small">
|
||||
<template #suffix>°</template>
|
||||
</n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="初始缩放">
|
||||
<n-input-number v-model:value="optionData.mapOptions.amapZindex" :min="0" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="模式" :alone="true">
|
||||
<setting-item>
|
||||
<n-radio-group v-model:value="optionData.mapOptions.viewMode" name="radiogroup">
|
||||
<n-space>
|
||||
<n-radio v-for="song in viewModeOptions" :key="song.value" :value="song.value">
|
||||
{{ song.label }}
|
||||
</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<template v-if="optionData.mapOptions.viewMode === '3D'">
|
||||
<setting-item-box>
|
||||
<setting-item name="天空色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.mapOptions.skyColor"></n-color-picker>
|
||||
</setting-item>
|
||||
<setting-item name="俯仰角">
|
||||
<n-input-number v-model:value="optionData.mapOptions.pitch" :min="0" :max="83" size="small"></n-input-number>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</template>
|
||||
</collapse-item>
|
||||
<collapse-item name="标记" :expanded="true">
|
||||
<setting-item-box name="样式">
|
||||
<setting-item name="类型">
|
||||
<n-select size="small" v-model:value="optionData.mapOptions.mapMarkerType" :options="MarkerOptions" />
|
||||
</setting-item>
|
||||
<setting-item name="颜色">
|
||||
<n-color-picker v-model:value="optionData.mapOptions.marker.fillColor" size="small"></n-color-picker>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</collapse-item>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { option, MarkerEnum, ThemeEnum, LangEnum, ViewModeEnum, FeaturesEnum } from './config'
|
||||
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
|
||||
defineProps({
|
||||
optionData: {
|
||||
type: Object as PropType<typeof option>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const themeOptions = [
|
||||
{
|
||||
value: ThemeEnum.NORMAL,
|
||||
label: '标准'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.DARK,
|
||||
label: '幻影黑'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.LIGHT,
|
||||
label: '月光银'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.WHITES_MOKE,
|
||||
label: '远山黛'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.FRESH,
|
||||
label: '草色青'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.GREY,
|
||||
label: '雅士灰'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.GRAFFITI,
|
||||
label: '涂鸦'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.MACARON,
|
||||
label: '马卡龙'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.BLUE,
|
||||
label: '靛青蓝'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.DARKBLUE,
|
||||
label: '极夜蓝'
|
||||
},
|
||||
{
|
||||
value: ThemeEnum.WINE,
|
||||
label: '酱籽'
|
||||
}
|
||||
]
|
||||
|
||||
const langOptions = [
|
||||
{
|
||||
value: LangEnum.ZH_CN,
|
||||
label: '中文简体'
|
||||
},
|
||||
{
|
||||
value: LangEnum.EN,
|
||||
label: '英文'
|
||||
},
|
||||
{
|
||||
value: LangEnum.ZH_EN,
|
||||
label: '中英文对照'
|
||||
}
|
||||
]
|
||||
|
||||
const viewModeOptions = [
|
||||
{
|
||||
value: ViewModeEnum.PLANE,
|
||||
label: '2D'
|
||||
},
|
||||
{
|
||||
value: ViewModeEnum.STEREOSCOPIC,
|
||||
label: '3D'
|
||||
}
|
||||
]
|
||||
|
||||
const featuresOptions = [
|
||||
{
|
||||
value: FeaturesEnum.BG,
|
||||
label: '显示地图背景'
|
||||
},
|
||||
{
|
||||
value: FeaturesEnum.POINT,
|
||||
label: '显示标识'
|
||||
},
|
||||
{
|
||||
value: FeaturesEnum.ROAD,
|
||||
label: '显示道路'
|
||||
},
|
||||
{
|
||||
value: FeaturesEnum.BUILDING,
|
||||
label: '显示建筑'
|
||||
}
|
||||
]
|
||||
|
||||
const MarkerOptions = [
|
||||
{
|
||||
value: MarkerEnum.CIRCLE_MARKER,
|
||||
label: '圆形标点'
|
||||
},
|
||||
{
|
||||
value: MarkerEnum.MARKER,
|
||||
label: '定位标点'
|
||||
},
|
||||
{
|
||||
value: MarkerEnum.NONE,
|
||||
label: '隐藏标点'
|
||||
}
|
||||
]
|
||||
</script>
|
||||
19
src/packages/components/Charts/Maps/MapAmap/data.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"markers": [
|
||||
{
|
||||
"name": "某某地市",
|
||||
"value": 10,
|
||||
"position": [116.300467, 39.907761]
|
||||
},
|
||||
{
|
||||
"name": "某某地市",
|
||||
"value": 15,
|
||||
"position": [116.400567, 39.908761]
|
||||
},
|
||||
{
|
||||
"name": "某某地市",
|
||||
"value": 20,
|
||||
"position": [116.200467, 39.937761]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
src/packages/components/Charts/Maps/MapAmap/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
|
||||
import image from '@/assets/images/chart/charts/map_amap.png'
|
||||
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
|
||||
|
||||
export const MapAmapConfig: ConfigType = {
|
||||
key: 'MapAmap',
|
||||
chartKey: 'VMapAmap',
|
||||
conKey: 'VCMapAmap',
|
||||
title: '高德地图',
|
||||
category: ChatCategoryEnum.MAP,
|
||||
categoryName: ChatCategoryEnumName.MAP,
|
||||
package: PackagesCategoryEnum.CHARTS,
|
||||
chartFrame: ChartFrameEnum.COMMON,
|
||||
image
|
||||
}
|
||||
130
src/packages/components/Charts/Maps/MapAmap/index.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div ref="vChartRef"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, PropType, toRefs, watch } from 'vue'
|
||||
import AMapLoader from '@amap/amap-jsapi-loader'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { MarkerEnum } from './config'
|
||||
import { isArray } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
type: Object as PropType<CreateComponentType>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
let {
|
||||
amapKey,
|
||||
amapStyleKey,
|
||||
amapLon,
|
||||
amapLat,
|
||||
amapZindex,
|
||||
mapMarkerType,
|
||||
lang,
|
||||
amapStyleKeyCustom,
|
||||
features,
|
||||
viewMode,
|
||||
pitch,
|
||||
skyColor,
|
||||
marker
|
||||
} = toRefs(props.chartConfig.option.mapOptions)
|
||||
|
||||
let mapIns: any = null
|
||||
let markers: any = []
|
||||
let AMapIns: any = null
|
||||
const vChartRef = ref<HTMLElement>()
|
||||
|
||||
const initMap = (newData: any) => {
|
||||
// 初始化
|
||||
AMapLoader.load({
|
||||
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!!
|
||||
version: '1.4.8', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
||||
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
|
||||
})
|
||||
.then(AMap => {
|
||||
AMapIns = AMap
|
||||
mapIns = new AMap.Map(vChartRef.value, {
|
||||
resizeEnable: true,
|
||||
zoom: amapZindex.value, // 地图显示的缩放级别
|
||||
center: [amapLon.value, amapLat.value],
|
||||
mapStyle: `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`, //自定义地图的显示样式
|
||||
lang: lang.value,
|
||||
features: features.value,
|
||||
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
|
||||
skyColor: skyColor.value,
|
||||
viewMode: viewMode.value, // 地图模式
|
||||
willReadFrequently: true
|
||||
})
|
||||
dataHandle(props.chartConfig.option.dataset)
|
||||
})
|
||||
.catch(e => {})
|
||||
}
|
||||
|
||||
const dataHandle = (newData: any) => {
|
||||
if (!mapIns && !AMapIns) {
|
||||
initMap(props.chartConfig.option)
|
||||
return
|
||||
}
|
||||
if (isArray(newData.markers)) {
|
||||
// 先清除旧标记
|
||||
mapIns.remove(markers)
|
||||
markers = []
|
||||
// 记录新标记
|
||||
if (mapMarkerType.value === MarkerEnum.MARKER) {
|
||||
newData.markers.forEach((markerItem: any) => {
|
||||
const markerInstance = new AMapIns.Marker({
|
||||
position: [markerItem.position[0], markerItem.position[1]],
|
||||
offset: new AMapIns.Pixel(-13, -30)
|
||||
})
|
||||
markers.push(markerInstance)
|
||||
markerInstance.setMap(mapIns)
|
||||
})
|
||||
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
|
||||
newData.markers.forEach((markerItem: any) => {
|
||||
const markerInstance = new AMapIns.CircleMarker({
|
||||
center: [markerItem.position[0], markerItem.position[1]],
|
||||
radius: markerItem.value,
|
||||
...marker.value
|
||||
})
|
||||
markers.push(markerInstance)
|
||||
markerInstance.setMap(mapIns)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const stopWatch = watch(
|
||||
() => props.chartConfig.option.mapOptions,
|
||||
option => {
|
||||
initMap(option)
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.chartConfig.option.dataset,
|
||||
newData => {
|
||||
try {
|
||||
dataHandle(newData)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: false
|
||||
}
|
||||
)
|
||||
|
||||
// 预览
|
||||
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
|
||||
stopWatch()
|
||||
dataHandle(newData)
|
||||
})
|
||||
</script>
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MapBaseConfig } from './MapBase/index'
|
||||
import { MapAmapConfig } from './MapAmap/index'
|
||||
|
||||
export default [ MapBaseConfig ]
|
||||
export default [MapBaseConfig, MapAmapConfig]
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CreateComponentType } from '@/packages/index.d'
|
||||
import { CountDownConfig } from './index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import { FlipType } from '@/components/Flipper'
|
||||
import { FlipType } from '@/components/Pages/Flipper'
|
||||
|
||||
type STYLE = '时分秒' | '冒号'
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<script setup lang="ts">
|
||||
import { PropType, toRefs, watch, ref, onMounted } from 'vue'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { Flipper } from '@/components/Flipper'
|
||||
import { Flipper } from '@/components/Pages/Flipper'
|
||||
import { OptionType } from './config'
|
||||
import { CountdownInst, CountdownProps } from 'naive-ui/es/countdown/src/Countdown'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CreateComponentType } from '@/packages/index.d'
|
||||
import { FlipperNumberConfig } from './index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import { FlipType } from '@/components/Flipper'
|
||||
import { FlipType } from '@/components/Pages/Flipper'
|
||||
|
||||
export interface OptionType {
|
||||
dataset: number | string
|
||||
|
||||
@@ -21,7 +21,7 @@ import { PropType, toRefs, watch, ref } from 'vue'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { Flipper } from '@/components/Flipper'
|
||||
import { Flipper } from '@/components/Pages/Flipper'
|
||||
import { OptionType } from './config'
|
||||
|
||||
const props = defineProps({
|
||||
|
||||
@@ -67,7 +67,7 @@ watch(
|
||||
onMounted(() => {
|
||||
try {
|
||||
if (navigator.userAgent.indexOf('Chrome') < -1 || navigator.userAgent.indexOf('Edg') > -1) {
|
||||
window['$message'].error('此组件仅在【谷歌】浏览器上能正常展示!')
|
||||
window['$message'].error('三维地图组件仅在【谷歌】浏览器上能正常展示!')
|
||||
chartEditStore.removeComponentList(undefined, false)
|
||||
return
|
||||
}
|
||||
|
||||
20
src/packages/components/Informations/Mores/Iframe/config.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { PublicConfigClass } from '@/packages/public'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import { IframeConfig } from './index'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
export const option = {
|
||||
// 网站路径
|
||||
dataset: "https://www.mtruning.club/",
|
||||
// 圆角
|
||||
borderRadius: 10
|
||||
}
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType
|
||||
{
|
||||
public key = IframeConfig.key
|
||||
public attr = { ...chartInitConfig, w: 800, h: 800, zIndex: -1 }
|
||||
public chartConfig = cloneDeep(IframeConfig)
|
||||
public option = cloneDeep(option)
|
||||
}
|
||||
36
src/packages/components/Informations/Mores/Iframe/config.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<collapse-item name="属性" :expanded="true">
|
||||
<setting-item-box name="路径" :alone="true">
|
||||
<setting-item name="请填写 https 协议的网址">
|
||||
<n-input v-model:value="optionData.dataset" size="small"></n-input>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="样式">
|
||||
<setting-item name="圆角">
|
||||
<n-input-number
|
||||
v-model:value="optionData.borderRadius"
|
||||
size="small"
|
||||
:min="0"
|
||||
placeholder="圆角"
|
||||
></n-input-number>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</collapse-item>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from "vue";
|
||||
import { option } from "./config";
|
||||
import {
|
||||
CollapseItem,
|
||||
SettingItemBox,
|
||||
SettingItem,
|
||||
} from "@/components/Pages/ChartItemSetting";
|
||||
|
||||
const props = defineProps({
|
||||
optionData: {
|
||||
type: Object as PropType<typeof option>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
15
src/packages/components/Informations/Mores/Iframe/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import image from '@/assets/images/chart/informations/iframe.png'
|
||||
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
|
||||
|
||||
export const IframeConfig: ConfigType = {
|
||||
key: 'Iframe',
|
||||
chartKey: 'VIframe',
|
||||
conKey: 'VCIframe',
|
||||
title: '远程网页',
|
||||
category: ChatCategoryEnum.MORE,
|
||||
categoryName: ChatCategoryEnumName.MORE,
|
||||
package: PackagesCategoryEnum.INFORMATIONS,
|
||||
chartFrame: ChartFrameEnum.COMMON,
|
||||
image
|
||||
}
|
||||
49
src/packages/components/Informations/Mores/Iframe/index.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div :style="getStyle(borderRadius)">
|
||||
<iframe :src="option.dataset" :width="w" :height="h" style="border-width: 0"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType, shallowReactive, watch, toRefs } from 'vue'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
type: Object as PropType<CreateComponentType>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const { w, h } = toRefs(props.chartConfig.attr)
|
||||
const { borderRadius } = toRefs(props.chartConfig.option)
|
||||
|
||||
const option = shallowReactive({
|
||||
dataset: ''
|
||||
})
|
||||
|
||||
const getStyle = (radius: number) => {
|
||||
return {
|
||||
borderRadius: `${radius}px`,
|
||||
overflow: 'hidden'
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑更新
|
||||
watch(
|
||||
() => props.chartConfig.option.dataset,
|
||||
(newData: string) => {
|
||||
option.dataset = newData
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
// 预览更新
|
||||
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: string) => {
|
||||
option.dataset = newData
|
||||
})
|
||||
</script>
|
||||
@@ -46,8 +46,7 @@ watch(
|
||||
option.dataset = newData
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: false
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@ export const VideoConfig: ConfigType = {
|
||||
category: ChatCategoryEnum.MORE,
|
||||
categoryName: ChatCategoryEnumName.MORE,
|
||||
package: PackagesCategoryEnum.INFORMATIONS,
|
||||
chartFrame: ChartFrameEnum.ECHARTS,
|
||||
chartFrame: ChartFrameEnum.COMMON,
|
||||
image
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ImageConfig } from './Image/index'
|
||||
import { IframeConfig } from './Iframe/index'
|
||||
import { VideoConfig } from './Video/index'
|
||||
import { WordCloudConfig } from './WordCloud/index'
|
||||
|
||||
export default [ImageConfig, VideoConfig, WordCloudConfig]
|
||||
export default [WordCloudConfig, ImageConfig, VideoConfig, IframeConfig]
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { PublicConfigClass } from '@/packages/public'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { TextBarrageConfig } from './index'
|
||||
import { chartInitConfig } from '@/settings/designSetting'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
export enum FontWeightEnum {
|
||||
NORMAL = '常规',
|
||||
BOLD = '加粗',
|
||||
}
|
||||
|
||||
export const FontWeightObject = {
|
||||
[FontWeightEnum.NORMAL]: 'normal',
|
||||
[FontWeightEnum.BOLD]: 'bold',
|
||||
}
|
||||
|
||||
export const option = {
|
||||
|
||||
dataset: '让数字化看得见',
|
||||
fontSize: 32,
|
||||
fontColor: '#ffffff',
|
||||
fontWeight: 'normal',
|
||||
// 字间距
|
||||
letterSpacing: 5,
|
||||
//阴影
|
||||
showShadow: true,
|
||||
boxShadow: 'none',
|
||||
hShadow: 0,
|
||||
vShadow: 0,
|
||||
blurShadow: 8,
|
||||
colorShadow: '#0075ff',
|
||||
//动画
|
||||
animationTime: 0,
|
||||
animationSpeed: 50,
|
||||
}
|
||||
|
||||
export default class Config extends PublicConfigClass implements CreateComponentType {
|
||||
public key = TextBarrageConfig.key
|
||||
public attr = { ...chartInitConfig, w: 500, h: 70, zIndex: -1 }
|
||||
public chartConfig = cloneDeep(TextBarrageConfig)
|
||||
public option = cloneDeep(option)
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<collapse-item name="信息" :expanded="true">
|
||||
<setting-item-box name="文字" :alone="true">
|
||||
<setting-item>
|
||||
<n-input v-model:value="optionData.dataset" size="small"></n-input>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</collapse-item>
|
||||
|
||||
<collapse-item name="样式" :expanded="true">
|
||||
<setting-item-box name="文字">
|
||||
<setting-item name="颜色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.fontColor"></n-color-picker>
|
||||
</setting-item>
|
||||
<setting-item name="字体大小">
|
||||
<n-input-number v-model:value="optionData.fontSize" size="small" placeholder="字体大小"></n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="字体粗细">
|
||||
<n-select v-model:value="optionData.fontWeight" size="small" :options="fontWeightOptions" />
|
||||
</setting-item>
|
||||
|
||||
<setting-item name="字间距">
|
||||
<n-input-number v-model:value="optionData.letterSpacing" size="small" placeholder="输入字间距"></n-input-number>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
<setting-item-box name="阴影">
|
||||
<setting-item>
|
||||
<n-space>
|
||||
<n-switch v-model:value="optionData.showShadow" size="small" />
|
||||
<n-text>展示阴影</n-text>
|
||||
</n-space>
|
||||
</setting-item>
|
||||
<setting-item name="颜色">
|
||||
<n-color-picker size="small" :modes="['hex']" v-model:value="optionData.colorShadow"></n-color-picker
|
||||
></setting-item>
|
||||
<setting-item name="x">
|
||||
<n-input-number v-model:value="optionData.hShadow" size="small"></n-input-number
|
||||
></setting-item>
|
||||
<setting-item name="y">
|
||||
<n-input-number v-model:value="optionData.vShadow" size="small"></n-input-number
|
||||
></setting-item>
|
||||
<setting-item name="模糊">
|
||||
<n-input-number v-model:value="optionData.blurShadow" size="small"></n-input-number
|
||||
></setting-item>
|
||||
</setting-item-box>
|
||||
|
||||
<setting-item-box name="动画">
|
||||
<setting-item name="动画速度">
|
||||
<n-input-number
|
||||
v-model:value="optionData.animationSpeed"
|
||||
size="small"
|
||||
placeholder="动画速度"
|
||||
:min="0"
|
||||
></n-input-number>
|
||||
</setting-item>
|
||||
<setting-item name="动画间隔">
|
||||
<n-input-number
|
||||
v-model:value="optionData.animationTime"
|
||||
size="small"
|
||||
placeholder="动画间隔"
|
||||
:min="0"
|
||||
></n-input-number>
|
||||
</setting-item>
|
||||
</setting-item-box>
|
||||
</collapse-item>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType } from 'vue'
|
||||
import { option, FontWeightEnum, FontWeightObject } from './config'
|
||||
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
|
||||
const props = defineProps({
|
||||
optionData: {
|
||||
type: Object as PropType<typeof option>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const fontWeightOptions = [
|
||||
{
|
||||
label: FontWeightEnum.NORMAL,
|
||||
value: FontWeightObject[FontWeightEnum.NORMAL]
|
||||
},
|
||||
{
|
||||
label: FontWeightEnum.BOLD,
|
||||
value: FontWeightObject[FontWeightEnum.BOLD]
|
||||
}
|
||||
]
|
||||
</script>
|
||||
@@ -0,0 +1,14 @@
|
||||
import image from '@/assets/images/chart/informations/text_barrage.png'
|
||||
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
|
||||
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
|
||||
|
||||
export const TextBarrageConfig: ConfigType = {
|
||||
key: 'TextBarrage',
|
||||
chartKey: 'VTextBarrage',
|
||||
conKey: 'VCTextBarrage',
|
||||
title: '弹幕文字',
|
||||
category: ChatCategoryEnum.TEXT,
|
||||
categoryName: ChatCategoryEnumName.TEXT,
|
||||
package: PackagesCategoryEnum.INFORMATIONS,
|
||||
image
|
||||
}
|
||||
102
src/packages/components/Informations/Texts/TextBarrage/index.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div class="go-text-box">
|
||||
<div class="content">
|
||||
<span>
|
||||
{{ option.dataset }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PropType, toRefs, shallowReactive, watch, computed, ref } from 'vue'
|
||||
import { CreateComponentType } from '@/packages/index.d'
|
||||
import { useChartDataFetch } from '@/hooks'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { option as configOption } from './config'
|
||||
import { values } from 'lodash'
|
||||
|
||||
const props = defineProps({
|
||||
chartConfig: {
|
||||
type: Object as PropType<CreateComponentType & typeof option>,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const { w } = toRefs(props.chartConfig.attr)
|
||||
|
||||
const { fontColor, fontSize, letterSpacing, fontWeight, animationTime, animationSpeed, boxShadow } = toRefs(
|
||||
props.chartConfig.option
|
||||
)
|
||||
|
||||
const option = shallowReactive({
|
||||
dataset: configOption.dataset
|
||||
})
|
||||
|
||||
// 手动更新
|
||||
watch(
|
||||
() => props.chartConfig.option.dataset,
|
||||
(newData: any) => {
|
||||
option.dataset = newData
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: false
|
||||
}
|
||||
)
|
||||
|
||||
//阴影
|
||||
watch(
|
||||
props.chartConfig.option,
|
||||
() => {
|
||||
try {
|
||||
if (props.chartConfig.option.showShadow) {
|
||||
boxShadow.value = `${props.chartConfig.option.hShadow}px ${props.chartConfig.option.vShadow}px ${props.chartConfig.option.blurShadow}px ${props.chartConfig.option.colorShadow}`
|
||||
} else {
|
||||
boxShadow.value = 'none'
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
const transitionDuration = computed(() => {
|
||||
return Math.floor((w.value as any) / (animationSpeed.value as any))
|
||||
})
|
||||
|
||||
// 预览更新
|
||||
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: string) => {
|
||||
option.dataset = newData
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@include go('text-box') {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.content {
|
||||
width: 100%;
|
||||
color: v-bind('fontColor');
|
||||
font-size: v-bind('fontSize + "px"');
|
||||
letter-spacing: v-bind('letterSpacing + "px"');
|
||||
font-weight: v-bind('fontWeight');
|
||||
text-shadow: v-bind('boxShadow');
|
||||
position: absolute;
|
||||
animation: barrage v-bind('transitionDuration + "s"') linear v-bind('animationTime + "s"') infinite;
|
||||
}
|
||||
@keyframes barrage {
|
||||
from {
|
||||
left: 100%;
|
||||
transform: translateX(0);
|
||||
}
|
||||
to {
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TextCommonConfig } from './TextCommon/index'
|
||||
import { TextBarrageConfig } from './TextBarrage/index'
|
||||
import { TextGradientConfig } from './TextGradient/index'
|
||||
|
||||
export default [TextCommonConfig, TextGradientConfig]
|
||||
export default [TextCommonConfig, TextGradientConfig, TextBarrageConfig]
|
||||
|
||||
9
src/packages/index.d.ts
vendored
@@ -96,13 +96,6 @@ export enum EventLife {
|
||||
MOUNTED = 'vnodeMounted',
|
||||
// 渲染之前
|
||||
BEFORE_MOUNT = 'vnodeBeforeMount',
|
||||
// 鼠标事件
|
||||
MOUSE_CLICK = 'click',
|
||||
MOUSE_OVER = "mouseover",
|
||||
MOUSE_LEAVE = "mouseleave",
|
||||
// 图表事件
|
||||
ECHART_LEGEND_SELECT_CHANGED = "legendselectchanged",
|
||||
ECHART_HIGH_LIGHT = "highlight"
|
||||
}
|
||||
|
||||
// 组件实例类
|
||||
@@ -138,7 +131,7 @@ export interface PublicConfigType {
|
||||
export interface CreateComponentType extends PublicConfigType, requestConfig {
|
||||
key: string
|
||||
chartConfig: ConfigType
|
||||
option: GlobalThemeJsonType
|
||||
option: GlobalThemeJsonType,
|
||||
}
|
||||
|
||||
// 组件成组实例类
|
||||
|
||||
@@ -8,10 +8,7 @@ import { SketchRule } from 'vue3-sketch-ruler'
|
||||
* @param app
|
||||
*/
|
||||
export function setupCustomComponents(app: App) {
|
||||
// 骨架屏
|
||||
app.component('GoSkeleton', GoSkeleton)
|
||||
// 加载
|
||||
app.component('GoLoading', GoLoading)
|
||||
// 标尺
|
||||
app.component('SketchRule', SketchRule)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
LockClosedOutline as LockClosedOutlineIcon,
|
||||
HelpCircleOutline as HelpOutlineIcon,
|
||||
CodeSlash as CodeSlashIcon,
|
||||
Create as CreateIcon,
|
||||
Rocket as RocketIcon,
|
||||
Duplicate as DuplicateIcon,
|
||||
DuplicateOutline as DuplicateOutlineIcon,
|
||||
@@ -53,7 +54,6 @@ import {
|
||||
ArrowForward as ArrowForwardIcon,
|
||||
Planet as PawIcon,
|
||||
Search as SearchIcon,
|
||||
Reload as ReloadIcon,
|
||||
ChevronUpOutline as ChevronUpOutlineIcon,
|
||||
ChevronDownOutline as ChevronDownOutlineIcon,
|
||||
Pulse as PulseIcon,
|
||||
@@ -92,7 +92,6 @@ import {
|
||||
FitToScreen as FitToScreenIcon,
|
||||
FitToHeight as FitToHeightIcon,
|
||||
FitToWidth as FitToWidthIcon,
|
||||
Save as SaveIcon,
|
||||
Carbon3DCursor as Carbon3DCursorIcon,
|
||||
Carbon3DSoftware as Carbon3DSoftwareIcon,
|
||||
Filter as FilterIcon,
|
||||
@@ -108,6 +107,8 @@ const ionicons5 = {
|
||||
DuplicateOutlineIcon,
|
||||
// 代码
|
||||
CodeSlashIcon,
|
||||
// 修改代码
|
||||
CreateIcon,
|
||||
// 事件(火箭)
|
||||
RocketIcon,
|
||||
// 退出
|
||||
@@ -207,8 +208,6 @@ const ionicons5 = {
|
||||
PawIcon,
|
||||
// 搜索(放大镜)
|
||||
SearchIcon,
|
||||
// 加载
|
||||
ReloadIcon,
|
||||
// 过滤器
|
||||
FilterIcon,
|
||||
// 向上
|
||||
@@ -274,8 +273,6 @@ const carbon = {
|
||||
FitToScreenIcon,
|
||||
FitToHeightIcon,
|
||||
FitToWidthIcon,
|
||||
// 保存
|
||||
SaveIcon,
|
||||
// 成组
|
||||
Carbon3DCursorIcon,
|
||||
// 解组
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { RouteRecordRaw } from 'vue-router'
|
||||
import type { AppRouteRecordRaw } from '@/router/types';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout, RedirectHome, RedirectUnPublish } from '@/router/constant';
|
||||
import { ErrorPage404, ErrorPage403, ErrorPage500, Layout } from '@/router/constant';
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { GoReload } from '@/components/GoReload'
|
||||
|
||||
|
||||
export const LoginRoute: RouteRecordRaw = {
|
||||
path: PageEnum.BASE_LOGIN,
|
||||
name: PageEnum.BASE_LOGIN_NAME,
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
meta: {
|
||||
title: '登录',
|
||||
@@ -60,21 +60,22 @@ export const ReloadRoute: AppRouteRecordRaw = {
|
||||
},
|
||||
}
|
||||
|
||||
export const RedirectRoute: RouteRecordRaw[] = [
|
||||
{
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: RedirectHome,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
},
|
||||
export const RedirectRoute: AppRouteRecordRaw = {
|
||||
path: PageEnum.REDIRECT,
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: Layout,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
},
|
||||
{
|
||||
path: PageEnum.REDIRECT_UN_PUBLISH,
|
||||
name: PageEnum.REDIRECT_UN_PUBLISH_NAME,
|
||||
component: RedirectUnPublish,
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_UN_PUBLISH_NAME,
|
||||
children: [
|
||||
{
|
||||
path: '/redirect/:path(.*)',
|
||||
name: PageEnum.REDIRECT_NAME,
|
||||
component: () => import('@/views/redirect/index.vue'),
|
||||
meta: {
|
||||
title: PageEnum.REDIRECT_NAME,
|
||||
hideBreadcrumb: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,10 +4,6 @@ export const ErrorPage403 = () => import('@/views/exception/403.vue');
|
||||
|
||||
export const ErrorPage500 = () => import('@/views/exception/500.vue');
|
||||
|
||||
export const RedirectHome = () => import('@/views/redirect/index.vue');
|
||||
|
||||
export const RedirectUnPublish = () => import('@/views/redirect/UnPublish.vue');
|
||||
|
||||
export const Layout = () => import('@/layout/index.vue');
|
||||
|
||||
export const ParentLayout = () => import('@/layout/parentLayout.vue');
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { App } from 'vue'
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import { RedirectRoute } from '@/router/base'
|
||||
import { createRouterGuards } from './router-guards'
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { HttpErrorPage, LoginRoute, ReloadRoute, RedirectRoute } from '@/router/base'
|
||||
import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base'
|
||||
import { Layout } from '@/router/constant'
|
||||
|
||||
import modules from '@/router/modules'
|
||||
@@ -18,16 +19,16 @@ const RootRoute: Array<RouteRecordRaw> = [
|
||||
},
|
||||
children: [
|
||||
...HttpErrorPage,
|
||||
...RedirectRoute,
|
||||
modules.projectRoutes,
|
||||
modules.chartRoutes,
|
||||
modules.previewRoutes
|
||||
modules.previewRoutes,
|
||||
modules.editRoutes
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
export const constantRouter: any[] = [LoginRoute, ...RootRoute, ReloadRoute];
|
||||
export const constantRouter: any[] = [LoginRoute, ...RootRoute, RedirectRoute, ReloadRoute];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(''),
|
||||
|
||||
@@ -12,7 +12,8 @@ const chartRoutes: RouteRecordRaw = {
|
||||
component: importPath['ChartEnum.CHART_HOME_NAME'],
|
||||
meta: {
|
||||
title: '工作空间',
|
||||
isRoot: true
|
||||
isRoot: true,
|
||||
noKeepAlive: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
src/router/modules/edit.route.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { RouteRecordRaw } from 'vue-router'
|
||||
import { EditEnum } from '@/enums/pageEnum'
|
||||
|
||||
// 引入路径
|
||||
const importPath = {
|
||||
[EditEnum.CHART_EDIT_NAME]: () => import('@/views/edit/index.vue')
|
||||
}
|
||||
|
||||
const chartRoutes: RouteRecordRaw = {
|
||||
path: EditEnum.CHART_EDIT,
|
||||
name: EditEnum.CHART_EDIT_NAME,
|
||||
component: importPath[EditEnum.CHART_EDIT_NAME],
|
||||
meta: {
|
||||
title: '编辑',
|
||||
isRoot: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default chartRoutes
|
||||
@@ -1,9 +1,11 @@
|
||||
import projectRoutes from './project.router'
|
||||
import chartRoutes from './chart.route'
|
||||
import previewRoutes from './preview.route'
|
||||
import editRoutes from './edit.route'
|
||||
|
||||
export default {
|
||||
projectRoutes,
|
||||
chartRoutes,
|
||||
previewRoutes
|
||||
previewRoutes,
|
||||
editRoutes
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { PreviewEnum } from '@/enums/pageEnum'
|
||||
|
||||
// 引入路径
|
||||
const importPath = {
|
||||
'PreviewEnum.CHART_PREVIEW_NAME': () => import('@/views/preview/index.vue')
|
||||
'PreviewEnum.CHART_PREVIEW_NAME': () => import('@/views/preview/wrapper.vue')
|
||||
}
|
||||
|
||||
const chartRoutes: RouteRecordRaw = {
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { Router } from 'vue-router';
|
||||
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import { loginCheck } from '@/utils'
|
||||
|
||||
// 路由白名单
|
||||
const routerAllowList = [
|
||||
// 登录
|
||||
PageEnum.BASE_LOGIN_NAME,
|
||||
// 预览
|
||||
PreviewEnum.CHART_PREVIEW_NAME
|
||||
]
|
||||
|
||||
export function createRouterGuards(router: Router) {
|
||||
// 前置
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
@@ -18,13 +10,13 @@ export function createRouterGuards(router: Router) {
|
||||
const isErrorPage = router.getRoutes().findIndex((item) => item.name === to.name);
|
||||
if (isErrorPage === -1) {
|
||||
next({ name: PageEnum.ERROR_PAGE_NAME_404 })
|
||||
return
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (!routerAllowList.includes(to.name) && !loginCheck()) {
|
||||
if (!loginCheck()) {
|
||||
if (to.name === PageEnum.BASE_LOGIN_NAME) {
|
||||
next()
|
||||
}
|
||||
next({ name: PageEnum.BASE_LOGIN_NAME })
|
||||
return
|
||||
}
|
||||
next()
|
||||
})
|
||||
|
||||
@@ -11,7 +11,6 @@ export const animations = [
|
||||
{ label: '放大晃动缩小', value: 'tada' },
|
||||
{ label: '扇形摇摆', value: 'wobble' },
|
||||
{ label: '左右上下晃动', value: 'jello' },
|
||||
{ label: 'Y轴旋转', value: 'flip' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -55,11 +55,11 @@ export const backgroundImageSize = 5
|
||||
// 预览展示方式
|
||||
export const previewScaleType = PreviewScaleEnum.FIT
|
||||
|
||||
// 数据请求间隔(s)
|
||||
export const requestInterval = 30
|
||||
// 编辑工作台同步到 JSON 的轮询间隔(5S)
|
||||
export const editToJsonInterval = 5000
|
||||
|
||||
// 工作台自动保存间隔(s)
|
||||
export const saveInterval = 30
|
||||
// 数据请求间隔
|
||||
export const requestInterval = 30
|
||||
|
||||
// 数据请求间隔单位
|
||||
export const requestIntervalUnit = RequestHttpIntervalEnum.SECOND
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
// 请求前缀
|
||||
export const axiosPre = '/api/goview'
|
||||
@@ -1,10 +1,10 @@
|
||||
// * 外部路径地址
|
||||
|
||||
// 项目文档地址
|
||||
export const docPath = "http://www.mtruning.club:81/"
|
||||
export const docPath = "https://www.mtruning.club/"
|
||||
|
||||
// 项目源码
|
||||
export const giteeSourceCodePath = "https://gitee.com/MTrun/go-view/"
|
||||
export const giteeSourceCodePath = "https://gitee.com/dromara/go-view"
|
||||
|
||||
// 赞助
|
||||
export const sponsorPath = "http://www.mtruning.club:81/more/sponsor.html"
|
||||
export const sponsorPath = "https://www.mtruning.club/sponsor/"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { App } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
|
||||
const store = createPinia();
|
||||
const pinia = createPinia();
|
||||
|
||||
export function setupStore(app: App<Element>) {
|
||||
app.use(store);
|
||||
app.use(pinia);
|
||||
}
|
||||
|
||||
export { store };
|
||||
export { pinia };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { CreateComponentType, CreateComponentGroupType, FilterEnum } from '@/packages/index.d'
|
||||
import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { SyncEnum } from '@/enums/editPageEnum'
|
||||
import {
|
||||
RequestHttpEnum,
|
||||
RequestContentTypeEnum,
|
||||
@@ -13,29 +12,6 @@ import {
|
||||
import { PreviewScaleEnum } from '@/enums/styleEnum'
|
||||
import type { ChartColorsNameType, GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||
|
||||
// 项目数据枚举
|
||||
export enum ProjectInfoEnum {
|
||||
// ID
|
||||
PROJECT_ID = "projectId",
|
||||
// 名称
|
||||
PROJECT_NAME = 'projectName',
|
||||
// 描述
|
||||
REMARKS = 'remarks',
|
||||
// 缩略图
|
||||
THUMBNAIL= 'thumbnail',
|
||||
// 是否公开发布
|
||||
RELEASE = 'release'
|
||||
}
|
||||
|
||||
// 项目数据
|
||||
export type ProjectInfoType = {
|
||||
[ProjectInfoEnum.PROJECT_ID]: string,
|
||||
[ProjectInfoEnum.PROJECT_NAME]: string,
|
||||
[ProjectInfoEnum.REMARKS]: string,
|
||||
[ProjectInfoEnum.THUMBNAIL]: string,
|
||||
[ProjectInfoEnum.RELEASE]: boolean
|
||||
}
|
||||
|
||||
// 编辑画布属性
|
||||
export enum EditCanvasTypeEnum {
|
||||
EDIT_LAYOUT_DOM = 'editLayoutDom',
|
||||
@@ -44,13 +20,12 @@ export enum EditCanvasTypeEnum {
|
||||
SCALE = 'scale',
|
||||
USER_SCALE = 'userScale',
|
||||
LOCK_SCALE = 'lockScale',
|
||||
SAVE_STATUS = 'saveStatus',
|
||||
IS_CREATE = 'isCreate',
|
||||
IS_DRAG = 'isDrag',
|
||||
IS_SELECT = 'isSelect'
|
||||
}
|
||||
|
||||
// 编辑区域(临时)
|
||||
// 编辑区域
|
||||
export type EditCanvasType = {
|
||||
// 编辑区域 DOM
|
||||
[EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null
|
||||
@@ -67,13 +42,11 @@ export type EditCanvasType = {
|
||||
[EditCanvasTypeEnum.IS_CREATE]: boolean
|
||||
// 拖拽中
|
||||
[EditCanvasTypeEnum.IS_DRAG]: boolean
|
||||
// 保存状态
|
||||
[EditCanvasTypeEnum.SAVE_STATUS]: SyncEnum
|
||||
// 框选中
|
||||
[EditCanvasTypeEnum.IS_SELECT]: boolean
|
||||
}
|
||||
|
||||
// 画布数据/滤镜/背景色/宽高主题等
|
||||
// 滤镜/背景色/宽高主题等
|
||||
export enum EditCanvasConfigEnum {
|
||||
WIDTH = 'width',
|
||||
HEIGHT = 'height',
|
||||
@@ -85,14 +58,7 @@ export enum EditCanvasConfigEnum {
|
||||
PREVIEW_SCALE_TYPE = 'previewScaleType'
|
||||
}
|
||||
|
||||
// 画布属性(需保存)
|
||||
export type EditCanvasConfigType = {
|
||||
// ID
|
||||
[EditCanvasConfigEnum.PROJECT_ID]: string,
|
||||
// 项目名称
|
||||
[EditCanvasConfigEnum.PROJECT_NAME]: string,
|
||||
// 项目描述
|
||||
[EditCanvasConfigEnum.REMARKS]: string,
|
||||
export interface EditCanvasConfigType {
|
||||
// 滤镜-启用
|
||||
[FilterEnum.FILTERS_SHOW]: boolean
|
||||
// 滤镜-色相
|
||||
@@ -164,7 +130,6 @@ export type RecordChartType = {
|
||||
|
||||
// Store 枚举
|
||||
export enum ChartEditStoreEnum {
|
||||
PROJECT_INFO = 'projectInfo',
|
||||
EDIT_RANGE = 'editRange',
|
||||
EDIT_CANVAS = 'editCanvas',
|
||||
RIGHT_MENU_SHOW = 'rightMenuShow',
|
||||
@@ -215,7 +180,6 @@ export interface RequestConfigType extends RequestPublicConfigType {
|
||||
|
||||
// Store 类型
|
||||
export interface ChartEditStoreType {
|
||||
[ChartEditStoreEnum.PROJECT_INFO]: ProjectInfoType
|
||||
[ChartEditStoreEnum.EDIT_CANVAS]: EditCanvasType
|
||||
[ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: EditCanvasConfigType
|
||||
[ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean
|
||||
|
||||
@@ -10,22 +10,14 @@ import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settin
|
||||
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
|
||||
// 全局设置
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
// 历史类型
|
||||
import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
// 画布枚举
|
||||
import { MenuEnum, SyncEnum } from '@/enums/editPageEnum'
|
||||
|
||||
import {
|
||||
getUUID,
|
||||
loadingStart,
|
||||
loadingFinish,
|
||||
loadingError,
|
||||
isString,
|
||||
isArray
|
||||
} from '@/utils'
|
||||
|
||||
HistoryActionTypeEnum,
|
||||
HistoryItemType,
|
||||
HistoryTargetTypeEnum
|
||||
} from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
|
||||
import { MenuEnum } from '@/enums/editPageEnum'
|
||||
import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils'
|
||||
import {
|
||||
ProjectInfoType,
|
||||
ChartEditStoreEnum,
|
||||
ChartEditStorage,
|
||||
ChartEditStoreType,
|
||||
@@ -44,14 +36,6 @@ const settingStore = useSettingStore()
|
||||
export const useChartEditStore = defineStore({
|
||||
id: 'useChartEditStore',
|
||||
state: (): ChartEditStoreType => ({
|
||||
// 项目数据
|
||||
projectInfo: {
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
remarks: '',
|
||||
thumbnail: '',
|
||||
release: false
|
||||
},
|
||||
// 画布属性
|
||||
editCanvas: {
|
||||
// 编辑区域 Dom
|
||||
@@ -70,9 +54,7 @@ export const useChartEditStore = defineStore({
|
||||
// 拖拽中
|
||||
isDrag: false,
|
||||
// 框选中
|
||||
isSelect: false,
|
||||
// 同步中
|
||||
saveStatus: SyncEnum.PENDING
|
||||
isSelect: false
|
||||
},
|
||||
// 右键菜单
|
||||
rightMenuShow: false,
|
||||
@@ -149,9 +131,6 @@ export const useChartEditStore = defineStore({
|
||||
componentList: []
|
||||
}),
|
||||
getters: {
|
||||
getProjectInfo(): ProjectInfoType {
|
||||
return this.projectInfo
|
||||
},
|
||||
getMousePosition(): MousePositionType {
|
||||
return this.mousePosition
|
||||
},
|
||||
@@ -186,10 +165,6 @@ export const useChartEditStore = defineStore({
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// * 设置 peojectInfo 数据项
|
||||
setProjectInfo<T extends keyof ProjectInfoType, K extends ProjectInfoType[T]>(key: T, value: K) {
|
||||
this.projectInfo[key] = value
|
||||
},
|
||||
// * 设置 editCanvas 数据项
|
||||
setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) {
|
||||
this.editCanvas[key] = value
|
||||
|
||||
@@ -6,10 +6,8 @@ import i18n from '@/i18n/index'
|
||||
import { setLocalStorage, getLocalStorage, reloadRoutePage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const { GO_LANG_STORE } = StorageEnum
|
||||
|
||||
const storageLang: LangStateType = getLocalStorage(GO_LANG_STORE)
|
||||
|
||||
// 语言
|
||||
@@ -17,7 +15,7 @@ export const useLangStore = defineStore({
|
||||
id: 'useLangStore',
|
||||
state: (): LangStateType =>
|
||||
storageLang || {
|
||||
lang,
|
||||
lang
|
||||
},
|
||||
getters: {
|
||||
getLang(): LangEnum {
|
||||
@@ -26,6 +24,8 @@ export const useLangStore = defineStore({
|
||||
},
|
||||
actions: {
|
||||
changeLang(lang: LangEnum): void {
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
if (this.lang === lang) return
|
||||
this.lang = lang
|
||||
i18n.global.locale = lang
|
||||
|
||||
31
src/store/modules/systemStore/systemStore.d.ts
vendored
@@ -1,31 +0,0 @@
|
||||
export enum SystemStoreUserInfoEnum {
|
||||
USER_TOKEN = 'userToken',
|
||||
TOKEN_NAME = 'tokenName',
|
||||
USER_ID = 'userId',
|
||||
USER_NAME = 'userName',
|
||||
NICK_NAME = 'nickName',
|
||||
}
|
||||
|
||||
export interface UserInfoType {
|
||||
[SystemStoreUserInfoEnum.USER_TOKEN]?: string,
|
||||
[SystemStoreUserInfoEnum.TOKEN_NAME]?: string,
|
||||
[SystemStoreUserInfoEnum.USER_ID]?: string,
|
||||
[SystemStoreUserInfoEnum.USER_NAME]?: string,
|
||||
[SystemStoreUserInfoEnum.NICK_NAME]?: string,
|
||||
}
|
||||
|
||||
export interface FetchInfoType {
|
||||
OSSUrl?: string,
|
||||
}
|
||||
|
||||
export enum SystemStoreEnum {
|
||||
// 用户
|
||||
USER_INFO = 'userInfo',
|
||||
// 请求
|
||||
FETCH_INFO = 'fetchInfo'
|
||||
}
|
||||
|
||||
export interface SystemStoreType {
|
||||
[SystemStoreEnum.USER_INFO]: UserInfoType
|
||||
[SystemStoreEnum.FETCH_INFO]: FetchInfoType
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { SystemStoreType, UserInfoType, FetchInfoType } from './systemStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
|
||||
const { GO_SYSTEM_STORE } = StorageEnum
|
||||
|
||||
const storageSystem: SystemStoreType = getLocalStorage(GO_SYSTEM_STORE)
|
||||
|
||||
// 系统数据记录
|
||||
export const useSystemStore = defineStore({
|
||||
id: 'useSystemStore',
|
||||
state: (): SystemStoreType => storageSystem || {
|
||||
userInfo: {
|
||||
userId: undefined,
|
||||
userName: undefined,
|
||||
userToken: undefined,
|
||||
nickName: undefined
|
||||
},
|
||||
fetchInfo: {
|
||||
OSSUrl: undefined
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
getUserInfo(): UserInfoType {
|
||||
return this.userInfo
|
||||
},
|
||||
getFetchInfo(): FetchInfoType {
|
||||
return this.fetchInfo
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setItem<T extends keyof SystemStoreType, K extends SystemStoreType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
});
|
||||
setLocalStorage(GO_SYSTEM_STORE, this.$state)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1 +1,9 @@
|
||||
// 页面全局样式
|
||||
// 页面全局样式
|
||||
// 去除高德地图 logo
|
||||
.amap-logo {
|
||||
display: none !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.amap-copyright {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||