mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 00:26:20 +08:00
Compare commits
547 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5d8d9786e3 | ||
![]() |
2cca7e8bfb | ||
![]() |
74ded8aed7 | ||
![]() |
d620758c2f | ||
![]() |
f2ec2ca273 | ||
![]() |
b66a83c10f | ||
![]() |
7bbb86249b | ||
![]() |
b0a45d4739 | ||
![]() |
1095d44110 | ||
![]() |
e938e8e9a8 | ||
![]() |
3b0077dc73 | ||
![]() |
3de5b53bcd | ||
![]() |
d7f5dfeb9f | ||
![]() |
85bc1f2340 | ||
![]() |
edede25c8f | ||
![]() |
6da30edef5 | ||
![]() |
d9286b5345 | ||
![]() |
8d218ec8d5 | ||
![]() |
72dbe574d3 | ||
![]() |
4c91ac11e2 | ||
![]() |
ce480c5d66 | ||
![]() |
7f5e415da9 | ||
![]() |
714a351036 | ||
![]() |
a78c3a305b | ||
![]() |
bb8c2dea40 | ||
![]() |
dce3aba20d | ||
![]() |
256e0275fe | ||
![]() |
c70cf3cace | ||
![]() |
4f4bec0c22 | ||
![]() |
491941e4c5 | ||
![]() |
f1678a7cc0 | ||
![]() |
ed8cffb2a1 | ||
![]() |
8284d106e2 | ||
![]() |
de305ecd47 | ||
![]() |
a222404220 | ||
![]() |
5335ae7578 | ||
![]() |
f32d2715ef | ||
![]() |
fb73be0928 | ||
![]() |
c2a159155c | ||
![]() |
70ee1c8403 | ||
![]() |
7346988622 | ||
![]() |
d6fdfd9f93 | ||
![]() |
d88915bac3 | ||
![]() |
a1b9bbc2ce | ||
![]() |
64d6fece08 | ||
![]() |
be3d98fa3d | ||
![]() |
ce0f528ba8 | ||
![]() |
085929a9c0 | ||
![]() |
de4eaddffd | ||
![]() |
e1804bd866 | ||
![]() |
334a0ea8e5 | ||
![]() |
bce6cee53a | ||
![]() |
32daad6198 | ||
![]() |
a4a5a44009 | ||
![]() |
c5b39f2c16 | ||
![]() |
4c0f2038af | ||
![]() |
d25dfcc7c0 | ||
![]() |
8992ef472e | ||
![]() |
f7a1b02236 | ||
![]() |
0dc2f1496b | ||
![]() |
dab977ffbc | ||
![]() |
92cc603680 | ||
![]() |
d3ec7a58ad | ||
![]() |
83e529681a | ||
![]() |
4d6f24d053 | ||
![]() |
45b0be7f7e | ||
![]() |
c999abb236 | ||
![]() |
816fffe960 | ||
![]() |
0ad30503a7 | ||
![]() |
d02ab2d220 | ||
![]() |
6753e24b3d | ||
![]() |
b90d3572a9 | ||
![]() |
1657439569 | ||
![]() |
8dd8a5ed01 | ||
![]() |
f1717973c4 | ||
![]() |
0cc53558fb | ||
![]() |
7e77177ed8 | ||
![]() |
bb1fee5885 | ||
![]() |
53b2b23620 | ||
![]() |
4c67d8c388 | ||
![]() |
0ab2a541cb | ||
![]() |
4dc5385104 | ||
![]() |
26bd4aeba6 | ||
![]() |
61d6057fa4 | ||
![]() |
9090cee184 | ||
![]() |
31042de6bc | ||
![]() |
aabafe8610 | ||
![]() |
098621892d | ||
![]() |
582d7e7351 | ||
![]() |
ca487426a1 | ||
![]() |
2387dcdc6d | ||
![]() |
9435b480ab | ||
![]() |
8c2ba755c1 | ||
![]() |
c7639c4909 | ||
![]() |
6af828260e | ||
![]() |
5a9a8644d6 | ||
![]() |
0bb3b7f90d | ||
![]() |
87ee7cd27a | ||
![]() |
ce030d2d1d | ||
![]() |
43c8bf0d0b | ||
![]() |
bc099041ce | ||
![]() |
0629cc7b14 | ||
![]() |
4e16438494 | ||
![]() |
c5713c75ec | ||
![]() |
e7ac09cf39 | ||
![]() |
be4c98b980 | ||
![]() |
e013f04151 | ||
![]() |
3948ba1b01 | ||
![]() |
e74a9ed337 | ||
![]() |
750a50ebfd | ||
![]() |
6d1adce462 | ||
![]() |
d01c1b4d05 | ||
![]() |
6844f69c20 | ||
![]() |
057b82632b | ||
![]() |
908a2fbb3a | ||
![]() |
2d2a265418 | ||
![]() |
e05a009989 | ||
![]() |
7fad00cb77 | ||
![]() |
93d4655285 | ||
![]() |
448d21287c | ||
![]() |
31f489fa90 | ||
![]() |
640ac6217f | ||
![]() |
37c25a42f5 | ||
![]() |
cdb460897b | ||
![]() |
84df7a4bb2 | ||
![]() |
476b2b8acc | ||
![]() |
4041284345 | ||
![]() |
a12c5706e8 | ||
![]() |
6fa35521b7 | ||
![]() |
00c446efff | ||
![]() |
5539190c39 | ||
![]() |
384f929443 | ||
![]() |
9ba15705b5 | ||
![]() |
d16f6f8e44 | ||
![]() |
fc2e2c8789 | ||
![]() |
df0e0cbe69 | ||
![]() |
7dcb38cac6 | ||
![]() |
eda251a426 | ||
![]() |
17d16ae545 | ||
![]() |
9ae67bf9ca | ||
![]() |
8ba4fb2449 | ||
![]() |
1bafeb6638 | ||
![]() |
fd57b83db6 | ||
![]() |
513ccb9543 | ||
![]() |
e962fa039a | ||
![]() |
58b30aae9a | ||
![]() |
4f9cdc5634 | ||
![]() |
5292838fcd | ||
![]() |
fd9450304d | ||
![]() |
bc499744c0 | ||
![]() |
c8b169494f | ||
![]() |
c1d3a94371 | ||
![]() |
0eb1275c34 | ||
![]() |
e08a155c40 | ||
![]() |
c37a15fefb | ||
![]() |
7e4312ec1e | ||
![]() |
839271d70a | ||
![]() |
768fadbffb | ||
![]() |
9aa2cf3ebf | ||
![]() |
b1f78c6696 | ||
![]() |
dda27477af | ||
![]() |
1a8cdeb374 | ||
![]() |
5f0bf59a8b | ||
![]() |
1b7896c435 | ||
![]() |
d39e13270c | ||
![]() |
5cabd4a6eb | ||
![]() |
451371a812 | ||
![]() |
6faacd2d85 | ||
![]() |
61aefcaa65 | ||
![]() |
acfba7cccc | ||
![]() |
cb28986683 | ||
![]() |
a89ba204eb | ||
![]() |
a45208673a | ||
![]() |
39188780ea | ||
![]() |
99326342bc | ||
![]() |
dfe560a542 | ||
![]() |
692df33fd8 | ||
![]() |
9316d950b1 | ||
![]() |
5abb0f2b37 | ||
![]() |
e47c618b18 | ||
![]() |
2abc8275c6 | ||
![]() |
f1d42769ea | ||
![]() |
dac9301af4 | ||
![]() |
20c10df846 | ||
![]() |
b11df08aa4 | ||
![]() |
6e391af3fe | ||
![]() |
7925c1ea28 | ||
![]() |
442bd440ba | ||
![]() |
4a4321a77d | ||
![]() |
aee08b14fa | ||
![]() |
b9dee8595f | ||
![]() |
a753eb35cb | ||
![]() |
c001535b56 | ||
![]() |
9afb4318fd | ||
![]() |
baa42a57fd | ||
![]() |
6981b73ef6 | ||
![]() |
266c33819f | ||
![]() |
9c26ee1b9c | ||
![]() |
f305637366 | ||
![]() |
40071529d2 | ||
![]() |
6f5711b088 | ||
![]() |
bc55b92c9b | ||
![]() |
f1e8e241b1 | ||
![]() |
5833043d14 | ||
![]() |
35f2d074ae | ||
![]() |
c0e40fa01e | ||
![]() |
ddb678ddfa | ||
![]() |
91e13c4287 | ||
![]() |
de7279399d | ||
![]() |
a89e497e82 | ||
![]() |
0f50e0458e | ||
![]() |
4730b3af31 | ||
![]() |
740d160198 | ||
![]() |
aefde45ad5 | ||
![]() |
3cc72d6791 | ||
![]() |
fbcba766ae | ||
![]() |
1455eb48db | ||
![]() |
ba97f80d33 | ||
![]() |
0902de7504 | ||
![]() |
da8e0bdf91 | ||
![]() |
06236c9fe0 | ||
![]() |
2c536976e8 | ||
![]() |
c2e2ca9bed | ||
![]() |
02c469b17a | ||
![]() |
deff31bc5d | ||
![]() |
e09a797d05 | ||
![]() |
8a7d9bcd4d | ||
![]() |
934ccd34ea | ||
![]() |
85f1e58bcc | ||
![]() |
e073b4c944 | ||
![]() |
554f4615a1 | ||
![]() |
d21578ab33 | ||
![]() |
857af11ced | ||
![]() |
50468e9581 | ||
![]() |
19dc88b4e0 | ||
![]() |
cfbd52bbe7 | ||
![]() |
c0edd7b70e | ||
![]() |
fe5848cf21 | ||
![]() |
c3b5abc392 | ||
![]() |
a40332cbfe | ||
![]() |
42908a4535 | ||
![]() |
a0920d284d | ||
![]() |
419b7aea07 | ||
![]() |
e807539b80 | ||
![]() |
0634f2ca9e | ||
![]() |
d09e998ae7 | ||
![]() |
e097600003 | ||
![]() |
3ee7051950 | ||
![]() |
5ad93c6004 | ||
![]() |
ce7f382b9b | ||
![]() |
1832d0c07a | ||
![]() |
e05a40f680 | ||
![]() |
ee85839ba3 | ||
![]() |
d6a3eecbc2 | ||
![]() |
8932bf9a2d | ||
![]() |
9d4d78d2c9 | ||
![]() |
2d553f204a | ||
![]() |
3b86435766 | ||
![]() |
e3637e7af4 | ||
![]() |
b41e3939ac | ||
![]() |
23e0932883 | ||
![]() |
8f2008ac74 | ||
![]() |
2bf48e0f23 | ||
![]() |
c0441cf5c3 | ||
![]() |
b3f6b04981 | ||
![]() |
8d93e047d0 | ||
![]() |
fb43e54847 | ||
![]() |
1e0ede09a2 | ||
![]() |
823f7b3226 | ||
![]() |
28d73f95bd | ||
![]() |
418ca2405e | ||
![]() |
7c21eb9b3a | ||
![]() |
923ecdab3c | ||
![]() |
eb231120e1 | ||
![]() |
a343b49014 | ||
![]() |
28078d4263 | ||
![]() |
de266e538d | ||
![]() |
b85a11d0f0 | ||
![]() |
770574c9b0 | ||
![]() |
0c633ff67d | ||
![]() |
d31cb904db | ||
![]() |
a542317dc3 | ||
![]() |
e4305daf98 | ||
![]() |
10b59395b2 | ||
![]() |
1dca636521 | ||
![]() |
5db1250a8d | ||
![]() |
136cbb1e3b | ||
![]() |
78535bdd86 | ||
![]() |
aaa30fbf10 | ||
![]() |
9092c34cd5 | ||
![]() |
3d55b0d45b | ||
![]() |
573a443007 | ||
![]() |
79eb909c66 | ||
![]() |
927220933e | ||
![]() |
5a3a7633ac | ||
![]() |
414101613e | ||
![]() |
21bae3ad49 | ||
![]() |
b303f1bea3 | ||
![]() |
8f1bd4ae76 | ||
![]() |
5c24a1c4c4 | ||
![]() |
e91d757169 | ||
![]() |
4cda7c6fc1 | ||
![]() |
a23020b76d | ||
![]() |
af6ab98945 | ||
![]() |
ecc2135b5e | ||
![]() |
4e4ce944bc | ||
![]() |
b63f7d17de | ||
![]() |
67d514ad0e | ||
![]() |
929141be96 | ||
![]() |
e82bafa43e | ||
![]() |
5fc28f92d5 | ||
![]() |
5ac055be2f | ||
![]() |
266b566850 | ||
![]() |
a281631ae3 | ||
![]() |
f964533701 | ||
![]() |
dd158a17fe | ||
![]() |
c8d59a0bbc | ||
![]() |
2423aeab64 | ||
![]() |
1a43142252 | ||
![]() |
52e295f1d5 | ||
![]() |
de8ea59177 | ||
![]() |
1dc6faf3e6 | ||
![]() |
598ce5a1bf | ||
![]() |
8c607b38f1 | ||
![]() |
b84cc5eb06 | ||
![]() |
f015a874e2 | ||
![]() |
4f35b95b6b | ||
![]() |
46e28f0203 | ||
![]() |
aab6b4f393 | ||
![]() |
54ea44cdad | ||
![]() |
a462be0a5e | ||
![]() |
b639650397 | ||
![]() |
9217a12bcc | ||
![]() |
6b594aec53 | ||
![]() |
fa33c6b0d7 | ||
![]() |
a2b594c962 | ||
![]() |
0dafaa5972 | ||
![]() |
b0a0cbcd6a | ||
![]() |
f6e27aee16 | ||
![]() |
23b5538eae | ||
![]() |
ab62739fd1 | ||
![]() |
b70fade587 | ||
![]() |
05bad7b9dc | ||
![]() |
13d660bede | ||
![]() |
8523afd512 | ||
![]() |
8480454b73 | ||
![]() |
e024f6a6e7 | ||
![]() |
cb1759b257 | ||
![]() |
81560fd3c6 | ||
![]() |
170a4bceb1 | ||
![]() |
cfda62ef9c | ||
![]() |
16cd2438dd | ||
![]() |
2a667c9e7f | ||
![]() |
52257f061d | ||
![]() |
50cf2d0b8f | ||
![]() |
2aabbc788a | ||
![]() |
bc18ecb277 | ||
![]() |
413df9f5e1 | ||
![]() |
3fcfac1f37 | ||
![]() |
5fca9ce2c5 | ||
![]() |
dc4b05272f | ||
![]() |
b8411c9311 | ||
![]() |
4806aced85 | ||
![]() |
3b3f6c903a | ||
![]() |
b3c4002b69 | ||
![]() |
7e00488635 | ||
![]() |
090d844014 | ||
![]() |
013cb7f16b | ||
![]() |
c2b207dd51 | ||
![]() |
83921284a6 | ||
![]() |
59b309aa7e | ||
![]() |
49c890ebec | ||
![]() |
c8dd3b6c14 | ||
![]() |
9999650a9a | ||
![]() |
b5364fe546 | ||
![]() |
74b0dfd54f | ||
![]() |
642d48870c | ||
![]() |
3b63e41b68 | ||
![]() |
d6cdff97b6 | ||
![]() |
97fe8e2058 | ||
![]() |
5c491a4258 | ||
![]() |
5225345496 | ||
![]() |
a248e20013 | ||
![]() |
ed40b333f3 | ||
![]() |
b7813b9ba8 | ||
![]() |
dbcc40f5ea | ||
![]() |
acea184320 | ||
![]() |
0f44291c5c | ||
![]() |
83bce6c1d4 | ||
![]() |
85a68d5fc3 | ||
![]() |
a0165d1eee | ||
![]() |
8447331197 | ||
![]() |
787bc462e7 | ||
![]() |
89414f173e | ||
![]() |
34781d42e8 | ||
![]() |
456a661488 | ||
![]() |
5902886798 | ||
![]() |
7a1b6e74ab | ||
![]() |
b653412260 | ||
![]() |
a530ec867b | ||
![]() |
d6f65d476e | ||
![]() |
052eff91c4 | ||
![]() |
e1cbe23e96 | ||
![]() |
f3f56288af | ||
![]() |
473e56e4e0 | ||
![]() |
eac2fb4aaa | ||
![]() |
7d40773b5b | ||
![]() |
935d4fc12d | ||
![]() |
2849743a4d | ||
![]() |
437211107f | ||
![]() |
2f2526c564 | ||
![]() |
754d1986e9 | ||
![]() |
034e39ef06 | ||
![]() |
bfdbccfece | ||
![]() |
246c5f795b | ||
![]() |
902d38dc2f | ||
![]() |
1abf7fdf5f | ||
![]() |
96ce18c073 | ||
![]() |
f8102446d0 | ||
![]() |
07b17b9798 | ||
![]() |
452b2599f4 | ||
![]() |
7028e0031d | ||
![]() |
6e0c70f415 | ||
![]() |
01b667facf | ||
![]() |
a82a69d00d | ||
![]() |
8b00112d5a | ||
![]() |
853bde9275 | ||
![]() |
5af452754b | ||
![]() |
9c5f11a54b | ||
![]() |
6c08dae921 | ||
![]() |
02eabe1f9f | ||
![]() |
2875a97b70 | ||
![]() |
067753d490 | ||
![]() |
7b6d5e44a9 | ||
![]() |
e85649bde2 | ||
![]() |
cecdfbaf29 | ||
![]() |
84c7d516df | ||
![]() |
15ea0d2f53 | ||
![]() |
ba2c1a3bf5 | ||
![]() |
2346a90c08 | ||
![]() |
6544f84bc2 | ||
![]() |
2aa5e5da76 | ||
![]() |
44b21bfc6c | ||
![]() |
2820d5a627 | ||
![]() |
9640484895 | ||
![]() |
f87b0f2f5e | ||
![]() |
656ee4e5c9 | ||
![]() |
7593ef6a4f | ||
![]() |
b3307fe283 | ||
![]() |
73dc492b2a | ||
![]() |
0bb9c035f7 | ||
![]() |
9e9ea3f43d | ||
![]() |
996f2f3c22 | ||
![]() |
b90a9557a3 | ||
![]() |
7df9b51344 | ||
![]() |
c753d945e0 | ||
![]() |
83c1683bfd | ||
![]() |
044e2e4e86 | ||
![]() |
59a9087728 | ||
![]() |
3b6b4f7303 | ||
![]() |
5fa730c49a | ||
![]() |
6cadcf087d | ||
![]() |
95aca2ab8d | ||
![]() |
e00578c40a | ||
![]() |
6717fe654e | ||
![]() |
ee7c31db44 | ||
![]() |
a36825a6d4 | ||
![]() |
628e820684 | ||
![]() |
0f5ddbf1ec | ||
![]() |
1ddfc31c3c | ||
![]() |
d27633fb31 | ||
![]() |
30fa4cfa2a | ||
![]() |
6e7f6f82ed | ||
![]() |
466d4edcd0 | ||
![]() |
0b0a7ceef9 | ||
![]() |
99daecdb60 | ||
![]() |
c8017b1365 | ||
![]() |
d8362f084f | ||
![]() |
9f6822991c | ||
![]() |
56a966cfbf | ||
![]() |
2884e863ce | ||
![]() |
1235978ab2 | ||
![]() |
9dd9fcd334 | ||
![]() |
a426b9027e | ||
![]() |
455d109f71 | ||
![]() |
6e85795737 | ||
![]() |
d1f59b493d | ||
![]() |
edc3096565 | ||
![]() |
3a5d1a5757 | ||
![]() |
2c867b3d63 | ||
![]() |
fb43fad555 | ||
![]() |
8e01377481 | ||
![]() |
e7c96363a1 | ||
![]() |
93812f734e | ||
![]() |
e15b4f14db | ||
![]() |
a5ff59237f | ||
![]() |
65735926d4 | ||
![]() |
47a448b8ae | ||
![]() |
5138e447e7 | ||
![]() |
837a365885 | ||
![]() |
43658e2fb3 | ||
![]() |
8fa6015b1a | ||
![]() |
91cbe0a03b | ||
![]() |
72634ffe6e | ||
![]() |
c420174c1d | ||
![]() |
b7487675ce | ||
![]() |
1b577922e7 | ||
![]() |
3ba8a67647 | ||
![]() |
beb4ae92c1 | ||
![]() |
cc46935a82 | ||
![]() |
53e79a2d94 | ||
![]() |
8ff5c03d53 | ||
![]() |
c69996d073 | ||
![]() |
b07003e184 | ||
![]() |
45a8eb974a | ||
![]() |
2dd3d85448 | ||
![]() |
da12da9d8c | ||
![]() |
30c5fc63c8 | ||
![]() |
7971896383 | ||
![]() |
a8b18c2697 | ||
![]() |
5ae894a5c7 | ||
![]() |
bcfa338227 | ||
![]() |
b1f31762e3 | ||
![]() |
93f9a19aa1 | ||
![]() |
61d853e6a5 | ||
![]() |
1f55c4180f | ||
![]() |
4b6025cb9a | ||
![]() |
2f6d133b96 | ||
![]() |
9035fd191e | ||
![]() |
bb89c5059c | ||
![]() |
66feb779a8 | ||
![]() |
948219c576 | ||
![]() |
60577d6720 | ||
![]() |
953bfc6f1a | ||
![]() |
2052eb5a65 | ||
![]() |
019555be0c | ||
![]() |
33a335a3f5 | ||
![]() |
9d2231b1cd | ||
![]() |
6d5388aaf1 | ||
![]() |
b2d49cbbf8 | ||
![]() |
1bb5156923 | ||
![]() |
62f8468775 | ||
![]() |
8e5740e715 | ||
![]() |
f3cf162af1 | ||
![]() |
381943078f | ||
![]() |
26f251e1ed | ||
![]() |
1214b7c32c |
12
.eslintrc.js
12
.eslintrc.js
@@ -1,6 +1,4 @@
|
||||
// @ts-check
|
||||
const { defineConfig } = require('eslint-define-config');
|
||||
module.exports = defineConfig({
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
@@ -20,11 +18,10 @@ module.exports = defineConfig({
|
||||
extends: [
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:jest/recommended',
|
||||
],
|
||||
rules: {
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
@@ -61,7 +58,7 @@ module.exports = defineConfig({
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/script-setup-uses-vars': 'off',
|
||||
'vue/require-explicit-emits': 'off',
|
||||
'vue/html-self-closing': [
|
||||
'error',
|
||||
{
|
||||
@@ -74,5 +71,6 @@ module.exports = defineConfig({
|
||||
math: 'always',
|
||||
},
|
||||
],
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
|
||||
|
||||
# Automatically normalize line endings (to LF) for all text-based files.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary
|
49
.github/workflows/deploy.yml
vendored
49
.github/workflows/deploy.yml
vendored
@@ -55,32 +55,31 @@ jobs:
|
||||
# ARGS: --delete --verbose --parallel=80
|
||||
|
||||
push-to-gh-pages:
|
||||
if: "contains(github.event.head_commit.message, '[release]')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Sed Config Base
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's#VITE_PUBLIC_PATH\s*=.*#VITE_PUBLIC_PATH = /vue-vben-admin/#g' ./.env.production
|
||||
sed -i "s#VITE_BUILD_COMPRESS\s*=.*#VITE_BUILD_COMPRESS = 'gzip'#g" ./.env.production
|
||||
sed -i "s#VITE_DROP_CONSOLE\s*=.*#VITE_DROP_CONSOLE = true#g" ./.env.production
|
||||
cat ./.env.production
|
||||
|
||||
- name: use Node.js 14
|
||||
uses: actions/setup-node@v2.1.2
|
||||
- name: use Node.js 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '14.x'
|
||||
node-version: '16.x'
|
||||
|
||||
- name: Get yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
@@ -94,25 +93,31 @@ jobs:
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com > ~/.ssh/known_hosts
|
||||
chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
|
||||
git config --local user.email "vbenadmin@163.com"
|
||||
git config --local user.name "vbenAdmin"
|
||||
|
||||
- name: Delete gh-pages branch
|
||||
run: |
|
||||
git push origin --delete gh-pages
|
||||
git config --global user.email "vbenadmin@163.com"
|
||||
git config --global user.name "vbenAdmin"
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
run: |
|
||||
yarn install
|
||||
yarn run build
|
||||
touch dist/.nojekyll
|
||||
cp dist/index.html dist/404.html
|
||||
|
||||
- name: Delete gh-pages branch
|
||||
run: |
|
||||
git push origin --delete gh-pages
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v2.5.0
|
||||
env:
|
||||
ACTIONS_DEPLOY_KEY: ${{secrets.ACTIONS_DEPLOY_KEY}}
|
||||
uses: peaceiris/actions-gh-pages@v3.9.0
|
||||
with:
|
||||
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
PUBLISH_BRANCH: gh-pages
|
||||
PUBLISH_DIR: ./dist
|
||||
with:
|
||||
forceOrphan: true
|
||||
CNAME: vben.vvbin.cn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
56
.github/workflows/ftp-schedule.yml
vendored
56
.github/workflows/ftp-schedule.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: schedule-push-to-ftp
|
||||
|
||||
# Timed deployment project
|
||||
on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: '0 20 * * *'
|
||||
|
||||
jobs:
|
||||
schedule-push-to-ftp:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Sed Config Base
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's#VITE_PUBLIC_PATH\s*=.*#VITE_PUBLIC_PATH = /next/#g' ./.env.production
|
||||
sed -i "s#VITE_BUILD_COMPRESS\s*=.*#VITE_BUILD_COMPRESS = 'gzip'#g" ./.env.production
|
||||
sed -i "s#VITE_DROP_CONSOLE\s*=.*#VITE_DROP_CONSOLE = true#g" ./.env.production
|
||||
cat ./.env.production
|
||||
|
||||
- name: use Node.js 15
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: '15.x'
|
||||
|
||||
- name: Get yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
yarn install
|
||||
yarn run build
|
||||
|
||||
- name: Deploy
|
||||
uses: SamKirkland/FTP-Deploy-Action@2.0.0
|
||||
env:
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
METHOD: sftp
|
||||
PORT: ${{ secrets.FTP_PORT }}
|
||||
LOCAL_DIR: dist
|
||||
REMOTE_DIR: /srv/www/vben-admin
|
||||
ARGS: --delete --verbose --parallel=80
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -27,3 +27,8 @@ pnpm-debug.log*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
|
||||
.history
|
||||
|
@@ -2,5 +2,5 @@ ports:
|
||||
- port: 3344
|
||||
onOpen: open-preview
|
||||
tasks:
|
||||
- init: yarn
|
||||
command: yarn dev
|
||||
- init: pnpm install
|
||||
command: pnpm run dev
|
||||
|
@@ -3,4 +3,6 @@
|
||||
# shellcheck source=./_/husky.sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
PATH="/usr/local/bin:$PATH"
|
||||
|
||||
npx --no-install commitlint --edit "$1"
|
||||
|
@@ -1,8 +0,0 @@
|
||||
module.exports = {
|
||||
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
|
||||
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
|
||||
'package.json': ['prettier --write'],
|
||||
'*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix'],
|
||||
'*.{scss,less,styl,html}': ['stylelint --fix', 'prettier --write'],
|
||||
'*.md': ['prettier --write'],
|
||||
};
|
@@ -4,7 +4,7 @@
|
||||
|
||||
[ -n "$CI" ] && exit 0
|
||||
|
||||
PATH="/usr/local/bin:$PATH"
|
||||
|
||||
# Format and submit code according to lintstagedrc.js configuration
|
||||
npm run lint:lint-staged
|
||||
|
||||
npm run lint:pretty
|
||||
|
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"octref.vetur",
|
||||
"vue.volar",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"stylelint.vscode-stylelint",
|
||||
"esbenp.prettier-vscode",
|
||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -8,6 +8,6 @@
|
||||
"url": "http://localhost:3100",
|
||||
"webRoot": "${workspaceFolder}/src",
|
||||
"sourceMaps": true
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
64
.vscode/settings.json
vendored
64
.vscode/settings.json
vendored
@@ -1,23 +1,10 @@
|
||||
{
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"volar.tsPlugin": true,
|
||||
"volar.tsPluginStatus": false,
|
||||
//===========================================
|
||||
//============= Editor ======================
|
||||
//===========================================
|
||||
"explorer.openEditors.visible": 0,
|
||||
"npm.packageManager": "pnpm",
|
||||
"editor.tabSize": 2,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
//===========================================
|
||||
//============= Other =======================
|
||||
//===========================================
|
||||
"breadcrumbs.enabled": true,
|
||||
"open-in-browser.default": "chrome",
|
||||
//===========================================
|
||||
//============= files =======================
|
||||
//===========================================
|
||||
"files.eol": "\n",
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
@@ -68,16 +55,10 @@
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "yarn",
|
||||
"liveServer.settings.donotShowInfoMsg": true,
|
||||
"telemetry.enableCrashReporter": false,
|
||||
"workbench.settings.enableNaturalLanguageSearch": false,
|
||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
|
||||
"path-intellisense.mappings": {
|
||||
"/@/": "${workspaceRoot}/src"
|
||||
},
|
||||
"prettier.requireConfig": true,
|
||||
"typescript.updateImportsOnFileMove.enabled": "always",
|
||||
"workbench.sideBar.location": "left",
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
@@ -107,7 +88,8 @@
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": false
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll.stylelint": true
|
||||
}
|
||||
},
|
||||
"i18n-ally.localesPaths": ["src/locales/lang"],
|
||||
@@ -117,6 +99,7 @@
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||
"i18n-ally.enabledParsers": ["ts"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
"cSpell.words": [
|
||||
"vben",
|
||||
@@ -149,6 +132,39 @@
|
||||
"lintstagedrc",
|
||||
"brotli",
|
||||
"tailwindcss",
|
||||
"sider"
|
||||
]
|
||||
"sider",
|
||||
"pnpm",
|
||||
"antd"
|
||||
],
|
||||
"vetur.format.scriptInitialIndent": true,
|
||||
"vetur.format.styleInitialIndent": true,
|
||||
"vetur.validation.script": false,
|
||||
"MicroPython.executeButton": [
|
||||
{
|
||||
"text": "▶",
|
||||
"tooltip": "运行",
|
||||
"alignment": "left",
|
||||
"command": "extension.executeFile",
|
||||
"priority": 3.5
|
||||
}
|
||||
],
|
||||
"MicroPython.syncButton": [
|
||||
{
|
||||
"text": "$(sync)",
|
||||
"tooltip": "同步",
|
||||
"alignment": "left",
|
||||
"command": "extension.execute",
|
||||
"priority": 4
|
||||
}
|
||||
],
|
||||
// 控制相关文件嵌套展示
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.expand": false,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.ts": "$(capture).test.ts, $(capture).test.tsx",
|
||||
"*.tsx": "$(capture).test.ts, $(capture).test.tsx",
|
||||
"*.env": "$(capture).env.*",
|
||||
"package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
|
||||
},
|
||||
"terminal.integrated.scrollback": 10000
|
||||
}
|
||||
|
48
.yarnclean
48
.yarnclean
@@ -1,48 +0,0 @@
|
||||
# test directories
|
||||
__tests__
|
||||
test
|
||||
tests
|
||||
powered-test
|
||||
|
||||
# asset directories
|
||||
docs
|
||||
doc
|
||||
website
|
||||
images
|
||||
assets
|
||||
|
||||
# examples
|
||||
example
|
||||
examples
|
||||
|
||||
# code coverage directories
|
||||
coverage
|
||||
.nyc_output
|
||||
|
||||
# build scripts
|
||||
Makefile
|
||||
Gulpfile.js
|
||||
Gruntfile.js
|
||||
|
||||
# configs
|
||||
appveyor.yml
|
||||
circle.yml
|
||||
codeship-services.yml
|
||||
codeship-steps.yml
|
||||
wercker.yml
|
||||
.tern-project
|
||||
.gitattributes
|
||||
.editorconfig
|
||||
.*ignore
|
||||
.eslintrc
|
||||
.jshintrc
|
||||
.flowconfig
|
||||
.documentup.json
|
||||
.yarn-metadata.json
|
||||
.travis.yml
|
||||
|
||||
# misc
|
||||
*.md
|
||||
|
||||
!istanbul-reports/lib/html/assets
|
||||
!istanbul-api/node_modules/istanbul-reports/lib/html/assets
|
@@ -1,3 +1,89 @@
|
||||
## 2.8.0(2021-11.03)
|
||||
|
||||
### Upgrade Instructions
|
||||
|
||||
- Package manager changed from `yarn` to `pnpm`
|
||||
- Delete `node_modules` and `yarn.lock`, install `pnpm` globally
|
||||
- Execute `pnpm install`
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **Others**
|
||||
- The `VITE_PROXY` configuration in the `.env` file supports single quotes
|
||||
- Remove warnings during build
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **BasicTable**
|
||||
- Fix the issue that editable cells cannot be submitted in some cases
|
||||
- Fix the problem that the `inset` attribute does not work
|
||||
- Fix the problem that the performance of `useTable` and `reload` method `await` of `BasicTable` instance are inconsistent
|
||||
- Fix the issue that `clickToRowSelect` would ignore the disabled state of the row selection box
|
||||
- Fix the problem that the page of `BasicTable` will be reset in some cases
|
||||
- Modify the `deleteTableDataRecord` method
|
||||
- **BasicModal**
|
||||
- Fixed the problem that `Modal` could not be closed even when clicking on the mask and pressing the `Esc` key
|
||||
- Fixed the issue that clicking the close button and the blank area next to the maximize button would also cause `Modal` to close
|
||||
- **BasicTree** Fix the problem that the node slot does not work
|
||||
- **CodeEditor** Fix the problem that may cause `Build` failure
|
||||
- **BasicForm** Fix the problem that the content width of the custom FormItem component may be out of range
|
||||
- **ApiTreeSelect** Fix the problem that the change of `params` failed to trigger the re-request of api data
|
||||
- **Others** -Fixed an issue where multiple tabs would not jump to routing when closing tabs in some cases
|
||||
- Fix the issue that some components may cause abnormal hot update
|
||||
- Fix the problem that some sub-components of `antdv` will be reported in the build process when directly `import` part of the `antdv`, such as: TabPane, RadioGroup
|
||||
|
||||
## 2.7.2(2021-09-14)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **BasicForm** New `Divider` in the form component for dividing the area of longer forms
|
||||
- **BasicTable**
|
||||
- Cell editor adds submit callback, which will decide whether to submit data to the form based on the result returned by the callback function
|
||||
- Add check method for row editing, allowing only check but not submit value, so asynchronously save data successfully before submit to table
|
||||
- Fix the problem that the `rowClassName` property cannot be used at the same time as `striped`.
|
||||
- New component **MarkdownViewer** for displaying rich text in Markdown format
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **CodeEditor** Fix JSON editor throwing exception when formatting invalid JSON text
|
||||
- **Tinymce** fixes an issue where inline mode throws an exception in some scenarios
|
||||
- **BasicTable**
|
||||
- Repair the problem that the editing icon is not displayed when the content of editable cell is empty
|
||||
- Repair the problem that the total row at the end of the table sometimes fails to align with the columns in the main part of the table.
|
||||
- **MarkDown** Repair the problem that the value of initial value property does not work.
|
||||
- **BasicUpload** Repair the problem that `accept` property does not support `MIME` and suffix name starting with dot.
|
||||
- **ApiSelect** Fix the problem of type definition of `value` property.
|
||||
- **Other**
|
||||
- Repair the problem that some wrapper components give error when using slots.
|
||||
- Repair the problem that `theme` parameter of `useECharts` does not work.
|
||||
- Repair the problem that when `Token` is invalid, pressing F5 to refresh the page may cause abnormal page loading.
|
||||
- Repair the problem that the improper call of `useRedo` may lead to `path` redirection abnormality.
|
||||
- Repair the problem that `vite` custom mode name does not support underscore.
|
||||
|
||||
## 2.7.1(2021-08-16)
|
||||
|
||||
- Upgrade vue 3.2, if the operation fails, delete node_modules and reinstall it
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **BasicTree** Add search function related properties and methods
|
||||
- **BasicForm** added `alwaysShowLines` to set the number of lines kept displayed when folding
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **Cropper** Fix the problem of failure to destroy in time
|
||||
- **BasicTable**
|
||||
- Fix the problem that `CellFormat` cannot use `Map` type data
|
||||
- Fixed an issue where the editable cell failed to display the `0` value correctly
|
||||
- Fixed the issue that selection-change event failed to trigger correctly when unchecked
|
||||
- Fix the problem that the background color of the full screen state under the light theme is incorrect
|
||||
- Fix the problem of obtaining complete data when `getSelectRows` does not support remote data cross-page selection
|
||||
- Fix the issue that the `size` property provided for editing components in `editComponentProps` is invalid
|
||||
- **Qrcode** Fixed the problem that the QR code component could not be drawn in time when it was created
|
||||
- **BasicModal** Fix the problem that the `helpMessage` property does not work
|
||||
- **BasicButton** Fix the problem that the button style performance is inconsistent with the official antd
|
||||
- **Others** Fix the problem that `useRedo` (reload the current route) will lose route `params` data
|
||||
|
||||
## 2.7.0(2021-08-03)
|
||||
|
||||
## (Breaking changes) Breaking changes
|
||||
|
141
CHANGELOG.md
141
CHANGELOG.md
@@ -1,3 +1,144 @@
|
||||
## [2.8.0](https://github.com/anncwb/vue-vben-admin/compare/v2.7.2...v2.8.0) (2021-11-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- fixed token clear error ([9640484](https://github.com/anncwb/vue-vben-admin/commit/96404848955f84d57b88dd240ab3a57b7017103c))
|
||||
- improve type introduction, fix [#1196](https://github.com/anncwb/vue-vben-admin/issues/1196) ([2820d5a](https://github.com/anncwb/vue-vben-admin/commit/2820d5a627260bb8eddfcd25df1cd7d1196932e8))
|
||||
- **api-select:** fixed `value` prop define ([f87b0f2](https://github.com/anncwb/vue-vben-admin/commit/f87b0f2f5efe4e9977c4cc0742dbcaefbad2ca02)), closes [#1175](https://github.com/anncwb/vue-vben-admin/issues/1175)
|
||||
- **card-list:** fixed build error ([628e820](https://github.com/anncwb/vue-vben-admin/commit/628e820684ce5d81f130548505efe83e8d516131))
|
||||
- **code-editor:** fixed formatting error ([e7c9636](https://github.com/anncwb/vue-vben-admin/commit/e7c96363a1963b7733a9ee498403eb6a062160e6))
|
||||
- **echarts:** theme setting supported ([93812f7](https://github.com/anncwb/vue-vben-admin/commit/93812f734ec85529aa27fc3100a2eaef8c7a6df5)), closes [#1095](https://github.com/anncwb/vue-vben-admin/issues/1095)
|
||||
- **markdown:** the hierarchy of markDown components after full screen ([c8017b1](https://github.com/anncwb/vue-vben-admin/commit/c8017b1365ea49f95a26148a539f8c30d8a8631f))
|
||||
- **markdown:** `value` not worked on init ([0bb9c03](https://github.com/anncwb/vue-vben-admin/commit/0bb9c035f77588c58d36b3fd45d89b9730cd70d7))
|
||||
- **modal:** avoid style pollution to the whole world ([#1128](https://github.com/anncwb/vue-vben-admin/issues/1128)) ([6e7f6f8](https://github.com/anncwb/vue-vben-admin/commit/6e7f6f82ed2819e02e2b3114884e665d0762d7e9))
|
||||
- **table:** `rowClassName` not worked with `striped` ([044e2e4](https://github.com/anncwb/vue-vben-admin/commit/044e2e4e866dd5b120daab03c47aba1ca1f9140a)), closes [#1167](https://github.com/anncwb/vue-vben-admin/issues/1167)
|
||||
- **table:** 修复表格背景颜色再深色模式下会被穿透问题 ([#1133](https://github.com/anncwb/vue-vben-admin/issues/1133)) ([30fa4cf](https://github.com/anncwb/vue-vben-admin/commit/30fa4cfa2ab6229efc67224fd082e32da0a95d49))
|
||||
- **table:** editable icon not show with empty cell ([edc3096](https://github.com/anncwb/vue-vben-admin/commit/edc30965653831b4572c5d5e067f556f4757ce75)), closes [#1103](https://github.com/anncwb/vue-vben-admin/issues/1103)
|
||||
- **table:** fix table footer style ([a426b90](https://github.com/anncwb/vue-vben-admin/commit/a426b9027ef524f9033d510d0c74cd17b2ad5bcf)), closes [#1112](https://github.com/anncwb/vue-vben-admin/issues/1112)
|
||||
- **table:** Solve the bug of setting ifshow to false in table column ([#1166](https://github.com/anncwb/vue-vben-admin/issues/1166)) ([5fa730c](https://github.com/anncwb/vue-vben-admin/commit/5fa730c49ae46fa448d49d597dc7b2b6a019b268))
|
||||
- **table-action:** `divider` not work as expected ([7593ef6](https://github.com/anncwb/vue-vben-admin/commit/7593ef6a4f081ed800658b70316ab2f1e3ee631d))
|
||||
- **tinymce:** fixed `inline` mode ([8e01377](https://github.com/anncwb/vue-vben-admin/commit/8e01377481a34cda221de6bbb01fc7d5b2824c82)), closes [#1092](https://github.com/anncwb/vue-vben-admin/issues/1092)
|
||||
- **upload:** `accept` not work as expected ([656ee4e](https://github.com/anncwb/vue-vben-admin/commit/656ee4e5c9b363b6ab59aa071915414e5ee95de4))
|
||||
- `getUserinfo` is compatible with empty roles data ([1ddfc31](https://github.com/anncwb/vue-vben-admin/commit/1ddfc31c3c4c792c5f741f6d0f0754ffc9a6613c))
|
||||
- `slots` worked in `basicTable` and `basicModal` ([5138e44](https://github.com/anncwb/vue-vben-admin/commit/5138e447e74ef01309457d22f44129c8b1b2f815))
|
||||
- `useRedo` called duplicate may cause exception ([1235978](https://github.com/anncwb/vue-vben-admin/commit/1235978ab23740dfb11e3de7ac26a7d10a4899dc)), closes [#1121](https://github.com/anncwb/vue-vben-admin/issues/1121)
|
||||
- 修复 `apiSelect` 绑定值 `attrs` 的问题 ([#1172](https://github.com/anncwb/vue-vben-admin/issues/1172)) ([c753d94](https://github.com/anncwb/vue-vben-admin/commit/c753d945e08f72cab5bc8a585601cab6a0523fca))
|
||||
- 修复弹窗全屏按钮异常关闭的问题([#1177](https://github.com/anncwb/vue-vben-admin/issues/1177)) ([#1182](https://github.com/anncwb/vue-vben-admin/issues/1182)) ([9e9ea3f](https://github.com/anncwb/vue-vben-admin/commit/9e9ea3f43d8c4b88649c1998bf89186b5f7ee6a2))
|
||||
- 修改 axios 中 urlPrefix 字段不生效问题 ([#1170](https://github.com/anncwb/vue-vben-admin/issues/1170)) ([7df9b51](https://github.com/anncwb/vue-vben-admin/commit/7df9b513447d8deab2fd8e86fa23c807adb6d440))
|
||||
- add loss action for userStore ([a36825a](https://github.com/anncwb/vue-vben-admin/commit/a36825a6d423aae9aaf1936ce55947ba8c2104b0))
|
||||
- fix all types of errors, compatible with volar plugin ([e15b4f1](https://github.com/anncwb/vue-vben-admin/commit/e15b4f14db51812effd55670b3d2da7b082e00a7))
|
||||
- fixed build warning for style of `intro.js` ([d27633f](https://github.com/anncwb/vue-vben-admin/commit/d27633fb31824e92cbeb24f8d626d8e33ce7179e)), closes [#1130](https://github.com/anncwb/vue-vben-admin/issues/1130)
|
||||
- Improve content height calculation ([#1136](https://github.com/anncwb/vue-vben-admin/issues/1136)) ([6717fe6](https://github.com/anncwb/vue-vben-admin/commit/6717fe654e88e6a939a16c523832870388ec1886))
|
||||
- name of vite `mode` support more characters ([9f68229](https://github.com/anncwb/vue-vben-admin/commit/9f6822991c4b2da78e0a5d0c7d6e0288f0d9d1cb)), closes [#1115](https://github.com/anncwb/vue-vben-admin/issues/1115)
|
||||
- refresh failed while token invalid ([3a5d1a5](https://github.com/anncwb/vue-vben-admin/commit/3a5d1a5757c0a2be17e6dd370cbb023ddbb30d5e)), closes [#1101](https://github.com/anncwb/vue-vben-admin/issues/1101)
|
||||
- warning in logout action ([b3307fe](https://github.com/anncwb/vue-vben-admin/commit/b3307fe2836fb6f9806d602d5bdb7e540c49f1b0))
|
||||
- **tinymce:** fixed `tinymce` destory method ([fb43fad](https://github.com/anncwb/vue-vben-admin/commit/fb43fad555b093af23194bdb3670bc1347c0010f))
|
||||
|
||||
### Features
|
||||
|
||||
- **demo:** add `JsonPreview` demo ([83c1683](https://github.com/anncwb/vue-vben-admin/commit/83c1683bfdcf4ea33de771895b46e41f276969e8)), closes [#1146](https://github.com/anncwb/vue-vben-admin/issues/1146)
|
||||
- **form:** add `Divider` for schema component type ([47a448b](https://github.com/anncwb/vue-vben-admin/commit/47a448b8aea572e54dac97dc4f9fb6c1c005685a))
|
||||
- **form:** component `Divider` support `helpMessage` ([a5ff592](https://github.com/anncwb/vue-vben-admin/commit/a5ff59237f2eb6ea4c1770acc594c75bf1f6e95f))
|
||||
- **markdown-viewer:** add new component ([73dc492](https://github.com/anncwb/vue-vben-admin/commit/73dc492b2a49793d945ccdae7f5c429c874f298c)), closes [#1181](https://github.com/anncwb/vue-vben-admin/issues/1181)
|
||||
- **table:** 添加和支持动态删除和插入数据 ([#1152](https://github.com/anncwb/vue-vben-admin/issues/1152)) ([59a9087](https://github.com/anncwb/vue-vben-admin/commit/59a90877287a289f746eec97d12c2d3a1d5476b0))
|
||||
- **table:** add `beforeEditSubmit` for editable cell ([2c867b3](https://github.com/anncwb/vue-vben-admin/commit/2c867b3d636d57cdc526a4ca600af7d747b7d833))
|
||||
- **table:** add `onValid` for editRow ([ee7c31d](https://github.com/anncwb/vue-vben-admin/commit/ee7c31db44fd8f99f0d26da368e1d82b5630f309))
|
||||
- **tree:** 1. 添加自定义数据过滤判断方法 2. 添加搜索完成自动展开结果选项 3. 添加搜索完成自动选中结果选项 4. 树节点数据变化时强制搜索(同步 searchData 避免展示错误) ([#1132](https://github.com/anncwb/vue-vben-admin/issues/1132)) ([e00578c](https://github.com/anncwb/vue-vben-admin/commit/e00578c40a585a4a35f235c0228aebaf62cea1ba))
|
||||
- add CardList component ([0f5ddbf](https://github.com/anncwb/vue-vben-admin/commit/0f5ddbf1ec777fc238a94bd037d37ea787316757))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- **tree:** 优化 Tree 搜索功能,添加搜索高亮功能,优化样式表现 ([#1153](https://github.com/anncwb/vue-vben-admin/issues/1153)) ([3b6b4f7](https://github.com/anncwb/vue-vben-admin/commit/3b6b4f73033e8757fd3a032f0910dfcc30dee151))
|
||||
- not waiting for router.isReady ([2884e86](https://github.com/anncwb/vue-vben-admin/commit/2884e863ce826cd92cd782f40cdee31588bc6d32))
|
||||
- optimize css volume ([466d4ed](https://github.com/anncwb/vue-vben-admin/commit/466d4edcd02fc91e2b4cdbbc3c501bfd2fde7a3d))
|
||||
|
||||
## [2.7.1](https://github.com/anncwb/vue-vben-admin/compare/v2.6.1...v2.7.1) (2021-08-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- `slots` working in components ([b1f3176](https://github.com/anncwb/vue-vben-admin/commit/b1f31762e3c86a432a8d559ab957444eaf5525ad))
|
||||
- add axios error info from response ([#1083](https://github.com/anncwb/vue-vben-admin/issues/1083)) ([72634ff](https://github.com/anncwb/vue-vben-admin/commit/72634ffe6e6649d36ee41f7633c8ee2ab80cf25e))
|
||||
- auto remove script dom in `useScript` ([a544dd3](https://github.com/anncwb/vue-vben-admin/commit/a544dd3e589329339177dad3d5c1f75dd6e6f0ca))
|
||||
- fixed `useRedo` may loss route params ([2dd3d85](https://github.com/anncwb/vue-vben-admin/commit/2dd3d8544866231895d23dba63785b683ae0062e)), closes [#1079](https://github.com/anncwb/vue-vben-admin/issues/1079)
|
||||
- fixed basicButton ghost style ([3ba8a67](https://github.com/anncwb/vue-vben-admin/commit/3ba8a67647d35fb9639a5af66f33d43eff493d15))
|
||||
- fixed basicButton primary style ([1b57792](https://github.com/anncwb/vue-vben-admin/commit/1b577922e752c02fe7c033c53be37ef81e4e9b8e))
|
||||
- fixed basicButton style ([beb4ae9](https://github.com/anncwb/vue-vben-admin/commit/beb4ae92c190780bbd3bc6bc7547d52e2ccf8cf1))
|
||||
- **cropper:** cropper not destroy in time ([3819430](https://github.com/anncwb/vue-vben-admin/commit/381943078fd55123fde3d5555e04f279d7f1c407)), closes [#1027](https://github.com/anncwb/vue-vben-admin/issues/1027)
|
||||
- **demo:** fix form style in modal ([30c5fc6](https://github.com/anncwb/vue-vben-admin/commit/30c5fc63c8600cfb03f917d79e56c0a7e7ff64e0)), closes [#1076](https://github.com/anncwb/vue-vben-admin/issues/1076)
|
||||
- **i18n:** add i18n translate data ([1f55c41](https://github.com/anncwb/vue-vben-admin/commit/1f55c4180f9c0cf48e3796a77d6f0bfd46107272))
|
||||
- **locales:** fix that vscode extension i18n-Ally detect zh-CN as zh ([#1044](https://github.com/anncwb/vue-vben-admin/issues/1044)) ([b2d49cb](https://github.com/anncwb/vue-vben-admin/commit/b2d49cbbf81cb15e75905deb95bdf7ac4af4e599))
|
||||
- **modal:** `helpMessage` doesn't work ([953bfc6](https://github.com/anncwb/vue-vben-admin/commit/953bfc6f1a559309ea2b1114b8ede911a3751cc7))
|
||||
- **page-wrapper:** fix `class` not working ([8879ae8](https://github.com/anncwb/vue-vben-admin/commit/8879ae8d773e8dc4c252c4234eefeab9bc135a30))
|
||||
- **qrcode:** qrcode not displayed properly ([26f251e](https://github.com/anncwb/vue-vben-admin/commit/26f251e1ed5bfd79c8615fb552ca302f917cc588)), closes [#1026](https://github.com/anncwb/vue-vben-admin/issues/1026)
|
||||
- **route:** the whitelist should include basicRoutes ([#1048](https://github.com/anncwb/vue-vben-admin/issues/1048)) ([1bb5156](https://github.com/anncwb/vue-vben-admin/commit/1bb51569236fd9bcc55dd9f237f51f218956b258))
|
||||
- **table:** `0` is not shown in editable cell ([33a335a](https://github.com/anncwb/vue-vben-admin/commit/33a335a3f52aead522b3fbee0d558e2e797580ff)), closes [#1039](https://github.com/anncwb/vue-vben-admin/issues/1039)
|
||||
- **table:** `cellFormat` support `Map` ([1214b7c](https://github.com/anncwb/vue-vben-admin/commit/1214b7c32c425750a4d0202a9b235eb9e45a6f47)), closes [#1031](https://github.com/anncwb/vue-vben-admin/issues/1031)
|
||||
- **table:** `getSelectRows` support multi-page ([4b6025c](https://github.com/anncwb/vue-vben-admin/commit/4b6025cb9a3ef067680201ec3052bc651e0a0c1b)), closes [#914](https://github.com/anncwb/vue-vben-admin/issues/914)
|
||||
- **table:** `selection-change` not triggered in unchecking ([019555b](https://github.com/anncwb/vue-vben-admin/commit/019555be0c88edc673cae382023d647e78959b30)), closes [#1053](https://github.com/anncwb/vue-vben-admin/issues/1053)
|
||||
- **table:** `size` not worked in `editComponentProps` ([7971896](https://github.com/anncwb/vue-vben-admin/commit/7971896383296c155b7ab16b5beb3544f34ee525)), closes [#1074](https://github.com/anncwb/vue-vben-admin/issues/1074)
|
||||
- **table:** fix `getSelectRows` for treeTable ([f2b8bb4](https://github.com/anncwb/vue-vben-admin/commit/f2b8bb43a0b9172b9ef9ced8e83bf91143a091d9)), closes [#1003](https://github.com/anncwb/vue-vben-admin/issues/1003)
|
||||
- **table:** fix `injection not found` warning ([53e79a2](https://github.com/anncwb/vue-vben-admin/commit/53e79a2d94df19c0e1aa7399d5ce4c27834e0350))
|
||||
- **types:** fix some type errors ([9035fd1](https://github.com/anncwb/vue-vben-admin/commit/9035fd191e4e8d954f42b3a4cd1e80ec70b7cbb6))
|
||||
- The Style of tableTitle slot ([#1023](https://github.com/anncwb/vue-vben-admin/issues/1023)) ([02e7756](https://github.com/anncwb/vue-vben-admin/commit/02e77560624cc4a95a5a20ffd5e0601f1f88c6f4))
|
||||
- fix build handler & misc ([#1060](https://github.com/anncwb/vue-vben-admin/issues/1060)) ([66feb77](https://github.com/anncwb/vue-vben-admin/commit/66feb779a8645a93760c784c510512118c4c6efa))
|
||||
- **table:** recursive updateTableDataRecord ([#1024](https://github.com/anncwb/vue-vben-admin/issues/1024)) ([72f953c](https://github.com/anncwb/vue-vben-admin/commit/72f953c8d3413a7f5482793258503017a81cc759))
|
||||
- **table:** wrong bg-color in fullscreen mode ([2052eb5](https://github.com/anncwb/vue-vben-admin/commit/2052eb5a65be38c44165efecdb15266de4638667))
|
||||
- **type:** fix ant-design-vue -> ([#1043](https://github.com/anncwb/vue-vben-admin/issues/1043)) ([6d5388a](https://github.com/anncwb/vue-vben-admin/commit/6d5388aaf143ac76bac0b68d56a3ab6b5993e807))
|
||||
- fix iframe heigth error ([#1012](https://github.com/anncwb/vue-vben-admin/issues/1012)) ([d76cfd7](https://github.com/anncwb/vue-vben-admin/commit/d76cfd7f809ba48880c950a64cb43a5c9c44176c))
|
||||
- Fix the invalid hot update of BasicButton when changing style outside ([#1016](https://github.com/anncwb/vue-vben-admin/issues/1016)) ([be2d11d](https://github.com/anncwb/vue-vben-admin/commit/be2d11d5d344a508e94abe3534726c80e1f1f271))
|
||||
- the position of tinymce upload image is wrong ([#1015](https://github.com/anncwb/vue-vben-admin/issues/1015)) ([2fd0fd2](https://github.com/anncwb/vue-vben-admin/commit/2fd0fd281e65d6d2551478c5f19250347dc14062))
|
||||
- **tree:** fix `checkAll` effects `disabled` node ([ddd1893](https://github.com/anncwb/vue-vben-admin/commit/ddd1893b113e13786037522341abb2e75f8f9d5b))
|
||||
- style property of actionColOpt is invalid ([#997](https://github.com/anncwb/vue-vben-admin/issues/997)) ([225bd4c](https://github.com/anncwb/vue-vben-admin/commit/225bd4c39de377d93c605f33bfdf3d8fd565f12b))
|
||||
- typo ([#980](https://github.com/anncwb/vue-vben-admin/issues/980)) ([7e6a89f](https://github.com/anncwb/vue-vben-admin/commit/7e6a89ffeb8c63467908d5807d3d7c4761620ee3))
|
||||
- **api-tree-select:** auto reload while `params` changed ([c734f68](https://github.com/anncwb/vue-vben-admin/commit/c734f6858daea6d11cd517463b06fcce58744947))
|
||||
- **dark-theme:** alert color in dark-theme ([9b7ede0](https://github.com/anncwb/vue-vben-admin/commit/9b7ede09b9efe4d5a15ab0cdeadac480a29c0f62))
|
||||
- **dark-theme:** bgcolor of `selected tree node` in dark theme ([8cf004a](https://github.com/anncwb/vue-vben-admin/commit/8cf004a5f59895e2487c3a350c83000e585b897e)), closes [#949](https://github.com/anncwb/vue-vben-admin/issues/949)
|
||||
- **dark-theme:** disabled link `button` color ([4281216](https://github.com/anncwb/vue-vben-admin/commit/42812162c46832ce4d3e332bd579c042309115bc))
|
||||
- **dark-theme:** fixed `TreeSelect` & `DatePicker` theme ([d1e0e8b](https://github.com/anncwb/vue-vben-admin/commit/d1e0e8bcea1c168631222989969e14f7d0d1b6a4)), closes [#955](https://github.com/anncwb/vue-vben-admin/issues/955)
|
||||
- **dark-theme:** style for checked tree nodes ([662b576](https://github.com/anncwb/vue-vben-admin/commit/662b576ac2088247cb58e295378f228462508a37))
|
||||
- **demo:** account page form validation ([8702965](https://github.com/anncwb/vue-vben-admin/commit/87029650570e470431fb94d35a273c5d07a73135))
|
||||
- **demo:** fix roles mock data ([c375e32](https://github.com/anncwb/vue-vben-admin/commit/c375e32305eae5128e09ad1bda39ce0cc6afd790))
|
||||
- **form:** remove console error for `setFieldsValue` ([8d185bb](https://github.com/anncwb/vue-vben-admin/commit/8d185bb5841c83eb49c78e8342e65067aa6f9b80)), closes [#952](https://github.com/anncwb/vue-vben-admin/issues/952)
|
||||
- **table:** fix `pagination` props working ([e327893](https://github.com/anncwb/vue-vben-admin/commit/e32789373eb5b1b531572b59692bf552dac365dc))
|
||||
- expandIcon slot of BasicTable component is invalid ([#975](https://github.com/anncwb/vue-vben-admin/issues/975)) ([98c206d](https://github.com/anncwb/vue-vben-admin/commit/98c206d9c9661a18dde4ec7782cbe1eb6e62ebeb))
|
||||
- **demo:** menu `error-log` link to 404 page ([341bd63](https://github.com/anncwb/vue-vben-admin/commit/341bd633d8ed38a5a357db8f97166c2eba2895d3))
|
||||
- **demo:** multi-modal used with dynamic component ([e1c4723](https://github.com/anncwb/vue-vben-admin/commit/e1c47233edf7675aede6d5f023726945a510ddf7))
|
||||
- **echarts:** fix graphic config cannot be used in echarts options ([#959](https://github.com/anncwb/vue-vben-admin/issues/959)) ([525484e](https://github.com/anncwb/vue-vben-admin/commit/525484e7a409b032d22231f90a92e700ef4290ae))
|
||||
- **form:** fix `validate` promise catch ([571f281](https://github.com/anncwb/vue-vben-admin/commit/571f28138f782553eb39cda2d632e5ac1aa1e145))
|
||||
- **img-rotate-drag-verify:** fix `resume` method support ([32d64db](https://github.com/anncwb/vue-vben-admin/commit/32d64dbe816a0afda6ee9e91863199afb3e7b48e)), closes [#946](https://github.com/anncwb/vue-vben-admin/issues/946)
|
||||
- **login:** fix `auto fill` style in dark-theme ([cebc6a5](https://github.com/anncwb/vue-vben-admin/commit/cebc6a590e1a19af7380a55aed43b23af274df0a))
|
||||
- **perm-guard:** Fix the problem that the routing query is lost after refreshing the page ([#941](https://github.com/anncwb/vue-vben-admin/issues/941)) ([9c4889f](https://github.com/anncwb/vue-vben-admin/commit/9c4889f0859bc60decf0ef40c383c1946de1d68a))
|
||||
- **qrcode:** Fix the problem that the QR code cannot be dynamically generated ([#974](https://github.com/anncwb/vue-vben-admin/issues/974)) ([fe4eae3](https://github.com/anncwb/vue-vben-admin/commit/fe4eae37146068f01ba08f033e0c2e8bd03e48b5))
|
||||
- **style:** fix checkbox-checked css in dark mode ([d3f08e3](https://github.com/anncwb/vue-vben-admin/commit/d3f08e37c5b6e46f33d525e9ef4b4c235d77a192))
|
||||
- **table:** component shown in `fullscreen` mode ([a07ab6d](https://github.com/anncwb/vue-vben-admin/commit/a07ab6d7aa1060f856649a9bdbec9dfa50b14f26))
|
||||
- **table:** editable cell display with validation ([202aa42](https://github.com/anncwb/vue-vben-admin/commit/202aa42b8d5a94e84ad386bcf7feab96926c70dd)), closes [#953](https://github.com/anncwb/vue-vben-admin/issues/953)
|
||||
- **table:** fix `dataPicker` show in `fullscreen` mode ([a5a9b3f](https://github.com/anncwb/vue-vben-admin/commit/a5a9b3fb34c64b6ea9c9ab3d58045f6e5963952b))
|
||||
- **table:** fix expand style ([14fb21d](https://github.com/anncwb/vue-vben-admin/commit/14fb21d0b7b9ac69c7b3c463de6d709bd5713d14)), closes [#969](https://github.com/anncwb/vue-vben-admin/issues/969)
|
||||
- **table:** fix tableSettings popup in fullscreen mode ([dce3fb0](https://github.com/anncwb/vue-vben-admin/commit/dce3fb0f20516aaf4817281f5d08109e53a73ecb))
|
||||
- **table-action:** stopButtonPropagation not working ([9b8f165](https://github.com/anncwb/vue-vben-admin/commit/9b8f165a365758d001e6d86ae7afe4ae3316d485))
|
||||
- Fix vite profile hot update error reporting ([#968](https://github.com/anncwb/vue-vben-admin/issues/968)) ([956ed2e](https://github.com/anncwb/vue-vben-admin/commit/956ed2e3f770cc9cf822ce80f71b1e7f179792fb))
|
||||
- **utils:** The date function gets a non-date when the parameter is null ([#954](https://github.com/anncwb/vue-vben-admin/issues/954)) ([350c85a](https://github.com/anncwb/vue-vben-admin/commit/350c85accf5033cc5a21b71bc36d5b7a74eb2573))
|
||||
- fixed moment locale config ([27207a7](https://github.com/anncwb/vue-vben-admin/commit/27207a78caccb04372e0275c5cee526ec460de0e))
|
||||
- typo for utils/env ([#1004](https://github.com/anncwb/vue-vben-admin/issues/1004)) ([e8eefd1](https://github.com/anncwb/vue-vben-admin/commit/e8eefd1bca41c181ec6395bf1d087d2018e2b1f1))
|
||||
- **table:** fix editable cell not support `ellipsis` ([4bb506f](https://github.com/anncwb/vue-vben-admin/commit/4bb506fb1f6ac7d246f8792d29f337ec003ff426)), closes [#944](https://github.com/anncwb/vue-vben-admin/issues/944)
|
||||
|
||||
### Features
|
||||
|
||||
- add `updatePath` for `useTabs` ([bcfa338](https://github.com/anncwb/vue-vben-admin/commit/bcfa33822736b761757a2673d977f752cb5c4f7c)), closes [#1068](https://github.com/anncwb/vue-vben-admin/issues/1068)
|
||||
- always refresh userinfo when page reload ([cc46935](https://github.com/anncwb/vue-vben-admin/commit/cc46935a8296dae62ecfc753a956338ba433927e))
|
||||
- **demo:** add `async-validator` demo ([8b4b767](https://github.com/anncwb/vue-vben-admin/commit/8b4b767f4ca78f7c6f7586d8ba662552c2b7bb51))
|
||||
- **form:** add `alwaysShowLines` prop ([93f9a19](https://github.com/anncwb/vue-vben-admin/commit/93f9a19aa16a3e9cb95338417c52d9a398e3f70b)), closes [#1051](https://github.com/anncwb/vue-vben-admin/issues/1051)
|
||||
- **preview:** add more features ([e23bd26](https://github.com/anncwb/vue-vben-admin/commit/e23bd2696da945291a9b652f1af39ad1936f376b))
|
||||
- **table:** add getRawDataSource() function ([#1029](https://github.com/anncwb/vue-vben-admin/issues/1029)) ([f3cf162](https://github.com/anncwb/vue-vben-admin/commit/f3cf162af1fa5634d4e562fa5239939af6f26093))
|
||||
- **tree:** add searchable function ([60577d6](https://github.com/anncwb/vue-vben-admin/commit/60577d6720fd3f8d4d1a88b20ab902d6161a0eec)), closes [#1057](https://github.com/anncwb/vue-vben-admin/issues/1057)
|
||||
- **use-loading:** add `setTip` method ([26d9476](https://github.com/anncwb/vue-vben-admin/commit/26d9476caff41cc355190604af42e0bd2ef0a353))
|
||||
- Added support for tailwindcss night mode mechanism ([#998](https://github.com/anncwb/vue-vben-admin/issues/998)) ([189bc6f](https://github.com/anncwb/vue-vben-admin/commit/189bc6feb3f2860be8c531dd1ca996f3a2cff018))
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- **table:** fixed code style ([da12da9](https://github.com/anncwb/vue-vben-admin/commit/da12da9d8caeba0e7732551cfbad9b0da3baaac4)), closes [#1070](https://github.com/anncwb/vue-vben-admin/issues/1070)
|
||||
- improve legacy compatibility ([e2664f6](https://github.com/anncwb/vue-vben-admin/commit/e2664f60029f03642f8b1a6afa9b1998705fce37))
|
||||
|
||||
# [2.7.0](https://github.com/anncwb/vue-vben-admin/compare/v2.5.9...v2.7.0) (2021-08-03)
|
||||
|
||||
### Bug Fixes
|
||||
|
@@ -1,3 +1,90 @@
|
||||
## 2.8.0(2021-11.03)
|
||||
|
||||
### 升级说明
|
||||
|
||||
- 包管理器由`yarn`改为 `pnpm`
|
||||
- 删除`node_modules`和`yarn.lock`,全局安装`pnpm`
|
||||
- 执行`pnpm install`
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **其它**
|
||||
- `.env`文件中的`VITE_PROXY`配置支持单引号
|
||||
- 移除 build 过程中的警告
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **BasicTable**
|
||||
- 修复可编辑单元格某些情况下无法提交的问题
|
||||
- 修复`inset`属性不起作用的问题
|
||||
- 修复`useTable`与`BasicTable`实例的`reload`方法`await`表现不一致的问题
|
||||
- 修复`clickToRowSelect`会无视行选择框 disabled 状态的问题
|
||||
- 修复`BasicTable`在某些情况下,分页会被重置的问题
|
||||
- 修改 `deleteTableDataRecord` 方法
|
||||
- **BasicModal**
|
||||
- 修复点击遮罩、按下`Esc`键都不能关闭`Modal`的问题
|
||||
- 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
|
||||
- **BasicTree** 修复节点插槽不起作用的问题
|
||||
- **CodeEditor** 修复可能会造成的`Build`失败的问题
|
||||
- **BasicForm** 修复自定义 FormItem 组件的内容宽度可能超出范围的问题
|
||||
- **ApiTreeSelect** 修复`params`变化未能触发重新请求 api 数据的问题
|
||||
- **其它**
|
||||
- 修复多标签在某些情况下关闭页签不会跳转路由的问题
|
||||
- 修复部分组件可能会造成热更新异常的问题
|
||||
- 修复直接`import`部分`antdv`子组件时会在 build 过程中报错的问题,如:TabPane、RadioGroup
|
||||
|
||||
## 2.7.2(2021-09-14)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **BasicForm** 表单组件新增`Divider`,用于较长表单的区域分割
|
||||
- **BasicTable**
|
||||
- 单元格编辑新增提交回调,将根据回调函数返回的结果来决定是否将数据提交到表格
|
||||
- 行编辑添加校验方法,允许只校验而不提交值,以便异步保存数据成功后才提交倒表格
|
||||
- 修复`rowClassName`属性无法和`striped`同时使用的问题
|
||||
- 新增组件 **MarkdownViewer** 用于显示 Markdown 格式的富文本
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **CodeEditor** 修复 JSON 编辑器在格式化无效 JSON 文本时会抛出异常的问题
|
||||
- **Tinymce** 修复 inline 模式在一些场景下会出现异常的问题
|
||||
- **BasicTable**
|
||||
- 修复可编辑单元格的内容为空时,不会显示编辑图标的问题
|
||||
- 修复表尾合计行与表格主体部分的列有时候未能对齐的问题
|
||||
- **MarkDown** 修复初始 value 属性的值不起作用的问题
|
||||
- **BasicUpload** 修复`accept`属性不支持`MIME`及点开头的后缀名的问题
|
||||
- **ApiSelect** 修复`value`属性的类型定义问题
|
||||
- **其它**
|
||||
- 修复部分封装组件在使用插槽时报错的问题
|
||||
- 修复`useECharts`的`theme`参数不起作用的问题
|
||||
- 修复`Token`失效时,按 F5 刷新页面可能会出现页面加载异常的问题
|
||||
- 修复`useRedo`的不当调用可能会导致重定向`path`异常的问题
|
||||
- 修复`vite`自定义模式名称不支持下划线的问题
|
||||
|
||||
## 2.7.1(2021-08-16)
|
||||
|
||||
- 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- **BasicTree** 添加搜索功能相关属性和方法
|
||||
- **BasicForm** 新增`alwaysShowLines`用于设置折叠时保留显示的行数
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **Cropper** 修复未能及时销毁的问题
|
||||
- **BasicTable**
|
||||
- 修复`CellFormat`无法使用`Map`类型数据的问题
|
||||
- 修复可编辑单元格未能正确显示`0`值的问题
|
||||
- 修复 selection-change 事件在取消勾选时未能正确触发的问题
|
||||
- 修复浅色主题下的全屏状态背景颜色不正确的问题
|
||||
- 修复`getSelectRows`不支持远程数据跨页选择时获取完整数据的问题
|
||||
- 修复在`editComponentProps`中为编辑组件提供的`size`属性无效的问题
|
||||
- **Qrcode** 修复二维码组件在创建时未能及时绘制的问题
|
||||
- **BasicModal** 修复`helpMessage`属性不起作用的问题
|
||||
- **BasicButton** 修复按钮样式表现与 antd 官方不一致的问题
|
||||
- **其它** 修复`useRedo`(重新加载当前路由)会丢失路由`params`数据的问题
|
||||
|
||||
## 2.7.0(2021-08-03)
|
||||
|
||||
## (破坏性更新) Breaking changes
|
||||
|
14
README.md
14
README.md
@@ -21,11 +21,11 @@ Vue Vben Admin is a free and open source middle and back-end template. Using the
|
||||
- **Authority** Built-in complete dynamic routing permission generation scheme.
|
||||
- **Component** Multiple commonly used components are encapsulated twice
|
||||
|
||||
## 预览
|
||||
## Preview
|
||||
|
||||
- [vue-vben-admin](https://vvbin.cn/next/) - Full version Chinese site
|
||||
- [vue-vben-admin](https://vben.vvbin.cn/) - Full version Chinese site
|
||||
- [vue-vben-admin-gh-pages](https://anncwb.github.io/vue-vben-admin/) - Full version of the github site
|
||||
- [vben-admin-thin-next](https://vvbin.cn/thin/next/) - Simplified Chinese site
|
||||
- [vben-admin-thin-next](https://vben.vvbin.cn/thin/next/) - Simplified Chinese site
|
||||
- [vben-admin-thin-gh-pages](https://anncwb.github.io/vben-admin-thin-next/) -Simplified github site
|
||||
|
||||
Test account: vben/123456
|
||||
@@ -44,7 +44,7 @@ Open the project in Gitpod (free online dev environment for GitHub) and start co
|
||||
|
||||
## Documentation
|
||||
|
||||
[Document](https://vvbin.cn/doc-next/)
|
||||
[Document](https://doc.vvbin.cn/)
|
||||
|
||||
## Preparation
|
||||
|
||||
@@ -70,20 +70,20 @@ git clone https://github.com/anncwb/vue-vben-admin.git
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
yarn install
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- run
|
||||
|
||||
```bash
|
||||
yarn serve
|
||||
pnpm serve
|
||||
```
|
||||
|
||||
- build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Change Log
|
||||
|
@@ -23,9 +23,9 @@ Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的`vue3
|
||||
|
||||
## 预览
|
||||
|
||||
- [vue-vben-admin](https://vvbin.cn/next/) - 完整版中文站点
|
||||
- [vue-vben-admin](https://vben.vvbin.cn/) - 完整版中文站点
|
||||
- [vue-vben-admin-gh-pages](https://anncwb.github.io/vue-vben-admin/) - 完整版 github 站点
|
||||
- [vben-admin-thin-next](https://vvbin.cn/thin/next/) - 简化版中文站点
|
||||
- [vben-admin-thin-next](https://vben.vvbin.cn/thin/next/) - 简化版中文站点
|
||||
- [vben-admin-thin-gh-pages](https://anncwb.github.io/vben-admin-thin-next/) - 简化版 github 站点
|
||||
|
||||
测试账号: vben/123456
|
||||
@@ -44,7 +44,7 @@ Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的`vue3
|
||||
|
||||
## 文档
|
||||
|
||||
[文档地址](https://vvbin.cn/doc-next/)
|
||||
[文档地址](https://doc.vvbin.cn/)
|
||||
|
||||
## 准备
|
||||
|
||||
@@ -70,20 +70,20 @@ git clone https://github.com/anncwb/vue-vben-admin.git
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
yarn install
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- 运行
|
||||
|
||||
```bash
|
||||
yarn serve
|
||||
pnpm serve
|
||||
```
|
||||
|
||||
- 打包
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 更新日志
|
||||
@@ -150,6 +150,7 @@ yarn build
|
||||
## 后台整合示例
|
||||
|
||||
- [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台
|
||||
- [matecloud](https://github.com/matevip/matecloud) - MateCloud 微服务脚手架,基于 Spring Cloud 2020.0.3、SpringBoot 2.5.3 的全开源平台
|
||||
|
||||
## 维护者
|
||||
|
||||
|
@@ -28,7 +28,7 @@ export function generateModifyVars(dark = false) {
|
||||
'success-color': '#55D187', // Success color
|
||||
'error-color': '#ED6F6F', // False color
|
||||
'warning-color': '#EFBD47', // Warning color
|
||||
'border-color-base': '#EEEEEE',
|
||||
//'border-color-base': '#EEEEEE',
|
||||
'font-size-base': '14px', // Main font size
|
||||
'border-radius-base': '2px', // Component/float fillet
|
||||
'link-color': primary, // Link color
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import inquirer from 'inquirer';
|
||||
import chalk from 'chalk';
|
||||
import colors from 'picocolors';
|
||||
import pkg from '../../../package.json';
|
||||
|
||||
async function generateIcon() {
|
||||
@@ -52,19 +52,19 @@ async function generateIcon() {
|
||||
const { prefix } = data;
|
||||
const isLocal = useType === 'local';
|
||||
const icons = Object.keys(data.icons).map(
|
||||
(item) => `${isLocal ? prefix + ':' : ''}${item}`
|
||||
(item) => `${isLocal ? prefix + ':' : ''}${item}`,
|
||||
);
|
||||
|
||||
await fs.writeFileSync(
|
||||
path.join(output, `icons.data.ts`),
|
||||
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`
|
||||
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
|
||||
);
|
||||
prefixSet.push(prefix);
|
||||
}
|
||||
}
|
||||
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
|
||||
console.log(
|
||||
`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`
|
||||
`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@@ -3,42 +3,45 @@
|
||||
*/
|
||||
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
|
||||
import fs, { writeFileSync } from 'fs-extra';
|
||||
import chalk from 'chalk';
|
||||
import colors from 'picocolors';
|
||||
|
||||
import { getRootPath, getEnvConfig } from '../utils';
|
||||
import { getEnvConfig, getRootPath } from '../utils';
|
||||
import { getConfigFileName } from '../getConfigFileName';
|
||||
|
||||
import pkg from '../../package.json';
|
||||
|
||||
function createConfig(
|
||||
{
|
||||
configName,
|
||||
config,
|
||||
configFileName = GLOB_CONFIG_FILE_NAME,
|
||||
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} }
|
||||
) {
|
||||
interface CreateConfigParams {
|
||||
configName: string;
|
||||
config: any;
|
||||
configFileName?: string;
|
||||
}
|
||||
|
||||
function createConfig(params: CreateConfigParams) {
|
||||
const { configName, config, configFileName } = params;
|
||||
try {
|
||||
const windowConf = `window.${configName}`;
|
||||
// Ensure that the variable will not be modified
|
||||
const configStr = `${windowConf}=${JSON.stringify(config)};
|
||||
let configStr = `${windowConf}=${JSON.stringify(config)};`;
|
||||
configStr += `
|
||||
Object.freeze(${windowConf});
|
||||
Object.defineProperty(window, "${configName}", {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
`.replace(/\s/g, '');
|
||||
|
||||
fs.mkdirp(getRootPath(OUTPUT_DIR));
|
||||
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
|
||||
|
||||
console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
||||
console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n');
|
||||
console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
|
||||
console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
|
||||
} catch (error) {
|
||||
console.log(chalk.red('configuration file configuration file failed to package:\n' + error));
|
||||
console.log(colors.red('configuration file configuration file failed to package:\n' + error));
|
||||
}
|
||||
}
|
||||
|
||||
export function runBuildConfig() {
|
||||
const config = getEnvConfig();
|
||||
const configFileName = getConfigFileName(config);
|
||||
createConfig({ config, configName: configFileName });
|
||||
createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// #!/usr/bin/env node
|
||||
|
||||
import { runBuildConfig } from './buildConf';
|
||||
import chalk from 'chalk';
|
||||
import colors from 'picocolors';
|
||||
|
||||
import pkg from '../../package.json';
|
||||
|
||||
@@ -11,12 +11,12 @@ export const runBuild = async () => {
|
||||
|
||||
// Generate configuration file
|
||||
if (!argvList.includes('disabled-config')) {
|
||||
await runBuildConfig();
|
||||
runBuildConfig();
|
||||
}
|
||||
|
||||
console.log(`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
||||
console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
|
||||
} catch (error) {
|
||||
console.log(chalk.red('vite build error:\n' + error));
|
||||
console.log(colors.red('vite build error:\n' + error));
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
@@ -28,17 +28,19 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
|
||||
if (envName === 'VITE_PORT') {
|
||||
realName = Number(realName);
|
||||
}
|
||||
if (envName === 'VITE_PROXY') {
|
||||
if (envName === 'VITE_PROXY' && realName) {
|
||||
try {
|
||||
realName = JSON.parse(realName);
|
||||
} catch (error) {}
|
||||
realName = JSON.parse(realName.replace(/'/g, '"'));
|
||||
} catch (error) {
|
||||
realName = '';
|
||||
}
|
||||
}
|
||||
ret[envName] = realName;
|
||||
if (typeof realName === 'string') {
|
||||
process.env[envName] = realName;
|
||||
} else if (typeof realName === 'object') {
|
||||
process.env[envName] = JSON.stringify(realName);
|
||||
}
|
||||
// if (typeof realName === 'string') {
|
||||
// process.env[envName] = realName;
|
||||
// } else if (typeof realName === 'object') {
|
||||
// process.env[envName] = JSON.stringify(realName);
|
||||
// }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -48,7 +50,7 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
|
||||
*/
|
||||
function getConfFiles() {
|
||||
const script = process.env.npm_lifecycle_script;
|
||||
const reg = new RegExp('--mode ([a-z]+)');
|
||||
const reg = new RegExp('--mode ([a-z_\\d]+)');
|
||||
const result = reg.exec(script as string) as any;
|
||||
if (result) {
|
||||
const mode = result[1] as string;
|
||||
|
@@ -1,21 +0,0 @@
|
||||
// TODO
|
||||
import type { GetManualChunk } from 'rollup';
|
||||
|
||||
//
|
||||
const vendorLibs: { match: string[]; output: string }[] = [
|
||||
// {
|
||||
// match: ['xlsx'],
|
||||
// output: 'xlsx',
|
||||
// },
|
||||
];
|
||||
|
||||
// @ts-ignore
|
||||
export const configManualChunk: GetManualChunk = (id: string) => {
|
||||
if (/[\\/]node_modules[\\/]/.test(id)) {
|
||||
const matchItem = vendorLibs.find((item) => {
|
||||
const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig');
|
||||
return reg.test(id);
|
||||
});
|
||||
return matchItem ? matchItem.output : null;
|
||||
}
|
||||
};
|
@@ -2,33 +2,33 @@
|
||||
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
|
||||
* https://github.com/anncwb/vite-plugin-compression
|
||||
*/
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
import type { PluginOption } from 'vite';
|
||||
import compressPlugin from 'vite-plugin-compression';
|
||||
|
||||
export function configCompressPlugin(
|
||||
compress: 'gzip' | 'brotli' | 'none',
|
||||
deleteOriginFile = false
|
||||
): Plugin | Plugin[] {
|
||||
deleteOriginFile = false,
|
||||
): PluginOption | PluginOption[] {
|
||||
const compressList = compress.split(',');
|
||||
|
||||
const plugins: Plugin[] = [];
|
||||
const plugins: PluginOption[] = [];
|
||||
|
||||
if (compressList.includes('gzip')) {
|
||||
plugins.push(
|
||||
compressPlugin({
|
||||
ext: '.gz',
|
||||
deleteOriginFile,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (compressList.includes('brotli')) {
|
||||
plugins.push(
|
||||
compressPlugin({
|
||||
ext: '.br',
|
||||
algorithm: 'brotliCompress',
|
||||
deleteOriginFile,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
return plugins;
|
||||
|
@@ -1,25 +0,0 @@
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* Temporarily solve the Vite circular dependency problem, and wait for a better solution to fix it later. I don't know what problems this writing will bring.
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export function configHmrPlugin(): Plugin {
|
||||
return {
|
||||
name: 'singleHMR',
|
||||
handleHotUpdate({ modules, file }) {
|
||||
if (file.match(/xml$/)) return [];
|
||||
|
||||
modules.forEach((m) => {
|
||||
if (!m.url.match(/\.(css|less)/)) {
|
||||
m.importedModules = new Set();
|
||||
m.importers = new Set();
|
||||
}
|
||||
});
|
||||
|
||||
return modules;
|
||||
},
|
||||
};
|
||||
}
|
@@ -2,10 +2,8 @@
|
||||
* Plugin to minimize and use ejs template syntax in index.html.
|
||||
* https://github.com/anncwb/vite-plugin-html
|
||||
*/
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
import html from 'vite-plugin-html';
|
||||
|
||||
import type { PluginOption } from 'vite';
|
||||
import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
import pkg from '../../../package.json';
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
||||
|
||||
@@ -18,11 +16,11 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
||||
};
|
||||
|
||||
const htmlPlugin: Plugin[] = html({
|
||||
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||
minify: isBuild,
|
||||
inject: {
|
||||
// Inject data into ejs template
|
||||
injectData: {
|
||||
data: {
|
||||
title: VITE_GLOB_APP_TITLE,
|
||||
},
|
||||
// Embed the generated app.config.js file
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// Image resource files used to compress the output of the production environment
|
||||
// https://github.com/anncwb/vite-plugin-imagemin
|
||||
|
||||
import viteImagemin from 'vite-plugin-imagemin';
|
||||
|
||||
export function configImageminPlugin() {
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
import { PluginOption } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import legacy from '@vitejs/plugin-legacy';
|
||||
|
||||
import purgeIcons from 'vite-plugin-purge-icons';
|
||||
import windiCSS from 'vite-plugin-windicss';
|
||||
import VitePluginCertificate from 'vite-plugin-mkcert';
|
||||
//import vueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||
import { configHtmlPlugin } from './html';
|
||||
import { configPwaConfig } from './pwa';
|
||||
import { configMockPlugin } from './mock';
|
||||
@@ -15,7 +15,6 @@ import { configVisualizerConfig } from './visualizer';
|
||||
import { configThemePlugin } from './theme';
|
||||
import { configImageminPlugin } from './imagemin';
|
||||
import { configSvgIconsPlugin } from './svgSprite';
|
||||
import { configHmrPlugin } from './hmr';
|
||||
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
const {
|
||||
@@ -26,19 +25,21 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
|
||||
} = viteEnv;
|
||||
|
||||
const vitePlugins: (Plugin | Plugin[])[] = [
|
||||
const vitePlugins: (PluginOption | PluginOption[])[] = [
|
||||
// have to
|
||||
vue(),
|
||||
// have to
|
||||
vueJsx(),
|
||||
// support name
|
||||
//vueSetupExtend(),
|
||||
VitePluginCertificate({
|
||||
source: 'coding',
|
||||
}),
|
||||
];
|
||||
|
||||
// vite-plugin-windicss
|
||||
vitePlugins.push(windiCSS());
|
||||
|
||||
// TODO
|
||||
!isBuild && vitePlugins.push(configHmrPlugin());
|
||||
|
||||
// @vitejs/plugin-legacy
|
||||
VITE_LEGACY && isBuild && vitePlugins.push(legacy());
|
||||
|
||||
@@ -60,17 +61,17 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
// rollup-plugin-visualizer
|
||||
vitePlugins.push(configVisualizerConfig());
|
||||
|
||||
//vite-plugin-theme
|
||||
// vite-plugin-theme
|
||||
vitePlugins.push(configThemePlugin(isBuild));
|
||||
|
||||
// The following plugins only work in the production environment
|
||||
if (isBuild) {
|
||||
//vite-plugin-imagemin
|
||||
// vite-plugin-imagemin
|
||||
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
|
||||
|
||||
// rollup-plugin-gzip
|
||||
vitePlugins.push(
|
||||
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE)
|
||||
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE),
|
||||
);
|
||||
|
||||
// vite-plugin-pwa
|
||||
|
@@ -2,7 +2,6 @@
|
||||
* Zero-config PWA for Vite
|
||||
* https://github.com/antfu/vite-plugin-pwa
|
||||
*/
|
||||
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
export function configPwaConfig(env: ViteEnv) {
|
||||
|
@@ -2,21 +2,82 @@
|
||||
* Introduces component library styles on demand.
|
||||
* https://github.com/anncwb/vite-plugin-style-import
|
||||
*/
|
||||
import { createStyleImportPlugin, VxeTableResolve } from 'vite-plugin-style-import';
|
||||
|
||||
import styleImport from 'vite-plugin-style-import';
|
||||
|
||||
export function configStyleImportPlugin(isBuild: boolean) {
|
||||
if (!isBuild) return [];
|
||||
const styleImportPlugin = styleImport({
|
||||
export function configStyleImportPlugin(_isBuild: boolean) {
|
||||
if (!_isBuild) {
|
||||
return [];
|
||||
}
|
||||
const styleImportPlugin = createStyleImportPlugin({
|
||||
libs: [
|
||||
{
|
||||
libraryName: 'ant-design-vue',
|
||||
esModule: true,
|
||||
resolveStyle: (name) => {
|
||||
return `ant-design-vue/es/${name}/style/index`;
|
||||
// 这里是无需额外引入样式文件的“子组件”列表
|
||||
const ignoreList = [
|
||||
'anchor-link',
|
||||
'sub-menu',
|
||||
'menu-item',
|
||||
'menu-divider',
|
||||
'menu-item-group',
|
||||
'breadcrumb-item',
|
||||
'breadcrumb-separator',
|
||||
'form-item',
|
||||
'step',
|
||||
'select-option',
|
||||
'select-opt-group',
|
||||
'card-grid',
|
||||
'card-meta',
|
||||
'collapse-panel',
|
||||
'descriptions-item',
|
||||
'list-item',
|
||||
'list-item-meta',
|
||||
'table-column',
|
||||
'table-column-group',
|
||||
'tab-pane',
|
||||
'tab-content',
|
||||
'timeline-item',
|
||||
'tree-node',
|
||||
'skeleton-input',
|
||||
'skeleton-avatar',
|
||||
'skeleton-title',
|
||||
'skeleton-paragraph',
|
||||
'skeleton-image',
|
||||
'skeleton-button',
|
||||
];
|
||||
// 这里是需要额外引入样式的子组件列表
|
||||
// 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失
|
||||
const replaceList = {
|
||||
textarea: 'input',
|
||||
'typography-text': 'typography',
|
||||
'typography-title': 'typography',
|
||||
'typography-paragraph': 'typography',
|
||||
'typography-link': 'typography',
|
||||
'dropdown-button': 'dropdown',
|
||||
'input-password': 'input',
|
||||
'input-search': 'input',
|
||||
'input-group': 'input',
|
||||
'radio-group': 'radio',
|
||||
'checkbox-group': 'checkbox',
|
||||
'layout-sider': 'layout',
|
||||
'layout-content': 'layout',
|
||||
'layout-footer': 'layout',
|
||||
'layout-header': 'layout',
|
||||
'month-picker': 'date-picker',
|
||||
'range-picker': 'date-picker',
|
||||
'image-preview-group': 'image',
|
||||
};
|
||||
|
||||
return ignoreList.includes(name)
|
||||
? ''
|
||||
: replaceList.hasOwnProperty(name)
|
||||
? `ant-design-vue/es/${replaceList[name]}/style/index`
|
||||
: `ant-design-vue/es/${name}/style/index`;
|
||||
},
|
||||
},
|
||||
],
|
||||
resolves: [VxeTableResolve()],
|
||||
});
|
||||
return styleImportPlugin;
|
||||
}
|
||||
|
@@ -3,11 +3,11 @@
|
||||
* https://github.com/anncwb/vite-plugin-svg-icons
|
||||
*/
|
||||
|
||||
import SvgIconsPlugin from 'vite-plugin-svg-icons';
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||
import path from 'path';
|
||||
|
||||
export function configSvgIconsPlugin(isBuild: boolean) {
|
||||
const svgIconsPlugin = SvgIconsPlugin({
|
||||
const svgIconsPlugin = createSvgIconsPlugin({
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
||||
svgoOptions: isBuild,
|
||||
// default
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* Vite plugin for website theme color switching
|
||||
* https://github.com/anncwb/vite-plugin-theme
|
||||
*/
|
||||
import type { Plugin } from 'vite';
|
||||
import type { PluginOption } from 'vite';
|
||||
import path from 'path';
|
||||
import {
|
||||
viteThemePlugin,
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { getThemeColors, generateColors } from '../../config/themeConfig';
|
||||
import { generateModifyVars } from '../../generate/generateModifyVars';
|
||||
|
||||
export function configThemePlugin(isBuild: boolean): Plugin[] {
|
||||
export function configThemePlugin(isBuild: boolean): PluginOption[] {
|
||||
const colors = generateColors({
|
||||
mixDarken,
|
||||
mixLighten,
|
||||
@@ -35,6 +35,11 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
|
||||
return s;
|
||||
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
|
||||
return s;
|
||||
default:
|
||||
if (s.indexOf('.ant-btn') >= -1) {
|
||||
// 按钮被重新定制过,需要过滤掉class防止覆盖
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
|
||||
},
|
||||
@@ -61,7 +66,7 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
|
||||
'border-color-base': '#303030',
|
||||
// 'border-color-split': '#30363d',
|
||||
'item-active-bg': '#111b26',
|
||||
'app-content-background': 'rgb(255 255 255 / 4%)',
|
||||
'app-content-background': '#1e1e1e',
|
||||
'tree-node-selected-bg': '#11263c',
|
||||
|
||||
'alert-success-border-color': '#274916',
|
||||
@@ -80,5 +85,5 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
|
||||
}),
|
||||
];
|
||||
|
||||
return plugin as unknown as Plugin[];
|
||||
return plugin as unknown as PluginOption[];
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ type ProxyItem = [string, string];
|
||||
|
||||
type ProxyList = ProxyItem[];
|
||||
|
||||
type ProxyTargetList = Record<string, ProxyOptions & { rewrite: (path: string) => string }>;
|
||||
type ProxyTargetList = Record<string, ProxyOptions>;
|
||||
|
||||
const httpsRE = /^https:\/\//;
|
||||
|
||||
|
@@ -1,3 +1,23 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const scopes = fs
|
||||
.readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name.replace(/s$/, ''));
|
||||
|
||||
// precomputed scope
|
||||
const scopeComplete = execSync('git status --porcelain || true')
|
||||
.toString()
|
||||
.trim()
|
||||
.split('\n')
|
||||
.find((r) => ~r.indexOf('M src'))
|
||||
?.replace(/(\/)/g, '%%')
|
||||
?.match(/src%%((\w|-)*)/)?.[1]
|
||||
?.replace(/s$/, '');
|
||||
|
||||
/** @type {import('cz-git').UserConfig} */
|
||||
module.exports = {
|
||||
ignores: [(commit) => commit.includes('init')],
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
@@ -7,6 +27,7 @@ module.exports = {
|
||||
'header-max-length': [2, 'always', 108],
|
||||
'subject-empty': [2, 'never'],
|
||||
'type-empty': [2, 'never'],
|
||||
'subject-case': [0],
|
||||
'type-enum': [
|
||||
2,
|
||||
'always',
|
||||
@@ -29,4 +50,58 @@ module.exports = {
|
||||
],
|
||||
],
|
||||
},
|
||||
prompt: {
|
||||
/** @use `yarn commit :f` */
|
||||
alias: {
|
||||
f: 'docs: fix typos',
|
||||
r: 'docs: update README',
|
||||
s: 'style: update code format',
|
||||
b: 'build: bump dependencies',
|
||||
c: 'chore: update config',
|
||||
},
|
||||
customScopesAlign: !scopeComplete ? 'top' : 'bottom',
|
||||
defaultScope: scopeComplete,
|
||||
scopes: [...scopes, 'mock'],
|
||||
allowEmptyIssuePrefixs: false,
|
||||
allowCustomIssuePrefixs: false,
|
||||
|
||||
// English
|
||||
typesAppend: [
|
||||
{ value: 'wip', name: 'wip: work in process' },
|
||||
{ value: 'workflow', name: 'workflow: workflow improvements' },
|
||||
{ value: 'types', name: 'types: type definition file changes' },
|
||||
],
|
||||
|
||||
// 中英文对照版
|
||||
// messages: {
|
||||
// type: '选择你要提交的类型 :',
|
||||
// scope: '选择一个提交范围 (可选):',
|
||||
// customScope: '请输入自定义的提交范围 :',
|
||||
// subject: '填写简短精炼的变更描述 :\n',
|
||||
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
|
||||
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
|
||||
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
|
||||
// customFooterPrefixs: '输入自定义issue前缀 :',
|
||||
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
|
||||
// confirmCommit: '是否提交或修改commit ?',
|
||||
// },
|
||||
// types: [
|
||||
// { value: 'feat', name: 'feat: 新增功能' },
|
||||
// { value: 'fix', name: 'fix: 修复缺陷' },
|
||||
// { value: 'docs', name: 'docs: 文档变更' },
|
||||
// { value: 'style', name: 'style: 代码格式' },
|
||||
// { value: 'refactor', name: 'refactor: 代码重构' },
|
||||
// { value: 'perf', name: 'perf: 性能优化' },
|
||||
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
|
||||
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
|
||||
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
|
||||
// { value: 'revert', name: 'revert: 回滚 commit' },
|
||||
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
|
||||
// { value: 'wip', name: 'wip: 正在开发中' },
|
||||
// { value: 'workflow', name: 'workflow: 工作流程改进' },
|
||||
// { value: 'types', name: 'types: 类型定义文件修改' },
|
||||
// ],
|
||||
// emptyScopesAlias: 'empty: 不填写',
|
||||
// customScopesAlias: 'custom: 自定义',
|
||||
},
|
||||
};
|
||||
|
21
index.html
21
index.html
@@ -8,7 +8,6 @@
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
|
||||
<title><%= title %></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</head>
|
||||
@@ -30,7 +29,7 @@
|
||||
}
|
||||
|
||||
html[data-theme='dark'] .app-loading .app-loading-title {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
color: rgb(255 255 255 / 85%);
|
||||
}
|
||||
|
||||
.app-loading {
|
||||
@@ -48,7 +47,6 @@
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
-webkit-transform: translate3d(-50%, -50%, 0);
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -66,7 +64,7 @@
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
font-size: 30px;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
color: rgb(0 0 0 / 85%);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -97,7 +95,7 @@
|
||||
height: 20px;
|
||||
background-color: #0065cc;
|
||||
border-radius: 100%;
|
||||
opacity: 0.3;
|
||||
opacity: 30%;
|
||||
transform: scale(0.75);
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
transform-origin: 50% 50%;
|
||||
@@ -111,43 +109,38 @@
|
||||
.dot i:nth-child(2) {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(4) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-animation-delay: 1.2s;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes antRotate {
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes antSpinMove {
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,36 +0,0 @@
|
||||
export default {
|
||||
preset: 'ts-jest',
|
||||
roots: ['<rootDir>/tests/'],
|
||||
clearMocks: true,
|
||||
moduleDirectories: ['node_modules', 'src'],
|
||||
moduleFileExtensions: ['js', 'ts', 'vue', 'tsx', 'jsx', 'json', 'node'],
|
||||
modulePaths: ['<rootDir>/src', '<rootDir>/node_modules'],
|
||||
testMatch: [
|
||||
'**/tests/**/*.[jt]s?(x)',
|
||||
'**/?(*.)+(spec|test).[tj]s?(x)',
|
||||
'(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/tests/server/',
|
||||
'<rootDir>/tests/__mocks__/',
|
||||
'/node_modules/',
|
||||
],
|
||||
transform: {
|
||||
'^.+\\.tsx?$': 'ts-jest',
|
||||
},
|
||||
transformIgnorePatterns: ['<rootDir>/tests/__mocks__/', '/node_modules/'],
|
||||
// A map from regular expressions to module names that allow to stub out resources with a single module
|
||||
moduleNameMapper: {
|
||||
'\\.(vs|fs|vert|frag|glsl|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
|
||||
'<rootDir>/tests/__mocks__/fileMock.ts',
|
||||
'\\.(sass|s?css|less)$': '<rootDir>/tests/__mocks__/styleMock.ts',
|
||||
'\\?worker$': '<rootDir>/tests/__mocks__/workerMock.ts',
|
||||
'^/@/(.*)$': '<rootDir>/src/$1',
|
||||
},
|
||||
testEnvironment: 'jsdom',
|
||||
verbose: true,
|
||||
collectCoverage: false,
|
||||
coverageDirectory: 'coverage',
|
||||
collectCoverageFrom: ['src/**/*.{js,ts,vue}'],
|
||||
coveragePathIgnorePatterns: ['^.+\\.d\\.ts$'],
|
||||
};
|
@@ -1,5 +1,21 @@
|
||||
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
|
||||
|
||||
// 问题描述
|
||||
// 1. `import.meta.globEager` 已被弃用, 需要升级vite版本,有兼容问题
|
||||
// 2. `vite-plugin-mock` 插件问题 https://github.com/vbenjs/vite-plugin-mock/issues/56
|
||||
|
||||
// const modules: Record<string, any> = import.meta.glob("./**/*.ts", {
|
||||
// import: "default",
|
||||
// eager: true,
|
||||
// });
|
||||
|
||||
// const mockModules = Object.keys(modules).reduce((pre, key) => {
|
||||
// if (!key.includes("/_")) {
|
||||
// pre.push(...modules[key]);
|
||||
// }
|
||||
// return pre;
|
||||
// }, [] as any[]);
|
||||
|
||||
const modules = import.meta.globEager('./**/*.ts');
|
||||
|
||||
const mockModules: any[] = [];
|
||||
|
@@ -1,8 +1,9 @@
|
||||
// Interface data format used to return a unified format
|
||||
import { ResultEnum } from '/@/enums/httpEnum';
|
||||
|
||||
export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
|
||||
return {
|
||||
code: 0,
|
||||
code: ResultEnum.SUCCESS,
|
||||
result,
|
||||
message,
|
||||
type: 'success',
|
||||
@@ -13,7 +14,7 @@ export function resultPageSuccess<T = any>(
|
||||
page: number,
|
||||
pageSize: number,
|
||||
list: T[],
|
||||
{ message = 'ok' } = {}
|
||||
{ message = 'ok' } = {},
|
||||
) {
|
||||
const pageData = pagination(page, pageSize, list);
|
||||
|
||||
@@ -26,7 +27,10 @@ export function resultPageSuccess<T = any>(
|
||||
};
|
||||
}
|
||||
|
||||
export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
|
||||
export function resultError(
|
||||
message = 'Request failed',
|
||||
{ code = ResultEnum.ERROR, result = null } = {},
|
||||
) {
|
||||
return {
|
||||
code,
|
||||
result,
|
||||
@@ -37,11 +41,9 @@ export function resultError(message = 'Request failed', { code = -1, result = nu
|
||||
|
||||
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
|
||||
const offset = (pageNo - 1) * Number(pageSize);
|
||||
const ret =
|
||||
offset + Number(pageSize) >= array.length
|
||||
? array.slice(offset, array.length)
|
||||
: array.slice(offset, offset + Number(pageSize));
|
||||
return ret;
|
||||
return offset + Number(pageSize) >= array.length
|
||||
? array.slice(offset, array.length)
|
||||
: array.slice(offset, offset + Number(pageSize));
|
||||
}
|
||||
|
||||
export interface requestParams {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { MockMethod } from 'vite-plugin-mock';
|
||||
import { resultSuccess, resultError } from '../_util';
|
||||
import { ResultEnum } from '../../src/enums/httpEnum';
|
||||
|
||||
const userInfo = {
|
||||
name: 'Vben',
|
||||
@@ -59,4 +60,12 @@ export default [
|
||||
return resultError();
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/basic-api/user/tokenExpired',
|
||||
method: 'post',
|
||||
statusCode: 200,
|
||||
response: () => {
|
||||
return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number });
|
||||
},
|
||||
},
|
||||
] as MockMethod[];
|
||||
|
325
mock/demo/api-cascader.ts
Normal file
325
mock/demo/api-cascader.ts
Normal file
@@ -0,0 +1,325 @@
|
||||
import { MockMethod } from 'vite-plugin-mock';
|
||||
import { resultSuccess } from '../_util';
|
||||
|
||||
const areaList: any[] = [
|
||||
{
|
||||
id: '530825900854620160',
|
||||
code: '430000',
|
||||
parentCode: '100000',
|
||||
levelType: 1,
|
||||
name: '湖南省',
|
||||
province: '湖南省',
|
||||
city: null,
|
||||
district: null,
|
||||
town: null,
|
||||
village: null,
|
||||
parentPath: '430000',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 16:33:42',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530825900883980288',
|
||||
code: '430100',
|
||||
parentCode: '430000',
|
||||
levelType: 2,
|
||||
name: '长沙市',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: null,
|
||||
town: null,
|
||||
village: null,
|
||||
parentPath: '430000,430100',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 16:33:42',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530825900951089152',
|
||||
code: '430102',
|
||||
parentCode: '430100',
|
||||
levelType: 3,
|
||||
name: '芙蓉区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '芙蓉区',
|
||||
town: null,
|
||||
village: null,
|
||||
parentPath: '430000,430100,430102',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 16:33:42',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530825901014003712',
|
||||
code: '430104',
|
||||
parentCode: '430100',
|
||||
levelType: 3,
|
||||
name: '岳麓区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '岳麓区',
|
||||
town: null,
|
||||
village: null,
|
||||
parentPath: '430000,430100,430104',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 16:33:42',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530825900988837888',
|
||||
code: '430103',
|
||||
parentCode: '430100',
|
||||
levelType: 3,
|
||||
name: '天心区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: null,
|
||||
village: null,
|
||||
parentPath: '430000,430100,430103',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 16:33:42',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530826672489115648',
|
||||
code: '430103002',
|
||||
parentCode: '430103',
|
||||
levelType: 4,
|
||||
name: '坡子街街道',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: null,
|
||||
parentPath: '430000,430100,430103,430103002',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-12-14 15:26:43',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241171607552',
|
||||
code: '430103002001',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '八角亭社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '八角亭社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002001',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2021-01-20 14:07:23',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241200967680',
|
||||
code: '430103002002',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '西牌楼社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '西牌楼社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002002',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241230327808',
|
||||
code: '430103002003',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '太平街社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '太平街社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002003',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241259687936',
|
||||
code: '430103002005',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '坡子街社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '坡子街社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002005',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241284853760',
|
||||
code: '430103002006',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '青山祠社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '青山祠社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002006',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241310019584',
|
||||
code: '430103002007',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '沙河社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '沙河社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002007',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241381322752',
|
||||
code: '430103002008',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '碧湘社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '碧湘社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002008',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241410682880',
|
||||
code: '430103002009',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '创远社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '创远社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002009',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241431654400',
|
||||
code: '430103002010',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '楚湘社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '楚湘社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002010',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241465208832',
|
||||
code: '430103002011',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '西湖社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '西湖社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002011',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241502957568',
|
||||
code: '430103002012',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '登仁桥社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '登仁桥社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002012',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
{
|
||||
id: '530840241553289216',
|
||||
code: '430103002013',
|
||||
parentCode: '430103002',
|
||||
levelType: 5,
|
||||
name: '文庙坪社区',
|
||||
province: '湖南省',
|
||||
city: '长沙市',
|
||||
district: '天心区',
|
||||
town: '坡子街街道',
|
||||
village: '文庙坪社区',
|
||||
parentPath: '430000,430100,430103,430103002,430103002013',
|
||||
createTime: '2020-11-30 15:47:31',
|
||||
updateTime: '2020-11-30 17:30:41',
|
||||
customized: false,
|
||||
usable: true,
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
url: '/basic-api/cascader/getAreaRecord',
|
||||
timeout: 1000,
|
||||
method: 'post',
|
||||
response: ({ body }) => {
|
||||
const { parentCode } = body || {};
|
||||
if (!parentCode) {
|
||||
return resultSuccess(areaList.filter((it) => it.code === '430000'));
|
||||
}
|
||||
return resultSuccess(areaList.filter((it) => it.parentCode === parentCode));
|
||||
},
|
||||
},
|
||||
] as MockMethod[];
|
@@ -1,11 +1,11 @@
|
||||
import { MockMethod } from 'vite-plugin-mock';
|
||||
import { resultSuccess } from '../_util';
|
||||
|
||||
const demoList = (keyword) => {
|
||||
const demoList = (keyword, count = 20) => {
|
||||
const result = {
|
||||
list: [] as any[],
|
||||
};
|
||||
for (let index = 0; index < 20; index++) {
|
||||
for (let index = 0; index < count; index++) {
|
||||
result.list.push({
|
||||
name: `${keyword ?? ''}选项${index}`,
|
||||
id: `${index}`,
|
||||
@@ -20,9 +20,9 @@ export default [
|
||||
timeout: 1000,
|
||||
method: 'get',
|
||||
response: ({ query }) => {
|
||||
const { keyword } = query;
|
||||
const { keyword, count } = query;
|
||||
console.log(keyword);
|
||||
return resultSuccess(demoList(keyword));
|
||||
return resultSuccess(demoList(keyword, count));
|
||||
},
|
||||
},
|
||||
] as MockMethod[];
|
||||
|
@@ -12,7 +12,7 @@ function getRandomPics(count = 10): string[] {
|
||||
|
||||
const demoList = (() => {
|
||||
const result: any[] = [];
|
||||
for (let index = 0; index < 60; index++) {
|
||||
for (let index = 0; index < 200; index++) {
|
||||
result.push({
|
||||
id: `${index}`,
|
||||
beginTime: '@datetime',
|
||||
@@ -27,6 +27,9 @@ const demoList = (() => {
|
||||
name6: '@cname()',
|
||||
name7: '@cname()',
|
||||
name8: '@cname()',
|
||||
radio1: `选项${index + 1}`,
|
||||
radio2: `选项${index + 1}`,
|
||||
radio3: `选项${index + 1}`,
|
||||
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()),
|
||||
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1),
|
||||
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1),
|
||||
|
@@ -221,11 +221,11 @@ const linkRoute = {
|
||||
name: 'Doc',
|
||||
meta: {
|
||||
title: 'routes.demo.iframe.doc',
|
||||
frameSrc: 'https://vvbin.cn/doc-next/',
|
||||
frameSrc: 'https://doc.vvbin.cn/',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'https://vvbin.cn/doc-next/',
|
||||
path: 'https://doc.vvbin.cn/',
|
||||
name: 'DocExternal',
|
||||
component: 'LAYOUT',
|
||||
meta: {
|
||||
|
@@ -7,7 +7,7 @@ export function createFakeUserList() {
|
||||
userId: '1',
|
||||
username: 'vben',
|
||||
realName: 'Vben Admin',
|
||||
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640',
|
||||
avatar: '',
|
||||
desc: 'manager',
|
||||
password: '123456',
|
||||
token: 'fakeToken1',
|
||||
@@ -24,7 +24,7 @@ export function createFakeUserList() {
|
||||
username: 'test',
|
||||
password: '123456',
|
||||
realName: 'test user',
|
||||
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640',
|
||||
avatar: '',
|
||||
desc: 'tester',
|
||||
token: 'fakeToken2',
|
||||
homePath: '/dashboard/workbench',
|
||||
@@ -52,7 +52,7 @@ export default [
|
||||
response: ({ body }) => {
|
||||
const { username, password } = body;
|
||||
const checkUser = createFakeUserList().find(
|
||||
(item) => item.username === username && password === item.password
|
||||
(item) => item.username === username && password === item.password,
|
||||
);
|
||||
if (!checkUser) {
|
||||
return resultError('Incorrect account or password!');
|
||||
@@ -111,4 +111,12 @@ export default [
|
||||
return resultSuccess(undefined, { message: 'Token has been destroyed' });
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/basic-api/testRetry',
|
||||
statusCode: 405,
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return resultError('Error!');
|
||||
},
|
||||
},
|
||||
] as MockMethod[];
|
||||
|
234
package.json
234
package.json
@@ -1,18 +1,19 @@
|
||||
{
|
||||
"name": "vben-admin",
|
||||
"version": "2.7.0",
|
||||
"version": "2.9.0",
|
||||
"author": {
|
||||
"name": "vben",
|
||||
"email": "anncwb@126.com",
|
||||
"url": "https://github.com/anncwb"
|
||||
},
|
||||
"scripts": {
|
||||
"bootstrap": "yarn install",
|
||||
"commit": "czg",
|
||||
"bootstrap": "pnpm install",
|
||||
"serve": "npm run dev",
|
||||
"dev": "vite",
|
||||
"build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
|
||||
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
|
||||
"build:no-cache": "yarn clean:cache && npm run build",
|
||||
"build:no-cache": "pnpm clean:cache && npm run build",
|
||||
"report": "cross-env REPORT=true npm run build",
|
||||
"type:check": "vue-tsc --noEmit --skipLibCheck",
|
||||
"preview": "npm run build && vite preview",
|
||||
@@ -23,123 +24,137 @@
|
||||
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
|
||||
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
|
||||
"lint:pretty": "pretty-quick --staged",
|
||||
"lint:lint-staged": "lint-staged",
|
||||
"test:unit": "jest",
|
||||
"test:unit-coverage": "jest --coverage",
|
||||
"test:gzip": "http-server dist --cors --gzip -c-1",
|
||||
"test:br": "http-server dist --cors --brotli -c-1",
|
||||
"reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||
"test:gzip": "npx http-server dist --cors --gzip -c-1",
|
||||
"test:br": "npx http-server dist --cors --brotli -c-1",
|
||||
"reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
|
||||
"prepare": "husky install",
|
||||
"gen:icon": "esno ./build/generate/icon/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^2.0.3",
|
||||
"@logicflow/core": "^0.6.6",
|
||||
"@logicflow/extension": "^0.6.6",
|
||||
"@vueuse/core": "^5.2.0",
|
||||
"@zxcvbn-ts/core": "^1.0.0-beta.0",
|
||||
"ant-design-vue": "2.2.2",
|
||||
"axios": "^0.21.1",
|
||||
"codemirror": "^5.62.2",
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@iconify/iconify": "^2.2.1",
|
||||
"@logicflow/core": "^1.1.13",
|
||||
"@logicflow/extension": "^1.1.13",
|
||||
"@vue/runtime-core": "^3.2.33",
|
||||
"@vue/shared": "^3.2.33",
|
||||
"@vueuse/core": "^8.3.0",
|
||||
"@vueuse/shared": "^8.3.0",
|
||||
"@zxcvbn-ts/core": "^2.0.1",
|
||||
"ant-design-vue": "^3.2.0",
|
||||
"axios": "^0.26.1",
|
||||
"codemirror": "^5.65.3",
|
||||
"cropperjs": "^1.5.12",
|
||||
"crypto-js": "^4.1.1",
|
||||
"echarts": "^5.1.2",
|
||||
"intro.js": "^4.1.0",
|
||||
"dayjs": "^1.11.1",
|
||||
"echarts": "^5.3.2",
|
||||
"exceljs": "^4.3.0",
|
||||
"intro.js": "^5.1.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"pinia": "2.0.0-beta.5",
|
||||
"pinia": "2.0.12",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.4.4",
|
||||
"qrcode": "^1.5.0",
|
||||
"qs": "^6.10.3",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"sortablejs": "^1.14.0",
|
||||
"tinymce": "^5.8.2",
|
||||
"vditor": "^3.8.6",
|
||||
"vue": "3.1.5",
|
||||
"vue-i18n": "9.1.7",
|
||||
"vue-json-pretty": "^2.0.2",
|
||||
"vue-router": "^4.0.10",
|
||||
"vue-types": "^4.0.1",
|
||||
"xlsx": "^0.17.0"
|
||||
"showdown": "^2.1.0",
|
||||
"sortablejs": "^1.15.0",
|
||||
"tinymce": "^5.10.7",
|
||||
"vditor": "^3.8.13",
|
||||
"vue": "^3.2.45",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-json-pretty": "^2.0.6",
|
||||
"vue-router": "^4.0.14",
|
||||
"vue-types": "^4.1.1",
|
||||
"vxe-table": "^4.3.9",
|
||||
"vxe-table-plugin-export-xlsx": "^3.0.4",
|
||||
"xe-utils": "^3.5.7",
|
||||
"xlsx": "^0.18.5",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^13.1.0",
|
||||
"@commitlint/config-conventional": "^13.1.0",
|
||||
"@iconify/json": "^1.1.382",
|
||||
"@purge-icons/generated": "^0.7.0",
|
||||
"@types/codemirror": "^5.60.2",
|
||||
"@types/crypto-js": "^4.0.2",
|
||||
"@types/fs-extra": "^9.0.12",
|
||||
"@types/inquirer": "^7.3.3",
|
||||
"@commitlint/cli": "^16.2.3",
|
||||
"@commitlint/config-conventional": "^16.2.1",
|
||||
"@iconify/json": "^2.1.30",
|
||||
"@purge-icons/generated": "^0.8.1",
|
||||
"@types/codemirror": "^5.60.5",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/inquirer": "^8.2.1",
|
||||
"@types/intro.js": "^3.0.2",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/mockjs": "^1.0.4",
|
||||
"@types/node": "^16.4.10",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mockjs": "^1.0.6",
|
||||
"@types/node": "^17.0.25",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qrcode": "^1.4.1",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@types/showdown": "^1.9.4",
|
||||
"@types/sortablejs": "^1.10.7",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
||||
"@typescript-eslint/parser": "^4.29.0",
|
||||
"@vitejs/plugin-legacy": "^1.5.0",
|
||||
"@vitejs/plugin-vue": "^1.3.0",
|
||||
"@vitejs/plugin-vue-jsx": "^1.1.7",
|
||||
"@vue/compiler-sfc": "3.1.5",
|
||||
"@vue/test-utils": "^2.0.0-rc.12",
|
||||
"autoprefixer": "^10.3.1",
|
||||
"commitizen": "^4.2.4",
|
||||
"conventional-changelog-cli": "^2.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
||||
"@typescript-eslint/parser": "^5.20.0",
|
||||
"@vitejs/plugin-legacy": "^1.8.1",
|
||||
"@vitejs/plugin-vue": "^2.3.1",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@vue/compiler-sfc": "^3.2.33",
|
||||
"@vue/test-utils": "^2.0.0-rc.21",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-define-config": "^1.0.9",
|
||||
"eslint-plugin-jest": "^24.4.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-vue": "^7.15.0",
|
||||
"esno": "^0.8.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"http-server": "^0.12.3",
|
||||
"husky": "^7.0.1",
|
||||
"inquirer": "^8.1.2",
|
||||
"is-ci": "^3.0.0",
|
||||
"jest": "^27.0.6",
|
||||
"less": "^4.1.1",
|
||||
"lint-staged": "^11.1.1",
|
||||
"cz-git": "^1.3.9",
|
||||
"czg": "^1.3.9",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"esno": "^0.14.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"husky": "^7.0.4",
|
||||
"inquirer": "^8.2.2",
|
||||
"less": "^4.1.2",
|
||||
"lint-staged": "12.3.7",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.3.6",
|
||||
"prettier": "^2.3.2",
|
||||
"pretty-quick": "^3.1.1",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.12",
|
||||
"postcss-html": "^1.4.1",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^2.6.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup-plugin-visualizer": "5.5.2",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"ts-jest": "^27.0.4",
|
||||
"ts-node": "^10.1.0",
|
||||
"typescript": "4.3.5",
|
||||
"vite": "2.4.4",
|
||||
"vite-plugin-compression": "^0.3.3",
|
||||
"vite-plugin-html": "^2.0.7",
|
||||
"vite-plugin-imagemin": "^0.4.3",
|
||||
"vite-plugin-mock": "^2.9.4",
|
||||
"vite-plugin-purge-icons": "^0.7.0",
|
||||
"vite-plugin-pwa": "^0.9.3",
|
||||
"vite-plugin-style-import": "^1.1.0",
|
||||
"vite-plugin-svg-icons": "^1.0.3",
|
||||
"vite-plugin-theme": "^0.8.1",
|
||||
"vite-plugin-windicss": "^1.2.7",
|
||||
"vue-eslint-parser": "^7.10.0",
|
||||
"vue-tsc": "^0.2.2"
|
||||
"rollup": "^2.70.2",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "^1.57.1",
|
||||
"stylelint": "^14.7.1",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended": "^7.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.4.0",
|
||||
"stylelint-config-standard": "^25.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.6.3",
|
||||
"vite": "^2.9.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-plugin-mkcert": "^1.6.0",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-purge-icons": "^0.8.1",
|
||||
"vite-plugin-pwa": "^0.11.13",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-theme": "^0.8.6",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vite-plugin-windicss": "^1.8.4",
|
||||
"vue-eslint-parser": "^8.3.0",
|
||||
"vue-tsc": "^1.0.9"
|
||||
},
|
||||
"resolutions": {
|
||||
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it",
|
||||
"bin-wrapper": "npm:bin-wrapper-china",
|
||||
"rollup": "^2.55.1"
|
||||
"rollup": "^2.56.3",
|
||||
"gifsicle": "5.2.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -152,5 +167,34 @@
|
||||
"homepage": "https://github.com/anncwb/vue-vben-admin",
|
||||
"engines": {
|
||||
"node": "^12 || >=14"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx}": [
|
||||
"eslint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
|
||||
"prettier --write--parser json"
|
||||
],
|
||||
"package.json": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.vue": [
|
||||
"eslint --fix",
|
||||
"prettier --write",
|
||||
"stylelint --fix"
|
||||
],
|
||||
"*.{scss,less,styl,html}": [
|
||||
"stylelint --fix",
|
||||
"prettier --write"
|
||||
],
|
||||
"*.md": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-git"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11091
pnpm-lock.yaml
generated
Normal file
11091
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,10 @@
|
||||
module.exports = {
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
vueIndentScriptAndStyle: true,
|
||||
singleQuote: true,
|
||||
quoteProps: 'as-needed',
|
||||
bracketSpacing: true,
|
||||
trailingComma: 'es5',
|
||||
jsxBracketSameLine: false,
|
||||
jsxSingleQuote: false,
|
||||
arrowParens: 'always',
|
||||
insertPragma: false,
|
||||
requirePragma: false,
|
||||
trailingComma: 'all',
|
||||
proseWrap: 'never',
|
||||
htmlWhitespaceSensitivity: 'strict',
|
||||
endOfLine: 'auto',
|
||||
rangeStart: 0,
|
||||
};
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,14 +4,4 @@
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;}
|
||||
|
||||
body{-webkit-text-size-adjust: none;}
|
||||
|
||||
body img{max-width: 96vw;}
|
||||
|
||||
body table img{max-width: 95%;}
|
||||
|
||||
body{font-family: sans-serif;}
|
||||
|
||||
table{border-collapse: collapse;}
|
||||
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css
vendored
Normal file
7
public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,14 +4,4 @@
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;}
|
||||
|
||||
body{-webkit-text-size-adjust: none;}
|
||||
|
||||
body img{max-width: 96vw;}
|
||||
|
||||
body table img{max-width: 95%;}
|
||||
|
||||
body{font-family: sans-serif;}
|
||||
|
||||
table{border-collapse: collapse;}
|
||||
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}
|
||||
|
870
public/resource/tinymce/skins/ui/oxide/skin.min.css
vendored
870
public/resource/tinymce/skins/ui/oxide/skin.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css
vendored
Normal file
7
public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}
|
19
src/App.vue
19
src/App.vue
@@ -6,23 +6,16 @@
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { ConfigProvider } from 'ant-design-vue';
|
||||
import { AppProvider } from '/@/components/Application';
|
||||
import { useTitle } from '/@/hooks/web/useTitle';
|
||||
import { useLocale } from '/@/locales/useLocale';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: { ConfigProvider, AppProvider },
|
||||
setup() {
|
||||
useTitle();
|
||||
import 'dayjs/locale/zh-cn';
|
||||
// support Multi-language
|
||||
const { getAntdLocale } = useLocale();
|
||||
|
||||
// support Multi-language
|
||||
const { getAntdLocale } = useLocale();
|
||||
|
||||
return { getAntdLocale };
|
||||
},
|
||||
});
|
||||
// Listening to page changes and dynamically changing site titles
|
||||
useTitle();
|
||||
</script>
|
||||
|
@@ -4,6 +4,7 @@ import { GetAccountInfoModel } from './model/accountModel';
|
||||
enum Api {
|
||||
ACCOUNT_INFO = '/account/getAccountInfo',
|
||||
SESSION_TIMEOUT = '/user/sessionTimeout',
|
||||
TOKEN_EXPIRED = '/user/tokenExpired',
|
||||
}
|
||||
|
||||
// Get personal center-basic settings
|
||||
@@ -11,3 +12,5 @@ enum Api {
|
||||
export const accountInfoApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.ACCOUNT_INFO });
|
||||
|
||||
export const sessionTimeoutApi = () => defHttp.post<void>({ url: Api.SESSION_TIMEOUT });
|
||||
|
||||
export const tokenExpiredApi = () => defHttp.post<void>({ url: Api.TOKEN_EXPIRED });
|
||||
|
9
src/api/demo/cascader.ts
Normal file
9
src/api/demo/cascader.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { AreaModel, AreaParams } from '/@/api/demo/model/areaModel';
|
||||
|
||||
enum Api {
|
||||
AREA_RECORD = '/cascader/getAreaRecord',
|
||||
}
|
||||
|
||||
export const areaRecord = (data: AreaParams) =>
|
||||
defHttp.post<AreaModel>({ url: Api.AREA_RECORD, data });
|
12
src/api/demo/model/areaModel.ts
Normal file
12
src/api/demo/model/areaModel.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface AreaModel {
|
||||
id: string;
|
||||
code: string;
|
||||
parentCode: string;
|
||||
name: string;
|
||||
levelType: number;
|
||||
[key: string]: string | number;
|
||||
}
|
||||
|
||||
export interface AreaParams {
|
||||
parentCode: string;
|
||||
}
|
@@ -14,6 +14,7 @@ export const demoListApi = (params: DemoParams) =>
|
||||
url: Api.DEMO_LIST,
|
||||
params,
|
||||
headers: {
|
||||
// @ts-ignore
|
||||
ignoreCancelToken: true,
|
||||
},
|
||||
});
|
||||
|
@@ -3,7 +3,7 @@ export interface BasicPageParams {
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
export interface BasicFetchResult<T extends any> {
|
||||
export interface BasicFetchResult<T> {
|
||||
items: T[];
|
||||
total: number;
|
||||
}
|
||||
|
@@ -10,13 +10,13 @@ const { uploadUrl = '' } = useGlobSetting();
|
||||
*/
|
||||
export function uploadApi(
|
||||
params: UploadFileParams,
|
||||
onUploadProgress: (progressEvent: ProgressEvent) => void
|
||||
onUploadProgress: (progressEvent: ProgressEvent) => void,
|
||||
) {
|
||||
return defHttp.uploadFile<UploadApiResult>(
|
||||
{
|
||||
url: uploadUrl,
|
||||
onUploadProgress,
|
||||
},
|
||||
params
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ enum Api {
|
||||
Logout = '/logout',
|
||||
GetUserInfo = '/getUserInfo',
|
||||
GetPermCode = '/getPermCode',
|
||||
TestRetry = '/testRetry',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,7 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
|
||||
},
|
||||
{
|
||||
errorMessageMode: mode,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
|
||||
* @description: getUserInfo
|
||||
*/
|
||||
export function getUserInfo() {
|
||||
return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo });
|
||||
return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' });
|
||||
}
|
||||
|
||||
export function getPermCode() {
|
||||
@@ -39,3 +40,16 @@ export function getPermCode() {
|
||||
export function doLogout() {
|
||||
return defHttp.get({ url: Api.Logout });
|
||||
}
|
||||
|
||||
export function testRetry() {
|
||||
return defHttp.get(
|
||||
{ url: Api.TestRetry },
|
||||
{
|
||||
retryRequest: {
|
||||
isOpenRetry: true,
|
||||
count: 5,
|
||||
waitTime: 1000,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div v-if="getShowDarkModeToggle" :class="getClass" @click="toggleDarkMode">
|
||||
<div :class="`${prefixCls}-inner`"> </div>
|
||||
<div :class="`${prefixCls}-inner`"></div>
|
||||
<SvgIcon size="14" name="sun" />
|
||||
<SvgIcon size="14" name="moon" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import { SvgIcon } from '/@/components/Icon';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
@@ -14,46 +14,32 @@
|
||||
import { updateDarkTheme } from '/@/logics/theme/dark';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DarkModeToggle',
|
||||
components: { SvgIcon },
|
||||
setup() {
|
||||
const { prefixCls } = useDesign('dark-switch');
|
||||
const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
|
||||
const { prefixCls } = useDesign('dark-switch');
|
||||
const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
|
||||
|
||||
const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
|
||||
const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
|
||||
|
||||
const getClass = computed(() => [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--dark`]: unref(isDark),
|
||||
},
|
||||
]);
|
||||
|
||||
function toggleDarkMode() {
|
||||
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
|
||||
setDarkMode(darkMode);
|
||||
updateDarkTheme(darkMode);
|
||||
updateHeaderBgColor();
|
||||
updateSidebarBgColor();
|
||||
}
|
||||
|
||||
return {
|
||||
getClass,
|
||||
isDark,
|
||||
prefixCls,
|
||||
toggleDarkMode,
|
||||
getShowDarkModeToggle,
|
||||
};
|
||||
const getClass = computed(() => [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--dark`]: unref(isDark),
|
||||
},
|
||||
});
|
||||
]);
|
||||
|
||||
function toggleDarkMode() {
|
||||
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
|
||||
setDarkMode(darkMode);
|
||||
updateDarkTheme(darkMode);
|
||||
updateHeaderBgColor();
|
||||
updateSidebarBgColor();
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-dark-switch';
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.@{prefix-cls} {
|
||||
border: 1px solid rgb(196, 188, 188);
|
||||
border: 1px solid rgb(196 188 188);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,11 +4,11 @@
|
||||
-->
|
||||
<template>
|
||||
<Dropdown
|
||||
placement="bottomCenter"
|
||||
placement="bottom"
|
||||
:trigger="['click']"
|
||||
:dropMenuList="localeList"
|
||||
:selectedKeys="selectedKeys"
|
||||
@menuEvent="handleMenuEvent"
|
||||
@menu-event="handleMenuEvent"
|
||||
overlayClassName="app-locale-picker-overlay"
|
||||
>
|
||||
<span class="cursor-pointer flex items-center">
|
||||
@@ -17,16 +17,16 @@
|
||||
</span>
|
||||
</Dropdown>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import type { LocaleType } from '/#/config';
|
||||
import type { DropMenu } from '/@/components/Dropdown';
|
||||
import { defineComponent, ref, watchEffect, unref, computed } from 'vue';
|
||||
import { ref, watchEffect, unref, computed } from 'vue';
|
||||
import { Dropdown } from '/@/components/Dropdown';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { useLocale } from '/@/locales/useLocale';
|
||||
import { localeList } from '/@/settings/localeSetting';
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
/**
|
||||
* Whether to display text
|
||||
*/
|
||||
@@ -35,45 +35,36 @@
|
||||
* Whether to refresh the interface when changing
|
||||
*/
|
||||
reload: { type: Boolean },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AppLocalPicker',
|
||||
components: { Dropdown, Icon },
|
||||
props,
|
||||
setup(props) {
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
|
||||
const { changeLocale, getLocale } = useLocale();
|
||||
|
||||
const getLocaleText = computed(() => {
|
||||
const key = selectedKeys.value[0];
|
||||
if (!key) {
|
||||
return '';
|
||||
}
|
||||
return localeList.find((item) => item.event === key)?.text;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
selectedKeys.value = [unref(getLocale)];
|
||||
});
|
||||
|
||||
async function toggleLocale(lang: LocaleType | string) {
|
||||
await changeLocale(lang as LocaleType);
|
||||
selectedKeys.value = [lang as string];
|
||||
props.reload && location.reload();
|
||||
}
|
||||
|
||||
function handleMenuEvent(menu: DropMenu) {
|
||||
if (unref(getLocale) === menu.event) {
|
||||
return;
|
||||
}
|
||||
toggleLocale(menu.event as string);
|
||||
}
|
||||
|
||||
return { localeList, handleMenuEvent, selectedKeys, getLocaleText };
|
||||
},
|
||||
});
|
||||
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
|
||||
const { changeLocale, getLocale } = useLocale();
|
||||
|
||||
const getLocaleText = computed(() => {
|
||||
const key = selectedKeys.value[0];
|
||||
if (!key) {
|
||||
return '';
|
||||
}
|
||||
return localeList.find((item) => item.event === key)?.text;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
selectedKeys.value = [unref(getLocale)];
|
||||
});
|
||||
|
||||
async function toggleLocale(lang: LocaleType | string) {
|
||||
await changeLocale(lang as LocaleType);
|
||||
selectedKeys.value = [lang as string];
|
||||
props.reload && location.reload();
|
||||
}
|
||||
|
||||
function handleMenuEvent(menu: DropMenu) {
|
||||
if (unref(getLocale) === menu.event) {
|
||||
return;
|
||||
}
|
||||
toggleLocale(menu.event as string);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
@@ -10,8 +10,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
@@ -19,11 +19,11 @@
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
/**
|
||||
* The theme of the current parent component
|
||||
*/
|
||||
theme: { type: String, validator: (v) => ['light', 'dark'].includes(v) },
|
||||
theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
|
||||
/**
|
||||
* Whether to show title
|
||||
*/
|
||||
@@ -32,45 +32,30 @@
|
||||
* The title is also displayed when the menu is collapsed
|
||||
*/
|
||||
alwaysShowTitle: { type: Boolean },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AppLogo',
|
||||
props: props,
|
||||
setup(props) {
|
||||
const { prefixCls } = useDesign('app-logo');
|
||||
const { getCollapsedShowTitle } = useMenuSetting();
|
||||
const userStore = useUserStore();
|
||||
const { title } = useGlobSetting();
|
||||
const go = useGo();
|
||||
|
||||
const getAppLogoClass = computed(() => [
|
||||
prefixCls,
|
||||
props.theme,
|
||||
{ 'collapsed-show-title': unref(getCollapsedShowTitle) },
|
||||
]);
|
||||
|
||||
const getTitleClass = computed(() => [
|
||||
`${prefixCls}__title`,
|
||||
{
|
||||
'xs:opacity-0': !props.alwaysShowTitle,
|
||||
},
|
||||
]);
|
||||
|
||||
function goHome() {
|
||||
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
}
|
||||
|
||||
return {
|
||||
getAppLogoClass,
|
||||
getTitleClass,
|
||||
getCollapsedShowTitle,
|
||||
goHome,
|
||||
title,
|
||||
prefixCls,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const { prefixCls } = useDesign('app-logo');
|
||||
const { getCollapsedShowTitle } = useMenuSetting();
|
||||
const userStore = useUserStore();
|
||||
const { title } = useGlobSetting();
|
||||
const go = useGo();
|
||||
|
||||
const getAppLogoClass = computed(() => [
|
||||
prefixCls,
|
||||
props.theme,
|
||||
{ 'collapsed-show-title': unref(getCollapsedShowTitle) },
|
||||
]);
|
||||
|
||||
const getTitleClass = computed(() => [
|
||||
`${prefixCls}__title`,
|
||||
{
|
||||
'xs:opacity-0': !props.alwaysShowTitle,
|
||||
},
|
||||
]);
|
||||
|
||||
function goHome() {
|
||||
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-app-logo';
|
||||
@@ -102,6 +87,7 @@
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
transition: all 0.5s;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -10,20 +10,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import AppSearchKeyItem from './AppSearchKeyItem.vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
export default defineComponent({
|
||||
name: 'AppSearchFooter',
|
||||
components: { AppSearchKeyItem },
|
||||
setup() {
|
||||
const { prefixCls } = useDesign('app-search-footer');
|
||||
const { t } = useI18n();
|
||||
return { prefixCls, t };
|
||||
},
|
||||
});
|
||||
const { prefixCls } = useDesign('app-search-footer');
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-app-search-footer';
|
||||
@@ -50,7 +42,7 @@
|
||||
background-color: linear-gradient(-225deg, #d5dbe4, #f8f8f8);
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff,
|
||||
0 1px 2px 1px rgba(30, 35, 90, 0.4);
|
||||
0 1px 2px 1px rgb(30 35 90 / 40%);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
|
@@ -3,11 +3,9 @@
|
||||
<Icon :icon="icon" />
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { Icon } from '/@/components/Icon';
|
||||
export default defineComponent({
|
||||
components: { Icon },
|
||||
props: { icon: String },
|
||||
defineProps({
|
||||
icon: String,
|
||||
});
|
||||
</script>
|
||||
|
@@ -56,85 +56,62 @@
|
||||
</transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, unref, ref, watch, nextTick } from 'vue';
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref, ref, watch, nextTick } from 'vue';
|
||||
import { SearchOutlined } from '@ant-design/icons-vue';
|
||||
import AppSearchFooter from './AppSearchFooter.vue';
|
||||
import Icon from '/@/components/Icon';
|
||||
import clickOutside from '/@/directives/clickOutside';
|
||||
// @ts-ignore
|
||||
import vClickOutside from '/@/directives/clickOutside';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useRefs } from '/@/hooks/core/useRefs';
|
||||
import { useMenuSearch } from './useMenuSearch';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AppSearchModal',
|
||||
components: { Icon, SearchOutlined, AppSearchFooter },
|
||||
directives: {
|
||||
clickOutside,
|
||||
},
|
||||
props,
|
||||
emits: ['close'],
|
||||
setup(props, { emit }) {
|
||||
const scrollWrap = ref<ElRef>(null);
|
||||
const inputRef = ref<Nullable<HTMLElement>>(null);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('app-search-modal');
|
||||
const [refs, setRefs] = useRefs();
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
|
||||
useMenuSearch(refs, scrollWrap, emit);
|
||||
|
||||
const getIsNotData = computed(() => !keyword || unref(searchResult).length === 0);
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible: boolean) => {
|
||||
visible &&
|
||||
nextTick(() => {
|
||||
unref(inputRef)?.focus();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
function handleClose() {
|
||||
searchResult.value = [];
|
||||
emit('close');
|
||||
}
|
||||
|
||||
return {
|
||||
t,
|
||||
prefixCls,
|
||||
getClass,
|
||||
handleSearch,
|
||||
searchResult,
|
||||
activeIndex,
|
||||
getIsNotData,
|
||||
handleEnter,
|
||||
setRefs,
|
||||
scrollWrap,
|
||||
handleMouseenter,
|
||||
handleClose,
|
||||
inputRef,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
const scrollWrap = ref(null);
|
||||
const inputRef = ref<Nullable<HTMLElement>>(null);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('app-search-modal');
|
||||
const [refs, setRefs] = useRefs();
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
|
||||
useMenuSearch(refs, scrollWrap, emit);
|
||||
|
||||
const getIsNotData = computed(() => !keyword || unref(searchResult).length === 0);
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible: boolean) => {
|
||||
visible &&
|
||||
nextTick(() => {
|
||||
unref(inputRef)?.focus();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
function handleClose() {
|
||||
searchResult.value = [];
|
||||
emit('close');
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-app-search-modal';
|
||||
@@ -148,7 +125,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-top: 50px;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
background-color: rgb(0 0 0 / 25%);
|
||||
justify-content: center;
|
||||
|
||||
&--mobile {
|
||||
@@ -182,7 +159,7 @@
|
||||
|
||||
&__item {
|
||||
&-enter {
|
||||
opacity: 0 !important;
|
||||
opacity: 0% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,16 +168,16 @@
|
||||
&-content {
|
||||
position: relative;
|
||||
width: 632px;
|
||||
margin: 0 auto auto auto;
|
||||
margin: 0 auto auto;
|
||||
background-color: @component-background;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 25%);
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-input__wrapper {
|
||||
display: flex;
|
||||
padding: 14px 14px 0 14px;
|
||||
padding: 14px 14px 0;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -268,7 +245,7 @@
|
||||
background-color: @primary-color;
|
||||
|
||||
.@{prefix-cls}-list__item-enter {
|
||||
opacity: 1;
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +259,7 @@
|
||||
|
||||
&-enter {
|
||||
width: 30px;
|
||||
opacity: 0;
|
||||
opacity: 0%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,12 +7,12 @@
|
||||
<Icon icon="ion:chevron-forward" :style="$attrs.iconStyle" />
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
/**
|
||||
* Arrow expand state
|
||||
*/
|
||||
@@ -29,31 +29,22 @@
|
||||
* Cancel padding/margin for inline
|
||||
*/
|
||||
inset: { type: Boolean },
|
||||
};
|
||||
});
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicArrow',
|
||||
components: { Icon },
|
||||
props,
|
||||
setup(props) {
|
||||
const { prefixCls } = useDesign('basic-arrow');
|
||||
const { prefixCls } = useDesign('basic-arrow');
|
||||
|
||||
// get component class
|
||||
const getClass = computed(() => {
|
||||
const { expand, up, down, inset } = props;
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--active`]: expand,
|
||||
up,
|
||||
inset,
|
||||
down,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
return { getClass };
|
||||
},
|
||||
// get component class
|
||||
const getClass = computed(() => {
|
||||
const { expand, up, down, inset } = props;
|
||||
return [
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}--active`]: expand,
|
||||
up,
|
||||
inset,
|
||||
down,
|
||||
},
|
||||
];
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
@@ -47,7 +47,7 @@
|
||||
const { prefixCls } = useDesign('basic-help');
|
||||
|
||||
const getTooltipStyle = computed(
|
||||
(): CSSProperties => ({ color: props.color, fontSize: props.fontSize })
|
||||
(): CSSProperties => ({ color: props.color, fontSize: props.fontSize }),
|
||||
);
|
||||
|
||||
const getOverlayStyle = computed((): CSSProperties => ({ maxWidth: props.maxWidth }));
|
||||
|
@@ -4,13 +4,13 @@
|
||||
<BasicHelp :class="`${prefixCls}-help`" v-if="helpMessage" :text="helpMessage" />
|
||||
</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useSlots, computed } from 'vue';
|
||||
import BasicHelp from './BasicHelp.vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
/**
|
||||
* Help text list or string
|
||||
* @default: ''
|
||||
@@ -29,24 +29,15 @@
|
||||
* @default: false
|
||||
*/
|
||||
normal: { type: Boolean },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicTitle',
|
||||
components: { BasicHelp },
|
||||
props,
|
||||
setup(props, { slots }) {
|
||||
const { prefixCls } = useDesign('basic-title');
|
||||
|
||||
const getClass = computed(() => [
|
||||
prefixCls,
|
||||
{ [`${prefixCls}-show-span`]: props.span && slots.default },
|
||||
{ [`${prefixCls}-normal`]: props.normal },
|
||||
]);
|
||||
|
||||
return { prefixCls, getClass };
|
||||
},
|
||||
});
|
||||
|
||||
const { prefixCls } = useDesign('basic-title');
|
||||
const slots = useSlots();
|
||||
const getClass = computed(() => [
|
||||
prefixCls,
|
||||
{ [`${prefixCls}-show-span`]: props.span && slots.default },
|
||||
{ [`${prefixCls}-normal`]: props.normal },
|
||||
]);
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-basic-title';
|
||||
|
@@ -2,40 +2,40 @@
|
||||
<Button v-bind="getBindValue" :class="getButtonClass" @click="onClick">
|
||||
<template #default="data">
|
||||
<Icon :icon="preIcon" v-if="preIcon" :size="iconSize" />
|
||||
<slot v-bind="data"></slot>
|
||||
<slot v-bind="data || {}"></slot>
|
||||
<Icon :icon="postIcon" v-if="postIcon" :size="iconSize" />
|
||||
</template>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { Button } from 'ant-design-vue';
|
||||
export default defineComponent({
|
||||
name: 'AButton',
|
||||
extends: Button,
|
||||
inheritAttrs: false,
|
||||
});
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { computed, unref } from 'vue';
|
||||
import Icon from '/@/components/Icon/src/Icon.vue';
|
||||
import { buttonProps } from './props';
|
||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'AButton',
|
||||
components: { Button, Icon },
|
||||
inheritAttrs: false,
|
||||
props: buttonProps,
|
||||
setup(props) {
|
||||
// get component class
|
||||
const attrs = useAttrs({ excludeDefaultKeys: false });
|
||||
const getButtonClass = computed(() => {
|
||||
const { color, disabled } = props;
|
||||
return [
|
||||
{
|
||||
[`ant-btn-${color}`]: !!color,
|
||||
[`is-disabled`]: disabled,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
// get inherit binding value
|
||||
const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
|
||||
|
||||
return { getBindValue, getButtonClass };
|
||||
},
|
||||
const props = defineProps(buttonProps);
|
||||
// get component class
|
||||
const attrs = useAttrs({ excludeDefaultKeys: false });
|
||||
const getButtonClass = computed(() => {
|
||||
const { color, disabled } = props;
|
||||
return [
|
||||
{
|
||||
[`ant-btn-${color}`]: !!color,
|
||||
[`is-disabled`]: disabled,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
// get inherit binding value
|
||||
const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
|
||||
</script>
|
||||
|
@@ -20,7 +20,6 @@
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PopButton',
|
||||
components: { Popconfirm, BasicButton },
|
||||
inheritAttrs: false,
|
||||
props,
|
||||
setup(props, { slots }) {
|
||||
@@ -34,13 +33,13 @@
|
||||
okText: t('common.okText'),
|
||||
cancelText: t('common.cancelText'),
|
||||
},
|
||||
{ ...props, ...unref(attrs) }
|
||||
{ ...props, ...unref(attrs) },
|
||||
);
|
||||
});
|
||||
|
||||
return () => {
|
||||
const bindValues = omit(unref(getBindValues), 'icon');
|
||||
const btnBind = omit(bindValues, 'title');
|
||||
const btnBind = omit(bindValues, 'title') as Recordable;
|
||||
if (btnBind.disabled) btnBind.color = '';
|
||||
const Button = h(BasicButton, btnBind, extendSlots(slots));
|
||||
|
||||
|
@@ -1,5 +1,12 @@
|
||||
const validColors = ['primary', 'error', 'warning', 'success', ''] as const;
|
||||
type ButtonColorType = typeof validColors[number];
|
||||
|
||||
export const buttonProps = {
|
||||
color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) },
|
||||
color: {
|
||||
type: String as PropType<ButtonColorType>,
|
||||
validator: (v) => validColors.includes(v),
|
||||
default: '',
|
||||
},
|
||||
loading: { type: Boolean },
|
||||
disabled: { type: Boolean },
|
||||
/**
|
||||
|
4
src/components/CardList/index.ts
Normal file
4
src/components/CardList/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { withInstall } from '/@/utils';
|
||||
import cardList from './src/CardList.vue';
|
||||
|
||||
export const CardList = withInstall(cardList);
|
177
src/components/CardList/src/CardList.vue
Normal file
177
src/components/CardList/src/CardList.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<div class="p-4 mb-2 bg-white">
|
||||
<BasicForm @register="registerForm" />
|
||||
</div>
|
||||
<div class="p-2 bg-white">
|
||||
<List
|
||||
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
|
||||
:data-source="data"
|
||||
:pagination="paginationProp"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-end space-x-2"
|
||||
><slot name="header"></slot>
|
||||
<Tooltip>
|
||||
<template #title>
|
||||
<div class="w-50">每行显示数量</div
|
||||
><Slider
|
||||
id="slider"
|
||||
v-bind="sliderProp"
|
||||
v-model:value="grid"
|
||||
@change="sliderChange"
|
||||
/></template>
|
||||
<Button><TableOutlined /></Button>
|
||||
</Tooltip>
|
||||
<Tooltip @click="fetch">
|
||||
<template #title>刷新</template>
|
||||
<Button><RedoOutlined /></Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #renderItem="{ item }">
|
||||
<ListItem>
|
||||
<Card>
|
||||
<template #title></template>
|
||||
<template #cover>
|
||||
<div :class="height">
|
||||
<Image :src="item.imgs[0]" />
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<!-- <SettingOutlined key="setting" />-->
|
||||
<EditOutlined key="edit" />
|
||||
<Dropdown
|
||||
:trigger="['hover']"
|
||||
:dropMenuList="[
|
||||
{
|
||||
text: '删除',
|
||||
event: '1',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, item.id),
|
||||
},
|
||||
},
|
||||
]"
|
||||
popconfirm
|
||||
>
|
||||
<EllipsisOutlined key="ellipsis" />
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
<CardMeta>
|
||||
<template #title>
|
||||
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
|
||||
</template>
|
||||
<template #avatar>
|
||||
<Avatar :src="item.avatar" />
|
||||
</template>
|
||||
<template #description>{{ item.time }}</template>
|
||||
</CardMeta>
|
||||
</Card>
|
||||
</ListItem>
|
||||
</template>
|
||||
</List>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import {
|
||||
EditOutlined,
|
||||
EllipsisOutlined,
|
||||
RedoOutlined,
|
||||
TableOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue';
|
||||
import { Dropdown } from '/@/components/Dropdown';
|
||||
import { BasicForm, useForm } from '/@/components/Form';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { Button } from '/@/components/Button';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { useSlider, grid } from './data';
|
||||
const ListItem = List.Item;
|
||||
const CardMeta = Card.Meta;
|
||||
const TypographyText = Typography.Text;
|
||||
// 获取slider属性
|
||||
const sliderProp = computed(() => useSlider(4));
|
||||
// 组件接收参数
|
||||
const props = defineProps({
|
||||
// 请求API的参数
|
||||
params: propTypes.object.def({}),
|
||||
//api
|
||||
api: propTypes.func,
|
||||
});
|
||||
//暴露内部方法
|
||||
const emit = defineEmits(['getMethod', 'delete']);
|
||||
//数据
|
||||
const data = ref([]);
|
||||
// 切换每行个数
|
||||
// cover图片自适应高度
|
||||
//修改pageSize并重新请求数据
|
||||
|
||||
const height = computed(() => {
|
||||
return `h-${120 - grid.value * 6}`;
|
||||
});
|
||||
//表单
|
||||
const [registerForm, { validate }] = useForm({
|
||||
schemas: [{ field: 'type', component: 'Input', label: '类型' }],
|
||||
labelWidth: 80,
|
||||
baseColProps: { span: 6 },
|
||||
actionColOptions: { span: 24 },
|
||||
autoSubmitOnEnter: true,
|
||||
submitFunc: handleSubmit,
|
||||
});
|
||||
//表单提交
|
||||
async function handleSubmit() {
|
||||
const data = await validate();
|
||||
await fetch(data);
|
||||
}
|
||||
function sliderChange(n) {
|
||||
pageSize.value = n * 4;
|
||||
fetch();
|
||||
}
|
||||
|
||||
// 自动请求并暴露内部方法
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
emit('getMethod', fetch);
|
||||
});
|
||||
|
||||
async function fetch(p = {}) {
|
||||
const { api, params } = props;
|
||||
if (api && isFunction(api)) {
|
||||
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p });
|
||||
data.value = res.items;
|
||||
total.value = res.total;
|
||||
}
|
||||
}
|
||||
//分页相关
|
||||
const page = ref(1);
|
||||
const pageSize = ref(36);
|
||||
const total = ref(0);
|
||||
const paginationProp = ref({
|
||||
showSizeChanger: false,
|
||||
showQuickJumper: true,
|
||||
pageSize,
|
||||
current: page,
|
||||
total,
|
||||
showTotal: (total) => `总 ${total} 条`,
|
||||
onChange: pageChange,
|
||||
onShowSizeChange: pageSizeChange,
|
||||
});
|
||||
|
||||
function pageChange(p, pz) {
|
||||
page.value = p;
|
||||
pageSize.value = pz;
|
||||
fetch();
|
||||
}
|
||||
function pageSizeChange(_current, size) {
|
||||
pageSize.value = size;
|
||||
fetch();
|
||||
}
|
||||
|
||||
async function handleDelete(id) {
|
||||
emit('delete', id);
|
||||
}
|
||||
</script>
|
25
src/components/CardList/src/data.ts
Normal file
25
src/components/CardList/src/data.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ref } from 'vue';
|
||||
// 每行个数
|
||||
export const grid = ref(12);
|
||||
// slider属性
|
||||
export const useSlider = (min = 6, max = 12) => {
|
||||
// 每行显示个数滑动条
|
||||
const getMarks = () => {
|
||||
const l = {};
|
||||
for (let i = min; i < max + 1; i++) {
|
||||
l[i] = {
|
||||
style: {
|
||||
color: '#fff',
|
||||
},
|
||||
label: i,
|
||||
};
|
||||
}
|
||||
return l;
|
||||
};
|
||||
return {
|
||||
min,
|
||||
max,
|
||||
marks: getMarks(),
|
||||
step: 1,
|
||||
};
|
||||
};
|
@@ -3,24 +3,17 @@
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, onMounted } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { onClickOutside } from '@vueuse/core';
|
||||
export default defineComponent({
|
||||
name: 'ClickOutSide',
|
||||
emits: ['mounted', 'clickOutside'],
|
||||
setup(_, { emit }) {
|
||||
const wrap = ref<ElRef>(null);
|
||||
const emit = defineEmits(['mounted', 'clickOutside']);
|
||||
const wrap = ref<ElRef>(null);
|
||||
|
||||
onClickOutside(wrap, () => {
|
||||
emit('clickOutside');
|
||||
});
|
||||
onClickOutside(wrap, () => {
|
||||
emit('clickOutside');
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
emit('mounted');
|
||||
});
|
||||
|
||||
return { wrap };
|
||||
},
|
||||
onMounted(() => {
|
||||
emit('mounted');
|
||||
});
|
||||
</script>
|
||||
|
@@ -4,3 +4,5 @@ import jsonPreview from './src/json-preview/JsonPreview.vue';
|
||||
|
||||
export const CodeEditor = withInstall(codeEditor);
|
||||
export const JsonPreview = withInstall(jsonPreview);
|
||||
|
||||
export * from './src/typing';
|
||||
|
@@ -8,45 +8,47 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { MODE } from './typing';
|
||||
|
||||
const MODE = {
|
||||
JSON: 'application/json',
|
||||
html: 'htmlmixed',
|
||||
js: 'javascript',
|
||||
};
|
||||
|
||||
const props = {
|
||||
const props = defineProps({
|
||||
value: { type: [Object, String] as PropType<Record<string, any> | string> },
|
||||
mode: { type: String, default: MODE.JSON },
|
||||
readonly: { type: Boolean },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CodeEditor',
|
||||
components: { CodeMirrorEditor },
|
||||
props,
|
||||
emits: ['change', 'update:value'],
|
||||
setup(props, { emit }) {
|
||||
const getValue = computed(() => {
|
||||
const { value, mode } = props;
|
||||
if (mode !== MODE.JSON) {
|
||||
return value as string;
|
||||
}
|
||||
return isString(value)
|
||||
? JSON.stringify(JSON.parse(value), null, 2)
|
||||
: JSON.stringify(value, null, 2);
|
||||
});
|
||||
|
||||
function handleValueChange(v) {
|
||||
emit('update:value', v);
|
||||
emit('change', v);
|
||||
}
|
||||
|
||||
return { handleValueChange, getValue };
|
||||
mode: {
|
||||
type: String as PropType<MODE>,
|
||||
default: MODE.JSON,
|
||||
validator(value: any) {
|
||||
// 这个值必须匹配下列字符串中的一个
|
||||
return Object.values(MODE).includes(value);
|
||||
},
|
||||
},
|
||||
readonly: { type: Boolean },
|
||||
autoFormat: { type: Boolean, default: true },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change', 'update:value', 'format-error']);
|
||||
|
||||
const getValue = computed(() => {
|
||||
const { value, mode, autoFormat } = props;
|
||||
if (!autoFormat || mode !== MODE.JSON) {
|
||||
return value as string;
|
||||
}
|
||||
let result = value;
|
||||
if (isString(value)) {
|
||||
try {
|
||||
result = JSON.parse(value);
|
||||
} catch (e) {
|
||||
emit('format-error', value);
|
||||
return value as string;
|
||||
}
|
||||
}
|
||||
return JSON.stringify(result, null, 2);
|
||||
});
|
||||
|
||||
function handleValueChange(v) {
|
||||
emit('update:value', v);
|
||||
emit('change', v);
|
||||
}
|
||||
</script>
|
||||
|
@@ -1,22 +1,14 @@
|
||||
<template>
|
||||
<div class="relative !h-full w-full overflow-hidden" ref="el"> </div>
|
||||
<div class="relative !h-full w-full overflow-hidden" ref="el"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
watchEffect,
|
||||
watch,
|
||||
defineComponent,
|
||||
unref,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onUnmounted, watchEffect, watch, unref, nextTick } from 'vue';
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
|
||||
import CodeMirror from 'codemirror';
|
||||
import { MODE } from './../typing';
|
||||
// css
|
||||
import './codemirror.css';
|
||||
import 'codemirror/theme/idea.css';
|
||||
@@ -26,95 +18,96 @@
|
||||
import 'codemirror/mode/css/css';
|
||||
import 'codemirror/mode/htmlmixed/htmlmixed';
|
||||
|
||||
const props = {
|
||||
mode: { type: String, default: 'application/json' },
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
type: String as PropType<MODE>,
|
||||
default: MODE.JSON,
|
||||
validator(value: any) {
|
||||
// 这个值必须匹配下列字符串中的一个
|
||||
return Object.values(MODE).includes(value);
|
||||
},
|
||||
},
|
||||
value: { type: String, default: '' },
|
||||
readonly: { type: Boolean, default: false },
|
||||
};
|
||||
});
|
||||
|
||||
export default defineComponent({
|
||||
props,
|
||||
emits: ['change'],
|
||||
setup(props, { emit }) {
|
||||
const el = ref();
|
||||
let editor: Nullable<CodeMirror.Editor>;
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const debounceRefresh = useDebounceFn(refresh, 100);
|
||||
const appStore = useAppStore();
|
||||
const el = ref();
|
||||
let editor: Nullable<CodeMirror.Editor>;
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
async (value) => {
|
||||
await nextTick();
|
||||
const oldValue = editor?.getValue();
|
||||
if (value !== oldValue) {
|
||||
editor?.setValue(value ? value : '');
|
||||
}
|
||||
},
|
||||
{ flush: 'post' }
|
||||
);
|
||||
const debounceRefresh = useDebounceFn(refresh, 100);
|
||||
const appStore = useAppStore();
|
||||
|
||||
watchEffect(() => {
|
||||
editor?.setOption('mode', props.mode);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => appStore.getDarkMode,
|
||||
async () => {
|
||||
setTheme();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
function setTheme() {
|
||||
unref(editor)?.setOption(
|
||||
'theme',
|
||||
appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight'
|
||||
);
|
||||
watch(
|
||||
() => props.value,
|
||||
async (value) => {
|
||||
await nextTick();
|
||||
const oldValue = editor?.getValue();
|
||||
if (value !== oldValue) {
|
||||
editor?.setValue(value ? value : '');
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
editor?.refresh();
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const addonOptions = {
|
||||
autoCloseBrackets: true,
|
||||
autoCloseTags: true,
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers'],
|
||||
};
|
||||
|
||||
editor = CodeMirror(el.value!, {
|
||||
value: '',
|
||||
mode: props.mode,
|
||||
readOnly: props.readonly,
|
||||
tabSize: 2,
|
||||
theme: 'material-palenight',
|
||||
lineWrapping: true,
|
||||
lineNumbers: true,
|
||||
...addonOptions,
|
||||
});
|
||||
editor?.setValue(props.value);
|
||||
setTheme();
|
||||
editor?.on('change', () => {
|
||||
emit('change', editor?.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
init();
|
||||
useWindowSizeFn(debounceRefresh);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
editor = null;
|
||||
});
|
||||
|
||||
return { el };
|
||||
},
|
||||
{ flush: 'post' },
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
editor?.setOption('mode', props.mode);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => appStore.getDarkMode,
|
||||
async () => {
|
||||
setTheme();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
function setTheme() {
|
||||
unref(editor)?.setOption(
|
||||
'theme',
|
||||
appStore.getDarkMode === 'light' ? 'idea' : 'material-palenight',
|
||||
);
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
editor?.refresh();
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const addonOptions = {
|
||||
autoCloseBrackets: true,
|
||||
autoCloseTags: true,
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers'],
|
||||
};
|
||||
|
||||
editor = CodeMirror(el.value!, {
|
||||
value: '',
|
||||
mode: props.mode,
|
||||
readOnly: props.readonly,
|
||||
tabSize: 2,
|
||||
theme: 'material-palenight',
|
||||
lineWrapping: true,
|
||||
lineNumbers: true,
|
||||
...addonOptions,
|
||||
});
|
||||
editor?.setValue(props.value);
|
||||
setTheme();
|
||||
editor?.on('change', () => {
|
||||
emit('change', editor?.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
init();
|
||||
useWindowSizeFn(debounceRefresh);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
editor = null;
|
||||
});
|
||||
</script>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
.CodeMirror {
|
||||
--base: #545281;
|
||||
--comment: hsl(210, 25%, 60%);
|
||||
--comment: hsl(210deg 25% 60%);
|
||||
--keyword: #af4ab1;
|
||||
--variable: #0055d1;
|
||||
--function: #c25205;
|
||||
@@ -125,9 +125,7 @@
|
||||
}
|
||||
|
||||
.cm-fat-cursor-mark {
|
||||
background-color: rgba(20, 255, 20, 0.5);
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
background-color: rgb(20 255 20 / 50%);
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
}
|
||||
|
||||
@@ -135,16 +133,14 @@
|
||||
width: auto;
|
||||
background-color: #7e7;
|
||||
border: 0;
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
}
|
||||
@-moz-keyframes blink {
|
||||
@keyframes blink {
|
||||
50% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
@keyframes blink {
|
||||
50% {
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -294,7 +290,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||
}
|
||||
|
||||
.CodeMirror-matchingtag {
|
||||
background: rgba(255, 150, 0, 0.3);
|
||||
background: rgb(255 150 0 / 30%);
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background {
|
||||
@@ -394,7 +390,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.CodeMirror-gutter-wrapper ::-moz-selection {
|
||||
.CodeMirrorwrapper ::selection {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@@ -414,11 +410,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||
border-width: 0;
|
||||
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-font-variant-ligatures: contextual;
|
||||
font-variant-ligatures: contextual;
|
||||
}
|
||||
|
||||
@@ -457,7 +450,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
@@ -505,15 +497,9 @@ div.CodeMirror-dragcursors {
|
||||
background: #d7d4f0;
|
||||
}
|
||||
|
||||
.CodeMirror-line::-moz-selection,
|
||||
.CodeMirror-line > span::-moz-selection,
|
||||
.CodeMirror-line > span > span::-moz-selection {
|
||||
background: #d7d4f0;
|
||||
}
|
||||
|
||||
.cm-searching {
|
||||
background-color: #ffa;
|
||||
background-color: rgba(255, 255, 0, 0.4);
|
||||
background-color: rgb(255 255 0 / 40%);
|
||||
}
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
|
@@ -2,13 +2,11 @@
|
||||
<vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import VueJsonPretty from 'vue-json-pretty';
|
||||
import 'vue-json-pretty/lib/styles.css';
|
||||
import { defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'JsonPreview',
|
||||
components: { VueJsonPretty },
|
||||
props: { data: Object },
|
||||
|
||||
defineProps({
|
||||
data: Object,
|
||||
});
|
||||
</script>
|
||||
|
5
src/components/CodeEditor/src/typing.ts
Normal file
5
src/components/CodeEditor/src/typing.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum MODE {
|
||||
JSON = 'application/json',
|
||||
HTML = 'htmlmixed',
|
||||
JS = 'javascript',
|
||||
}
|
@@ -54,7 +54,7 @@
|
||||
return;
|
||||
}
|
||||
nextTick(() => {
|
||||
const wrap = unref(scrollbar.wrap);
|
||||
const wrap = unref(scrollbar.wrap) as any;
|
||||
if (!wrap) {
|
||||
return;
|
||||
}
|
||||
|
@@ -1,40 +1,14 @@
|
||||
<template>
|
||||
<div :class="prefixCls">
|
||||
<CollapseHeader v-bind="$props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
|
||||
<template #title>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
<template #action>
|
||||
<slot name="action"></slot>
|
||||
</template>
|
||||
</CollapseHeader>
|
||||
|
||||
<div class="p-2">
|
||||
<CollapseTransition :enable="canExpan">
|
||||
<Skeleton v-if="loading" :active="loading" />
|
||||
<div :class="`${prefixCls}__body`" v-else v-show="show">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</CollapseTransition>
|
||||
</div>
|
||||
<div :class="`${prefixCls}__footer`" v-if="$slots.footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
// component
|
||||
<script lang="tsx">
|
||||
import { ref, unref, defineComponent, type PropType, type ExtractPropTypes } from 'vue';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { Skeleton } from 'ant-design-vue';
|
||||
import { CollapseTransition } from '/@/components/Transition';
|
||||
import CollapseHeader from './CollapseHeader.vue';
|
||||
import { triggerWindowResize } from '/@/utils/event';
|
||||
// hook
|
||||
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
const props = {
|
||||
const collapseContainerProps = {
|
||||
title: { type: String, default: '' },
|
||||
loading: { type: Boolean },
|
||||
/**
|
||||
@@ -59,38 +33,58 @@
|
||||
lazyTime: { type: Number, default: 0 },
|
||||
};
|
||||
|
||||
export type CollapseContainerProps = ExtractPropTypes<typeof collapseContainerProps>;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CollapseContainer',
|
||||
components: {
|
||||
Skeleton,
|
||||
CollapseHeader,
|
||||
CollapseTransition,
|
||||
},
|
||||
props,
|
||||
setup(props) {
|
||||
const show = ref(true);
|
||||
|
||||
props: collapseContainerProps,
|
||||
|
||||
setup(props, { expose, slots }) {
|
||||
const { prefixCls } = useDesign('collapse-container');
|
||||
|
||||
/**
|
||||
* @description: Handling development events
|
||||
*/
|
||||
function handleExpand() {
|
||||
show.value = !show.value;
|
||||
const show = ref(true);
|
||||
|
||||
const handleExpand = (val: boolean) => {
|
||||
show.value = isNil(val) ? !show.value : val;
|
||||
if (props.triggerWindowResize) {
|
||||
// 200 milliseconds here is because the expansion has animation,
|
||||
useTimeoutFn(triggerWindowResize, 200);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
show,
|
||||
handleExpand,
|
||||
prefixCls,
|
||||
};
|
||||
|
||||
expose({ handleExpand });
|
||||
|
||||
return () => (
|
||||
<div class={unref(prefixCls)}>
|
||||
<CollapseHeader
|
||||
{...props}
|
||||
prefixCls={unref(prefixCls)}
|
||||
onExpand={handleExpand}
|
||||
show={show.value}
|
||||
v-slots={{
|
||||
title: slots.title,
|
||||
action: slots.action,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="p-2">
|
||||
<CollapseTransition enable={props.canExpan}>
|
||||
{props.loading ? (
|
||||
<Skeleton active={props.loading} />
|
||||
) : (
|
||||
<div class={`${prefixCls}__body`} v-show={show.value}>{slots.default?.()}</div>
|
||||
)}
|
||||
</CollapseTransition>
|
||||
</div>
|
||||
|
||||
{slots.footer && <div class={`${prefixCls}__footer`}>{slots.footer()}</div>}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{namespace}-collapse-container';
|
||||
|
||||
|
@@ -1,38 +1,44 @@
|
||||
<template>
|
||||
<div :class="[`${prefixCls}__header px-2 py-5`, $attrs.class]">
|
||||
<BasicTitle :helpMessage="helpMessage" normal>
|
||||
<template v-if="title">
|
||||
{{ title }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
</BasicTitle>
|
||||
<div :class="`${prefixCls}__action`">
|
||||
<slot name="action"></slot>
|
||||
<BasicArrow v-if="canExpan" up :expand="show" @click="$emit('expand')" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="tsx">
|
||||
import { defineComponent, computed, unref, type ExtractPropTypes } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { BasicArrow, BasicTitle } from '/@/components/Basic';
|
||||
|
||||
const props = {
|
||||
prefixCls: { type: String },
|
||||
const collapseHeaderProps = {
|
||||
prefixCls: String,
|
||||
title: String,
|
||||
show: Boolean,
|
||||
canExpan: Boolean,
|
||||
helpMessage: {
|
||||
type: [Array, String] as PropType<string[] | string>,
|
||||
default: '',
|
||||
},
|
||||
title: { type: String },
|
||||
show: { type: Boolean },
|
||||
canExpan: { type: Boolean },
|
||||
};
|
||||
|
||||
export type CollapseHeaderProps = ExtractPropTypes<typeof collapseHeaderProps>;
|
||||
|
||||
export default defineComponent({
|
||||
components: { BasicArrow, BasicTitle },
|
||||
name: 'CollapseHeader',
|
||||
inheritAttrs: false,
|
||||
props,
|
||||
props: collapseHeaderProps,
|
||||
emits: ['expand'],
|
||||
setup(props, { slots, attrs, emit }) {
|
||||
const { prefixCls } = useDesign('collapse-container');
|
||||
const _prefixCls = computed(() => props.prefixCls || unref(prefixCls));
|
||||
return () => (
|
||||
<div class={[`${unref(_prefixCls)}__header px-2 py-5`, attrs.class]}>
|
||||
<BasicTitle helpMessage={props.helpMessage} normal>
|
||||
{slots.title?.() || props.title}
|
||||
</BasicTitle>
|
||||
|
||||
<div class={`${unref(_prefixCls)}__action`}>
|
||||
{slots.action
|
||||
? slots.action({ expand: props.show, onClick: () => emit('expand') })
|
||||
: props.canExpan && (
|
||||
<BasicArrow up expand={props.show} onClick={() => emit('expand')} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<script lang="tsx">
|
||||
import type { ContextMenuItem, ItemContentProps, Axis } from './typing';
|
||||
import type { FunctionalComponent, CSSProperties } from 'vue';
|
||||
import type { FunctionalComponent, CSSProperties, PropType } from 'vue';
|
||||
import { defineComponent, nextTick, onMounted, computed, ref, unref, onUnmounted } from 'vue';
|
||||
import Icon from '/@/components/Icon';
|
||||
import { Menu, Divider } from 'ant-design-vue';
|
||||
@@ -46,7 +46,7 @@
|
||||
name: 'ContextMenu',
|
||||
props,
|
||||
setup(props) {
|
||||
const wrapRef = ref<ElRef>(null);
|
||||
const wrapRef = ref(null);
|
||||
const showRef = ref(false);
|
||||
|
||||
const getStyle = computed((): CSSProperties => {
|
||||
@@ -60,9 +60,11 @@
|
||||
const top = body.clientHeight < y + menuHeight ? y - menuHeight : y;
|
||||
return {
|
||||
...styles,
|
||||
position: 'absolute',
|
||||
width: `${width}px`,
|
||||
left: `${left + 1}px`,
|
||||
top: `${top + 1}px`,
|
||||
zIndex: 9999,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -87,7 +89,8 @@
|
||||
}
|
||||
|
||||
function renderMenuItem(items: ContextMenuItem[]) {
|
||||
return items.map((item) => {
|
||||
const visibleItems = items.filter((item) => !item.hidden);
|
||||
return visibleItems.map((item) => {
|
||||
const { disabled, label, children, divider = false } = item;
|
||||
|
||||
const contentProps = {
|
||||
@@ -124,15 +127,11 @@
|
||||
}
|
||||
const { items } = props;
|
||||
return (
|
||||
<Menu
|
||||
inlineIndent={12}
|
||||
mode="vertical"
|
||||
class={prefixCls}
|
||||
ref={wrapRef}
|
||||
style={unref(getStyle)}
|
||||
>
|
||||
{renderMenuItem(items)}
|
||||
</Menu>
|
||||
<div class={prefixCls}>
|
||||
<Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
|
||||
{renderMenuItem(items)}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
@@ -178,22 +177,25 @@
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
background-color: @component-background;
|
||||
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid rgb(0 0 0 / 8%);
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.1),
|
||||
0 1px 5px 0 rgba(0, 0, 0, 0.06);
|
||||
box-shadow: 0 2px 2px 0 rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 10%),
|
||||
0 1px 5px 0 rgb(0 0 0 / 6%);
|
||||
background-clip: padding-box;
|
||||
user-select: none;
|
||||
|
||||
&__item {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.item-style();
|
||||
|
||||
.ant-divider {
|
||||
margin: 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__popup {
|
||||
.ant-divider {
|
||||
margin: 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.item-style();
|
||||
|
@@ -6,6 +6,7 @@ export interface Axis {
|
||||
export interface ContextMenuItem {
|
||||
label: string;
|
||||
icon?: string;
|
||||
hidden?: boolean;
|
||||
disabled?: boolean;
|
||||
handler?: Fn;
|
||||
divider?: boolean;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<CountButton :size="size" :count="count" :value="state" :beforeStartFunc="sendCodeApi" />
|
||||
</template>
|
||||
<template #[item]="data" v-for="item in Object.keys($slots).filter((k) => k !== 'addonAfter')">
|
||||
<slot :name="item" v-bind="data"></slot>
|
||||
<slot :name="item" v-bind="data || {}"></slot>
|
||||
</template>
|
||||
</a-input>
|
||||
</template>
|
||||
|
@@ -122,11 +122,14 @@
|
||||
import { isFunction } from '/@/utils/is';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
type apiFunParams = { file: Blob; name: string; filename: string };
|
||||
|
||||
const props = {
|
||||
circled: { type: Boolean, default: true },
|
||||
uploadApi: {
|
||||
type: Function as PropType<({ file: Blob, name: string, filename: string }) => Promise<any>>,
|
||||
type: Function as PropType<(params: apiFunParams) => Promise<any>>,
|
||||
},
|
||||
src: { type: String },
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
@@ -136,7 +139,7 @@
|
||||
emits: ['uploadSuccess', 'register'],
|
||||
setup(props, { emit }) {
|
||||
let filename = '';
|
||||
const src = ref('');
|
||||
const src = ref(props.src || '');
|
||||
const previewSource = ref('');
|
||||
const cropper = ref<Cropper>();
|
||||
let scaleX = 1;
|
||||
@@ -184,7 +187,7 @@
|
||||
try {
|
||||
setModalProps({ confirmLoading: true });
|
||||
const result = await uploadApi({ name: 'file', file: blob, filename });
|
||||
emit('uploadSuccess', { source: previewSource.value, data: result.data });
|
||||
emit('uploadSuccess', { source: previewSource.value, data: result.url });
|
||||
closeModal();
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
@@ -232,17 +235,17 @@
|
||||
background: #eee;
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
rgba(0, 0, 0, 0.25) 25%,
|
||||
rgb(0 0 0 / 25%) 25%,
|
||||
transparent 0,
|
||||
transparent 75%,
|
||||
rgba(0, 0, 0, 0.25) 0
|
||||
rgb(0 0 0 / 25%) 0
|
||||
),
|
||||
linear-gradient(
|
||||
45deg,
|
||||
rgba(0, 0, 0, 0.25) 25%,
|
||||
rgb(0 0 0 / 25%) 25%,
|
||||
transparent 0,
|
||||
transparent 75%,
|
||||
rgba(0, 0, 0, 0.25) 0
|
||||
rgb(0 0 0 / 25%) 0
|
||||
);
|
||||
background-position: 0 0, 12px 12px;
|
||||
background-size: 24px 24px;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import { defineComponent, onMounted, ref, unref, computed } from 'vue';
|
||||
import { defineComponent, onMounted, ref, unref, computed, onUnmounted } from 'vue';
|
||||
import Cropper from 'cropperjs';
|
||||
import 'cropperjs/dist/cropper.css';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
@@ -93,6 +93,10 @@
|
||||
|
||||
onMounted(init);
|
||||
|
||||
onUnmounted(() => {
|
||||
cropper.value?.destroy();
|
||||
});
|
||||
|
||||
async function init() {
|
||||
const imgEl = unref(imgElRef);
|
||||
if (!imgEl) {
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
<CopperModal
|
||||
@register="register"
|
||||
@uploadSuccess="handleUploadSuccess"
|
||||
@upload-success="handleUploadSuccess"
|
||||
:uploadApi="uploadApi"
|
||||
:src="sourceValue"
|
||||
/>
|
||||
@@ -77,7 +77,7 @@
|
||||
const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) }));
|
||||
|
||||
const getImageWrapperStyle = computed(
|
||||
(): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) })
|
||||
(): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) }),
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
@@ -88,12 +88,12 @@
|
||||
() => sourceValue.value,
|
||||
(v: string) => {
|
||||
emit('update:value', v);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function handleUploadSuccess({ source }) {
|
||||
function handleUploadSuccess({ source, data }) {
|
||||
sourceValue.value = source;
|
||||
emit('change', source);
|
||||
emit('change', { source, data });
|
||||
createMessage.success(t('component.cropper.uploadSuccess'));
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
t,
|
||||
prefixCls,
|
||||
register,
|
||||
openModal,
|
||||
openModal: openModal as any,
|
||||
getIconWidth,
|
||||
sourceValue,
|
||||
getClass,
|
||||
@@ -135,15 +135,14 @@
|
||||
}
|
||||
|
||||
&-image-mask {
|
||||
opacity: 0;
|
||||
opacity: 0%;
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: inherit;
|
||||
border: inherit;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
background: rgb(0 0 0 / 40%);
|
||||
cursor: pointer;
|
||||
-webkit-transition: opacity 0.4s;
|
||||
transition: opacity 0.4s;
|
||||
|
||||
::v-deep(svg) {
|
||||
@@ -152,7 +151,7 @@
|
||||
}
|
||||
|
||||
&-image-mask:hover {
|
||||
opacity: 40;
|
||||
opacity: 4000%;
|
||||
}
|
||||
|
||||
&-upload-btn {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user