Compare commits
1425 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d13264b10e | ||
|
|
29a1c4ae35 | ||
|
|
9ac15e530a | ||
|
|
d4b446280a | ||
|
|
4593898549 | ||
|
|
c030d1a309 | ||
|
|
fd71e471b2 | ||
|
|
bc245e0a7a | ||
|
|
8236461c37 | ||
|
|
e1e8344764 | ||
|
|
14398e083e | ||
|
|
f36fe075ce | ||
|
|
25cf9d7fce | ||
|
|
9355788221 | ||
|
|
64042b51e9 | ||
|
|
7145af48ad | ||
|
|
ddb5468656 | ||
|
|
793cdd8f4c | ||
|
|
faafbb59c6 | ||
|
|
cd0ea07c2f | ||
|
|
f6e3807a3d | ||
|
|
fc36496aee | ||
|
|
1c8881d7a4 | ||
|
|
f6e8aacd0f | ||
|
|
79ddc39492 | ||
|
|
e63c5fb8e5 | ||
|
|
695f4827fd | ||
|
|
5a8b183c0f | ||
|
|
2845a889ed | ||
|
|
6333103050 | ||
|
|
cb6be91538 | ||
|
|
8cdd4b4af5 | ||
|
|
f4ec2029d9 | ||
|
|
b84b0f229f | ||
|
|
ef6a01a32f | ||
|
|
b451b8066a | ||
|
|
57efd516c5 | ||
|
|
d5979e6bf3 | ||
|
|
d75970cb2a | ||
|
|
ad4bb07cd7 | ||
|
|
9c558c3625 | ||
|
|
b467bb6c56 | ||
|
|
5cd021ea85 | ||
|
|
3d64382c9b | ||
|
|
6d5d4354d9 | ||
|
|
1b43446b5c | ||
|
|
7a9984f392 | ||
|
|
3c6fbfb106 | ||
|
|
bab46964ff | ||
|
|
661919f27a | ||
|
|
f3a03349b4 | ||
|
|
29791bf986 | ||
|
|
a06f0f29c6 | ||
|
|
b426d94180 | ||
|
|
5618d87e58 | ||
|
|
721d4f7685 | ||
|
|
7a025bcd38 | ||
|
|
24a8125621 | ||
|
|
468584a906 | ||
|
|
c056ec9377 | ||
|
|
87239994ae | ||
|
|
da09860a53 | ||
|
|
195ee5b2a6 | ||
|
|
32621ee299 | ||
|
|
40645180a0 | ||
|
|
59d4b1e544 | ||
|
|
8962a2c4ac | ||
|
|
6955f35ad1 | ||
|
|
1f722e7d7f | ||
|
|
5e587dfd88 | ||
|
|
2c687e5648 | ||
|
|
fdb0f63283 | ||
|
|
002e675b47 | ||
|
|
114f2a2dd0 | ||
|
|
c314d49e11 | ||
|
|
f5d0556808 | ||
|
|
27bc2a488f | ||
|
|
3a5999c341 | ||
|
|
a80a099ee7 | ||
|
|
68f458738a | ||
|
|
0f08f69738 | ||
|
|
a664066465 | ||
|
|
e6c11665a5 | ||
|
|
c119384c22 | ||
|
|
787cccb89f | ||
|
|
3df5d75c46 | ||
|
|
de6ad2479e | ||
|
|
632dfbaf10 | ||
|
|
68c14c24b8 | ||
|
|
d343d6d54d | ||
|
|
391a160f97 | ||
|
|
2d95110f75 | ||
|
|
e2ced8d36d | ||
|
|
a2b4511602 | ||
|
|
bdccc71b64 | ||
|
|
d7038a7d18 | ||
|
|
3998e1f685 | ||
|
|
5def9d5f81 | ||
|
|
c62937371e | ||
|
|
52843dcf97 | ||
|
|
ef5680d5ad | ||
|
|
bd3f24c84b | ||
|
|
399f85c52e | ||
|
|
14430e5c89 | ||
|
|
b703757d28 | ||
|
|
b642eabbb3 | ||
|
|
673596d8f9 | ||
|
|
b14e927e6c | ||
|
|
b03ae41ac7 | ||
|
|
92a0a9fe2f | ||
|
|
2511acfea1 | ||
|
|
361a4e0414 | ||
|
|
7e310236fe | ||
|
|
8705606c70 | ||
|
|
1f812a5258 | ||
|
|
e9264fa472 | ||
|
|
9164a1aefc | ||
|
|
30351a02ee | ||
|
|
7f918408a6 | ||
|
|
82f69bcad0 | ||
|
|
83b25eabbb | ||
|
|
47da6db51a | ||
|
|
eee092a7fd | ||
|
|
4c0f65fcbc | ||
|
|
acbd979569 | ||
|
|
52b68c18bf | ||
|
|
c6a74a75da | ||
|
|
e39eb62f52 | ||
|
|
4ecec4865d | ||
|
|
589007a22a | ||
|
|
4d4c9516c6 | ||
|
|
8491f26617 | ||
|
|
fcb3768a76 | ||
|
|
966bb769df | ||
|
|
dc8f7caab0 | ||
|
|
683346d652 | ||
|
|
f5fe39b2d2 | ||
|
|
51beb53f51 | ||
|
|
9d3f03c83a | ||
|
|
3eda1e4ef7 | ||
|
|
7181f83d66 | ||
|
|
fffad6e1b8 | ||
|
|
7f3906e5cb | ||
|
|
f836d175f0 | ||
|
|
f49cafc0cc | ||
|
|
a3ecad3436 | ||
|
|
a019dbd44e | ||
|
|
b316f960a1 | ||
|
|
d049b26825 | ||
|
|
852579c6ee | ||
|
|
5adcfa1877 | ||
|
|
f74458629e | ||
|
|
798f9249f8 | ||
|
|
6b4383643f | ||
|
|
256e8d0452 | ||
|
|
4112214c1f | ||
|
|
c183158ffe | ||
|
|
d523790c0f | ||
|
|
615ce34a72 | ||
|
|
1d59b3566c | ||
|
|
8071b90a2b | ||
|
|
8966584ca0 | ||
|
|
822711a530 | ||
|
|
1fe8aeb9e1 | ||
|
|
f021ba8a98 | ||
|
|
e4af05cd56 | ||
|
|
43d1cdb91c | ||
|
|
ed3f66681f | ||
|
|
c718d57e77 | ||
|
|
ce2e88a532 | ||
|
|
e60015a477 | ||
|
|
761e3ac76d | ||
|
|
2cf5535376 | ||
|
|
1a3d76d7b9 | ||
|
|
942a536289 | ||
|
|
fb1f6abf2e | ||
|
|
61ecb421e6 | ||
|
|
0098f9db2f | ||
|
|
2a348a7f18 | ||
|
|
838dff4758 | ||
|
|
7fb78a86ba | ||
|
|
07c815e943 | ||
|
|
9a4392eceb | ||
|
|
dc25e457eb | ||
|
|
d65ed9725c | ||
|
|
41ce095505 | ||
|
|
0e2290ce8a | ||
|
|
1b8db5b7f1 | ||
|
|
0cb42c1117 | ||
|
|
a289fe3da5 | ||
|
|
f53192cfa2 | ||
|
|
235e014542 | ||
|
|
211b05c643 | ||
|
|
3e1bd687f1 | ||
|
|
072fb01a04 | ||
|
|
81fbf4f5ba | ||
|
|
88c86f49bf | ||
|
|
3023214072 | ||
|
|
6ea6f89ab2 | ||
|
|
43c6672ab1 | ||
|
|
5cb56127d5 | ||
|
|
afa333243f | ||
|
|
047e99e27c | ||
|
|
eef6f37ace | ||
|
|
e8ede6e606 | ||
|
|
bfb4ea4123 | ||
|
|
51b0403f64 | ||
|
|
a5cd396de6 | ||
|
|
754bc3d3c9 | ||
|
|
07a2bcfb97 | ||
|
|
20222201ae | ||
|
|
a2a5ddd66c | ||
|
|
7bfc7602a7 | ||
|
|
b52b2cedad | ||
|
|
e93df6ba2c | ||
|
|
f9f29ccc3c | ||
|
|
3bd63ab7c8 | ||
|
|
301ea445bb | ||
|
|
475bee28c6 | ||
|
|
cd69920b41 | ||
|
|
83aab4e47d | ||
|
|
e12093c966 | ||
|
|
f21d546d18 | ||
|
|
26c8a6ba43 | ||
|
|
827bb8ba69 | ||
|
|
d1d2ef37d2 | ||
|
|
659594898b | ||
|
|
7569401fe0 | ||
|
|
dc9c86273d | ||
|
|
0e816e678a | ||
|
|
ff1c2a890c | ||
|
|
b802ad8a75 | ||
|
|
c11fb54b0b | ||
|
|
856dec3991 | ||
|
|
1d8c71da3f | ||
|
|
4152d0f715 | ||
|
|
0ead8cc052 | ||
|
|
2b5ecf3f8a | ||
|
|
de7aeeaeb3 | ||
|
|
994c52f6aa | ||
|
|
c6eb744257 | ||
|
|
4f462c5cfd | ||
|
|
60850970a8 | ||
|
|
3b2d5e45bb | ||
|
|
a604d3223a | ||
|
|
00bd1c45a1 | ||
|
|
4bc6dc7af7 | ||
|
|
3a8effd01f | ||
|
|
da67088e9c | ||
|
|
bacd4d23a3 | ||
|
|
020f667749 | ||
|
|
84652e8c82 | ||
|
|
565ebd936e | ||
|
|
3af127c66f | ||
|
|
849bb04249 | ||
|
|
09d647877f | ||
|
|
c868afbcbf | ||
|
|
3f033bfdec | ||
|
|
eca2f43e0e | ||
|
|
eeb17040f7 | ||
|
|
11dee1ed62 | ||
|
|
11a6232f83 | ||
|
|
9eded24e0e | ||
|
|
7548882148 | ||
|
|
4ad89955d4 | ||
|
|
a53553d658 | ||
|
|
2602cb0998 | ||
|
|
e402de29d5 | ||
|
|
a4cc1cc615 | ||
|
|
2d900baad1 | ||
|
|
17d6f6db05 | ||
|
|
7f3ba543b7 | ||
|
|
b33cb8a12c | ||
|
|
cfa8b78c2e | ||
|
|
4024daf189 | ||
|
|
77d7c3bb61 | ||
|
|
868ad57e12 | ||
|
|
eaf9724295 | ||
|
|
30e98de38a | ||
|
|
79c606370c | ||
|
|
b70597b5f5 | ||
|
|
a469282730 | ||
|
|
c3708360fa | ||
|
|
80f0560e0f | ||
|
|
84951cdc44 | ||
|
|
a72cb797ab | ||
|
|
6898e6b816 | ||
|
|
adb0b966ff | ||
|
|
81284b8d21 | ||
|
|
1a2b112e64 | ||
|
|
442c484dc9 | ||
|
|
2368c2f25f | ||
|
|
2320c58254 | ||
|
|
c9a4f36414 | ||
|
|
1df9a981b2 | ||
|
|
cbc917b834 | ||
|
|
240a568d16 | ||
|
|
eb1a847faa | ||
|
|
e09e57879b | ||
|
|
ddd2982971 | ||
|
|
621da7e4ef | ||
|
|
420827c389 | ||
|
|
ce9399b894 | ||
|
|
1bdd08c59a | ||
|
|
52d62dda81 | ||
|
|
d69e3cedae | ||
|
|
648bfcdd0d | ||
|
|
e4b8ff0a64 | ||
|
|
4576ef854d | ||
|
|
7323668db5 | ||
|
|
b11d709070 | ||
|
|
e25ac006c2 | ||
|
|
9e85e7edce | ||
|
|
804bcd440c | ||
|
|
6e4c896cb7 | ||
|
|
0cae89f8e3 | ||
|
|
59a7607c07 | ||
|
|
6dca0c157f | ||
|
|
d2aa5a64aa | ||
|
|
2620a55c5a | ||
|
|
14e33215f8 | ||
|
|
6862c2a744 | ||
|
|
fb215e8d87 | ||
|
|
f52ad2151b | ||
|
|
1a47b7d09d | ||
|
|
f292071a34 | ||
|
|
dd616d29e8 | ||
|
|
0509f18d66 | ||
|
|
f59fb119e4 | ||
|
|
46127cac1f | ||
|
|
c1abf76211 | ||
|
|
fe5b45d48d | ||
|
|
10ac1ebf7b | ||
|
|
e5d8144510 | ||
|
|
f9a65fba7a | ||
|
|
9b4138349b | ||
|
|
db9c9db5a9 | ||
|
|
24e992339f | ||
|
|
f26d1babf7 | ||
|
|
de3347cea1 | ||
|
|
e900fac4bd | ||
|
|
396218a467 | ||
|
|
d3a66ffa8c | ||
|
|
1e7ffb4c2e | ||
|
|
3df5d4c690 | ||
|
|
02a8331996 | ||
|
|
a29ad6a091 | ||
|
|
3ef1e65412 | ||
|
|
2deaec1fc6 | ||
|
|
c9b0b23d36 | ||
|
|
f06cca4ead | ||
|
|
a1990ce3e4 | ||
|
|
cbbf023030 | ||
|
|
307aa724eb | ||
|
|
cd6f37d80f | ||
|
|
b903134770 | ||
|
|
11effdd297 | ||
|
|
8873d8372d | ||
|
|
964aa29d12 | ||
|
|
b45a3c6539 | ||
|
|
b72b7ad0fb | ||
|
|
0e3106d8c1 | ||
|
|
71a6626fa9 | ||
|
|
68006bac88 | ||
|
|
34cbcc38a6 | ||
|
|
f4daee85c7 | ||
|
|
dd347039b5 | ||
|
|
0c9367d58a | ||
|
|
af10c4f1c3 | ||
|
|
52fbeda941 | ||
|
|
ace23af363 | ||
|
|
a097d89d68 | ||
|
|
77cb817523 | ||
|
|
c956e271a2 | ||
|
|
6413f30d18 | ||
|
|
789e748df0 | ||
|
|
c89edae375 | ||
|
|
f4dca4922b | ||
|
|
73b9ef5ee7 | ||
|
|
462742961a | ||
|
|
5a647fabfa | ||
|
|
2580ceac20 | ||
|
|
6905391785 | ||
|
|
7406226e68 | ||
|
|
af9ee00ad3 | ||
|
|
01f63a4b6b | ||
|
|
45e48755d3 | ||
|
|
f6c740738f | ||
|
|
29780cd4b7 | ||
|
|
a050b7c7d5 | ||
|
|
1f25387f81 | ||
|
|
36fb7b53ba | ||
|
|
354295ffda | ||
|
|
4f28018f4f | ||
|
|
5d37666bea | ||
|
|
705e81db7f | ||
|
|
57d5859727 | ||
|
|
06387ab33e | ||
|
|
5f0c3b3639 | ||
|
|
414fb8afd1 | ||
|
|
58fbaaa8f4 | ||
|
|
040790a672 | ||
|
|
bf36e39f3b | ||
|
|
a780946915 | ||
|
|
1d537c2799 | ||
|
|
6a3e383f30 | ||
|
|
cb72c6b586 | ||
|
|
384e1a63b3 | ||
|
|
e6357d0a54 | ||
|
|
a0ebb42e1e | ||
|
|
324fec8f94 | ||
|
|
226efc3d85 | ||
|
|
e785997d99 | ||
|
|
7998b51e6b | ||
|
|
e54384fcd7 | ||
|
|
39946cad1b | ||
|
|
6041ae9344 | ||
|
|
dc9fda8d86 | ||
|
|
7dd3877955 | ||
|
|
5386fc54ff | ||
|
|
c3839f092f | ||
|
|
4c8207ef9a | ||
|
|
539a7de1ad | ||
|
|
935b2c4edb | ||
|
|
e1a03166b0 | ||
|
|
c7be304085 | ||
|
|
2f8c815053 | ||
|
|
249e1c6ebd | ||
|
|
22c97d1c01 | ||
|
|
ff3d45ec91 | ||
|
|
4caf671e1c | ||
|
|
741876dcaa | ||
|
|
5c6f32a7db | ||
|
|
80b24cbfbc | ||
|
|
8afed9768d | ||
|
|
1f4dacff02 | ||
|
|
a046c0ec45 | ||
|
|
82d0fd2b11 | ||
|
|
e2fb55d910 | ||
|
|
7754c41d34 | ||
|
|
eea30c3a0d | ||
|
|
bfe41a0642 | ||
|
|
4ba0151c42 | ||
|
|
98bdfb160e | ||
|
|
6327649501 | ||
|
|
6937f5e1b1 | ||
|
|
e3ce4196fe | ||
|
|
bb67a051c2 | ||
|
|
812dd1f184 | ||
|
|
37d6612434 | ||
|
|
9cbafdfab8 | ||
|
|
1c4d806e58 | ||
|
|
aba2ee29dd | ||
|
|
51deb29145 | ||
|
|
1f7a677db3 | ||
|
|
0fb0652919 | ||
|
|
39c7e723ba | ||
|
|
a9ddf159cc | ||
|
|
22b93e1ae3 | ||
|
|
93b83048cf | ||
|
|
1c18f3a4f2 | ||
|
|
b5a01a7a42 | ||
|
|
caf211c34e | ||
|
|
8b79c70be7 | ||
|
|
6a4a218152 | ||
|
|
6bc420d57f | ||
|
|
db0325a59c | ||
|
|
eab2f0df20 | ||
|
|
2d1fbff2c5 | ||
|
|
75c3ac71ae | ||
|
|
61ffd222cc | ||
|
|
3499327984 | ||
|
|
c90ed003f7 | ||
|
|
bd9169bcd1 | ||
|
|
0c46ab7d5a | ||
|
|
3bc464011a | ||
|
|
74fe67fe4d | ||
|
|
48fcce54dc | ||
|
|
b91be6bb2f | ||
|
|
181ad39e18 | ||
|
|
4af6e5e91f | ||
|
|
d67c6acfa2 | ||
|
|
f4633a5832 | ||
|
|
36841f6f8f | ||
|
|
86b4df871a | ||
|
|
03ad8cc9e8 | ||
|
|
de39ffa260 | ||
|
|
becccb8368 | ||
|
|
1b75bb2cec | ||
|
|
2a9f9b725e | ||
|
|
5f15e84065 | ||
|
|
deeb5f9d62 | ||
|
|
b715198a02 | ||
|
|
005b1a9715 | ||
|
|
d120bb794c | ||
|
|
e625d56c65 | ||
|
|
2d1d19e457 | ||
|
|
c5d0a7fd74 | ||
|
|
c72fcbd10d | ||
|
|
5f388c8b09 | ||
|
|
b02c3c8e5c | ||
|
|
1d9e0eb3a3 | ||
|
|
0a5b553bb8 | ||
|
|
865d57b4d3 | ||
|
|
8e40c38730 | ||
|
|
ddee496c73 | ||
|
|
9c4d12d18b | ||
|
|
6efa0e307e | ||
|
|
f0ac2d739d | ||
|
|
1cb78b4ccd | ||
|
|
fc6f41a549 | ||
|
|
db86d075f0 | ||
|
|
3db4e12bb2 | ||
|
|
f4a7372b4f | ||
|
|
877d2f77bd | ||
|
|
02334489ed | ||
|
|
cd714d954f | ||
|
|
9e4655070c | ||
|
|
f84d69feb7 | ||
|
|
3c91ad2f59 | ||
|
|
873848b9a7 | ||
|
|
f906a172dd | ||
|
|
6b9c74dcea | ||
|
|
539cf9ada4 | ||
|
|
a69d2dfd71 | ||
|
|
3f9b9a6903 | ||
|
|
9949a16f34 | ||
|
|
7e30cf40a9 | ||
|
|
fba0df8cb9 | ||
|
|
7a97005524 | ||
|
|
ee8b57da91 | ||
|
|
e63f19a00d | ||
|
|
deabf23475 | ||
|
|
0b3fc938ae | ||
|
|
bdd0cdbe55 | ||
|
|
ae261cb684 | ||
|
|
0036a895e9 | ||
|
|
f317d15580 | ||
|
|
76a487854b | ||
|
|
b3f616ddc6 | ||
|
|
9b19cbefc8 | ||
|
|
a4ba6b947b | ||
|
|
fb510ff180 | ||
|
|
2710cbc85a | ||
|
|
b82f17bcf1 | ||
|
|
f9c33394a9 | ||
|
|
0a15a6eb64 | ||
|
|
45777c01ee | ||
|
|
b331cc55ce | ||
|
|
74ef5a8083 | ||
|
|
8dd82aacf2 | ||
|
|
35d130a01b | ||
|
|
15319bf586 | ||
|
|
832cae635e | ||
|
|
1c83752f56 | ||
|
|
7973457417 | ||
|
|
8083e94ecd | ||
|
|
b3485af14c | ||
|
|
01eaef2bf9 | ||
|
|
3e241cf8bc | ||
|
|
2df4dc0535 | ||
|
|
135a1e3d52 | ||
|
|
4366fdd4a6 | ||
|
|
a47d3f10f9 | ||
|
|
004c9eadd5 | ||
|
|
b483a5f4e8 | ||
|
|
06e0f4234f | ||
|
|
e9a5c0ae69 | ||
|
|
0c17702f65 | ||
|
|
ddf682d66a | ||
|
|
018c5f857b | ||
|
|
b5d89ff082 | ||
|
|
54046a4717 | ||
|
|
505773043b | ||
|
|
e9bb811244 | ||
|
|
6ef6ea1479 | ||
|
|
93bd4002db | ||
|
|
b9ec829747 | ||
|
|
f307327af3 | ||
|
|
936be9928d | ||
|
|
b639369846 | ||
|
|
5577e4cf62 | ||
|
|
63206fea2e | ||
|
|
40727dac2d | ||
|
|
d703909177 | ||
|
|
fc61060b7f | ||
|
|
73e21e77ec | ||
|
|
6be05819b0 | ||
|
|
0e116ad1b9 | ||
|
|
016c232ef2 | ||
|
|
9856419292 | ||
|
|
cf3a204eac | ||
|
|
dc3e364b90 | ||
|
|
d22ef17b95 | ||
|
|
4126692c5a | ||
|
|
d22f1c97ae | ||
|
|
735023330a | ||
|
|
6301cb287e | ||
|
|
85ebb0242a | ||
|
|
81a670d608 | ||
|
|
a547e5c34b | ||
|
|
cf6b6dd4dd | ||
|
|
574464c1ea | ||
|
|
816dfa4e3b | ||
|
|
9d7e52c25e | ||
|
|
d41b6ca459 | ||
|
|
4d1b5209e7 | ||
|
|
7da21f23aa | ||
|
|
40a9caceb8 | ||
|
|
7e4f21ff33 | ||
|
|
cd6f5090d7 | ||
|
|
1efd0a3d5b | ||
|
|
4434d7b8c9 | ||
|
|
24e184eace | ||
|
|
8ccd9cfd85 | ||
|
|
cb2c23dc96 | ||
|
|
29912cac8d | ||
|
|
6376a81c4a | ||
|
|
aff4b2f9b7 | ||
|
|
153fe8fcd0 | ||
|
|
95d8b3d1a6 | ||
|
|
19ce869763 | ||
|
|
e6b6d3ca27 | ||
|
|
8e7be239ee | ||
|
|
4bd97f9d81 | ||
|
|
49d182eabc | ||
|
|
9411a29adf | ||
|
|
61bb96e1fe | ||
|
|
6a6100a814 | ||
|
|
40fcf9d0cc | ||
|
|
65946c55d1 | ||
|
|
e2b4df3dcf | ||
|
|
04fee167b9 | ||
|
|
243c273084 | ||
|
|
b43cf4dd5d | ||
|
|
cf9c38fdd5 | ||
|
|
6e4e6df08f | ||
|
|
7b5630223d | ||
|
|
3d985decbc | ||
|
|
dbe23eaac7 | ||
|
|
e38df0f319 | ||
|
|
c2ac66fdbf | ||
|
|
5ad25ff14d | ||
|
|
04e1b527b5 | ||
|
|
09210f98e9 | ||
|
|
bfe228a367 | ||
|
|
a01978196d | ||
|
|
f795481895 | ||
|
|
83e199c1ea | ||
|
|
8734e7fc1b | ||
|
|
b48e4adacd | ||
|
|
a45e2b120e | ||
|
|
52b6f103a5 | ||
|
|
927f4a366c | ||
|
|
b28347d191 | ||
|
|
df057ebe4d | ||
|
|
aa7b4a0e94 | ||
|
|
ca9d44f55f | ||
|
|
247631fd68 | ||
|
|
3357928e80 | ||
|
|
fc263d79a8 | ||
|
|
ee10616acf | ||
|
|
30c3ad6c90 | ||
|
|
5ad6d6d904 | ||
|
|
e2c7fc0af0 | ||
|
|
172fb06d8e | ||
|
|
634522d27b | ||
|
|
03b14a0fb5 | ||
|
|
ec54ec2607 | ||
|
|
340bb08f2a | ||
|
|
022487a877 | ||
|
|
6ec1bbe1ae | ||
|
|
9d55f8ab24 | ||
|
|
fc61f3fca1 | ||
|
|
cca3368d8f | ||
|
|
57f6547b91 | ||
|
|
200b22cf0c | ||
|
|
e9b8f3138c | ||
|
|
dd9663451e | ||
|
|
78e0e7dba1 | ||
|
|
b94fb70e02 | ||
|
|
e94c149cd1 | ||
|
|
94ba3c4514 | ||
|
|
c129a37ccf | ||
|
|
6608a4266b | ||
|
|
809bfbb42a | ||
|
|
676ff8789b | ||
|
|
3b1a9bd0c4 | ||
|
|
202b9dc3bc | ||
|
|
ce96deb224 | ||
|
|
14afe59eeb | ||
|
|
790a8bdb9a | ||
|
|
8bd0f7a589 | ||
|
|
235eb82c45 | ||
|
|
f043447e4f | ||
|
|
e92a74a088 | ||
|
|
799a385ff9 | ||
|
|
2c74dc0ccd | ||
|
|
c191b12514 | ||
|
|
2c9e593af0 | ||
|
|
f1dbab7d55 | ||
|
|
ea77d7e76d | ||
|
|
64d8e3b1e1 | ||
|
|
bd4975d180 | ||
|
|
2a916a099c | ||
|
|
bc084922f7 | ||
|
|
42f755b755 | ||
|
|
7f2c629305 | ||
|
|
6136095e0f | ||
|
|
0a34e07cc5 | ||
|
|
71c6f4483f | ||
|
|
731a74905c | ||
|
|
8b0e47103c | ||
|
|
4da24e27a4 | ||
|
|
169f1b327b | ||
|
|
360f9afb54 | ||
|
|
0e45a59860 | ||
|
|
cfc2e407a4 | ||
|
|
a467fdb43f | ||
|
|
474db2be0d | ||
|
|
e946037c57 | ||
|
|
b2e1fe314f | ||
|
|
81fb44da80 | ||
|
|
0e8da35b0a | ||
|
|
4d2cf73330 | ||
|
|
de2ce12163 | ||
|
|
5df89f2ce4 | ||
|
|
045c0b4c0c | ||
|
|
8b4ffa0795 | ||
|
|
14359a37ae | ||
|
|
f4b2ed4f7d | ||
|
|
a8e4a1c2e0 | ||
|
|
9048d181af | ||
|
|
1cb02994bf | ||
|
|
6fad85e957 | ||
|
|
db9b2ee6b3 | ||
|
|
8efeb77102 | ||
|
|
0215a800e2 | ||
|
|
87d282f98b | ||
|
|
60c392d3d0 | ||
|
|
34c3aa25da | ||
|
|
80690d4cc8 | ||
|
|
18f3dc2d44 | ||
|
|
e8256b4e1a | ||
|
|
4f67bb0250 | ||
|
|
5dd071adf4 | ||
|
|
aaf5e7f49d | ||
|
|
6a5958409a | ||
|
|
e0ff98b1d7 | ||
|
|
a815e07cdd | ||
|
|
aa2fe9740c | ||
|
|
75a358a4d2 | ||
|
|
d5646be6f8 | ||
|
|
cb04ebcd95 | ||
|
|
9889ccfc74 | ||
|
|
f528bd861a | ||
|
|
f793654bd8 | ||
|
|
8d064a2165 | ||
|
|
1240899b08 | ||
|
|
558752b890 | ||
|
|
997548b7d6 | ||
|
|
865d597fe8 | ||
|
|
b0a043b464 | ||
|
|
e003b6f9a7 | ||
|
|
9e9e940dfd | ||
|
|
d6dac704eb | ||
|
|
9aa8dff650 | ||
|
|
14c2503b0d | ||
|
|
cb282c6f9a | ||
|
|
66a5a40482 | ||
|
|
8d211ed20b | ||
|
|
bbf2814285 | ||
|
|
a15e479a3e | ||
|
|
505d6ec010 | ||
|
|
314ac65e23 | ||
|
|
118a9a2c5d | ||
|
|
347f47bbef | ||
|
|
a73c35468d | ||
|
|
f9a1446ed5 | ||
|
|
874ba45034 | ||
|
|
febe08eb9d | ||
|
|
9123b34c82 | ||
|
|
c66d7cafa6 | ||
|
|
73c54992e2 | ||
|
|
be1a44ad61 | ||
|
|
28b307fb98 | ||
|
|
a1dc723445 | ||
|
|
23f4a70693 | ||
|
|
be5b4b39e5 | ||
|
|
cf706e0e30 | ||
|
|
8bc80d2088 | ||
|
|
b94f8c92f0 | ||
|
|
c3be75bed1 | ||
|
|
91c8d8077f | ||
|
|
f598eed149 | ||
|
|
971bae3be0 | ||
|
|
9a6abf4d5a | ||
|
|
d756077a48 | ||
|
|
a1fc87bb1e | ||
|
|
07186d2ae1 | ||
|
|
d2164d9ada | ||
|
|
7eacaf8fc5 | ||
|
|
9aa2de526e | ||
|
|
12dfc5b407 | ||
|
|
1fc964ec16 | ||
|
|
7f2f7b100b | ||
|
|
8292140f1f | ||
|
|
c26e610a23 | ||
|
|
c96cfe81ab | ||
|
|
bb1cc0b60e | ||
|
|
1e74073344 | ||
|
|
d83d1dd888 | ||
|
|
e34573e72f | ||
|
|
9d3f4879ef | ||
|
|
6317277a70 | ||
|
|
a1130ec60b | ||
|
|
a1a3ccf6fb | ||
|
|
aedb8bee9c | ||
|
|
6620d1c8fe | ||
|
|
0ecc7dfead | ||
|
|
9f5859ee93 | ||
|
|
d559e1717c | ||
|
|
e649be58a2 | ||
|
|
157c37c862 | ||
|
|
da910ac670 | ||
|
|
3831363815 | ||
|
|
94a6ea13bd | ||
|
|
06c1ad0f69 | ||
|
|
d6873781e8 | ||
|
|
ab6c9647a7 | ||
|
|
59b0350993 | ||
|
|
df0be4c070 | ||
|
|
87f3ef4353 | ||
|
|
2611bbaea4 | ||
|
|
7c0d8cf792 | ||
|
|
2d17baccd2 | ||
|
|
fe31723726 | ||
|
|
bb10b22421 | ||
|
|
6445f3a634 | ||
|
|
d1f28d9c94 | ||
|
|
1e5366123c | ||
|
|
7feff7c90b | ||
|
|
429b3bc045 | ||
|
|
e76f1b89da | ||
|
|
f25e8595c3 | ||
|
|
6977ce55a3 | ||
|
|
222e0e5ff2 | ||
|
|
6996d9bbe2 | ||
|
|
f70e08adac | ||
|
|
223ecc0e6b | ||
|
|
43f36f556c | ||
|
|
4579e00283 | ||
|
|
b5e9b14048 | ||
|
|
2288e72c5f | ||
|
|
4882cc0417 | ||
|
|
499d3d0424 | ||
|
|
d6b17debb4 | ||
|
|
8f970e0008 | ||
|
|
18d778a1cc | ||
|
|
d667c4e45d | ||
|
|
b7f8ffd56f | ||
|
|
c20f9d527f | ||
|
|
b859d00cb9 | ||
|
|
a2d28ad360 | ||
|
|
c6702fbc18 | ||
|
|
5018f96786 | ||
|
|
f29f408b67 | ||
|
|
a475a3b851 | ||
|
|
9335f79c30 | ||
|
|
9dab691649 | ||
|
|
16abc65f49 | ||
|
|
23ac80886d | ||
|
|
b242e757e0 | ||
|
|
a69965a605 | ||
|
|
3321427eb4 | ||
|
|
3ffe354770 | ||
|
|
52e0d3a4bc | ||
|
|
e865a5ca62 | ||
|
|
528a4ddb03 | ||
|
|
36f3b649c6 | ||
|
|
ce91c0cc30 | ||
|
|
e31e9e3520 | ||
|
|
df313ebe7f | ||
|
|
e1cf36e952 | ||
|
|
493194652c | ||
|
|
5030e75c2c | ||
|
|
3c70eac7ca | ||
|
|
f9b22962a4 | ||
|
|
7ce0c21b0c | ||
|
|
7a7a8c923f | ||
|
|
d5d5e28f7e | ||
|
|
b22ac27075 | ||
|
|
3cb5f4bdfe | ||
|
|
d355e4575d | ||
|
|
bdbb118e55 | ||
|
|
9a174d99db | ||
|
|
9c8725066c | ||
|
|
9f0f3de864 | ||
|
|
ac84ed2d6a | ||
|
|
9d7e15f4df | ||
|
|
c3563f4501 | ||
|
|
a543202edc | ||
|
|
52cf517a91 | ||
|
|
11b649dc8c | ||
|
|
19663bacb1 | ||
|
|
41c276d0e0 | ||
|
|
6bb73add28 | ||
|
|
2c16b6c078 | ||
|
|
5ddc955805 | ||
|
|
6a3afa4240 | ||
|
|
deabd7b83c | ||
|
|
422e5858ef | ||
|
|
3c019d1376 | ||
|
|
f676e8423e | ||
|
|
f687d1de01 | ||
|
|
6fe28bc2ef | ||
|
|
86b5af3423 | ||
|
|
8f3dce058c | ||
|
|
825b8bb4a5 | ||
|
|
05320d1070 | ||
|
|
33d2a396ce | ||
|
|
ae4cce8abf | ||
|
|
b85950e4ca | ||
|
|
aecf52551b | ||
|
|
fc877ed836 | ||
|
|
5580921b7d | ||
|
|
6b7d0a0fe2 | ||
|
|
f55efbe1e2 | ||
|
|
8e6fc3c417 | ||
|
|
7943ab6017 | ||
|
|
81725a58cf | ||
|
|
5cbcf46aaa | ||
|
|
49dd3f726a | ||
|
|
73f9ebc709 | ||
|
|
f6884ba4f9 | ||
|
|
5d39d0e139 | ||
|
|
6a1463ef17 | ||
|
|
5d00f23cb3 | ||
|
|
6ea106b25d | ||
|
|
d501bf7506 | ||
|
|
1408060053 | ||
|
|
0c37c01496 | ||
|
|
d2049f7839 | ||
|
|
33cdf672b3 | ||
|
|
145c89acc3 | ||
|
|
706d7d6dc1 | ||
|
|
2c35d0f897 | ||
|
|
f227ae89ec | ||
|
|
ac43d53884 | ||
|
|
4b70549bcb | ||
|
|
ea601ae404 | ||
|
|
201411841c | ||
|
|
d857acc58e | ||
|
|
d005252f13 | ||
|
|
2065992b17 | ||
|
|
74e96980e6 | ||
|
|
09110d1ef7 | ||
|
|
bcf55e63f1 | ||
|
|
dd22b2580e | ||
|
|
62a0e46698 | ||
|
|
14b68135fb | ||
|
|
d44b62e489 | ||
|
|
b0f5c2a493 | ||
|
|
d6cfbc60a8 | ||
|
|
fe51f5ced4 | ||
|
|
b257b0453e | ||
|
|
a88105a086 | ||
|
|
2dc792690e | ||
|
|
aa146b1cdf | ||
|
|
c44b20bae3 | ||
|
|
cad8964841 | ||
|
|
ec9a989214 | ||
|
|
7f05932fb9 | ||
|
|
d51694e1cb | ||
|
|
3079483e6b | ||
|
|
bee4264a39 | ||
|
|
c949ea2667 | ||
|
|
2bcb28d0c0 | ||
|
|
bd257554cd | ||
|
|
68a27e0b61 | ||
|
|
8b589bdb9c | ||
|
|
1a25710aac | ||
|
|
271d59ca51 | ||
|
|
37e5e57d5b | ||
|
|
f817b20545 | ||
|
|
5f8619805e | ||
|
|
c9d4629bfa | ||
|
|
c9c27c83d4 | ||
|
|
7a6a985c47 | ||
|
|
225df7b1e6 | ||
|
|
97ede69609 | ||
|
|
c5ded86d8a | ||
|
|
b4f049ecda | ||
|
|
56692eb6cb | ||
|
|
7c22c60190 | ||
|
|
2f2c4d4a44 | ||
|
|
c1c71916db | ||
|
|
4b15a7454c | ||
|
|
22e723587d | ||
|
|
969adaf5bb | ||
|
|
c2214e8300 | ||
|
|
10af659227 | ||
|
|
5cd3757f4f | ||
|
|
81f674ea01 | ||
|
|
1846ee0ffe | ||
|
|
14a825093a | ||
|
|
d70f477bc1 | ||
|
|
c9c897ffb5 | ||
|
|
462dea3e05 | ||
|
|
4e7a0084dd | ||
|
|
0268df0e24 | ||
|
|
f926ca66c0 | ||
|
|
16b5898928 | ||
|
|
c1bb66cc9d | ||
|
|
f7502d0d18 | ||
|
|
b4975f649c | ||
|
|
89353c1f7e | ||
|
|
fce10b6dca | ||
|
|
2cf95c6706 | ||
|
|
58ab1599db | ||
|
|
9745c2ea1a | ||
|
|
9db46e2949 | ||
|
|
7949505104 | ||
|
|
db0d5133e8 | ||
|
|
54415377ee | ||
|
|
d7f55477da | ||
|
|
faca586fa7 | ||
|
|
5f3ba7b9c7 | ||
|
|
abace4a58d | ||
|
|
5895cea587 | ||
|
|
cdbcef5232 | ||
|
|
d5d6bfdc56 | ||
|
|
75ae7f0c15 | ||
|
|
6931451f18 | ||
|
|
f5625e1354 | ||
|
|
d1be4a30b6 | ||
|
|
5c13362db2 | ||
|
|
6c71dce80c | ||
|
|
790c397951 | ||
|
|
e28e74b874 | ||
|
|
b99ea22d89 | ||
|
|
8938195c5d | ||
|
|
887b4a7862 | ||
|
|
7c9c39fa0e | ||
|
|
3b800753ec | ||
|
|
647119052c | ||
|
|
e9ce6bbd4e | ||
|
|
1fee27f78e | ||
|
|
e7a334861d | ||
|
|
267ae3436d | ||
|
|
60ff9f1891 | ||
|
|
f83efd23df | ||
|
|
db60f02745 | ||
|
|
3e109bd27c | ||
|
|
c4ccf6e3fa | ||
|
|
fb1a246e4a | ||
|
|
a418b03c06 | ||
|
|
e9fee000ca | ||
|
|
71c13e0653 | ||
|
|
32d7f933f8 | ||
|
|
f28dd810ce | ||
|
|
aaedd88ca7 | ||
|
|
00dee40917 | ||
|
|
019248b605 | ||
|
|
826f37bcc4 | ||
|
|
fa02a23e4c | ||
|
|
7143fb6f67 | ||
|
|
e1524c26cd | ||
|
|
72088dff2e | ||
|
|
8e6d3cf30e | ||
|
|
144992ccec | ||
|
|
673e883ae6 | ||
|
|
f197ed7972 | ||
|
|
ce642aceed | ||
|
|
d5411489c0 | ||
|
|
26c66627f8 | ||
|
|
c654986042 | ||
|
|
c5b5c15f99 | ||
|
|
7727b0f1c3 | ||
|
|
3d551ac45b | ||
|
|
555a00b731 | ||
|
|
9f9091b23e | ||
|
|
14c343142f | ||
|
|
890920775a | ||
|
|
7b38d2d74f | ||
|
|
e85c2870e2 | ||
|
|
cfbc5802e4 | ||
|
|
40cdb820fb | ||
|
|
f63beb776e | ||
|
|
20f031b2e2 | ||
|
|
b0f28b7e7c | ||
|
|
62bb6de80d | ||
|
|
3db4d883af | ||
|
|
8cb514d70e | ||
|
|
2d7880351b | ||
|
|
e1ee3ef2db | ||
|
|
aff30c48a0 | ||
|
|
55eea50a6e | ||
|
|
9ff212c94d | ||
|
|
6350c7e9e6 | ||
|
|
d097c1c17c | ||
|
|
b9ee6b4039 | ||
|
|
f1238a03b3 | ||
|
|
e90cf3ee77 | ||
|
|
468607c8e8 | ||
|
|
5bd9283177 | ||
|
|
117b12348c | ||
|
|
0d325b6eb8 | ||
|
|
86d5903f32 | ||
|
|
3b518d6f33 | ||
|
|
78f57e7d4b | ||
|
|
f710f1bfc0 | ||
|
|
c5d4fc62e6 | ||
|
|
60606d5eb9 | ||
|
|
8751236380 | ||
|
|
2291ce3680 | ||
|
|
16ed589857 | ||
|
|
b59254ca42 | ||
|
|
6e3f9b285d | ||
|
|
8bcff774fa | ||
|
|
9b04b12dec | ||
|
|
b22d81a9e9 | ||
|
|
6c80a3a8cd | ||
|
|
059d836653 | ||
|
|
2c3ecfeb6f | ||
|
|
b07e5eecc3 | ||
|
|
1847bc90cf | ||
|
|
899aaae47c | ||
|
|
bcc05086a4 | ||
|
|
d2cc547875 | ||
|
|
c6127f440e | ||
|
|
c2849ad49f | ||
|
|
9c6ba294f9 | ||
|
|
b2a8707e91 | ||
|
|
193e3085a9 | ||
|
|
2401f38e9f | ||
|
|
4ea65727a1 | ||
|
|
3d6cfe260c | ||
|
|
4c33a09c3c | ||
|
|
8d25743680 | ||
|
|
4bc5b763a2 | ||
|
|
00ea179c90 | ||
|
|
a17d40d2d0 | ||
|
|
62ddd703f1 | ||
|
|
77ab0ccae2 | ||
|
|
f377ac3fcc | ||
|
|
a81becd77b | ||
|
|
a004f1c758 | ||
|
|
b19b015986 | ||
|
|
3f0c1213ad | ||
|
|
f3a781d857 | ||
|
|
a07a32f648 | ||
|
|
1e1117b187 | ||
|
|
0e161b1735 | ||
|
|
98cbb8dc29 | ||
|
|
9c17d2d335 | ||
|
|
d4ea7f48c0 | ||
|
|
3ecfe3ba94 | ||
|
|
a959594348 | ||
|
|
faa1027c04 | ||
|
|
6f68732ef9 | ||
|
|
3a4e936938 | ||
|
|
8b4b79fa10 | ||
|
|
ce0dda0455 | ||
|
|
fd1ee398c4 | ||
|
|
1488017bf2 | ||
|
|
367f4236ad | ||
|
|
ec202f22e8 | ||
|
|
08081da29e | ||
|
|
5511424bd6 | ||
|
|
9f2c848413 | ||
|
|
d5efe2b499 | ||
|
|
9b989fc40f | ||
|
|
567e85d1f8 | ||
|
|
af00036e7f | ||
|
|
e58e6e2a3e | ||
|
|
370039664f | ||
|
|
d244363321 | ||
|
|
984d502259 | ||
|
|
34b418af96 | ||
|
|
eee0c0c878 | ||
|
|
952ef368ab | ||
|
|
dfaa789f7c | ||
|
|
74dd549ffb | ||
|
|
4d8f369ba0 | ||
|
|
824e2d72c7 | ||
|
|
143aa79797 | ||
|
|
0e1120f407 | ||
|
|
c8dbb9672a | ||
|
|
372b74776f | ||
|
|
abcc3c6411 | ||
|
|
ec4ab8762c | ||
|
|
bc93de8ff2 | ||
|
|
b426f3c6f2 | ||
|
|
99d9bb29ce | ||
|
|
5e109c666b | ||
|
|
0bed216735 | ||
|
|
d55bb8d336 | ||
|
|
7c32b3edf0 | ||
|
|
121cb7e442 | ||
|
|
dec3e1ea92 | ||
|
|
664b6610f3 | ||
|
|
44163f0fb2 | ||
|
|
d43865fcad | ||
|
|
fed92f3853 | ||
|
|
823d2a816e | ||
|
|
046c21edf6 | ||
|
|
8236d80b42 | ||
|
|
90e7eb1c79 | ||
|
|
ef09868af1 | ||
|
|
028981e3ae | ||
|
|
e8a6274cf6 | ||
|
|
ffd0265526 | ||
|
|
13d7344bc0 | ||
|
|
2ad36f92c5 | ||
|
|
36b02f4423 | ||
|
|
01df990aa8 | ||
|
|
49b71fcf5d | ||
|
|
9e43d77ac4 | ||
|
|
3ab9af720b | ||
|
|
abae304f87 | ||
|
|
659d8bff66 | ||
|
|
1786e10101 | ||
|
|
bda7f929e7 | ||
|
|
c309f80a94 | ||
|
|
97c987c561 | ||
|
|
48949104e0 | ||
|
|
a38cc4fe34 | ||
|
|
495dfbcb28 | ||
|
|
6e4dbd912b | ||
|
|
82904d956d | ||
|
|
ec7118b376 | ||
|
|
058b32a263 | ||
|
|
e7b960838e | ||
|
|
14e776a287 | ||
|
|
73f11b920f | ||
|
|
5c93040a8e | ||
|
|
a517769e8a | ||
|
|
4bb59a9f05 | ||
|
|
b37879d2d4 | ||
|
|
05defc39d7 | ||
|
|
18bfad07d2 | ||
|
|
b83591255d | ||
|
|
804350bc81 | ||
|
|
46e1cae0bb | ||
|
|
81062d4580 | ||
|
|
55481db2ee | ||
|
|
ecdd12f5a9 | ||
|
|
ef92cdc183 | ||
|
|
08f4a6cf2c | ||
|
|
38889acb4e | ||
|
|
c0517cd29a | ||
|
|
084449ccf3 | ||
|
|
0e8203ae03 | ||
|
|
236440be52 | ||
|
|
6f7e4bb272 | ||
|
|
38dcd3635a | ||
|
|
a3f3330dad | ||
|
|
bbc6c57c08 | ||
|
|
2f36a8edef | ||
|
|
df637fb887 | ||
|
|
be74c92a35 | ||
|
|
a219a64e20 | ||
|
|
25c22a276a | ||
|
|
6e6be057ca | ||
|
|
af69efa48b | ||
|
|
c551083fa4 | ||
|
|
9767feed29 | ||
|
|
4392818e92 | ||
|
|
8d22bafeb6 | ||
|
|
89ddd1fb78 | ||
|
|
24513fa22b | ||
|
|
cddde0c2a0 | ||
|
|
9c674e0018 | ||
|
|
0c6476d283 | ||
|
|
bf0c529a59 | ||
|
|
877bb4d4a2 | ||
|
|
dc4db0b2b3 | ||
|
|
a738d4a3b9 | ||
|
|
e9866a04df | ||
|
|
4f5193d602 | ||
|
|
37b92c55ba | ||
|
|
9299f1bcb6 | ||
|
|
7fe12192df | ||
|
|
1169644ab3 | ||
|
|
6f7770ed43 | ||
|
|
8059fd6f90 | ||
|
|
556dbd8d78 | ||
|
|
6695fd8c14 | ||
|
|
3ab0229275 | ||
|
|
99467127a0 | ||
|
|
90d73b7bd5 | ||
|
|
2e326e1798 | ||
|
|
251eac93c7 | ||
|
|
c74d70808c | ||
|
|
e63b2d7152 | ||
|
|
16b29b56a5 | ||
|
|
6d79c4fe2f | ||
|
|
4b1fb60ee3 | ||
|
|
1d2be54f9e | ||
|
|
83547e32db | ||
|
|
70ddb929f2 | ||
|
|
8b22961394 | ||
|
|
c15d42c179 | ||
|
|
098e473cab | ||
|
|
f6f3d9368a | ||
|
|
9558a420e9 | ||
|
|
4d3b69ca34 | ||
|
|
fdcc4a44c8 | ||
|
|
5de0494538 | ||
|
|
2045f833e4 | ||
|
|
cc4f89aac1 | ||
|
|
1c2f2c17d4 | ||
|
|
ace7a6621f | ||
|
|
d02fe55a1e | ||
|
|
9b753a8f5b | ||
|
|
11e82582b8 | ||
|
|
419358863e | ||
|
|
1d0d7f9975 | ||
|
|
c5f564372b | ||
|
|
a50f0cd727 | ||
|
|
96f6f55138 | ||
|
|
6a45c8b358 | ||
|
|
165937596e | ||
|
|
fb976f043b | ||
|
|
ecb9c4e51a | ||
|
|
9e8c3b495c | ||
|
|
24a37fc33c | ||
|
|
d09a21114d | ||
|
|
6e2b12501f | ||
|
|
2a56e116cf | ||
|
|
6de4f238d8 | ||
|
|
1b426c5957 | ||
|
|
82454a650c | ||
|
|
227b6bd7ef | ||
|
|
9554025daf | ||
|
|
0eb5d607bf | ||
|
|
750f4bc276 | ||
|
|
d0aada1d3d | ||
|
|
8a4848387c | ||
|
|
6904fc7da3 | ||
|
|
28c55a05e6 | ||
|
|
562c829267 | ||
|
|
b200ed242d | ||
|
|
815cfe55df | ||
|
|
40a1094d74 | ||
|
|
346650c091 | ||
|
|
7f74715f51 | ||
|
|
b6fcee517d | ||
|
|
4f62551f6b | ||
|
|
3980249271 | ||
|
|
e3b11b1130 | ||
|
|
f866f23af1 | ||
|
|
c793bc24f0 | ||
|
|
591a46d559 | ||
|
|
2852f26702 | ||
|
|
fc818fdfd6 | ||
|
|
5566ef87f8 | ||
|
|
366fe34d6f | ||
|
|
37a0e83124 | ||
|
|
061a3f393a | ||
|
|
1dff22aeab | ||
|
|
78e6fd4809 | ||
|
|
96bbf3d0f2 | ||
|
|
a842eaba4e | ||
|
|
37565bf8e4 | ||
|
|
beb158b387 | ||
|
|
408eb06f8d | ||
|
|
abe0e44635 | ||
|
|
cfaf414f1c | ||
|
|
f9c4dc616b | ||
|
|
bf845bab6b | ||
|
|
bae9c85990 | ||
|
|
56bbb8d0ff | ||
|
|
60d3565231 | ||
|
|
81340fd287 | ||
|
|
c10c348c73 | ||
|
|
65cb7d9674 | ||
|
|
24f1a10ff7 | ||
|
|
767d11182a | ||
|
|
cf363f667e | ||
|
|
0d1046b8c7 | ||
|
|
2c05f5779e | ||
|
|
9af200f89e | ||
|
|
7e221cfd46 | ||
|
|
640882d178 | ||
|
|
3a1436abef | ||
|
|
d431f0490d | ||
|
|
4c2a6c92a6 | ||
|
|
086c230e9e | ||
|
|
27e2ff50f2 | ||
|
|
3134e5596b | ||
|
|
315274abf9 | ||
|
|
52bbf65fa8 | ||
|
|
9c018ec63b | ||
|
|
bd7e457cdb | ||
|
|
36a0f8515b | ||
|
|
cac10a337d | ||
|
|
edb53cc58f | ||
|
|
1dceeecdad | ||
|
|
f8071ada0b | ||
|
|
21bc8edbd8 | ||
|
|
2a8aeb5041 | ||
|
|
1a7760cf6d | ||
|
|
aee4eed5ac | ||
|
|
87215fb590 | ||
|
|
5409126187 | ||
|
|
9840782ce5 | ||
|
|
d18f42cd6f | ||
|
|
9372e98459 | ||
|
|
9400f4660d | ||
|
|
f0d66b8fba | ||
|
|
78abe72815 | ||
|
|
1ce75916ef | ||
|
|
46959d4baa | ||
|
|
b24cc44493 | ||
|
|
46f6c29e1d | ||
|
|
5ad75b8420 | ||
|
|
2030459f20 | ||
|
|
2855bf812b | ||
|
|
69989893d9 | ||
|
|
ffc61f4a31 | ||
|
|
dd051f28d2 | ||
|
|
a3d2def72b | ||
|
|
e8552b4385 |
@@ -1 +1,2 @@
|
||||
VITE_API_BASE_URL=http://localhost:3001/api/v1/
|
||||
VITE_API_BASE_URL=/api/v1/
|
||||
VITE_PUBLIC_VAPID_KEY=BH3w49sZA6jXUnE-yt4jO6VKh73lsdsvwoJ6Hx7fmPIDKoqGiUl2GEoZzy-iJfn4SfQQcx7yQdHf9RknwrL_lSM
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
VITE_API_BASE_URL=/api/v1/
|
||||
VITE_API_BASE_URL=api/v1/
|
||||
VITE_PUBLIC_VAPID_KEY=BH3w49sZA6jXUnE-yt4jO6VKh73lsdsvwoJ6Hx7fmPIDKoqGiUl2GEoZzy-iJfn4SfQQcx7yQdHf9RknwrL_lSM
|
||||
|
||||
45
.github/ISSUE_TEMPLATE/rfc.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: 功能提案
|
||||
description: Request for Comments
|
||||
title: '[RFC]'
|
||||
labels: ['RFC']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
一份提案(RFC)定位为 **「在某功能/重构的具体开发前,用于开发者间 review 技术设计/方案的文档」**,
|
||||
目的是让协作的开发者间清晰的知道「要做什么」和「具体会怎么做」,以及所有的开发者都能公开透明的参与讨论;
|
||||
以便评估和讨论产生的影响 (遗漏的考虑、向后兼容性、与现有功能的冲突),
|
||||
因此提案侧重在对解决问题的 **方案、设计、步骤** 的描述上。
|
||||
|
||||
如果仅希望讨论是否添加或改进某功能本身,请使用 -> [Issue: 功能改进](https://github.com/jxxghp/MoviePilot/issues/new?assignees=&labels=feature+request&projects=&template=feature_request.yml&title=%5BFeature+Request%5D%3A+)
|
||||
- type: textarea
|
||||
id: background
|
||||
attributes:
|
||||
label: 背景 or 问题
|
||||
description: 简单描述遇到的什么问题或需要改动什么。可以引用其他 issue、讨论、文档等。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: goal
|
||||
attributes:
|
||||
label: '目标 & 方案简述'
|
||||
description: 简单描述提案此提案实现后,**预期的目标效果**,以及简单大致描述会采取的方案/步骤,可能会/不会产生什么影响。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: design
|
||||
attributes:
|
||||
label: '方案设计 & 实现步骤'
|
||||
description: |
|
||||
详细描述你设计的具体方案,可以考虑拆分列表或要点,一步步描述具体打算如何实现的步骤和相关细节。
|
||||
这部份不需要一次性写完整,即使在创建完此提案 issue 后,依旧可以再次编辑修改。
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: alternative
|
||||
attributes:
|
||||
label: '替代方案 & 对比'
|
||||
description: |
|
||||
[可选] 为来实现目标效果,还考虑过什么其他方案,有什么对比?
|
||||
validations:
|
||||
required: false
|
||||
26
.github/workflows/build.yml
vendored
@@ -1,12 +1,12 @@
|
||||
name: Build Moviepilot-Frontend
|
||||
name: Build Moviepilot-Frontend v2
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v2
|
||||
paths:
|
||||
- package.json
|
||||
- 'package.json'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -24,23 +24,39 @@ jobs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '20'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Download Icons
|
||||
run: |
|
||||
pwd
|
||||
curl -sL "https://github.com/jxxghp/MoviePilot-Plugins/archive/refs/heads/main.zip" | busybox unzip -d /tmp -
|
||||
mv /tmp/MoviePilot-Plugins-main/icons public/plugin_icon
|
||||
rm -rf /tmp/MoviePilot-Plugins-main
|
||||
|
||||
- name: Build frontend
|
||||
id: build_frontend
|
||||
run: |
|
||||
yarn
|
||||
yarn build
|
||||
echo "$frontend_version" > dist/version.txt
|
||||
zip -r dist.zip dist
|
||||
|
||||
- name: Delete Release
|
||||
uses: dev-drprasad/delete-tag-and-release@v1.1
|
||||
with:
|
||||
tag_name: ${{ env.frontend_version }}
|
||||
delete_release: true
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Generate Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ env.frontend_version }}
|
||||
name: ${{ env.frontend_version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
make_latest: false
|
||||
files: |
|
||||
dist.zip
|
||||
env:
|
||||
|
||||
2
.gitignore
vendored
@@ -11,6 +11,7 @@ node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
dev-dist
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
@@ -32,3 +33,4 @@ dist-ssr
|
||||
|
||||
# iconify dist files
|
||||
src/@iconify/*.js
|
||||
public/plugin_icon/**
|
||||
|
||||
@@ -21,14 +21,9 @@
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
"max-line-length": [
|
||||
120,
|
||||
{
|
||||
"ignore": "comments"
|
||||
}
|
||||
],
|
||||
"liberty/use-logical-spec": true,
|
||||
"selector-class-pattern": null,
|
||||
"color-function-notation": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"fix": true
|
||||
}
|
||||
16
.vscode/settings.json
vendored
@@ -6,9 +6,6 @@
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": false
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": false
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
|
||||
},
|
||||
@@ -25,14 +22,18 @@
|
||||
},
|
||||
// Vue
|
||||
"[vue]": {
|
||||
"editor.formatOnSave": false
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
// Extension: Volar
|
||||
"volar.preview.port": 3000,
|
||||
"volar.completion.preferredTagNameCase": "pascal",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll.stylelint": true
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"eslint.alwaysShowStatus": true,
|
||||
"eslint.format.enable": true,
|
||||
@@ -53,6 +54,7 @@
|
||||
"stylelint",
|
||||
"touchless",
|
||||
"triggerer",
|
||||
"unref",
|
||||
"vuetify"
|
||||
],
|
||||
// Extension: Comment Anchors
|
||||
@@ -104,4 +106,4 @@
|
||||
]
|
||||
},
|
||||
"vue3snippets.enable-compile-vue-file-on-did-save-code": false
|
||||
}
|
||||
}
|
||||
32
README.md
@@ -1,35 +1,39 @@
|
||||
# MoviePilot-Frontend
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
[MoviePilot](https://github.com/jxxghp/MoviePilot) 的前端项目,NodeJS版本:>= `v20.12.1`。
|
||||
|
||||
## Recommended IDE Setup
|
||||
## 推荐的IDE设置
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur).
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (并禁用 Vetur).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
## 配置Vite
|
||||
|
||||
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates.
|
||||
请参阅 [Vite 配置参考](https://vitejs.dev/config/).
|
||||
|
||||
However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can run `Volar: Switch TS Plugin on/off` from VSCode command palette.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
## 依赖安装
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
### 开发运行
|
||||
|
||||
```sh
|
||||
yarn dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
### 编译打包
|
||||
|
||||
```sh
|
||||
yarn build
|
||||
```
|
||||
|
||||
### 静态运行
|
||||
|
||||
1. 使用 `nginx` 等Web服务器托管 `dist` 静态文件,nginx配置参考 `public/nginx.conf`。
|
||||
|
||||
2. 使用 `node` 命令直接运行`service.js`,默认监听 `3000` 端口,设置环境变量 `NGINX_PORT` 来调整运行端口。
|
||||
|
||||
```shell
|
||||
node dist/service.js
|
||||
```
|
||||
|
||||
71
auto-imports.d.ts
vendored
@@ -1,10 +1,13 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
||||
const computed: typeof import('vue')['computed']
|
||||
@@ -19,13 +22,11 @@ declare global {
|
||||
const createGenericProjection: typeof import('@vueuse/math')['createGenericProjection']
|
||||
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
|
||||
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
|
||||
const createLogger: typeof import('vuex')['createLogger']
|
||||
const createNamespacedHelpers: typeof import('vuex')['createNamespacedHelpers']
|
||||
const createPinia: typeof import('pinia')['createPinia']
|
||||
const createProjection: typeof import('@vueuse/math')['createProjection']
|
||||
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
|
||||
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
|
||||
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
|
||||
const createStore: typeof import('vuex')['createStore']
|
||||
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
|
||||
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
@@ -33,14 +34,17 @@ declare global {
|
||||
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineStore: typeof import('pinia')['defineStore']
|
||||
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
@@ -50,10 +54,11 @@ declare global {
|
||||
const logicNot: typeof import('@vueuse/math')['logicNot']
|
||||
const logicOr: typeof import('@vueuse/math')['logicOr']
|
||||
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||
const mapActions: typeof import('vuex')['mapActions']
|
||||
const mapGetters: typeof import('vuex')['mapGetters']
|
||||
const mapMutations: typeof import('vuex')['mapMutations']
|
||||
const mapState: typeof import('vuex')['mapState']
|
||||
const mapActions: typeof import('pinia')['mapActions']
|
||||
const mapGetters: typeof import('pinia')['mapGetters']
|
||||
const mapState: typeof import('pinia')['mapState']
|
||||
const mapStores: typeof import('pinia')['mapStores']
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
@@ -64,6 +69,7 @@ declare global {
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onElementRemoval: typeof import('@vueuse/core')['onElementRemoval']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
|
||||
const onLongPress: typeof import('@vueuse/core')['onLongPress']
|
||||
@@ -75,8 +81,10 @@ declare global {
|
||||
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||
const reactify: typeof import('@vueuse/core')['reactify']
|
||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
@@ -93,9 +101,12 @@ declare global {
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
||||
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||
const syncRef: typeof import('@vueuse/core')['syncRef']
|
||||
const syncRefs: typeof import('@vueuse/core')['syncRefs']
|
||||
const templateRef: typeof import('@vueuse/core')['templateRef']
|
||||
@@ -105,6 +116,7 @@ declare global {
|
||||
const toReactive: typeof import('@vueuse/core')['toReactive']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||
@@ -143,6 +155,7 @@ declare global {
|
||||
const useCeil: typeof import('@vueuse/math')['useCeil']
|
||||
const useClamp: typeof import('@vueuse/math')['useClamp']
|
||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
|
||||
const useCloned: typeof import('@vueuse/core')['useCloned']
|
||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||
@@ -185,6 +198,7 @@ declare global {
|
||||
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
||||
const useGamepad: typeof import('@vueuse/core')['useGamepad']
|
||||
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useIdle: typeof import('@vueuse/core')['useIdle']
|
||||
const useImage: typeof import('@vueuse/core')['useImage']
|
||||
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
|
||||
@@ -204,6 +218,7 @@ declare global {
|
||||
const useMemoize: typeof import('@vueuse/core')['useMemoize']
|
||||
const useMemory: typeof import('@vueuse/core')['useMemory']
|
||||
const useMin: typeof import('@vueuse/math')['useMin']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useMounted: typeof import('@vueuse/core')['useMounted']
|
||||
const useMouse: typeof import('@vueuse/core')['useMouse']
|
||||
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
|
||||
@@ -229,6 +244,7 @@ declare global {
|
||||
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
|
||||
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
|
||||
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
|
||||
const usePreferredReducedTransparency: typeof import('@vueuse/core')['usePreferredReducedTransparency']
|
||||
const usePrevious: typeof import('@vueuse/core')['usePrevious']
|
||||
const useProjection: typeof import('@vueuse/math')['useProjection']
|
||||
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
||||
@@ -237,6 +253,7 @@ declare global {
|
||||
const useRound: typeof import('@vueuse/math')['useRound']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSSRWidth: typeof import('@vueuse/core')['useSSRWidth']
|
||||
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
|
||||
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
|
||||
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
|
||||
@@ -251,11 +268,11 @@ declare global {
|
||||
const useStepper: typeof import('@vueuse/core')['useStepper']
|
||||
const useStorage: typeof import('@vueuse/core')['useStorage']
|
||||
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
|
||||
const useStore: typeof import('vuex')['useStore']
|
||||
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
|
||||
const useSum: typeof import('@vueuse/math')['useSum']
|
||||
const useSupported: typeof import('@vueuse/core')['useSupported']
|
||||
const useSwipe: typeof import('@vueuse/core')['useSwipe']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
|
||||
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
|
||||
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
|
||||
@@ -308,13 +325,17 @@ declare global {
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
|
||||
// for vue template auto import
|
||||
import { UnwrapRef } from 'vue'
|
||||
declare module 'vue' {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
|
||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||
@@ -329,13 +350,11 @@ declare module 'vue' {
|
||||
readonly createGenericProjection: UnwrapRef<typeof import('@vueuse/math')['createGenericProjection']>
|
||||
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
|
||||
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
|
||||
readonly createLogger: UnwrapRef<typeof import('vuex')['createLogger']>
|
||||
readonly createNamespacedHelpers: UnwrapRef<typeof import('vuex')['createNamespacedHelpers']>
|
||||
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
|
||||
readonly createProjection: UnwrapRef<typeof import('@vueuse/math')['createProjection']>
|
||||
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
|
||||
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
|
||||
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
|
||||
readonly createStore: UnwrapRef<typeof import('vuex')['createStore']>
|
||||
readonly createTemplatePromise: UnwrapRef<typeof import('@vueuse/core')['createTemplatePromise']>
|
||||
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
|
||||
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
|
||||
@@ -343,14 +362,17 @@ declare module 'vue' {
|
||||
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
|
||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
|
||||
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
|
||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
@@ -360,10 +382,11 @@ declare module 'vue' {
|
||||
readonly logicNot: UnwrapRef<typeof import('@vueuse/math')['logicNot']>
|
||||
readonly logicOr: UnwrapRef<typeof import('@vueuse/math')['logicOr']>
|
||||
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||
readonly mapActions: UnwrapRef<typeof import('vuex')['mapActions']>
|
||||
readonly mapGetters: UnwrapRef<typeof import('vuex')['mapGetters']>
|
||||
readonly mapMutations: UnwrapRef<typeof import('vuex')['mapMutations']>
|
||||
readonly mapState: UnwrapRef<typeof import('vuex')['mapState']>
|
||||
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
|
||||
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
|
||||
readonly mapState: UnwrapRef<typeof import('pinia')['mapState']>
|
||||
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
|
||||
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
|
||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
|
||||
@@ -374,6 +397,7 @@ declare module 'vue' {
|
||||
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
|
||||
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
|
||||
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
|
||||
readonly onElementRemoval: UnwrapRef<typeof import('@vueuse/core')['onElementRemoval']>
|
||||
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
|
||||
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
|
||||
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
|
||||
@@ -385,8 +409,10 @@ declare module 'vue' {
|
||||
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
|
||||
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
|
||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
@@ -403,9 +429,12 @@ declare module 'vue' {
|
||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
||||
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
||||
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
||||
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
||||
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
||||
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
||||
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
|
||||
@@ -415,6 +444,7 @@ declare module 'vue' {
|
||||
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
|
||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
|
||||
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
|
||||
@@ -453,6 +483,7 @@ declare module 'vue' {
|
||||
readonly useCeil: UnwrapRef<typeof import('@vueuse/math')['useCeil']>
|
||||
readonly useClamp: UnwrapRef<typeof import('@vueuse/math')['useClamp']>
|
||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||
@@ -495,6 +526,7 @@ declare module 'vue' {
|
||||
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
|
||||
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
|
||||
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
|
||||
readonly useId: UnwrapRef<typeof import('vue')['useId']>
|
||||
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
|
||||
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
|
||||
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
|
||||
@@ -514,6 +546,7 @@ declare module 'vue' {
|
||||
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
|
||||
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
|
||||
readonly useMin: UnwrapRef<typeof import('@vueuse/math')['useMin']>
|
||||
readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
|
||||
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
|
||||
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
|
||||
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
|
||||
@@ -539,6 +572,7 @@ declare module 'vue' {
|
||||
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
|
||||
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
|
||||
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
|
||||
readonly usePreferredReducedTransparency: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedTransparency']>
|
||||
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
|
||||
readonly useProjection: UnwrapRef<typeof import('@vueuse/math')['useProjection']>
|
||||
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
||||
@@ -547,6 +581,7 @@ declare module 'vue' {
|
||||
readonly useRound: UnwrapRef<typeof import('@vueuse/math')['useRound']>
|
||||
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
|
||||
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
|
||||
readonly useSSRWidth: UnwrapRef<typeof import('@vueuse/core')['useSSRWidth']>
|
||||
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
|
||||
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
|
||||
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
|
||||
@@ -561,11 +596,11 @@ declare module 'vue' {
|
||||
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
|
||||
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
|
||||
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
|
||||
readonly useStore: UnwrapRef<typeof import('vuex')['useStore']>
|
||||
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
|
||||
readonly useSum: UnwrapRef<typeof import('@vueuse/math')['useSum']>
|
||||
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
|
||||
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
|
||||
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
|
||||
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
|
||||
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
|
||||
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
|
||||
@@ -615,4 +650,4 @@ declare module 'vue' {
|
||||
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
|
||||
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
|
||||
}
|
||||
}
|
||||
}
|
||||
8
components.d.ts
vendored
@@ -1,20 +1,20 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
|
||||
ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default']
|
||||
ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default']
|
||||
LoadingBanner: typeof import('./src/@core/components/LoadingBanner.vue')['default']
|
||||
MoreBtn: typeof import('./src/@core/components/MoreBtn.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
StatIcon: typeof import('./src/@core/components/StatIcon.vue')['default']
|
||||
ThemeSwitcher: typeof import('./src/@core/components/ThemeSwitcher.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
33
index.html
@@ -1,6 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html
|
||||
lang="en"
|
||||
style="
|
||||
overflow: hidden auto;
|
||||
min-block-size: calc(100% + env(safe-area-inset-top) + env(safe-area-inset-bottom));
|
||||
background: var(--initial-loader-bg, #fff);
|
||||
"
|
||||
>
|
||||
<head>
|
||||
<meta http-equiv="pragma" content="no-cache" />
|
||||
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="expires" content="0" />
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="initial-scale=1, viewport-fit=cover, width=device-width, user-scalable=no" />
|
||||
@@ -11,7 +21,6 @@
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash.jpg" />
|
||||
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="manifest.json" crossorigin="use-credentials" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
@@ -26,15 +35,21 @@
|
||||
<meta name="HandheldFriendly" content="True" />
|
||||
<meta name="MobileOptimized" content="320" />
|
||||
<link rel="stylesheet" type="text/css" href="/loader.css" />
|
||||
<script>
|
||||
const loaderColor = localStorage.getItem('materio-initial-loader-bg') || '#FFFFFF'
|
||||
if (loaderColor) document.documentElement.style.setProperty('--initial-loader-bg', loaderColor)
|
||||
const primaryColor = localStorage.getItem('materio-initial-loader-color') || '#9155FD'
|
||||
if (primaryColor) document.documentElement.style.setProperty('--initial-loader-color', primaryColor)
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body style="margin: 0">
|
||||
<div id="loading-bg">
|
||||
<div class="loading-logo">
|
||||
<!-- Logo -->
|
||||
<svg
|
||||
width="100px"
|
||||
height="100px"
|
||||
width="10rem"
|
||||
height="10rem"
|
||||
viewBox="0 0 192 192"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -202,13 +217,5 @@
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<script>
|
||||
const loaderColor = localStorage.getItem('materio-initial-loader-bg') || '#FFFFFF'
|
||||
const primaryColor = localStorage.getItem('materio-initial-loader-color') || '#9155FD'
|
||||
|
||||
if (loaderColor) document.documentElement.style.setProperty('--initial-loader-bg', loaderColor)
|
||||
|
||||
if (primaryColor) document.documentElement.style.setProperty('--initial-loader-color', primaryColor)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
146
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "moviepilot",
|
||||
"version": "1.3.5",
|
||||
"version": "2.3.4",
|
||||
"private": true,
|
||||
"bin": "dist/service.js",
|
||||
"scripts": {
|
||||
@@ -19,91 +19,93 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.2.0",
|
||||
"@casl/vue": "^2.2.0",
|
||||
"@floating-ui/dom": "1.2.8",
|
||||
"@vueuse/core": "^10.1.2",
|
||||
"@vueuse/math": "^10.1.2",
|
||||
"apexcharts-clevision": "^3.28.5",
|
||||
"axios": "1.4.0",
|
||||
"axios-mock-adapter": "^1.21.4",
|
||||
"chart.js": "^4.1.2",
|
||||
"express": "^4.18.2",
|
||||
"express-http-proxy": "^2.0.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"@fullcalendar/core": "^6.1.15",
|
||||
"@fullcalendar/daygrid": "^6.1.15",
|
||||
"@fullcalendar/interaction": "^6.1.15",
|
||||
"@fullcalendar/list": "^6.1.15",
|
||||
"@fullcalendar/timegrid": "^6.1.15",
|
||||
"@fullcalendar/vue3": "^6.1.15",
|
||||
"@iconify/utils": "^2.2.1",
|
||||
"@vue-flow/background": "^1.3.2",
|
||||
"@vue-flow/controls": "^1.1.2",
|
||||
"@vue-flow/core": "^1.42.1",
|
||||
"@vue-flow/minimap": "^1.5.2",
|
||||
"@vue-flow/node-resizer": "^1.4.0",
|
||||
"@vue-flow/node-toolbar": "^1.1.0",
|
||||
"@vue-js-cron/vuetify": "^5.0.9",
|
||||
"@vueuse/core": "^12.4.0",
|
||||
"@vueuse/math": "^12.4.0",
|
||||
"ace-builds": "^1.37.4",
|
||||
"apexcharts": "^4.0.0",
|
||||
"axios": "^1.7.9",
|
||||
"colorthief": "^2.6.0",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.13",
|
||||
"express": "^4.21.2",
|
||||
"express-http-proxy": "^2.1.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mousetrap": "^1.6.5",
|
||||
"nprogress": "^0.2.0",
|
||||
"postcss-purgecss": "^5.0.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"pull-refresh-vue3": "^0.3.1",
|
||||
"roboto-fontface": "^0.10.0",
|
||||
"sass": "^1.59.3",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"unplugin-vue-define-options": "^1.3.5",
|
||||
"vite-plugin-pwa": "^0.16.4",
|
||||
"vue": "^3.3.2",
|
||||
"vue-chartjs": "^5.2.0",
|
||||
"vue-flatpickr-component": "11.0.3",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-prism-component": "^2.0.0",
|
||||
"vue-router": "^4.2.0",
|
||||
"vue-toast-notification": "^3",
|
||||
"vue3-apexcharts": "^1.4.1",
|
||||
"vue3-perfect-scrollbar": "^1.6.0",
|
||||
"vuetify": "3.3.5",
|
||||
"vuetify-use-dialog": "^0.6.0",
|
||||
"vuex": "^4.1.0",
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"sass": "^1.83.4",
|
||||
"tailwindcss": "^ 3.4.17",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-toast-notification": "^3.1.3",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
"vue3-apexcharts": "^1.8.0",
|
||||
"vue3-perfect-scrollbar": "^2.0.0",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuetify": "3.7.3",
|
||||
"vuetify-use-dialog": "^0.6.11",
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config-vue": "^0.38.6",
|
||||
"@fullcalendar/core": "^6.1.8",
|
||||
"@fullcalendar/daygrid": "^6.1.8",
|
||||
"@fullcalendar/interaction": "^6.1.7",
|
||||
"@fullcalendar/list": "^6.1.7",
|
||||
"@fullcalendar/timegrid": "^6.1.7",
|
||||
"@fullcalendar/vue3": "^6.1.8",
|
||||
"@iconify-json/mdi": "^1.1.52",
|
||||
"@iconify/tools": "^2.2.0",
|
||||
"@iconify/vue": "4.1.1",
|
||||
"@intlify/unplugin-vue-i18n": "^0.10.0",
|
||||
"@iconify/tools": "^4.0.4",
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.3",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/webfontloader": "^1.6.34",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
||||
"@typescript-eslint/parser": "^5.59.5",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||
"@typescript-eslint/parser": "^8.20.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.40.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"eslint-plugin-regex": "^1.10.0",
|
||||
"eslint-plugin-sonarjs": "^0.19.0",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
"eslint-plugin-sonarjs": "^3.0.1",
|
||||
"eslint-plugin-unicorn": "^56.0.1",
|
||||
"eslint-plugin-vue": "^9.12.0",
|
||||
"postcss": "^8.4.24",
|
||||
"postcss": "^8.5.1",
|
||||
"postcss-html": "^1.5.0",
|
||||
"stylelint": "14.15.0",
|
||||
"stylelint-config-idiomatic-order": "9.0.0",
|
||||
"stylelint-config-standard-scss": "6.1.0",
|
||||
"stylelint-use-logical-spec": "4.1.0",
|
||||
"type-fest": "^3.10.0",
|
||||
"stylelint": "^16.13.2",
|
||||
"stylelint-config-idiomatic-order": "^10.0.0",
|
||||
"stylelint-config-standard-scss": "^14.0.0",
|
||||
"stylelint-use-logical-spec": "5.0.1",
|
||||
"terser": "^5.36.0",
|
||||
"type-fest": "^4.15.0",
|
||||
"typescript": "^5.0.4",
|
||||
"unplugin-auto-import": "^0.15.1",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vite": "^4.3.5",
|
||||
"vite-plugin-pages": "^0.29.0",
|
||||
"vite-plugin-vue-layouts": "^0.8.0",
|
||||
"vite-plugin-vuetify": "1.0.2",
|
||||
"vue-shepherd": "^3.0.0",
|
||||
"vue-tsc": "^1.6.5"
|
||||
"unplugin-auto-import": "^19.0.0",
|
||||
"unplugin-vue-components": "^28.0.0",
|
||||
"unplugin-vue-define-options": "^1.5.3",
|
||||
"vite": "^5.4.11",
|
||||
"vite-plugin-pages": "^0.32.1",
|
||||
"vite-plugin-pwa": "^0.21.1",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vite-plugin-vuetify": "2.0.4",
|
||||
"vue-shepherd": "^4.1.0",
|
||||
"vue-tsc": "^2.0.10",
|
||||
"workbox-build": "^7.3.0",
|
||||
"workbox-window": "^7.3.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.18",
|
||||
"resolutions": {
|
||||
"postcss": "8"
|
||||
}
|
||||
"packageManager": "yarn@1.22.18"
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
background: var(--initial-loader-bg, #fff);
|
||||
min-block-size: calc(100% + env(safe-area-inset-top));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#loading-bg {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
display: block;
|
||||
background: var(--initial-loader-bg, #fff);
|
||||
block-size: 100vh;
|
||||
@@ -20,8 +9,8 @@ html {
|
||||
|
||||
.loading-logo {
|
||||
position: absolute;
|
||||
inset-block-start: 40%;
|
||||
inset-inline-start: calc(50% - 50px);
|
||||
inset-block-start: 35%;
|
||||
inset-inline-start: calc(50% - 5rem);
|
||||
}
|
||||
|
||||
.loading {
|
||||
@@ -83,4 +72,4 @@ html {
|
||||
opacity: 1;
|
||||
transform: rotate(1turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
{
|
||||
"name": "MoviePilot",
|
||||
"short_name": "MoviePilot",
|
||||
"start_url": "./",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "./android-chrome-192x192_maskable.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "./android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "./android-chrome-512x512_maskable.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"theme_color": "#28243D",
|
||||
"background_color": "#28243D",
|
||||
"display": "standalone",
|
||||
"shortcuts": [
|
||||
{
|
||||
"name": "推荐",
|
||||
"url": "./ranking",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./sparkles-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "电影订阅",
|
||||
"url": "./subscribe-movie",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./clock-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "电视剧订阅",
|
||||
"url": "./subscribe-tv",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./clock-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "设置",
|
||||
"url": "./setting",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./cog-icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11,6 +11,13 @@ http {
|
||||
|
||||
keepalive_timeout 3600;
|
||||
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
||||
gzip_proxied any;
|
||||
gzip_min_length 256;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 6;
|
||||
|
||||
server {
|
||||
|
||||
include mime.types;
|
||||
@@ -28,9 +35,16 @@ http {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||
# 静态资源
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
root html;
|
||||
}
|
||||
|
||||
location /assets {
|
||||
# 静态资源
|
||||
expires 7d;
|
||||
expires 1y;
|
||||
add_header Cache-Control "public";
|
||||
root html;
|
||||
}
|
||||
@@ -75,6 +89,26 @@ http {
|
||||
# 超时设置
|
||||
proxy_read_timeout 600s;
|
||||
}
|
||||
|
||||
location /cookiecloud {
|
||||
# 后端cookiecloud地址
|
||||
proxy_pass http://backend_api;
|
||||
rewrite ^.+mock-server/?(.*)$ /$1 break;
|
||||
proxy_http_version 1.1;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_redirect off;
|
||||
proxy_set_header Connection "";
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Nginx-Proxy true;
|
||||
|
||||
# 超时设置
|
||||
proxy_read_timeout 600s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
upstream backend_api {
|
||||
|
||||
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 81 KiB |
2
public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow: /
|
||||
@@ -25,10 +25,25 @@ app.use(
|
||||
})
|
||||
);
|
||||
|
||||
// 配置代理中间件将CookieCloud请求转发给后端API
|
||||
app.use(
|
||||
'/cookiecloud',
|
||||
proxy(`${proxyConfig.URL}:${proxyConfig.PORT}`, {
|
||||
// 路径加上 /cookiecloud 前缀
|
||||
proxyReqPathResolver: (req) => {
|
||||
return `/cookiecloud${req.url}`
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 处理根路径的请求
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'index.html')) // 指向你的前端入口文件
|
||||
res.sendFile(path.join(__dirname, 'index.html'))
|
||||
})
|
||||
|
||||
// 处理所有其他请求,重定向到前端入口文件
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'index.html'))
|
||||
})
|
||||
|
||||
app.listen(port, () => {
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<script lang="ts" setup>
|
||||
// 定义输入参数
|
||||
const props = defineProps({
|
||||
// 是否显示
|
||||
innerClass: String,
|
||||
})
|
||||
// 定义触发的自定义事件
|
||||
const emit = defineEmits(['click'])
|
||||
|
||||
const emit = defineEmits(['click', 'update:modelValue'])
|
||||
// 按钮点击
|
||||
function onClick() {
|
||||
emit('update:modelValue', false)
|
||||
emit('click')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<IconBtn
|
||||
class="absolute right-3 top-3"
|
||||
:class="props.innerClass ? props.innerClass : 'absolute right-3 top-3'"
|
||||
@click.stop="onClick"
|
||||
>
|
||||
<VIcon icon="mdi-close" />
|
||||
|
||||
15
src/@core/components/LoadingBanner.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
// 定义输入参数
|
||||
const props = defineProps({
|
||||
progress: Number,
|
||||
text: String,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full text-center text-gray-500 text-sm flex flex-col items-center">
|
||||
<VProgressCircular v-if="!props.text || !props.progress" class="mb-3" size="64" indeterminate color="primary" />
|
||||
<VProgressCircular v-if="props.progress" class="mb-3" color="primary" :model-value="props.progress" size="64" />
|
||||
<span>{{ props.text }}</span>
|
||||
</div>
|
||||
</template>
|
||||
18
src/@core/components/StatIcon.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
color?: string
|
||||
message?: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="absolute top-2 right-2 flex items-center justify-between p-2 shadow">
|
||||
<VBadge :color="props.color" bordered>
|
||||
<template #badge>
|
||||
<VIcon icon="mdi-pulse"></VIcon>
|
||||
</template>
|
||||
</VBadge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,7 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useTheme } from 'vuetify'
|
||||
import { ref } from 'vue'
|
||||
import { useDisplay, useTheme } from 'vuetify'
|
||||
import type { ThemeSwitcherTheme } from '@layouts/types'
|
||||
import api from '@/api'
|
||||
import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import { saveLocalTheme } from '../utils/theme'
|
||||
|
||||
// 显示器宽度
|
||||
const display = useDisplay()
|
||||
|
||||
const props = defineProps<{
|
||||
themes: ThemeSwitcherTheme[]
|
||||
@@ -11,59 +18,33 @@ const { name: themeName, global: globalTheme } = useTheme()
|
||||
|
||||
const savedTheme = ref(localStorage.getItem('theme') ?? themeName)
|
||||
|
||||
const {
|
||||
state: currentThemeName,
|
||||
next: getNextThemeName,
|
||||
index: currentThemeIndex,
|
||||
} = useCycleList(
|
||||
const { state: currentThemeName, next: getNextThemeName } = useCycleList(
|
||||
props.themes.map(t => t.name),
|
||||
{ initialValue: savedTheme.value },
|
||||
)
|
||||
|
||||
function changeTheme() {
|
||||
const nextTheme = getNextThemeName()
|
||||
const $toast = useToast()
|
||||
|
||||
globalTheme.name.value = nextTheme
|
||||
savedTheme.value = nextTheme
|
||||
localStorage.setItem('theme', nextTheme)
|
||||
// 修改载入时背景色
|
||||
localStorage.setItem('materio-initial-loader-bg', globalTheme.current.value.colors.background)
|
||||
// 自定义CSS弹窗
|
||||
const cssDialog = ref(false)
|
||||
|
||||
themeTransition()
|
||||
}
|
||||
// 自定义 CSS
|
||||
const customCSS = ref('')
|
||||
|
||||
// Update icon if theme is changed from other sources
|
||||
watch(
|
||||
() => globalTheme.name.value,
|
||||
(val) => {
|
||||
currentThemeName.value = val
|
||||
},
|
||||
)
|
||||
|
||||
// Apply saved theme on page load
|
||||
// onMounted(() => {
|
||||
// globalTheme.name.value = savedTheme.value
|
||||
// })
|
||||
|
||||
function hasScrollbar(el?: Element | null) {
|
||||
if (!el || el.nodeType !== Node.ELEMENT_NODE)
|
||||
return false
|
||||
|
||||
const style = window.getComputedStyle(el)
|
||||
return style.overflowY === 'scroll' || (style.overflowY === 'auto' && el.scrollHeight > el.clientHeight)
|
||||
}
|
||||
// 编辑器主题
|
||||
const editorTheme = computed(() => (currentThemeName.value === 'light' ? 'github' : 'monokai'))
|
||||
|
||||
// 主题切换动画
|
||||
function themeTransition() {
|
||||
const x = performance.now()
|
||||
for (let i = 0; i++ < 1e7; (i << 9) & ((9 % 9) * 9 + 9));
|
||||
const cost = performance.now() - x
|
||||
if (cost > 10)
|
||||
return
|
||||
if (cost > 10) return
|
||||
|
||||
const el: HTMLElement = document.querySelector('[data-v-app]')!
|
||||
const children = el.querySelectorAll('*') as NodeListOf<HTMLElement>
|
||||
|
||||
children.forEach((el) => {
|
||||
children.forEach(el => {
|
||||
if (hasScrollbar(el)) {
|
||||
el.dataset.scrollX = String(el.scrollLeft)
|
||||
el.dataset.scrollY = String(el.scrollTop)
|
||||
@@ -95,7 +76,7 @@ function themeTransition() {
|
||||
})
|
||||
|
||||
document.body.append(copy)
|
||||
; (copy.querySelectorAll('[data-scroll-x], [data-scroll-y]') as NodeListOf<HTMLElement>).forEach((el) => {
|
||||
;(copy.querySelectorAll('[data-scroll-x], [data-scroll-y]') as NodeListOf<HTMLElement>).forEach(el => {
|
||||
el.scrollLeft = +el.dataset.scrollX!
|
||||
el.scrollTop = +el.dataset.scrollY!
|
||||
})
|
||||
@@ -113,12 +94,142 @@ function themeTransition() {
|
||||
el.addEventListener('transitionend', onTransitionend)
|
||||
el.addEventListener('transitioncancel', onTransitionend)
|
||||
}
|
||||
|
||||
// 更新主题
|
||||
function updateTheme() {
|
||||
const autoTheme = checkPrefersColorSchemeIsDark() ? 'dark' : 'light'
|
||||
const theme = currentThemeName.value === 'auto' ? autoTheme : currentThemeName.value
|
||||
globalTheme.name.value = theme
|
||||
savedTheme.value = theme
|
||||
themeTransition()
|
||||
// 保存主题到本地
|
||||
saveLocalTheme(theme, globalTheme)
|
||||
}
|
||||
|
||||
// 切换主题
|
||||
function changeTheme(theme: string) {
|
||||
let nextTheme = theme
|
||||
if (!theme) nextTheme = getNextThemeName()
|
||||
currentThemeName.value = nextTheme
|
||||
// 保存主题到服务端
|
||||
try {
|
||||
api.post('/user/config/Layout', {
|
||||
theme: nextTheme,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('保存主题到服务端失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 是否有滚动条
|
||||
function hasScrollbar(el?: Element | null) {
|
||||
if (!el || el.nodeType !== Node.ELEMENT_NODE) return false
|
||||
|
||||
const style = window.getComputedStyle(el)
|
||||
return style.overflowY === 'scroll' || (style.overflowY === 'auto' && el.scrollHeight > el.clientHeight)
|
||||
}
|
||||
|
||||
// 监听系统主题变化
|
||||
try {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateTheme)
|
||||
} catch (e) {
|
||||
console.error('当前设备不支持监听系统主题变化')
|
||||
}
|
||||
|
||||
// 查询当前主题的图标
|
||||
const getThemeIcon = computed(() => {
|
||||
const theme = props.themes.find(t => t.name === currentThemeName.value)
|
||||
return theme?.icon ?? 'mdi-circle'
|
||||
})
|
||||
|
||||
// 监听设置主题变化
|
||||
watch(
|
||||
() => currentThemeName.value,
|
||||
() => updateTheme(),
|
||||
)
|
||||
|
||||
// 获取自定义 CSS
|
||||
async function getCustomCSS() {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.get('system/setting/UserCustomCSS')
|
||||
if (result && result.success && result.data?.value) {
|
||||
customCSS.value = result.data?.value ?? ''
|
||||
if (customCSS.value) {
|
||||
const style = document.createElement('style')
|
||||
style.innerHTML = result.data?.value ?? ''
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存自定义 CSS
|
||||
async function saveCustomCSS() {
|
||||
cssDialog.value = false
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('system/setting/UserCustomCSS', customCSS.value, {
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
})
|
||||
|
||||
if (result.success) $toast.success('自定义CSS保存成功,请刷新页面生效!')
|
||||
} catch (e) {
|
||||
console.error('保存自定义 CSS 到服务端失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCustomCSS()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<IconBtn @click="changeTheme">
|
||||
<VIcon :icon="props.themes[currentThemeIndex].icon" />
|
||||
</IconBtn>
|
||||
<VMenu v-if="props.themes">
|
||||
<template v-slot:activator="{ props }">
|
||||
<IconBtn v-bind="props">
|
||||
<VIcon :icon="getThemeIcon" />
|
||||
</IconBtn>
|
||||
</template>
|
||||
<VList>
|
||||
<VListItem v-for="theme in props.themes" :key="theme.name" @click="changeTheme(theme.name)">
|
||||
<template #prepend>
|
||||
<VIcon :icon="theme.icon" />
|
||||
</template>
|
||||
<VListItemTitle>{{ theme.title }}</VListItemTitle>
|
||||
</VListItem>
|
||||
<VListItem @click="cssDialog = true">
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-palette" />
|
||||
</template>
|
||||
<VListItemTitle>自定义</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
<!-- 自定义 CSS -- -->
|
||||
<VDialog v-if="cssDialog" v-model="cssDialog" persistent max-width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard title="自定义主题风格">
|
||||
<DialogCloseBtn @click="cssDialog = false" />
|
||||
<VDivider />
|
||||
<VAceEditor
|
||||
v-model:value="customCSS"
|
||||
lang="css"
|
||||
:theme="editorTheme"
|
||||
style="block-size: 100%; min-block-size: 30rem"
|
||||
/>
|
||||
<VDivider />
|
||||
<VCardText class="text-center">
|
||||
<VBtn @click="saveCustomCSS" class="w-1/2">
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-content-save" />
|
||||
</template>
|
||||
保存
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="sass">
|
||||
|
||||
@@ -212,10 +212,6 @@ h6,
|
||||
}
|
||||
}
|
||||
|
||||
.v-data-table-footer {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
// 👉 v-field
|
||||
.v-field:hover .v-field__outline {
|
||||
--v-field-border-opacity: var(--v-medium-emphasis-opacity);
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
/* stylelint-enable */
|
||||
background-color: rgb(var(--v-theme-surface), 0.9);
|
||||
background-color: rgb(var(--v-theme-surface), 0.8);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.auth-wrapper {
|
||||
min-block-size: calc(var(--vh, 1vh) * 100 + env(safe-area-inset-top));
|
||||
min-block-size: calc(var(--vh, 1vh) * 100 + env(safe-area-inset-top) + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.auth-footer-mask {
|
||||
|
||||
@@ -176,10 +176,6 @@
|
||||
th {
|
||||
background: rgb(var(--v-table-header-background)) !important;
|
||||
}
|
||||
|
||||
.v-data-table-footer {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
// 👉 Pagination
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
@use "sass:map";
|
||||
@use "vuetify/lib/styles/settings" as vuetify_settings;
|
||||
|
||||
@mixin avatar-font-sizes($map: $avatar-sizes) {
|
||||
@each $sizeName, $multiplier in vuetify_settings.$size-scales {
|
||||
/* stylelint-disable-next-line scss/no-global-function-names */
|
||||
$size: map-get($map, $sizeName);
|
||||
$size: map.get($map, $sizeName);
|
||||
|
||||
&.v-avatar--size-#{$sizeName} {
|
||||
font-size: #{$size}px;
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
.fc-header-toolbar {
|
||||
flex-wrap: wrap;
|
||||
margin: 1.25rem;
|
||||
column-gap: 0.5rem;
|
||||
row-gap: 1rem;
|
||||
gap: 1rem 0.5rem;
|
||||
}
|
||||
|
||||
.fc-toolbar-chunk {
|
||||
@@ -238,7 +237,7 @@
|
||||
inline-size: 1.5625rem;
|
||||
margin-inline-end: 0.25rem;
|
||||
|
||||
@media (max-width: 1264px) {
|
||||
@media (width <= 1264px) {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
|
||||
18
src/@core/utils/compatibility.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 浏览器兼容性处理
|
||||
*/
|
||||
|
||||
/**
|
||||
* 修复低版本Safari等浏览器数组不支持at函数的问题
|
||||
*/
|
||||
;(function fixArrayAt() {
|
||||
if (!Array.prototype.at) {
|
||||
Array.prototype.at = function (index: number) {
|
||||
if (index >= 0) {
|
||||
return this[index]
|
||||
} else {
|
||||
return this[this.length + index]
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
26
src/@core/utils/dom.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export function removeEl(selector: string) {
|
||||
if (selector) {
|
||||
const el = document.querySelector(selector)
|
||||
el?.parentNode?.removeChild(el)
|
||||
}
|
||||
}
|
||||
|
||||
export function useDefer(maxFrameCount = 1) {
|
||||
const frameCount = ref(0)
|
||||
const refreshFrameCount = () => {
|
||||
requestAnimationFrame(() => {
|
||||
frameCount.value++
|
||||
if (frameCount.value < maxFrameCount) refreshFrameCount()
|
||||
})
|
||||
}
|
||||
refreshFrameCount()
|
||||
return function (showInFrameCount: number) {
|
||||
return frameCount.value >= showInFrameCount
|
||||
}
|
||||
}
|
||||
|
||||
export function ensureRenderComplete(callback: () => void) {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(callback)
|
||||
})
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import ZH_CN from 'dayjs/locale/zh-cn'
|
||||
|
||||
import { isToday } from './index'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.locale(ZH_CN)
|
||||
|
||||
export function avatarText(value: string) {
|
||||
if (!value)
|
||||
return ''
|
||||
if (!value) return ''
|
||||
const nameArray = value.split(' ')
|
||||
|
||||
return nameArray.map(word => word.charAt(0).toUpperCase()).join('')
|
||||
@@ -12,19 +18,23 @@ export function avatarText(value: string) {
|
||||
export function kFormatter(num: number) {
|
||||
const regex = /\B(?=(\d{3})+(?!\d))/g
|
||||
|
||||
return Math.abs(num) > 9999 ? `${Math.sign(num) * +((Math.abs(num) / 1000).toFixed(1))}k` : Math.abs(num).toFixed(0).replace(regex, ',')
|
||||
return Math.abs(num) > 9999
|
||||
? `${Math.sign(num) * +(Math.abs(num) / 1000).toFixed(1)}k`
|
||||
: Math.abs(num).toFixed(0).replace(regex, ',')
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and return date in Humanize format
|
||||
* Intl docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format
|
||||
* Intl Constructor: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
|
||||
* @param {String} value date to format
|
||||
* @param {string} value date to format
|
||||
* @param {Intl.DateTimeFormatOptions} formatting Intl object to format with
|
||||
*/
|
||||
export function formatDate(value: string, formatting: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' }) {
|
||||
if (!value)
|
||||
return value
|
||||
export function formatDate(
|
||||
value: string,
|
||||
formatting: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' },
|
||||
) {
|
||||
if (!value) return value
|
||||
|
||||
return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
|
||||
}
|
||||
@@ -32,39 +42,43 @@ export function formatDate(value: string, formatting: Intl.DateTimeFormatOptions
|
||||
/**
|
||||
* Return short human friendly month representation of date
|
||||
* Can also convert date to only time if date is of today (Better UX)
|
||||
* @param {String} value date to format
|
||||
* @param {Boolean} toTimeForCurrentDay Shall convert to time if day is today/current
|
||||
* @param {string} value date to format
|
||||
* @param {boolean} toTimeForCurrentDay Shall convert to time if day is today/current
|
||||
*/
|
||||
export function formatDateToMonthShort(value: string, toTimeForCurrentDay = true) {
|
||||
const date = new Date(value)
|
||||
let formatting: Record<string, string> = { month: 'short', day: 'numeric' }
|
||||
|
||||
if (toTimeForCurrentDay && isToday(date))
|
||||
formatting = { hour: 'numeric', minute: 'numeric' }
|
||||
if (toTimeForCurrentDay && isToday(date)) formatting = { hour: 'numeric', minute: 'numeric' }
|
||||
|
||||
return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
|
||||
}
|
||||
|
||||
export const prefixWithPlus = (value: number) => value > 0 ? `+${value}` : value
|
||||
export const prefixWithPlus = (value: number) => (value > 0 ? `+${value}` : value)
|
||||
|
||||
// 格式化为Sxx
|
||||
export const formatSeason = (value: string) => value ? `S${value.padStart(2, '0')}` : ''
|
||||
export const formatSeason = (value: string) => (value ? `S${value.padStart(2, '0')}` : '')
|
||||
|
||||
// 格式化为xx[TGMK]B
|
||||
export function formatFileSize(bytes: number) {
|
||||
if (bytes < 0)
|
||||
throw new Error('字节数不能为负数。')
|
||||
|
||||
const units = ['B', 'K', 'M', 'G', 'T']
|
||||
export function formatFileSize(bytes: number, decimals = 2, prefix = false) {
|
||||
// 负数标记
|
||||
let negative = false
|
||||
let size = bytes
|
||||
if (bytes < 0) {
|
||||
negative = true
|
||||
size = Math.abs(bytes)
|
||||
}
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
let unitIndex = 0
|
||||
|
||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||
size /= 1024
|
||||
unitIndex++
|
||||
}
|
||||
|
||||
return `${size.toFixed(2)} ${units[unitIndex]}`
|
||||
if (negative) return `-${size.toFixed(decimals)} ${units[unitIndex]}`
|
||||
else
|
||||
return prefix ? `+${size.toFixed(decimals)} ${units[unitIndex]}` : `${size.toFixed(decimals)} ${units[unitIndex]}`
|
||||
}
|
||||
|
||||
// 将时间秒格式化为时分秒
|
||||
@@ -75,22 +89,18 @@ export function formatSeconds(seconds: number) {
|
||||
|
||||
let formattedTime = ''
|
||||
|
||||
if (hours > 0)
|
||||
formattedTime += `${hours}小时`
|
||||
if (hours > 0) formattedTime += `${hours}小时`
|
||||
|
||||
if (minutes > 0)
|
||||
formattedTime += `${minutes}分`
|
||||
if (minutes > 0) formattedTime += `${minutes}分`
|
||||
|
||||
if ((remainingSeconds > 0 || formattedTime === '') && hours <= 0)
|
||||
formattedTime += `${remainingSeconds}秒`
|
||||
if ((remainingSeconds > 0 || formattedTime === '') && hours <= 0) formattedTime += `${remainingSeconds}秒`
|
||||
|
||||
return formattedTime
|
||||
}
|
||||
|
||||
// YYYY-MM-DD 转化为Date
|
||||
export function parseDate(dateString: string): Date | null {
|
||||
if (!dateString)
|
||||
return null
|
||||
if (!dateString) return null
|
||||
const [year, month, day] = dateString.split('-').map(Number)
|
||||
|
||||
return new Date(year, month - 1, day)
|
||||
@@ -98,8 +108,7 @@ export function parseDate(dateString: string): Date | null {
|
||||
|
||||
// 文件大小格式化
|
||||
export function formatBytes(bytes: number, decimals = 2) {
|
||||
if (bytes === 0)
|
||||
return '0 bytes'
|
||||
if (bytes === 0) return '0 bytes'
|
||||
|
||||
const k = 1024
|
||||
const dm = decimals < 0 ? 0 : decimals
|
||||
@@ -107,5 +116,49 @@ export function formatBytes(bytes: number, decimals = 2) {
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
|
||||
return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`
|
||||
return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`
|
||||
}
|
||||
|
||||
// 格式化剧集列表
|
||||
export function formatEp(nums: number[]): string {
|
||||
if (!nums.length) return ''
|
||||
|
||||
if (nums.length === 1) return nums[0].toString()
|
||||
|
||||
// 将数组升序排序
|
||||
nums.sort((a, b) => a - b)
|
||||
const formattedRanges: string[] = []
|
||||
let start = nums[0]
|
||||
let end = nums[0]
|
||||
|
||||
for (let i = 1; i < nums.length; i++) {
|
||||
if (nums[i] === end + 1) {
|
||||
end = nums[i]
|
||||
} else {
|
||||
if (start === end) formattedRanges.push(start.toString())
|
||||
else formattedRanges.push(`${start.toString()}-${end.toString()}`)
|
||||
|
||||
start = end = nums[i]
|
||||
}
|
||||
}
|
||||
|
||||
if (start === end) formattedRanges.push(start.toString())
|
||||
else formattedRanges.push(`${start.toString()}-${end.toString()}`)
|
||||
|
||||
return formattedRanges.join('、')
|
||||
}
|
||||
|
||||
// 将yyyy-mm-dd hh:mm:ss转换为时间差,如:1小时前,1天前
|
||||
export function formatDateDifference(dateString: string): string {
|
||||
if (!dateString) return ''
|
||||
return dayjs(dateString).fromNow()
|
||||
}
|
||||
|
||||
// 格式化评份,如为10及以下的数按原值显示,否则格式化为xxM、xxK显示
|
||||
export function formatRating(rating: number): string {
|
||||
if (!rating) return ''
|
||||
if (rating <= 10) return rating.toString()
|
||||
if (rating < 1000) return rating.toLocaleString()
|
||||
if (rating < 1000 * 1000) return `${(rating / 1000).toFixed(1)}K`
|
||||
return `${(rating / 1000 / 1000).toFixed(1)}M`
|
||||
}
|
||||
|
||||
23
src/@core/utils/image.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import ColorThief from 'colorthief'
|
||||
|
||||
// 将 RGB 转换为十六进制
|
||||
function rgbStringToHex(rgbArray: number[]): string {
|
||||
if (rgbArray.length !== 3 || rgbArray.some(isNaN))
|
||||
throw new Error('Invalid RGB string format')
|
||||
|
||||
const [r, g, b] = rgbArray
|
||||
|
||||
const toHex = (c: number): string => {
|
||||
const hex = c.toString(16)
|
||||
return hex.length === 1 ? `0${hex}` : hex
|
||||
}
|
||||
|
||||
return `#${toHex(r)}${toHex(g)}${toHex(b)}`
|
||||
}
|
||||
|
||||
// 提取主要颜色
|
||||
export async function getDominantColor(image: HTMLImageElement): Promise<string> {
|
||||
const colorThief = new ColorThief()
|
||||
const dominantColor = colorThief.getColor(image)
|
||||
return rgbStringToHex(dominantColor)
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// 👉 IsEmpty
|
||||
export function isEmpty(value: unknown): boolean {
|
||||
if (value === null || value === undefined || value === '')
|
||||
return true
|
||||
if (value === null || value === undefined || value === '') return true
|
||||
|
||||
return !!(Array.isArray(value) && value.length === 0)
|
||||
}
|
||||
@@ -33,37 +32,6 @@ export function isToday(date: Date) {
|
||||
)
|
||||
}
|
||||
|
||||
// 计算时间差,返回xx天xx小时xx分钟
|
||||
export function calculateTimeDifference(inputTime: string): string {
|
||||
if (!inputTime)
|
||||
return ''
|
||||
|
||||
const inputDate = new Date(inputTime)
|
||||
const currentDate = new Date()
|
||||
|
||||
const timeDifference = currentDate.getTime() - inputDate.getTime()
|
||||
const secondsDifference = Math.floor(timeDifference / 1000)
|
||||
|
||||
if (secondsDifference < 60) {
|
||||
return `${secondsDifference}秒`
|
||||
}
|
||||
else if (secondsDifference < 3600) {
|
||||
const minutes = Math.floor(secondsDifference / 60)
|
||||
|
||||
return `${minutes}分钟`
|
||||
}
|
||||
else if (secondsDifference < 86400) {
|
||||
const hours = Math.floor(secondsDifference / 3600)
|
||||
|
||||
return `${hours}小时`
|
||||
}
|
||||
else {
|
||||
const days = Math.floor(secondsDifference / 86400)
|
||||
|
||||
return `${days}天`
|
||||
}
|
||||
}
|
||||
|
||||
// 判断一个数组subArray是不是在另一个数组mainArray中
|
||||
export function isContained(subArray: any[], mainArray: any[]): boolean {
|
||||
return subArray.every(element => mainArray.includes(element))
|
||||
@@ -76,9 +44,24 @@ export function isIntersected(array1: any[], array2: any[]): boolean {
|
||||
|
||||
export function isNullOrEmptyObject(obj: any): boolean {
|
||||
// 首先判断是否为 null 或 undefined
|
||||
if (obj === null || obj === undefined)
|
||||
return true
|
||||
if (obj === null || obj === undefined) return true
|
||||
|
||||
// 然后判断是否为空对象
|
||||
return !!(typeof obj === 'object' && Object.keys(obj).length === 0)
|
||||
}
|
||||
|
||||
// 判断系统配置色是否是黑暗的
|
||||
export function checkPrefersColorSchemeIsDark(): boolean {
|
||||
try {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 从URL中获取参数值
|
||||
export function getQueryValue(key: string, url = window.location.href): string {
|
||||
const reg = new RegExp(`[?&]${key}=([^&#]*)`, 'i')
|
||||
const res = reg.exec(url)
|
||||
return res ? res[1] : ''
|
||||
}
|
||||
|
||||
45
src/@core/utils/navigator.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import copy from 'copy-to-clipboard'
|
||||
|
||||
// 请求和获取剪贴板内容
|
||||
export async function getClipboardContent() {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
return await navigator.clipboard.readText()
|
||||
} else {
|
||||
const input = document.createElement('textarea')
|
||||
document.body.appendChild(input)
|
||||
input.select()
|
||||
document.execCommand('paste')
|
||||
const content = input.value
|
||||
document.body.removeChild(input)
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
||||
// 将内容复制到剪贴板
|
||||
export async function copyToClipboard(content: string) {
|
||||
const success = copy(content)
|
||||
return success
|
||||
}
|
||||
|
||||
// VAPID公钥转Uint8Array
|
||||
export function urlBase64ToUint8Array(base64String: string) {
|
||||
const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
|
||||
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
|
||||
|
||||
const rawData = window.atob(base64)
|
||||
const outputArray = new Uint8Array(rawData.length)
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i)
|
||||
}
|
||||
return outputArray
|
||||
}
|
||||
|
||||
// 判断是否为PWA
|
||||
export const isPWA = async (): Promise<boolean> => {
|
||||
if ('serviceWorker' in navigator) {
|
||||
const registrations = await navigator.serviceWorker.getRegistrations()
|
||||
return registrations.length > 0
|
||||
}
|
||||
return (window.navigator as any).standalone === true
|
||||
}
|
||||
6
src/@core/utils/theme.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export function saveLocalTheme(name: string, theme: any) {
|
||||
// 存储主题到本地
|
||||
localStorage.setItem('theme', name)
|
||||
localStorage.setItem('materio-initial-loader-bg', theme.current.value.colors.background)
|
||||
localStorage.setItem('materio-initial-loader-color', theme.current.value.colors.primary)
|
||||
}
|
||||
122
src/@core/utils/workflow.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { useVueFlow } from '@vue-flow/core'
|
||||
import { ref, watch } from 'vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
/**
|
||||
* @returns {string} - A unique id.
|
||||
*/
|
||||
function getId() {
|
||||
// 生成以act_开头的唯一id
|
||||
return 'act_' + Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
|
||||
/**
|
||||
* In a real world scenario you'd want to avoid creating refs in a global scope like this as they might not be cleaned up properly.
|
||||
* @type {{draggedData: Ref<any>, isDragOver: Ref<boolean>, isDragging: Ref<boolean>}}
|
||||
*/
|
||||
const state = {
|
||||
/**
|
||||
* The type of the node being dragged.
|
||||
*/
|
||||
draggedData: ref<any | null>({}),
|
||||
isDragOver: ref(false),
|
||||
isDragging: ref(false),
|
||||
}
|
||||
|
||||
export default function useDragAndDrop() {
|
||||
const { draggedData, isDragOver, isDragging } = state
|
||||
|
||||
const { addNodes, screenToFlowCoordinate, onNodesInitialized, updateNode } = useVueFlow()
|
||||
|
||||
watch(isDragging, dragging => {
|
||||
document.body.style.userSelect = dragging ? 'none' : ''
|
||||
})
|
||||
|
||||
function onDragStart(event: any, data: any) {
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.setData('application/vueflow', data)
|
||||
event.dataTransfer.effectAllowed = 'move'
|
||||
}
|
||||
|
||||
draggedData.value = data
|
||||
isDragging.value = true
|
||||
|
||||
document.addEventListener('drop', onDragEnd)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the drag over event.
|
||||
*
|
||||
* @param {DragEvent} event
|
||||
*/
|
||||
function onDragOver(event: any) {
|
||||
event.preventDefault()
|
||||
|
||||
if (draggedData.value) {
|
||||
isDragOver.value = true
|
||||
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.dropEffect = 'move'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onDragLeave() {
|
||||
isDragOver.value = false
|
||||
}
|
||||
|
||||
function onDragEnd() {
|
||||
isDragging.value = false
|
||||
isDragOver.value = false
|
||||
draggedData.value = null
|
||||
document.removeEventListener('drop', onDragEnd)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the drop event.
|
||||
*
|
||||
* @param {DragEvent} event
|
||||
*/
|
||||
function onDrop(event: any) {
|
||||
const position = screenToFlowCoordinate({
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
})
|
||||
|
||||
const nodeId = getId()
|
||||
|
||||
const newNode = {
|
||||
id: nodeId,
|
||||
type: draggedData.value?.type,
|
||||
name: draggedData.value?.name,
|
||||
description: draggedData.value?.description,
|
||||
position,
|
||||
data: draggedData.value?.data ? cloneDeep(draggedData.value.data) : {},
|
||||
}
|
||||
|
||||
/**
|
||||
* Align node position after drop, so it's centered to the mouse
|
||||
*
|
||||
* We can hook into events even in a callback, and we can remove the event listener after it's been called.
|
||||
*/
|
||||
const { off } = onNodesInitialized(() => {
|
||||
updateNode(nodeId, node => ({
|
||||
position: { x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2 },
|
||||
}))
|
||||
|
||||
off()
|
||||
})
|
||||
|
||||
addNodes(newNode)
|
||||
}
|
||||
|
||||
return {
|
||||
draggedData,
|
||||
isDragOver,
|
||||
isDragging,
|
||||
onDragStart,
|
||||
onDragLeave,
|
||||
onDragOver,
|
||||
onDrop,
|
||||
}
|
||||
}
|
||||
1
src/@iconify/tsconfig.tsbuildinfo
Normal file
@@ -0,0 +1 @@
|
||||
{"root":["./build-icons.ts"],"version":"5.7.3"}
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Component } from 'vue'
|
||||
import { PerfectScrollbar } from 'vue3-perfect-scrollbar'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import logo from '@images/logo.svg?raw'
|
||||
|
||||
@@ -54,8 +53,8 @@ function handleNavScroll(evt: Event) {
|
||||
<RouterLink to="/" class="app-logo d-flex align-center app-title-wrapper">
|
||||
<div class="d-flex" v-html="logo" />
|
||||
|
||||
<h1 class="font-weight-bold leading-normal text-2xl">
|
||||
MOVIEPILOT
|
||||
<h1 class="font-weight-bold leading-normal text-xl">
|
||||
MOVIEPILOT <span class="text-sm text-gray-500">v2</span>
|
||||
</h1>
|
||||
</RouterLink>
|
||||
</slot>
|
||||
@@ -85,6 +84,7 @@ function handleNavScroll(evt: Event) {
|
||||
.visible {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
// 👉 Vertical Nav
|
||||
.layout-vertical-nav {
|
||||
position: fixed;
|
||||
@@ -96,8 +96,8 @@ function handleNavScroll(evt: Event) {
|
||||
inset-block-start: 0;
|
||||
inset-inline-start: 0;
|
||||
transition: transform 0.25s ease-in-out, inline-size 0.25s ease-in-out, box-shadow 0.25s ease-in-out;
|
||||
will-change: transform, inline-size;
|
||||
visibility: hidden;
|
||||
will-change: transform, inline-size;
|
||||
|
||||
&:not(.overlay-nav) {
|
||||
visibility: visible;
|
||||
|
||||
@@ -51,14 +51,23 @@ export default defineComponent({
|
||||
const main = h(
|
||||
'main',
|
||||
{ class: 'layout-page-content' },
|
||||
h(Transition, { name: 'fade-slide', mode: 'out-in', appear: true },
|
||||
h(Transition, { name: 'fade-slide', mode: 'out-in', appear: true }, () =>
|
||||
h('section', { class: 'page-content-container' }, slots.default?.()),
|
||||
),
|
||||
)
|
||||
|
||||
// 👉 根据路由 meta 决定 footer 高度
|
||||
const shouldShowFooter = !route.meta.hideFooter
|
||||
|
||||
// 👉 Footer
|
||||
const footer = h('footer', { class: 'layout-footer' }, [
|
||||
h('div', { class: 'footer-content-container' }, slots.footer?.()),
|
||||
h(
|
||||
'div',
|
||||
{
|
||||
class: ['footer-content-container', !shouldShowFooter && 'footer-content-container-noheight'],
|
||||
},
|
||||
slots.footer?.(),
|
||||
),
|
||||
])
|
||||
|
||||
// 👉 Overlay
|
||||
@@ -80,11 +89,7 @@ export default defineComponent({
|
||||
scrollDistance.value && 'window-scrolled',
|
||||
],
|
||||
},
|
||||
[
|
||||
verticalNav,
|
||||
h('div', { class: 'layout-content-wrapper' }, [navbar, main, footer]),
|
||||
layoutOverlay,
|
||||
],
|
||||
[verticalNav, h('div', { class: 'layout-content-wrapper' }, [navbar, main, footer]), layoutOverlay],
|
||||
)
|
||||
}
|
||||
},
|
||||
@@ -92,9 +97,9 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@configured-variables" as variables;
|
||||
@use "@layouts/styles/placeholders";
|
||||
@use "@layouts/styles/mixins";
|
||||
@use '@configured-variables' as variables;
|
||||
@use '@layouts/styles/placeholders';
|
||||
@use '@layouts/styles/mixins';
|
||||
|
||||
.layout-wrapper.layout-nav-type-vertical {
|
||||
// TODO(v2): Check why we need height in vertical nav & min-height in horizontal nav
|
||||
@@ -116,9 +121,7 @@ export default defineComponent({
|
||||
inset-block-start: 0;
|
||||
|
||||
.navbar-content-container {
|
||||
block-size: calc(
|
||||
env(safe-area-inset-top) + variables.$layout-vertical-nav-navbar-height
|
||||
);
|
||||
block-size: calc(env(safe-area-inset-top) + variables.$layout-vertical-nav-navbar-height);
|
||||
}
|
||||
|
||||
@at-root {
|
||||
|
||||
@@ -33,7 +33,10 @@ defineProps<{
|
||||
.nav-link a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 0 3.125rem 3.125rem 0 !important;
|
||||
cursor: pointer;
|
||||
margin-inline-end: 1.125em;
|
||||
padding-inline: 1.375rem 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,3 +18,12 @@ defineProps<{
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.layout-vertical-nav {
|
||||
.nav-section-title {
|
||||
padding-left: 1.375rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
@use "@configured-variables" as variables;
|
||||
|
||||
html {
|
||||
min-height: calc(100% + env(safe-area-inset-top));
|
||||
min-height: calc(100% + env(safe-area-inset-top) + env(safe-area-inset-bottom));
|
||||
background: rgb(var(--v-theme-background));
|
||||
overflow-y: overlay;
|
||||
}
|
||||
@@ -65,6 +65,10 @@ body,
|
||||
block-size: variables.$layout-vertical-nav-footer-height;
|
||||
}
|
||||
|
||||
.footer-content-container-noheight {
|
||||
block-size: 0px !important;
|
||||
}
|
||||
|
||||
.layout-footer-sticky & {
|
||||
position: sticky;
|
||||
inset-block-end: 0;
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100% + env(safe-area-inset-top))
|
||||
min-height: calc(100% + env(safe-area-inset-top) + env(safe-area-inset-bottom))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
@use "_global";
|
||||
@use "vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.min.css";
|
||||
@use "_classes";
|
||||
|
||||
18
src/@layouts/types.d.ts
vendored
@@ -6,19 +6,19 @@ export interface UserConfig {
|
||||
app: {
|
||||
title: Lowercase<string>
|
||||
logo: VNode
|
||||
contentWidth: typeof ContentWidth[keyof typeof ContentWidth]
|
||||
contentLayoutNav: typeof AppContentLayoutNav[keyof typeof AppContentLayoutNav]
|
||||
contentWidth: (typeof ContentWidth)[keyof typeof ContentWidth]
|
||||
contentLayoutNav: (typeof AppContentLayoutNav)[keyof typeof AppContentLayoutNav]
|
||||
overlayNavFromBreakpoint: number
|
||||
enableI18n: boolean
|
||||
isRtl: boolean
|
||||
iconRenderer?: Component
|
||||
}
|
||||
navbar: {
|
||||
type: typeof NavbarType[keyof typeof NavbarType]
|
||||
type: (typeof NavbarType)[keyof typeof NavbarType]
|
||||
navbarBlur: boolean
|
||||
}
|
||||
footer: {
|
||||
type:typeof FooterType[keyof typeof FooterType]
|
||||
type: (typeof FooterType)[keyof typeof FooterType]
|
||||
}
|
||||
verticalNav: {
|
||||
isVerticalNavCollapsed: boolean
|
||||
@@ -120,6 +120,13 @@ export interface NavLink extends NavLinkProps, Partial<AclProperties> {
|
||||
disable?: boolean
|
||||
}
|
||||
|
||||
export interface NavMenu extends NavLink {
|
||||
header: string
|
||||
description?: string
|
||||
admin?: boolean
|
||||
footer?: boolean
|
||||
}
|
||||
|
||||
// 👉 Vertical nav group
|
||||
export interface NavGroup extends Partial<AclProperties> {
|
||||
title: string
|
||||
@@ -143,7 +150,7 @@ interface I18nLanguage {
|
||||
// avatar | text | icon
|
||||
// Thanks: https://stackoverflow.com/a/60617060/10796681
|
||||
type Notification = {
|
||||
id:number
|
||||
id: number
|
||||
title: string
|
||||
subtitle: string
|
||||
time: string
|
||||
@@ -157,5 +164,6 @@ type Notification = {
|
||||
|
||||
interface ThemeSwitcherTheme {
|
||||
name: string
|
||||
title: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
76
src/App.vue
@@ -1,43 +1,65 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import { useTheme } from 'vuetify'
|
||||
import store from './store'
|
||||
import { checkPrefersColorSchemeIsDark } from '@/@core/utils'
|
||||
import { ensureRenderComplete, removeEl } from './@core/utils/dom'
|
||||
|
||||
// 第一时间应用主题
|
||||
// 生效主题
|
||||
const { global: globalTheme } = useTheme()
|
||||
globalTheme.name.value = localStorage.getItem('theme') || 'light'
|
||||
let themeValue = localStorage.getItem('theme') || 'light'
|
||||
const autoTheme = checkPrefersColorSchemeIsDark() ? 'dark' : 'light'
|
||||
globalTheme.name.value = themeValue === 'auto' ? autoTheme : themeValue
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
// 显示状态
|
||||
const show = ref(false)
|
||||
|
||||
// SSE持续接收消息
|
||||
function startSSEMessager() {
|
||||
const token = store.state.auth.token
|
||||
if (token) {
|
||||
const eventSource = new EventSource(
|
||||
`${import.meta.env.VITE_API_BASE_URL}system/message?token=${token}`,
|
||||
)
|
||||
|
||||
eventSource.addEventListener('message', (event) => {
|
||||
const message = event.data
|
||||
if (message)
|
||||
$toast.info(message)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
eventSource.close()
|
||||
})
|
||||
// ApexCharts 全局配置
|
||||
declare global {
|
||||
interface Window {
|
||||
Apex: any
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载时,加载当前用户数据
|
||||
onBeforeMount(async () => {
|
||||
startSSEMessager()
|
||||
if (window.Apex) {
|
||||
// 数据标签
|
||||
window.Apex.dataLabels = {
|
||||
formatter: function (_: number, { seriesIndex, w }: { seriesIndex: number; w: any }) {
|
||||
// 如果有小数点,保留两位小数,否则保留整数
|
||||
const data = w.config.series[seriesIndex]
|
||||
return data.toFixed(data % 1 === 0 ? 0 : 1)
|
||||
},
|
||||
}
|
||||
// 图例
|
||||
window.Apex.legend = {
|
||||
labels: {
|
||||
useSeriesColors: true,
|
||||
},
|
||||
}
|
||||
// 标题
|
||||
window.Apex.title = {
|
||||
style: {
|
||||
color: 'rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
ensureRenderComplete(() => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
// 移除加载动画
|
||||
removeEl('#loading-bg')
|
||||
// 将background属性从html的style中移除
|
||||
document.documentElement.style.removeProperty('background')
|
||||
// 显示页面
|
||||
show.value = true
|
||||
}, 1500)
|
||||
})
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VApp>
|
||||
<VApp v-show="show">
|
||||
<RouterView />
|
||||
</VApp>
|
||||
</template>
|
||||
|
||||
69
src/ace-config.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import ace from 'ace-builds'
|
||||
|
||||
import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url'
|
||||
|
||||
import modeJavascriptUrl from 'ace-builds/src-noconflict/mode-javascript?url'
|
||||
|
||||
import modeHtmlUrl from 'ace-builds/src-noconflict/mode-html?url'
|
||||
|
||||
import modeYamlUrl from 'ace-builds/src-noconflict/mode-yaml?url'
|
||||
|
||||
import modeCssUrl from 'ace-builds/src-noconflict/mode-css?url'
|
||||
|
||||
import modeIniUrl from 'ace-builds/src-noconflict/mode-ini?url'
|
||||
|
||||
import themeGithubUrl from 'ace-builds/src-noconflict/theme-github?url'
|
||||
|
||||
import themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url'
|
||||
|
||||
import themeMonokaiUrl from 'ace-builds/src-noconflict/theme-monokai?url'
|
||||
|
||||
import workerBaseUrl from 'ace-builds/src-noconflict/worker-base?url'
|
||||
|
||||
import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'
|
||||
|
||||
import workerJavascriptUrl from 'ace-builds/src-noconflict/worker-javascript?url'
|
||||
|
||||
import workerHtmlUrl from 'ace-builds/src-noconflict/worker-html?url'
|
||||
|
||||
import workerYamlUrl from 'ace-builds/src-noconflict/worker-yaml?url'
|
||||
|
||||
import workerCssUrl from 'ace-builds/src-noconflict/worker-css?url'
|
||||
|
||||
import snippetsHtmlUrl from 'ace-builds/src-noconflict/snippets/html?url'
|
||||
|
||||
import snippetsJsUrl from 'ace-builds/src-noconflict/snippets/javascript?url'
|
||||
|
||||
import snippetsYamlUrl from 'ace-builds/src-noconflict/snippets/yaml?url'
|
||||
|
||||
import snippetsJsonUrl from 'ace-builds/src-noconflict/snippets/json?url'
|
||||
|
||||
import snippertsCssUrl from 'ace-builds/src-noconflict/snippets/css?url'
|
||||
|
||||
import snippertsIniUrl from 'ace-builds/src-noconflict/snippets/ini?url'
|
||||
|
||||
import 'ace-builds/src-noconflict/ext-language_tools'
|
||||
|
||||
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl)
|
||||
ace.config.setModuleUrl('ace/mode/javascript', modeJavascriptUrl)
|
||||
ace.config.setModuleUrl('ace/mode/html', modeHtmlUrl)
|
||||
ace.config.setModuleUrl('ace/mode/yaml', modeYamlUrl)
|
||||
ace.config.setModuleUrl('ace/mode/css', modeCssUrl)
|
||||
ace.config.setModuleUrl('ace/mode/ini', modeIniUrl)
|
||||
ace.config.setModuleUrl('ace/theme/github', themeGithubUrl)
|
||||
ace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl)
|
||||
ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl)
|
||||
ace.config.setModuleUrl('ace/mode/base', workerBaseUrl)
|
||||
ace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl)
|
||||
ace.config.setModuleUrl('ace/mode/javascript_worker', workerJavascriptUrl)
|
||||
ace.config.setModuleUrl('ace/mode/html_worker', workerHtmlUrl)
|
||||
ace.config.setModuleUrl('ace/mode/yaml_worker', workerYamlUrl)
|
||||
ace.config.setModuleUrl('ace/mode/css_worker', workerCssUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/html', snippetsHtmlUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/javascript', snippetsJsUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/javascript', snippetsYamlUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/json', snippetsJsonUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/css', snippertsCssUrl)
|
||||
ace.config.setModuleUrl('ace/snippets/ini', snippertsIniUrl)
|
||||
|
||||
ace.require('ace/ext/language_tools')
|
||||
80
src/api/constants.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
export const storageOptions = [
|
||||
{
|
||||
title: '本地',
|
||||
value: 'local',
|
||||
icon: 'mdi-folder-multiple-outline',
|
||||
},
|
||||
{
|
||||
title: '阿里云盘',
|
||||
value: 'alipan',
|
||||
icon: 'mdi-cloud-outline',
|
||||
},
|
||||
{
|
||||
title: '115网盘',
|
||||
value: 'u115',
|
||||
icon: 'mdi-cloud-outline',
|
||||
},
|
||||
{
|
||||
title: 'RClone',
|
||||
value: 'rclone',
|
||||
icon: 'mdi-cloud-outline',
|
||||
},
|
||||
{
|
||||
title: 'AList',
|
||||
value: 'alist',
|
||||
icon: 'mdi-cloud-outline',
|
||||
},
|
||||
]
|
||||
|
||||
export const innerFilterRules = [
|
||||
{ title: '特效字幕', value: ' SPECSUB ' },
|
||||
{ title: '中文字幕', value: ' CNSUB ' },
|
||||
{ title: '国语配音', value: ' CNVOI ' },
|
||||
{ title: '官种', value: ' GZ ' },
|
||||
{ title: '排除: 国语配音', value: ' !CNVOI ' },
|
||||
{ title: '粤语配音', value: ' HKVOI ' },
|
||||
{ title: '排除: 粤语配音', value: ' !HKVOI ' },
|
||||
{ title: '促销: 免费', value: ' FREE ' },
|
||||
{ title: '分辨率: 4K', value: ' 4K ' },
|
||||
{ title: '分辨率: 1080P', value: ' 1080P ' },
|
||||
{ title: '分辨率: 720P', value: ' 720P ' },
|
||||
{ title: '排除: 720P', value: ' !720P ' },
|
||||
{ title: '质量: 蓝光原盘', value: ' BLU ' },
|
||||
{ title: '排除: 蓝光原盘', value: ' !BLU ' },
|
||||
{ title: '质量: BLURAY', value: ' BLURAY ' },
|
||||
{ title: '排除: BLURAY', value: ' !BLURAY ' },
|
||||
{ title: '质量: UHD', value: ' UHD ' },
|
||||
{ title: '排除: UHD', value: ' !UHD ' },
|
||||
{ title: '质量: REMUX', value: ' REMUX ' },
|
||||
{ title: '排除: REMUX', value: ' !REMUX ' },
|
||||
{ title: '质量: WEB-DL', value: ' WEBDL ' },
|
||||
{ title: '排除: WEB-DL', value: ' !WEBDL ' },
|
||||
{ title: '质量: 60fps', value: ' 60FPS ' },
|
||||
{ title: '排除: 60fps', value: ' !60FPS ' },
|
||||
{ title: '编码: H265', value: ' H265 ' },
|
||||
{ title: '排除: H265', value: ' !H265 ' },
|
||||
{ title: '编码: H264', value: ' H264 ' },
|
||||
{ title: '排除: H264', value: ' !H264 ' },
|
||||
{ title: '效果: 杜比视界', value: ' DOLBY ' },
|
||||
{ title: '排除: 杜比视界', value: ' !DOLBY ' },
|
||||
{ title: '效果: 杜比全景声', value: ' ATMOS ' },
|
||||
{ title: '排除: 杜比全景声', value: ' !ATMOS ' },
|
||||
{ title: '效果: HDR', value: ' HDR ' },
|
||||
{ title: '排除: HDR', value: ' !HDR ' },
|
||||
{ title: '效果: SDR', value: ' SDR ' },
|
||||
{ title: '排除: SDR', value: ' !SDR ' },
|
||||
{ title: '效果: 3D', value: ' 3D ' },
|
||||
{ title: '排除: 3D', value: ' !3D ' },
|
||||
]
|
||||
|
||||
export const storageDict = storageOptions.reduce((dict, item) => {
|
||||
dict[item.value] = item.title
|
||||
return dict
|
||||
}, {} as Record<string, string>)
|
||||
|
||||
export const transferTypeOptions = [
|
||||
{ title: '复制', value: 'copy' },
|
||||
{ title: '移动', value: 'move' },
|
||||
{ title: '硬链接', value: 'link' },
|
||||
{ title: '软链接', value: 'softlink' },
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import router from '@/router'
|
||||
import store from '@/store'
|
||||
import { useAuthStore } from '@/stores'
|
||||
|
||||
// 创建axios实例
|
||||
const api = axios.create({
|
||||
@@ -8,32 +8,46 @@ const api = axios.create({
|
||||
})
|
||||
|
||||
// 添加请求拦截器
|
||||
api.interceptors.request.use((config) => {
|
||||
api.interceptors.request.use(config => {
|
||||
// 认证 Store
|
||||
const authStore = useAuthStore()
|
||||
// 在请求头中添加token
|
||||
const token = store.state.auth.token
|
||||
if (token)
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
|
||||
if (authStore.token) {
|
||||
config.headers.Authorization = `Bearer ${authStore.token}`
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
// 添加响应拦截器
|
||||
api.interceptors.response.use((response) => {
|
||||
return response.data
|
||||
}, (error) => {
|
||||
if (!error.response) {
|
||||
// 请求超时
|
||||
api.interceptors.response.use(
|
||||
response => {
|
||||
return response.data
|
||||
},
|
||||
error => {
|
||||
if (!error.response) {
|
||||
// 请求超时
|
||||
return Promise.reject(new Error(error))
|
||||
} else if (error.response.status === 403) {
|
||||
// 认证 Store
|
||||
const authStore = useAuthStore()
|
||||
// 清除登录状态信息
|
||||
authStore.logout()
|
||||
// token验证失败,跳转到登录页面
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
}
|
||||
else if (error.response.status === 403) {
|
||||
// 清除登录状态信息
|
||||
store.dispatch('auth/clearToken')
|
||||
|
||||
// token验证失败,跳转到登录页面
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
export default api
|
||||
|
||||
export async function fetchGlobalSettings() {
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.get('system/global')
|
||||
return result.data || {}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch global settings', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
995
src/api/types.ts
|
Before Width: | Height: | Size: 27 KiB |
BIN
src/assets/images/logos/bangumi.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/images/logos/bangumi_title.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 119 KiB |
BIN
src/assets/images/logos/douban-black.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/images/logos/douban_title.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |