mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-11 19:05:20 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99d7eaeff0 | ||
|
|
c8f5eb7c2e | ||
|
|
109e16e8fb | ||
|
|
555f6e04e8 | ||
|
|
bcde0a54bf | ||
|
|
eee7f25bc3 | ||
|
|
b10157b09a | ||
|
|
a09a21fa5d | ||
|
|
ec2918b427 | ||
|
|
57bfc19ecf | ||
|
|
aa110d4187 | ||
|
|
9e8febfc11 | ||
|
|
5905c2ce25 | ||
|
|
b03ef0d494 | ||
|
|
585f77ed49 | ||
|
|
1c580ea2f9 | ||
|
|
b1af6575b9 | ||
|
|
b24c5fdee1 | ||
|
|
a256ada847 | ||
|
|
a8cdab629d | ||
|
|
09cca0a920 | ||
|
|
6a0aa6aae2 | ||
|
|
565cc06c27 | ||
|
|
29caa4b770 | ||
|
|
953cf4795a | ||
|
|
31bc8395aa | ||
|
|
eb94b39e40 | ||
|
|
c16bbe0f9a | ||
|
|
b60caa60d5 | ||
|
|
1ea97e9206 | ||
|
|
32970bca71 | ||
|
|
1fc9f87eaa | ||
|
|
b2f5960097 | ||
|
|
1cfcc66548 | ||
|
|
60152a313f | ||
|
|
d50ff20ff8 | ||
|
|
3aed5ef955 | ||
|
|
61e0e8dbe2 | ||
|
|
1ba5d52ee7 | ||
|
|
03bc5bb882 | ||
|
|
8011b4b793 | ||
|
|
deb124ae23 | ||
|
|
a3114e40d1 | ||
|
|
0b9ecfc3a5 | ||
|
|
c32bb4157b | ||
|
|
7f9c9f05b8 | ||
|
|
906a074634 | ||
|
|
286ec0e714 | ||
|
|
0f81414497 | ||
|
|
b451831db2 | ||
|
|
ae13185319 | ||
|
|
f2bcbaefd2 | ||
|
|
96ddcf49c5 | ||
|
|
322a4e2729 | ||
|
|
8e48960253 | ||
|
|
3b419a8e96 | ||
|
|
bf1685bf79 | ||
|
|
3ab84428f0 | ||
|
|
fdda732c4c | ||
|
|
f46b30498b | ||
|
|
d7ee2576f2 | ||
|
|
d2c03bc298 | ||
|
|
6283e23d29 | ||
|
|
dc9923ac13 | ||
|
|
62ac80257a | ||
|
|
868452f13c | ||
|
|
6c368f7ea7 | ||
|
|
732d63d588 | ||
|
|
ae40947801 | ||
|
|
079d4dfa06 | ||
|
|
67c50bf622 | ||
|
|
f1e494b1fc | ||
|
|
f4f275490e | ||
|
|
baad96106f | ||
|
|
15fa7754b5 | ||
|
|
8f175f8447 | ||
|
|
9c45cfd7ed | ||
|
|
f2426c3f66 | ||
|
|
36ae6e460d | ||
|
|
7ae93efe07 | ||
|
|
8b97d92d0a | ||
|
|
e5c06335ec | ||
|
|
2bd8e49302 | ||
|
|
c0d401e296 | ||
|
|
e07d2b6639 | ||
|
|
220a87627d | ||
|
|
87bca2ac4e | ||
|
|
c320906149 | ||
|
|
27958a1a90 | ||
|
|
82c7011522 | ||
|
|
fa6d57d809 | ||
|
|
1060fc7476 | ||
|
|
56bc38e9e7 | ||
|
|
18be65d6fe | ||
|
|
3409085195 | ||
|
|
17e17ac077 | ||
|
|
c655e1da38 | ||
|
|
0ea158724f | ||
|
|
fb521498ff | ||
|
|
399550ccad | ||
|
|
c7c30c86f2 | ||
|
|
5f6c0882d6 | ||
|
|
6e05a4f3a5 | ||
|
|
ea8aa6a231 | ||
|
|
ae2570c677 | ||
|
|
c76d952d41 | ||
|
|
cdf9fb24be | ||
|
|
2131e16781 | ||
|
|
b0c8425639 | ||
|
|
f0869567de | ||
|
|
be2a19949b | ||
|
|
8627cccb58 | ||
|
|
4a8eaebf17 | ||
|
|
e7edd0a5a4 | ||
|
|
9ccbea0a04 | ||
|
|
ab715ef840 | ||
|
|
117822fe7c | ||
|
|
da922678a1 | ||
|
|
133e9e0e1f | ||
|
|
7cc6081d15 | ||
|
|
5a24f62a62 | ||
|
|
be597355a7 | ||
|
|
51afcb6c5b | ||
|
|
92ebb70eaa | ||
|
|
ab19f30342 | ||
|
|
fc9bc7bea2 | ||
|
|
793da29f22 | ||
|
|
5afe4da607 | ||
|
|
a7a56c03ce | ||
|
|
7639b588d8 | ||
|
|
1d536cdd53 | ||
|
|
9f08245b6d | ||
|
|
ff9bf20e57 | ||
|
|
b201730100 | ||
|
|
6ca098f9e2 | ||
|
|
e0eef05f5c | ||
|
|
6398e5ec70 | ||
|
|
6f93219c44 | ||
|
|
9b957ac019 | ||
|
|
e0d1b127aa | ||
|
|
64072b3435 | ||
|
|
f81f7720f0 | ||
|
|
69fab610e6 | ||
|
|
d693e1f9ea | ||
|
|
2a9ca67355 | ||
|
|
3fb01860d4 | ||
|
|
d92a46d09c | ||
|
|
ec605bfba4 | ||
|
|
d2f999a5e2 | ||
|
|
627f541f17 | ||
|
|
c457dca555 | ||
|
|
ff3ec7395e | ||
|
|
fdaba146ca | ||
|
|
31a6d30c23 | ||
|
|
fa3b185fd5 | ||
|
|
101d4fb497 | ||
|
|
ccd308f5b0 | ||
|
|
999d9f8e01 | ||
|
|
313db0d74e | ||
|
|
634e9705a7 | ||
|
|
c959cec738 | ||
|
|
95330e04a3 | ||
|
|
a099d09af7 | ||
|
|
a0d0197ad7 | ||
|
|
d49e711a34 | ||
|
|
e3b8cd75b9 | ||
|
|
7a240eaabb | ||
|
|
01564e96d3 | ||
|
|
03f4b5c219 | ||
|
|
99e1d44f7d | ||
|
|
8c55659c18 | ||
|
|
3ea980b2f8 | ||
|
|
f5fc987b51 | ||
|
|
9cfa4af2b2 | ||
|
|
3efdf1fa87 | ||
|
|
25fc832605 | ||
|
|
a7e404c5d5 | ||
|
|
90b27f0564 | ||
|
|
632440965d | ||
|
|
aedfac446b | ||
|
|
3372b0025a | ||
|
|
0112b92e77 | ||
|
|
0caf53b147 | ||
|
|
4d1354d5f4 | ||
|
|
fc4562eca2 | ||
|
|
5b048a5510 | ||
|
|
d23049b2fe | ||
|
|
caac5607b9 | ||
|
|
fb2e69b12d | ||
|
|
fc1838ff39 | ||
|
|
25689cf40f | ||
|
|
c746a3d215 | ||
|
|
548d924fa0 | ||
|
|
18a6be3ecd | ||
|
|
afef0cb72f | ||
|
|
1221b47eca | ||
|
|
a356eeb5da | ||
|
|
25bb0972b9 | ||
|
|
0914075cf6 | ||
|
|
74b258e1b6 | ||
|
|
27eb0a21e4 | ||
|
|
d77c6d50d8 | ||
|
|
6a64c18a7b | ||
|
|
b97ff714ae | ||
|
|
1f23eea805 | ||
|
|
cb0cb7df21 | ||
|
|
f3e8628664 | ||
|
|
4758471f9f | ||
|
|
c10bd5a549 | ||
|
|
d53faf96eb | ||
|
|
2307b8ed1a | ||
|
|
711af8d4a5 | ||
|
|
458c9c456b | ||
|
|
29069df48c | ||
|
|
300e84ae2c | ||
|
|
bf11768b92 | ||
|
|
91bd1d9263 | ||
|
|
ac40f9ff12 | ||
|
|
f930837220 | ||
|
|
1d5e3acc93 | ||
|
|
2aec1f9846 | ||
|
|
b56a681b98 | ||
|
|
2713419b32 | ||
|
|
764a3492cc | ||
|
|
29fc471ac4 | ||
|
|
54a597aad3 | ||
|
|
778961d0b6 | ||
|
|
14b01ac761 | ||
|
|
f87848c05b | ||
|
|
153e5a806d | ||
|
|
ee1b8a906f | ||
|
|
734685d45a | ||
|
|
e3b540c212 | ||
|
|
201f578bbc | ||
|
|
ce9aa369d2 | ||
|
|
c5c41c0859 | ||
|
|
d3009f82dd | ||
|
|
0eb9a1fdb0 | ||
|
|
83f6d9926a | ||
|
|
14134842b0 | ||
|
|
4c094c4710 | ||
|
|
3ac41075fd | ||
|
|
fdc97773d1 | ||
|
|
917a739595 | ||
|
|
21475f81ae | ||
|
|
a2a9a0560c | ||
|
|
b879846cdb | ||
|
|
a24011cd72 | ||
|
|
410dd2ecdc | ||
|
|
96b111b894 | ||
|
|
630572c8f9 | ||
|
|
6a381a6366 | ||
|
|
fd04f12677 | ||
|
|
86b8cd17a4 | ||
|
|
bb8ee01693 | ||
|
|
5fb0bca3af | ||
|
|
1e4d1f373d | ||
|
|
87c78d0fcc | ||
|
|
041d2b7947 | ||
|
|
5e7b90d995 | ||
|
|
fadc3dcb55 | ||
|
|
4eea091944 | ||
|
|
9f8d46f395 | ||
|
|
2c54a057c9 | ||
|
|
e1e5cacc6d | ||
|
|
edf9066967 | ||
|
|
7097d12b87 | ||
|
|
08aaeb6372 | ||
|
|
4310f80ec0 | ||
|
|
01577f6494 | ||
|
|
9aa570b2c6 | ||
|
|
d611d7d698 | ||
|
|
f05549b06c | ||
|
|
8c4db8dd40 | ||
|
|
ddee69d291 | ||
|
|
28960c9fab | ||
|
|
449301e519 | ||
|
|
28dab3dc2f | ||
|
|
7995d98db5 | ||
|
|
1f319f3533 | ||
|
|
7d2dbaa62d | ||
|
|
ed5999526b | ||
|
|
2409f75491 | ||
|
|
0c840095d1 | ||
|
|
3eaf0b4856 | ||
|
|
394735a5d9 | ||
|
|
5bfa10bfe7 | ||
|
|
3f12d9cbd5 | ||
|
|
54d89754df | ||
|
|
9470524615 | ||
|
|
b5faa6eaaa | ||
|
|
eab476cfe8 | ||
|
|
b773def012 | ||
|
|
a9f8b23a7a | ||
|
|
61bb6535fb | ||
|
|
eb0bdffe06 | ||
|
|
e129485285 | ||
|
|
aac7de172e | ||
|
|
e19d2412fc | ||
|
|
7cba2cf76c | ||
|
|
55d7a49dbc | ||
|
|
f695864fd8 | ||
|
|
ae4883fbe7 | ||
|
|
836dfd2861 | ||
|
|
6e0523c6d7 | ||
|
|
cd9ba084ae | ||
|
|
c8a0c0de67 | ||
|
|
5dd8d9df91 | ||
|
|
2dbee94e85 | ||
|
|
9001797037 | ||
|
|
5e7104d5a3 | ||
|
|
7c33b22d63 | ||
|
|
b7cb1e379c | ||
|
|
274a6ce52e | ||
|
|
8079e4e7b8 | ||
|
|
920efb8fab | ||
|
|
92aeb2b9da | ||
|
|
ced76cf343 | ||
|
|
3750d6ecd5 | ||
|
|
7444f30384 | ||
|
|
b0fd5ba47f | ||
|
|
cc098bc2e5 | ||
|
|
1cfcf8d194 | ||
|
|
d1e9f741d0 | ||
|
|
0cde9d07ee | ||
|
|
a266425348 | ||
|
|
6dbe02e321 | ||
|
|
39979879c9 | ||
|
|
ba3f604a5c | ||
|
|
9572582401 | ||
|
|
2bcef0ba75 | ||
|
|
31cd7c4007 | ||
|
|
1c4c1799b0 | ||
|
|
2d558df15e | ||
|
|
7b769da4e2 | ||
|
|
4e95d62933 | ||
|
|
83255280b9 | ||
|
|
2546cebdea | ||
|
|
f14a3fe0f1 | ||
|
|
c3eb845be4 | ||
|
|
1eef77dca5 | ||
|
|
d7d9f47fe5 | ||
|
|
fce6a996d9 | ||
|
|
48a484d7de | ||
|
|
4b81d3c612 | ||
|
|
21b6edd7eb | ||
|
|
9a43e022e9 | ||
|
|
62bef3f13d | ||
|
|
c87f5fa004 | ||
|
|
8d99f3ffbb | ||
|
|
100ca7b54b | ||
|
|
4a2624f12a | ||
|
|
21b01a85a8 | ||
|
|
e039ae436e | ||
|
|
b13a1a45f8 | ||
|
|
667fe2bbba | ||
|
|
f083871ca0 | ||
|
|
782e1ba235 | ||
|
|
b92c6edc4e | ||
|
|
bdf4657c73 | ||
|
|
8559438611 | ||
|
|
04045fd410 | ||
|
|
1c71a9d8a8 | ||
|
|
9a9ae9782c | ||
|
|
da2569850b | ||
|
|
b475035415 | ||
|
|
7baee27585 | ||
|
|
2cb2f1ce0a | ||
|
|
8c1407e2a9 | ||
|
|
7bcb113085 | ||
|
|
42dc27addf | ||
|
|
aac30398c4 | ||
|
|
ceae888372 | ||
|
|
61df7050db | ||
|
|
af5561cbbf | ||
|
|
bce30f922d | ||
|
|
d6ed394557 | ||
|
|
7b512a1681 | ||
|
|
7af0597cd5 | ||
|
|
2f5cf6d93c | ||
|
|
d672d2d104 | ||
|
|
c0d1fb1ef4 | ||
|
|
3c882ad0ce | ||
|
|
58acd2eb68 | ||
|
|
590473e7d2 | ||
|
|
21139157c8 | ||
|
|
8f8296ab64 | ||
|
|
40bf07d2a4 | ||
|
|
fd2b4fb86d | ||
|
|
783e867ef6 | ||
|
|
3873d9f978 | ||
|
|
7dece938c8 | ||
|
|
0842d66c79 | ||
|
|
d071e50d62 | ||
|
|
337f01aff1 | ||
|
|
5614e41eb0 | ||
|
|
4f0fdbe453 | ||
|
|
49c068db78 | ||
|
|
fbba44d482 | ||
|
|
10c07b0a09 | ||
|
|
20893698ba | ||
|
|
31de659ed3 | ||
|
|
6c08a16c66 | ||
|
|
21e7178f48 | ||
|
|
aefd267eb2 | ||
|
|
fb1a3980d4 | ||
|
|
cfc467f8a5 | ||
|
|
48120f012d | ||
|
|
c907a78437 | ||
|
|
915c0d09a9 | ||
|
|
80638862cc | ||
|
|
a7350948cd | ||
|
|
1e1be013b5 | ||
|
|
4062584eae | ||
|
|
abedddffa6 | ||
|
|
38858ccdb2 | ||
|
|
d56e6359d0 | ||
|
|
5886991464 | ||
|
|
838326616b | ||
|
|
fcf80fe946 | ||
|
|
2e63a7056c | ||
|
|
7c807e3ec8 | ||
|
|
b558aa0934 | ||
|
|
38757758cb | ||
|
|
84dd3d8fd1 | ||
|
|
19423c2d30 | ||
|
|
98bba7d7fa | ||
|
|
dcaa9ce000 | ||
|
|
3cae44a136 | ||
|
|
df8a3d2692 | ||
|
|
56e43f1808 | ||
|
|
2f6b95cccf | ||
|
|
ad9f6b2b64 | ||
|
|
165c3dc976 | ||
|
|
cbe6390b41 | ||
|
|
026eaf6606 | ||
|
|
ee184f8e62 | ||
|
|
5745231dc9 | ||
|
|
cbdc3a9861 | ||
|
|
ba5c42ad6d | ||
|
|
b056a731a1 | ||
|
|
b4cd94f2d9 | ||
|
|
3b8cb43f02 | ||
|
|
82cb11c3c4 | ||
|
|
eb7522a90b | ||
|
|
3898201b1e | ||
|
|
bb6ab0c17b | ||
|
|
652c40ab1f | ||
|
|
ca0d6215a9 | ||
|
|
61d155257c | ||
|
|
91399f1a1f | ||
|
|
2e738c5977 | ||
|
|
c0bd51cf03 | ||
|
|
ca5afe04f8 | ||
|
|
47db0b9f4e | ||
|
|
27f17a377a | ||
|
|
ecaf731ecf | ||
|
|
9fba2a85f6 | ||
|
|
93f75be182 | ||
|
|
d537901f59 | ||
|
|
260c1ed4a4 | ||
|
|
ac2bd52463 | ||
|
|
16c6f8fee1 | ||
|
|
8a0db21f17 | ||
|
|
9ab08a71c0 | ||
|
|
381c32a3b4 | ||
|
|
350c0f10c4 | ||
|
|
d5b982f813 | ||
|
|
6587375ff2 | ||
|
|
f5ecb81bad | ||
|
|
0141cd81c4 | ||
|
|
ff412c7497 | ||
|
|
623f239f91 | ||
|
|
c7ba304c6a | ||
|
|
c8393604d1 | ||
|
|
c5d47a67aa | ||
|
|
3a1423cd59 | ||
|
|
d57f4cf6cd | ||
|
|
af420942c4 | ||
|
|
eac4e5e66f | ||
|
|
b8822a98f7 | ||
|
|
95322b42c0 | ||
|
|
33f5a06d32 | ||
|
|
a7e5126c92 | ||
|
|
c62f3e5b8e | ||
|
|
5d3f413a05 | ||
|
|
644154ca38 | ||
|
|
cccce5ff74 | ||
|
|
aa1fe98188 | ||
|
|
b6a78550d6 | ||
|
|
70b7f2c493 | ||
|
|
ea44e5f209 | ||
|
|
41ef87d9f8 | ||
|
|
c0b4a70aa0 | ||
|
|
955875cb7a | ||
|
|
827e8571aa | ||
|
|
aed08b0f59 | ||
|
|
3ddaf41e27 | ||
|
|
38a9cce6bf | ||
|
|
ae255ef381 | ||
|
|
4316bef01e | ||
|
|
8491c5706d | ||
|
|
7b7fab1f32 | ||
|
|
5a6fccdc2f | ||
|
|
23668be46d | ||
|
|
f92f2c1666 | ||
|
|
895740a3cb | ||
|
|
4c76c3231f | ||
|
|
ca9d3f9559 | ||
|
|
3ca3c5e75c | ||
|
|
c2c0b1dfdc | ||
|
|
c633774487 | ||
|
|
c2d86fc517 | ||
|
|
d7c8d150ca | ||
|
|
6b8a4e65f2 | ||
|
|
482e43dd1f | ||
|
|
1437babc6c | ||
|
|
5ed882943a | ||
|
|
e678b3fb3a | ||
|
|
a5770bc4e4 | ||
|
|
59821bb939 | ||
|
|
b58040be44 | ||
|
|
be3b8ad52e | ||
|
|
0fdaf97461 | ||
|
|
f5f036372f | ||
|
|
3fceb983e6 | ||
|
|
ae6a39196d | ||
|
|
2810ff2753 | ||
|
|
205c0cf8d3 | ||
|
|
d9c801a091 | ||
|
|
0833aa3b30 | ||
|
|
9c90bbc146 | ||
|
|
231b387076 | ||
|
|
3de432652f | ||
|
|
cad714493e | ||
|
|
6a690a6108 | ||
|
|
1b85c52557 | ||
|
|
b37be92ea9 | ||
|
|
f95979f445 | ||
|
|
09e07218ae | ||
|
|
085f5a9451 | ||
|
|
eb4e935554 | ||
|
|
57986cf425 | ||
|
|
7bf14b9acc | ||
|
|
3ba0be34d9 | ||
|
|
0f828a3c75 | ||
|
|
16a768a142 | ||
|
|
f380d20279 | ||
|
|
be908ab36c | ||
|
|
b545454537 | ||
|
|
a5ff8dd1d6 | ||
|
|
59f23e518b | ||
|
|
858b3f0176 | ||
|
|
89b8494ad0 | ||
|
|
64ecd75bd5 | ||
|
|
138eb3393d | ||
|
|
1ad51d2925 | ||
|
|
317e175bca | ||
|
|
0e287aa7d1 | ||
|
|
28018b705b | ||
|
|
46ec72d6be | ||
|
|
82494a87af | ||
|
|
95c19b447a | ||
|
|
9c6eae936a | ||
|
|
77605a9360 | ||
|
|
82880c3f06 | ||
|
|
11143c771b | ||
|
|
0968eaa5a8 | ||
|
|
0687f9d472 | ||
|
|
25f0f5951a | ||
|
|
eec0ce65ad | ||
|
|
be4e100168 | ||
|
|
59e4f1063c | ||
|
|
359e21f02b | ||
|
|
6894bd9c0e | ||
|
|
7040f02823 | ||
|
|
41408de337 | ||
|
|
72e243dce8 | ||
|
|
77d4840e2a | ||
|
|
0d5961821c | ||
|
|
f34980b173 | ||
|
|
5b21a6e529 | ||
|
|
6dbb737d4b | ||
|
|
76ecfbaaa2 | ||
|
|
d9aacbcb92 | ||
|
|
e088325d95 | ||
|
|
b29dd2c580 | ||
|
|
89e82fd5b0 | ||
|
|
9f0b671d42 | ||
|
|
7de7c724dc | ||
|
|
3525b1d92a | ||
|
|
30cea84886 | ||
|
|
0c2cc7f575 |
+3
-3
@@ -7,6 +7,6 @@ LOG_LEVEL='debug'
|
|||||||
|
|
||||||
SECRET='whyour'
|
SECRET='whyour'
|
||||||
|
|
||||||
QINIU_AK=''
|
QINIU_AK = ''
|
||||||
QINIU_SK=''
|
QINIU_SK = ''
|
||||||
QINIU_SCOPE=''
|
QINIU_SCOPE = ''
|
||||||
@@ -1,2 +1 @@
|
|||||||
sentrycli_cdnurl=https://npmmirror.com/mirrors/sentry-cli/
|
sentrycli_cdnurl=https://cdn.npm.taobao.org/dist/sentry-cli
|
||||||
strict-peer-dependencies=false
|
|
||||||
@@ -9,6 +9,10 @@ export default defineConfig({
|
|||||||
type: 'none',
|
type: 'none',
|
||||||
},
|
},
|
||||||
fastRefresh: {},
|
fastRefresh: {},
|
||||||
|
// antd: {
|
||||||
|
// dark: true,
|
||||||
|
// },
|
||||||
|
mfsu: {},
|
||||||
esbuild: {},
|
esbuild: {},
|
||||||
webpack5: {},
|
webpack5: {},
|
||||||
dynamicImport: {
|
dynamicImport: {
|
||||||
|
|||||||
@@ -163,11 +163,11 @@ task <file_path> desi <env_name> <account_number>
|
|||||||
|
|
||||||
* file_url: 脚本地址
|
* file_url: 脚本地址
|
||||||
* repo_url: 仓库地址
|
* repo_url: 仓库地址
|
||||||
* whitelist: 拉取仓库时的白名单,即就是需要拉取的脚本的路径包含的字符串,多个竖线分割
|
* whitelist: 拉取仓库时的白名单,即就是需要拉取的脚本的路径包含的字符串
|
||||||
* blacklist: 拉取仓库时的黑名单,即就是需要拉取的脚本的路径不包含的字符串,多个竖线分割
|
* blacklist: 拉取仓库时的黑名单,即就是需要拉取的脚本的路径不包含的字符串
|
||||||
* dependence: 拉取仓库需要的依赖文件,会直接从仓库拷贝到scripts下的仓库目录,不受黑名单影响,多个竖线分割
|
* dependence: 拉取仓库需要的依赖文件,会直接从仓库拷贝到scripts下的仓库目录,不受黑名单影响
|
||||||
* extensions: 拉取仓库的文件后缀,多个竖线分割
|
|
||||||
* branch: 拉取仓库的分支
|
* branch: 拉取仓库的分支
|
||||||
|
* extensions: 拉取仓库的文件后缀
|
||||||
* days: 需要保留的日志的天数
|
* days: 需要保留的日志的天数
|
||||||
* file_path: 任务执行时的文件路径
|
* file_path: 任务执行时的文件路径
|
||||||
* env_name: 任务执行时需要并发或者指定时的环境变量名称
|
* env_name: 任务执行时需要并发或者指定时的环境变量名称
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default (app: Router) => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -50,6 +51,7 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
res.send({ code: 200, data: content });
|
res.send({ code: 200, data: content });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -74,6 +76,7 @@ export default (app: Router) => {
|
|||||||
fs.writeFileSync(path, content);
|
fs.writeFileSync(path, content);
|
||||||
res.send({ code: 200, message: '保存成功' });
|
res.send({ code: 200, message: '保存成功' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+23
-7
@@ -42,6 +42,7 @@ export default (app: Router) => {
|
|||||||
return res.send({ code: 400, message: 'param schedule error' });
|
return res.send({ code: 400, message: 'param schedule error' });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -59,6 +60,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.run(req.body);
|
const data = await cronService.run(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -76,6 +78,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.stop(req.body);
|
const data = await cronService.stop(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -99,6 +102,7 @@ export default (app: Router) => {
|
|||||||
);
|
);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -119,6 +123,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.addLabels(req.body.ids, req.body.labels);
|
const data = await cronService.addLabels(req.body.ids, req.body.labels);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -136,6 +141,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.disabled(req.body);
|
const data = await cronService.disabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -153,6 +159,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.enabled(req.body);
|
const data = await cronService.enabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -172,6 +179,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.log(req.params.id);
|
const data = await cronService.log(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -182,9 +190,9 @@ export default (app: Router) => {
|
|||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
labels: Joi.array().optional().allow(null),
|
labels: Joi.array().optional().allow(null),
|
||||||
command: Joi.string().required(),
|
command: Joi.string().optional(),
|
||||||
schedule: Joi.string().required(),
|
schedule: Joi.string().optional(),
|
||||||
name: Joi.string().optional().allow(null),
|
name: Joi.string().optional(),
|
||||||
id: Joi.number().required(),
|
id: Joi.number().required(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@@ -202,6 +210,7 @@ export default (app: Router) => {
|
|||||||
return res.send({ code: 400, message: 'param schedule error' });
|
return res.send({ code: 400, message: 'param schedule error' });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -219,6 +228,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.remove(req.body);
|
const data = await cronService.remove(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -236,6 +246,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.pin(req.body);
|
const data = await cronService.pin(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -253,6 +264,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.unPin(req.body);
|
const data = await cronService.unPin(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -267,6 +279,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.import_crontab();
|
const data = await cronService.import_crontab();
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -286,6 +299,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.getDb({ id: req.params.id });
|
const data = await cronService.getDb({ id: req.params.id });
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -297,10 +311,10 @@ export default (app: Router) => {
|
|||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
ids: Joi.array().items(Joi.number().required()),
|
ids: Joi.array().items(Joi.number().required()),
|
||||||
status: Joi.string().required(),
|
status: Joi.string().required(),
|
||||||
pid: Joi.string().optional().allow(null),
|
pid: Joi.string().optional(),
|
||||||
log_path: Joi.string().optional().allow(null),
|
log_path: Joi.string().optional(),
|
||||||
last_running_time: Joi.number().optional().allow(null),
|
last_running_time: Joi.number().optional(),
|
||||||
last_execution_time: Joi.number().optional().allow(null),
|
last_execution_time: Joi.number().optional(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
@@ -314,6 +328,7 @@ export default (app: Router) => {
|
|||||||
});
|
});
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -333,6 +348,7 @@ export default (app: Router) => {
|
|||||||
const data = await cronService.logs(req.params.id);
|
const data = await cronService.logs(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.create(req.body);
|
const data = await dependenceService.create(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -60,6 +61,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.update(req.body);
|
const data = await dependenceService.update(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -77,6 +79,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.remove(req.body);
|
const data = await dependenceService.remove(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -94,6 +97,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.remove(req.body, true);
|
const data = await dependenceService.remove(req.body, true);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -113,6 +117,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.getDb({ id: req.params.id });
|
const data = await dependenceService.getDb({ id: req.params.id });
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -130,6 +135,7 @@ export default (app: Router) => {
|
|||||||
const data = await dependenceService.reInstall(req.body);
|
const data = await dependenceService.reInstall(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+9
-1
@@ -38,6 +38,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.create(req.body);
|
const data = await envService.create(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -60,6 +61,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.update(req.body);
|
const data = await envService.update(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -77,6 +79,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.remove(req.body);
|
const data = await envService.remove(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -100,6 +103,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.move(req.params.id, req.body);
|
const data = await envService.move(req.params.id, req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -117,6 +121,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.disabled(req.body);
|
const data = await envService.disabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -134,6 +139,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.enabled(req.body);
|
const data = await envService.enabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -154,6 +160,7 @@ export default (app: Router) => {
|
|||||||
const data = await envService.updateNames(req.body);
|
const data = await envService.updateNames(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -170,9 +177,10 @@ export default (app: Router) => {
|
|||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
const envService = Container.get(EnvService);
|
const envService = Container.get(EnvService);
|
||||||
const data = await envService.getDb({ id: req.params.id });
|
const data = await envService.getDb(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-5
@@ -6,7 +6,6 @@ import config from '../config';
|
|||||||
import { getFileContentByName, readDirs } from '../config/util';
|
import { getFileContentByName, readDirs } from '../config/util';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
const route = Router();
|
const route = Router();
|
||||||
const blacklist = ['.tmp'];
|
|
||||||
|
|
||||||
export default (app: Router) => {
|
export default (app: Router) => {
|
||||||
app.use('/logs', route);
|
app.use('/logs', route);
|
||||||
@@ -14,7 +13,7 @@ export default (app: Router) => {
|
|||||||
route.get('/', async (req: Request, res: Response, next: NextFunction) => {
|
route.get('/', async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
const result = readDirs(config.logPath, config.logPath, blacklist);
|
const result = readDirs(config.logPath, config.logPath);
|
||||||
res.send({
|
res.send({
|
||||||
code: 200,
|
code: 200,
|
||||||
data: result,
|
data: result,
|
||||||
@@ -30,9 +29,6 @@ export default (app: Router) => {
|
|||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
if (blacklist.includes(req.path)) {
|
|
||||||
return res.send({ code: 403, message: '暂无权限' });
|
|
||||||
}
|
|
||||||
const filePath = join(
|
const filePath = join(
|
||||||
config.logPath,
|
config.logPath,
|
||||||
(req.query.path || '') as string,
|
(req.query.path || '') as string,
|
||||||
@@ -41,6 +37,7 @@ export default (app: Router) => {
|
|||||||
const content = getFileContentByName(filePath);
|
const content = getFileContentByName(filePath);
|
||||||
res.send({ code: 200, data: content });
|
res.send({ code: 200, data: content });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+7
-1
@@ -16,6 +16,7 @@ export default (app: Router) => {
|
|||||||
const data = await openService.list();
|
const data = await openService.list();
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -25,7 +26,7 @@ export default (app: Router) => {
|
|||||||
'/apps',
|
'/apps',
|
||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
name: Joi.string().optional().allow('').disallow('system'),
|
name: Joi.string().optional().allow(''),
|
||||||
scopes: Joi.array().items(Joi.string().required()),
|
scopes: Joi.array().items(Joi.string().required()),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@@ -36,6 +37,7 @@ export default (app: Router) => {
|
|||||||
const data = await openService.create(req.body);
|
const data = await openService.create(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -57,6 +59,7 @@ export default (app: Router) => {
|
|||||||
const data = await openService.update(req.body);
|
const data = await openService.update(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -74,6 +77,7 @@ export default (app: Router) => {
|
|||||||
const data = await openService.remove(req.body);
|
const data = await openService.remove(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -93,6 +97,7 @@ export default (app: Router) => {
|
|||||||
const data = await openService.resetSecret(req.params.id);
|
const data = await openService.resetSecret(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -113,6 +118,7 @@ export default (app: Router) => {
|
|||||||
const result = await openService.authToken(req.query as any);
|
const result = await openService.authToken(req.query as any);
|
||||||
return res.send(result);
|
return res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+31
-44
@@ -3,7 +3,6 @@ import {
|
|||||||
getFileContentByName,
|
getFileContentByName,
|
||||||
readDirs,
|
readDirs,
|
||||||
getLastModifyFilePath,
|
getLastModifyFilePath,
|
||||||
readDir,
|
|
||||||
} from '../config/util';
|
} from '../config/util';
|
||||||
import { Router, Request, Response, NextFunction } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
@@ -11,38 +10,17 @@ import { Logger } from 'winston';
|
|||||||
import config from '../config';
|
import config from '../config';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { celebrate, Joi } from 'celebrate';
|
import { celebrate, Joi } from 'celebrate';
|
||||||
import path, { join, parse } from 'path';
|
import path, { join } from 'path';
|
||||||
import ScriptService from '../services/script';
|
import ScriptService from '../services/script';
|
||||||
import multer from 'multer';
|
|
||||||
const route = Router();
|
const route = Router();
|
||||||
|
|
||||||
const storage = multer.diskStorage({
|
|
||||||
destination: function (req, file, cb) {
|
|
||||||
cb(null, config.scriptPath);
|
|
||||||
},
|
|
||||||
filename: function (req, file, cb) {
|
|
||||||
cb(null, file.originalname);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const upload = multer({ storage: storage });
|
|
||||||
|
|
||||||
export default (app: Router) => {
|
export default (app: Router) => {
|
||||||
app.use('/scripts', route);
|
app.use('/scripts', route);
|
||||||
|
|
||||||
route.get('/', async (req: Request, res: Response, next: NextFunction) => {
|
route.get('/', async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
let result = [];
|
const result = readDirs(config.scriptPath, config.scriptPath);
|
||||||
const blacklist = ['node_modules', '.git'];
|
|
||||||
if (req.query.path) {
|
|
||||||
const targetPath = path.join(
|
|
||||||
config.scriptPath,
|
|
||||||
req.query.path as string,
|
|
||||||
);
|
|
||||||
result = readDir(targetPath, config.scriptPath, blacklist);
|
|
||||||
} else {
|
|
||||||
result = readDirs(config.scriptPath, config.scriptPath, blacklist);
|
|
||||||
}
|
|
||||||
res.send({
|
res.send({
|
||||||
code: 200,
|
code: 200,
|
||||||
data: result,
|
data: result,
|
||||||
@@ -66,6 +44,7 @@ export default (app: Router) => {
|
|||||||
const content = getFileContentByName(filePath);
|
const content = getFileContentByName(filePath);
|
||||||
res.send({ code: 200, data: content });
|
res.send({ code: 200, data: content });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -73,7 +52,14 @@ export default (app: Router) => {
|
|||||||
|
|
||||||
route.post(
|
route.post(
|
||||||
'/',
|
'/',
|
||||||
upload.single('file'),
|
celebrate({
|
||||||
|
body: Joi.object({
|
||||||
|
filename: Joi.string().required(),
|
||||||
|
path: Joi.string().optional().allow(''),
|
||||||
|
content: Joi.string().allow(''),
|
||||||
|
originFilename: Joi.string().allow(''),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
@@ -83,7 +69,6 @@ export default (app: Router) => {
|
|||||||
content: string;
|
content: string;
|
||||||
originFilename: string;
|
originFilename: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
path = config.scriptPath;
|
path = config.scriptPath;
|
||||||
}
|
}
|
||||||
@@ -99,18 +84,15 @@ export default (app: Router) => {
|
|||||||
message: '文件路径禁止访问',
|
message: '文件路径禁止访问',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.file) {
|
|
||||||
fs.renameSync(req.file.path, join(path, req.file.filename));
|
|
||||||
return res.send({ code: 200 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!originFilename) {
|
if (!originFilename) {
|
||||||
originFilename = filename;
|
originFilename = filename;
|
||||||
}
|
}
|
||||||
const originFilePath = `${path}${originFilename.replace(/\//g, '')}`;
|
const originFilePath = `${path}${originFilename.replace(/\//g, '')}`;
|
||||||
const filePath = `${path}${filename.replace(/\//g, '')}`;
|
const filePath = `${path}${filename.replace(/\//g, '')}`;
|
||||||
if (fs.existsSync(originFilePath)) {
|
if (fs.existsSync(originFilePath)) {
|
||||||
|
if (!fs.existsSync(config.bakPath)) {
|
||||||
|
fs.mkdirSync(config.bakPath);
|
||||||
|
}
|
||||||
fs.copyFileSync(
|
fs.copyFileSync(
|
||||||
originFilePath,
|
originFilePath,
|
||||||
`${config.bakPath}${originFilename.replace(/\//g, '')}`,
|
`${config.bakPath}${originFilename.replace(/\//g, '')}`,
|
||||||
@@ -122,6 +104,7 @@ export default (app: Router) => {
|
|||||||
fs.writeFileSync(filePath, content);
|
fs.writeFileSync(filePath, content);
|
||||||
return res.send({ code: 200 });
|
return res.send({ code: 200 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -133,7 +116,7 @@ export default (app: Router) => {
|
|||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
filename: Joi.string().required(),
|
filename: Joi.string().required(),
|
||||||
path: Joi.string().optional().allow(''),
|
path: Joi.string().optional().allow(''),
|
||||||
content: Joi.string().required().allow(''),
|
content: Joi.string().required(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
@@ -148,6 +131,7 @@ export default (app: Router) => {
|
|||||||
fs.writeFileSync(filePath, content);
|
fs.writeFileSync(filePath, content);
|
||||||
return res.send({ code: 200 });
|
return res.send({ code: 200 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -172,6 +156,7 @@ export default (app: Router) => {
|
|||||||
fs.unlinkSync(filePath);
|
fs.unlinkSync(filePath);
|
||||||
res.send({ code: 200 });
|
res.send({ code: 200 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -202,6 +187,7 @@ export default (app: Router) => {
|
|||||||
return next(err);
|
return next(err);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -212,22 +198,22 @@ export default (app: Router) => {
|
|||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
filename: Joi.string().required(),
|
filename: Joi.string().required(),
|
||||||
content: Joi.string().optional().allow(''),
|
|
||||||
path: Joi.string().optional().allow(''),
|
path: Joi.string().optional().allow(''),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
let { filename, content, path } = req.body;
|
let { filename, path } = req.body as {
|
||||||
const { name, ext } = parse(filename);
|
filename: string;
|
||||||
const filePath = join(config.scriptPath, path, `${name}.swap${ext}`);
|
path: string;
|
||||||
fs.writeFileSync(filePath, content || '', { encoding: 'utf8' });
|
};
|
||||||
|
const filePath = join(path, filename);
|
||||||
const scriptService = Container.get(ScriptService);
|
const scriptService = Container.get(ScriptService);
|
||||||
const result = await scriptService.runScript(filePath);
|
const result = await scriptService.runScript(filePath);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -238,21 +224,22 @@ export default (app: Router) => {
|
|||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
filename: Joi.string().required(),
|
filename: Joi.string().required(),
|
||||||
content: Joi.string().optional().allow(''),
|
|
||||||
path: Joi.string().optional().allow(''),
|
path: Joi.string().optional().allow(''),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
let { filename, content, path } = req.body;
|
let { filename, path } = req.body as {
|
||||||
const { name, ext } = parse(filename);
|
filename: string;
|
||||||
const filePath = join(config.scriptPath, path, `${name}.swap${ext}`);
|
path: string;
|
||||||
|
};
|
||||||
|
const filePath = join(path, filename);
|
||||||
const scriptService = Container.get(ScriptService);
|
const scriptService = Container.get(ScriptService);
|
||||||
const result = await scriptService.stopScript(filePath);
|
const result = await scriptService.stopScript(filePath);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,13 +29,7 @@ export default (app: Router) => {
|
|||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
type: Joi.string().required(),
|
type: Joi.string().required(),
|
||||||
schedule: Joi.string().optional().allow('').allow(null),
|
schedule: Joi.string().optional().allow('').allow(null),
|
||||||
interval_schedule: Joi.object({
|
interval_schedule: Joi.object().optional().allow('').allow(null),
|
||||||
type: Joi.string().required(),
|
|
||||||
value: Joi.number().min(1).required(),
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.allow('')
|
|
||||||
.allow(null),
|
|
||||||
name: Joi.string().optional().allow('').allow(null),
|
name: Joi.string().optional().allow('').allow(null),
|
||||||
url: Joi.string().required(),
|
url: Joi.string().required(),
|
||||||
whitelist: Joi.string().optional().allow('').allow(null),
|
whitelist: Joi.string().optional().allow('').allow(null),
|
||||||
@@ -65,6 +59,7 @@ export default (app: Router) => {
|
|||||||
return res.send({ code: 400, message: 'param schedule error' });
|
return res.send({ code: 400, message: 'param schedule error' });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -82,6 +77,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.run(req.body);
|
const data = await subscriptionService.run(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -99,6 +95,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.stop(req.body);
|
const data = await subscriptionService.stop(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -116,6 +113,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.disabled(req.body);
|
const data = await subscriptionService.disabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -133,6 +131,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.enabled(req.body);
|
const data = await subscriptionService.enabled(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -152,6 +151,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.log(req.params.id);
|
const data = await subscriptionService.log(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -195,6 +195,7 @@ export default (app: Router) => {
|
|||||||
return res.send({ code: 400, message: 'param schedule error' });
|
return res.send({ code: 400, message: 'param schedule error' });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -212,6 +213,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.remove(req.body);
|
const data = await subscriptionService.remove(req.body);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -231,6 +233,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.getDb({ id: req.params.id });
|
const data = await subscriptionService.getDb({ id: req.params.id });
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -257,6 +260,7 @@ export default (app: Router) => {
|
|||||||
});
|
});
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -276,6 +280,7 @@ export default (app: Router) => {
|
|||||||
const data = await subscriptionService.logs(req.params.id);
|
const data = await subscriptionService.logs(req.params.id);
|
||||||
return res.send({ code: 200, data });
|
return res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export default (app: Router) => {
|
|||||||
const data = await systemService.getLogRemoveFrequency();
|
const data = await systemService.getLogRemoveFrequency();
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -75,6 +76,7 @@ export default (app: Router) => {
|
|||||||
);
|
);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -89,6 +91,7 @@ export default (app: Router) => {
|
|||||||
const result = await systemService.checkUpdate();
|
const result = await systemService.checkUpdate();
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -103,6 +106,7 @@ export default (app: Router) => {
|
|||||||
const result = await systemService.updateSystem();
|
const result = await systemService.updateSystem();
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -123,6 +127,7 @@ export default (app: Router) => {
|
|||||||
const result = await systemService.notify(req.body);
|
const result = await systemService.notify(req.body);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.login({ ...req.body }, req);
|
const data = await userService.login({ ...req.body }, req);
|
||||||
return res.send(data);
|
return res.send(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53,6 +54,7 @@ export default (app: Router) => {
|
|||||||
await userService.logout(req.platform);
|
await userService.logout(req.platform);
|
||||||
res.send({ code: 200 });
|
res.send({ code: 200 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -73,6 +75,7 @@ export default (app: Router) => {
|
|||||||
await userService.updateUsernameAndPassword(req.body);
|
await userService.updateUsernameAndPassword(req.body);
|
||||||
res.send({ code: 200, message: '更新成功' });
|
res.send({ code: 200, message: '更新成功' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -106,6 +109,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.initTwoFactor();
|
const data = await userService.initTwoFactor();
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -125,6 +129,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.activeTwoFactor(req.body.code);
|
const data = await userService.activeTwoFactor(req.body.code);
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -139,6 +144,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.deactiveTwoFactor();
|
const data = await userService.deactiveTwoFactor();
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -160,6 +166,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.twoFactorLogin(req.body, req);
|
const data = await userService.twoFactorLogin(req.body, req);
|
||||||
res.send(data);
|
res.send(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -174,6 +181,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.getLoginLog();
|
const data = await userService.getLoginLog();
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -188,6 +196,7 @@ export default (app: Router) => {
|
|||||||
const data = await userService.getNotificationMode();
|
const data = await userService.getNotificationMode();
|
||||||
res.send({ code: 200, data });
|
res.send({ code: 200, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -202,6 +211,7 @@ export default (app: Router) => {
|
|||||||
const result = await userService.updateNotificationMode(req.body);
|
const result = await userService.updateNotificationMode(req.body);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -222,6 +232,7 @@ export default (app: Router) => {
|
|||||||
await userService.updateUsernameAndPassword(req.body);
|
await userService.updateUsernameAndPassword(req.body);
|
||||||
res.send({ code: 200, message: '更新成功' });
|
res.send({ code: 200, message: '更新成功' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -236,6 +247,7 @@ export default (app: Router) => {
|
|||||||
const result = await userService.updateNotificationMode(req.body);
|
const result = await userService.updateNotificationMode(req.body);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -251,6 +263,7 @@ export default (app: Router) => {
|
|||||||
const result = await userService.updateAvatar(req.file!.filename);
|
const result = await userService.updateAvatar(req.file!.filename);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+5
-3
@@ -1,18 +1,20 @@
|
|||||||
import 'reflect-metadata'; // We need this in order to use @Decorators
|
import 'reflect-metadata'; // We need this in order to use @Decorators
|
||||||
|
|
||||||
import config from './config';
|
import config from './config';
|
||||||
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
|
||||||
import Logger from './loaders/logger';
|
import Logger from './loaders/logger';
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
async function startServer() {
|
async function startServer() {
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
await require('./loaders/db').default();
|
|
||||||
|
|
||||||
await require('./loaders/initFile').default();
|
await require('./loaders/initFile').default();
|
||||||
|
|
||||||
await require('./loaders/sentry').default({ expressApp: app });
|
await require('./loaders/sentry').default({ expressApp: app });
|
||||||
|
|
||||||
|
await require('./loaders/db').default();
|
||||||
|
|
||||||
await require('./loaders/app').default({ expressApp: app });
|
await require('./loaders/app').default({ expressApp: app });
|
||||||
|
|
||||||
const server = app
|
const server = app
|
||||||
|
|||||||
+2
-14
@@ -4,21 +4,10 @@ import { createRandomString } from './util';
|
|||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
if (!process.env.QL_DIR) {
|
|
||||||
// 声明QL_DIR环境变量
|
|
||||||
let qlHomePath = path.join(__dirname, '../../');
|
|
||||||
// 生产环境
|
|
||||||
if (qlHomePath.endsWith('/static/')) {
|
|
||||||
qlHomePath = path.join(qlHomePath, '../');
|
|
||||||
}
|
|
||||||
process.env.QL_DIR = qlHomePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastVersionFile = `http://qn.whyour.cn/version.ts?v=${Date.now()}`;
|
const lastVersionFile = `http://qn.whyour.cn/version.ts?v=${Date.now()}`;
|
||||||
|
|
||||||
const rootPath = process.env.QL_DIR as string;
|
const envFound = dotenv.config();
|
||||||
const envFound = dotenv.config({ path: path.join(rootPath, '.env') });
|
const rootPath = process.cwd();
|
||||||
|
|
||||||
const dataPath = path.join(rootPath, 'data/');
|
const dataPath = path.join(rootPath, 'data/');
|
||||||
const samplePath = path.join(rootPath, 'sample/');
|
const samplePath = path.join(rootPath, 'sample/');
|
||||||
const configPath = path.join(dataPath, 'config/');
|
const configPath = path.join(dataPath, 'config/');
|
||||||
@@ -80,7 +69,6 @@ export default {
|
|||||||
'cookie.sh',
|
'cookie.sh',
|
||||||
'crontab.list',
|
'crontab.list',
|
||||||
'env.sh',
|
'env.sh',
|
||||||
'token.json',
|
|
||||||
],
|
],
|
||||||
writePathList: [configPath, scriptPath],
|
writePathList: [configPath, scriptPath],
|
||||||
bakPath,
|
bakPath,
|
||||||
|
|||||||
+19
-69
@@ -2,7 +2,6 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import got from 'got';
|
import got from 'got';
|
||||||
import iconv from 'iconv-lite';
|
import iconv from 'iconv-lite';
|
||||||
import { exec } from 'child_process';
|
|
||||||
|
|
||||||
export function getFileContentByName(fileName: string) {
|
export function getFileContentByName(fileName: string) {
|
||||||
if (fs.existsSync(fileName)) {
|
if (fs.existsSync(fileName)) {
|
||||||
@@ -278,80 +277,31 @@ export async function concurrentRun(
|
|||||||
return replyList;
|
return replyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FileType {
|
export function readDirs(dir: string, baseDir: string = '') {
|
||||||
'directory',
|
|
||||||
'file',
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readDirs(
|
|
||||||
dir: string,
|
|
||||||
baseDir: string = '',
|
|
||||||
blacklist: string[] = [],
|
|
||||||
) {
|
|
||||||
const relativePath = path.relative(baseDir, dir);
|
const relativePath = path.relative(baseDir, dir);
|
||||||
const files = fs.readdirSync(dir);
|
const files = fs.readdirSync(dir);
|
||||||
const result: any = files
|
const result: any = files.map((file: string) => {
|
||||||
.filter((x) => !blacklist.includes(x))
|
const subPath = path.join(dir, file);
|
||||||
.map((file: string) => {
|
const stats = fs.statSync(subPath);
|
||||||
const subPath = path.join(dir, file);
|
const key = path.join(relativePath, file);
|
||||||
const stats = fs.statSync(subPath);
|
if (stats.isDirectory()) {
|
||||||
const key = path.join(relativePath, file);
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
return {
|
|
||||||
title: file,
|
|
||||||
key,
|
|
||||||
type: 'directory',
|
|
||||||
disabled: true,
|
|
||||||
parent: relativePath,
|
|
||||||
children: readDirs(subPath, baseDir).sort(
|
|
||||||
(a: any, b: any) =>
|
|
||||||
(FileType as any)[a.type] - (FileType as any)[b.type],
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
title: file,
|
title: file,
|
||||||
type: 'file',
|
value: file,
|
||||||
key,
|
key,
|
||||||
|
type: 'directory',
|
||||||
|
disabled: true,
|
||||||
parent: relativePath,
|
parent: relativePath,
|
||||||
|
children: readDirs(subPath, baseDir),
|
||||||
};
|
};
|
||||||
});
|
}
|
||||||
return result.sort(
|
return {
|
||||||
(a: any, b: any) => (FileType as any)[a.type] - (FileType as any)[b.type],
|
title: file,
|
||||||
);
|
value: file,
|
||||||
}
|
type: 'file',
|
||||||
|
key,
|
||||||
export function readDir(
|
parent: relativePath,
|
||||||
dir: string,
|
};
|
||||||
baseDir: string = '',
|
});
|
||||||
blacklist: string[] = [],
|
|
||||||
) {
|
|
||||||
const relativePath = path.relative(baseDir, dir);
|
|
||||||
const files = fs.readdirSync(dir);
|
|
||||||
const result: any = files
|
|
||||||
.filter((x) => !blacklist.includes(x))
|
|
||||||
.map((file: string) => {
|
|
||||||
const subPath = path.join(dir, file);
|
|
||||||
const stats = fs.statSync(subPath);
|
|
||||||
const key = path.join(relativePath, file);
|
|
||||||
return {
|
|
||||||
title: file,
|
|
||||||
type: stats.isDirectory() ? 'directory' : 'file',
|
|
||||||
key,
|
|
||||||
parent: relativePath,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function promiseExec(command: string): Promise<string> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
exec(
|
|
||||||
command,
|
|
||||||
{ maxBuffer: 200 * 1024 * 1024, encoding: 'utf8' },
|
|
||||||
(err, stdout, stderr) => {
|
|
||||||
resolve(stdout || stderr || JSON.stringify(err));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-1
@@ -18,7 +18,9 @@ export default async () => {
|
|||||||
await AppModel.sync();
|
await AppModel.sync();
|
||||||
await AuthModel.sync();
|
await AuthModel.sync();
|
||||||
await EnvModel.sync();
|
await EnvModel.sync();
|
||||||
await SubscriptionModel.sync();
|
await SubscriptionModel.sync({ alter: true });
|
||||||
|
|
||||||
|
await sequelize.sync();
|
||||||
|
|
||||||
// try {
|
// try {
|
||||||
// const queryInterface = sequelize.getQueryInterface();
|
// const queryInterface = sequelize.getQueryInterface();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import path from 'path';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import chokidar from 'chokidar';
|
import chokidar from 'chokidar';
|
||||||
import config from '../config/index';
|
import config from '../config/index';
|
||||||
import { promiseExec } from '../config/util';
|
|
||||||
|
|
||||||
function linkToNodeModule(src: string, dst?: string) {
|
function linkToNodeModule(src: string, dst?: string) {
|
||||||
const target = path.join(config.rootPath, 'node_modules', dst || src);
|
const target = path.join(config.rootPath, 'node_modules', dst || src);
|
||||||
@@ -17,32 +16,7 @@ function linkToNodeModule(src: string, dst?: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function linkCommand() {
|
|
||||||
const commandPath = await promiseExec('which node');
|
|
||||||
const commandDir = path.dirname(commandPath);
|
|
||||||
const linkShell = [
|
|
||||||
{
|
|
||||||
src: 'update.sh',
|
|
||||||
dest: 'ql',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'task.sh',
|
|
||||||
dest: 'task',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const link of linkShell) {
|
|
||||||
const source = path.join(config.rootPath, 'shell', link.src);
|
|
||||||
const target = path.join(commandDir, link.dest);
|
|
||||||
if (fs.existsSync(target)) {
|
|
||||||
fs.unlinkSync(target);
|
|
||||||
}
|
|
||||||
fs.symlink(source, target, (err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async (src: string = 'deps') => {
|
export default async (src: string = 'deps') => {
|
||||||
await linkCommand();
|
|
||||||
linkToNodeModule(src);
|
linkToNodeModule(src);
|
||||||
|
|
||||||
const source = path.join(config.rootPath, src);
|
const source = path.join(config.rootPath, src);
|
||||||
|
|||||||
+8
-23
@@ -80,6 +80,13 @@ export default ({ app }: { app: Application }) => {
|
|||||||
) {
|
) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
const remoteAddress = req.socket.remoteAddress;
|
||||||
|
if (
|
||||||
|
remoteAddress === '::ffff:127.0.0.1' &&
|
||||||
|
originPath === '/api/crons/status'
|
||||||
|
) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
const data = fs.readFileSync(config.authConfigFile, 'utf8');
|
const data = fs.readFileSync(config.authConfigFile, 'utf8');
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -129,6 +136,7 @@ export default ({ app }: { app: Application }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.use(errors());
|
app.use(errors());
|
||||||
|
app.use(Sentry.Handlers.errorHandler());
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
(
|
(
|
||||||
@@ -147,29 +155,6 @@ export default ({ app }: { app: Application }) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
app.use(
|
|
||||||
(
|
|
||||||
err: Error & { errors: any[] },
|
|
||||||
req: Request,
|
|
||||||
res: Response,
|
|
||||||
next: NextFunction,
|
|
||||||
) => {
|
|
||||||
if (err.name.includes('Sequelize')) {
|
|
||||||
return res
|
|
||||||
.status(500)
|
|
||||||
.send({
|
|
||||||
code: 400,
|
|
||||||
message: `${err.name} ${err.message}`,
|
|
||||||
validation: err.errors,
|
|
||||||
})
|
|
||||||
.end();
|
|
||||||
}
|
|
||||||
return next(err);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(Sentry.Handlers.errorHandler());
|
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
(
|
(
|
||||||
err: Error & { status: number },
|
err: Error & { status: number },
|
||||||
|
|||||||
@@ -21,17 +21,14 @@ export default async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
|
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
|
||||||
DependenceModel.findAll({
|
DependenceModel.findAll({ where: {}, raw: true }).then(async (docs) => {
|
||||||
where: {},
|
|
||||||
order: [['type', 'DESC']],
|
|
||||||
raw: true,
|
|
||||||
}).then(async (docs) => {
|
|
||||||
const groups = _.groupBy(docs, 'type');
|
const groups = _.groupBy(docs, 'type');
|
||||||
const keys = Object.keys(groups).sort((a, b) => parseInt(b) - parseInt(a));
|
for (const key in groups) {
|
||||||
for (const key of keys) {
|
if (Object.prototype.hasOwnProperty.call(groups, key)) {
|
||||||
const group = groups[key];
|
const group = groups[key];
|
||||||
const depIds = group.map((x) => x.id);
|
const depIds = group.map((x) => x.id);
|
||||||
await dependenceService.reInstall(depIds as number[]);
|
await dependenceService.reInstall(depIds as number[]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import dotenv from 'dotenv';
|
|||||||
import Logger from './logger';
|
import Logger from './logger';
|
||||||
import { fileExist } from '../config/util';
|
import { fileExist } from '../config/util';
|
||||||
|
|
||||||
const rootPath = process.env.QL_DIR as string;;
|
const rootPath = process.cwd();
|
||||||
const dataPath = path.join(rootPath, 'data/');
|
const dataPath = path.join(rootPath, 'data/');
|
||||||
const configPath = path.join(dataPath, 'config/');
|
const configPath = path.join(dataPath, 'config/');
|
||||||
const scriptPath = path.join(dataPath, 'scripts/');
|
const scriptPath = path.join(dataPath, 'scripts/');
|
||||||
const logPath = path.join(dataPath, 'log/');
|
const logPath = path.join(dataPath, 'log/');
|
||||||
const uploadPath = path.join(dataPath, 'upload/');
|
const uploadPath = path.join(dataPath, 'upload/');
|
||||||
const bakPath = path.join(dataPath, 'bak/');
|
|
||||||
const samplePath = path.join(rootPath, 'sample/');
|
const samplePath = path.join(rootPath, 'sample/');
|
||||||
const confFile = path.join(configPath, 'config.sh');
|
const confFile = path.join(configPath, 'config.sh');
|
||||||
const authConfigFile = path.join(configPath, 'auth.json');
|
const authConfigFile = path.join(configPath, 'auth.json');
|
||||||
@@ -28,7 +27,6 @@ export default async () => {
|
|||||||
const configDirExist = await fileExist(configPath);
|
const configDirExist = await fileExist(configPath);
|
||||||
const uploadDirExist = await fileExist(uploadPath);
|
const uploadDirExist = await fileExist(uploadPath);
|
||||||
const sshDirExist = await fileExist(sshPath);
|
const sshDirExist = await fileExist(sshPath);
|
||||||
const bakDirExist = await fileExist(bakPath);
|
|
||||||
|
|
||||||
if (!configDirExist) {
|
if (!configDirExist) {
|
||||||
fs.mkdirSync(configPath);
|
fs.mkdirSync(configPath);
|
||||||
@@ -58,10 +56,6 @@ export default async () => {
|
|||||||
fs.mkdirSync(sshPath);
|
fs.mkdirSync(sshPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bakDirExist) {
|
|
||||||
fs.mkdirSync(bakPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
dotenv.config({ path: confFile });
|
dotenv.config({ path: confFile });
|
||||||
|
|
||||||
Logger.info('✌️ Init file down');
|
Logger.info('✌️ Init file down');
|
||||||
|
|||||||
@@ -3,30 +3,12 @@ import _ from 'lodash';
|
|||||||
import SystemService from '../services/system';
|
import SystemService from '../services/system';
|
||||||
import ScheduleService from '../services/schedule';
|
import ScheduleService from '../services/schedule';
|
||||||
import SubscriptionService from '../services/subscription';
|
import SubscriptionService from '../services/subscription';
|
||||||
import config from '../config';
|
|
||||||
import { fileExist } from '../config/util';
|
|
||||||
|
|
||||||
export default async () => {
|
export default async () => {
|
||||||
const systemService = Container.get(SystemService);
|
const systemService = Container.get(SystemService);
|
||||||
const scheduleService = Container.get(ScheduleService);
|
const scheduleService = Container.get(ScheduleService);
|
||||||
const subscriptionService = Container.get(SubscriptionService);
|
const subscriptionService = Container.get(SubscriptionService);
|
||||||
|
|
||||||
// 生成内置token
|
|
||||||
let tokenCommand = `ts-node-transpile-only ${config.rootPath}/back/token.ts`;
|
|
||||||
const tokenFile = `${config.rootPath}/static/build/token.js`;
|
|
||||||
if (await fileExist(tokenFile)) {
|
|
||||||
tokenCommand = `node ${tokenFile}`;
|
|
||||||
}
|
|
||||||
const cron = {
|
|
||||||
id: 'token',
|
|
||||||
name: '生成token',
|
|
||||||
command: tokenCommand,
|
|
||||||
};
|
|
||||||
scheduleService.createIntervalTask(cron as any, {
|
|
||||||
days: 28,
|
|
||||||
runImmediately: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 运行删除日志任务
|
// 运行删除日志任务
|
||||||
const data = await systemService.getLogRemoveFrequency();
|
const data = await systemService.getLogRemoveFrequency();
|
||||||
if (data && data.info && data.info.frequency) {
|
if (data && data.info && data.info.frequency) {
|
||||||
@@ -35,7 +17,7 @@ export default async () => {
|
|||||||
name: '删除日志',
|
name: '删除日志',
|
||||||
command: `ql rmlog ${data.info.frequency}`,
|
command: `ql rmlog ${data.info.frequency}`,
|
||||||
};
|
};
|
||||||
scheduleService.createIntervalTask(cron, {
|
await scheduleService.createIntervalTask(cron, {
|
||||||
days: data.info.frequency,
|
days: data.info.frequency,
|
||||||
runImmediately: true,
|
runImmediately: true,
|
||||||
});
|
});
|
||||||
@@ -44,11 +26,6 @@ export default async () => {
|
|||||||
// 运行所有订阅
|
// 运行所有订阅
|
||||||
const subs = await subscriptionService.list();
|
const subs = await subscriptionService.list();
|
||||||
for (const sub of subs) {
|
for (const sub of subs) {
|
||||||
await subscriptionService.handleTask(
|
await subscriptionService.handleTask(sub, true, true, true);
|
||||||
sub,
|
|
||||||
!sub.is_disabled,
|
|
||||||
true,
|
|
||||||
!sub.is_disabled,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-13
@@ -10,7 +10,6 @@ import { promises, existsSync } from 'fs';
|
|||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { Op } from 'sequelize';
|
import { Op } from 'sequelize';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class CronService {
|
export default class CronService {
|
||||||
@@ -198,21 +197,13 @@ export default class CronService {
|
|||||||
const err = await this.killTask(doc.command);
|
const err = await this.killTask(doc.command);
|
||||||
const absolutePath = path.resolve(config.logPath, `${doc.log_path}`);
|
const absolutePath = path.resolve(config.logPath, `${doc.log_path}`);
|
||||||
const logFileExist = doc.log_path && (await fileExist(absolutePath));
|
const logFileExist = doc.log_path && (await fileExist(absolutePath));
|
||||||
|
|
||||||
const endTime = dayjs();
|
|
||||||
const diffTimeStr = doc.last_execution_time
|
|
||||||
? `,耗时 ${endTime.diff(
|
|
||||||
dayjs(doc.last_execution_time * 1000),
|
|
||||||
'second',
|
|
||||||
)}`
|
|
||||||
: '';
|
|
||||||
if (logFileExist) {
|
if (logFileExist) {
|
||||||
const str = err ? `\n${err}` : '';
|
const str = err ? `\n${err}` : '';
|
||||||
fs.appendFileSync(
|
fs.appendFileSync(
|
||||||
`${absolutePath}`,
|
`${absolutePath}`,
|
||||||
`${str}\n## 执行结束... ${endTime.format(
|
`${str}\n## 执行结束... ${new Date()
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
.toLocaleString('zh', { hour12: false })
|
||||||
)}${diffTimeStr}`,
|
.replace(' 24:', ' 00:')} `,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +228,6 @@ export default class CronService {
|
|||||||
const killLogs = [];
|
const killLogs = [];
|
||||||
if (pids && pids.length > 0) {
|
if (pids && pids.length > 0) {
|
||||||
// node 执行脚本时还会有10个子进程,但是ps -ef中不存在,所以截取前三个
|
// node 执行脚本时还会有10个子进程,但是ps -ef中不存在,所以截取前三个
|
||||||
pids = pids.slice(0, 3);
|
|
||||||
for (const id of pids) {
|
for (const id of pids) {
|
||||||
const c = `kill -9 ${id.slice(1)}`;
|
const c = `kill -9 ${id.slice(1)}`;
|
||||||
try {
|
try {
|
||||||
|
|||||||
+20
-14
@@ -14,7 +14,6 @@ import { spawn } from 'child_process';
|
|||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import { Op } from 'sequelize';
|
import { Op } from 'sequelize';
|
||||||
import { concurrentRun } from '../config/util';
|
import { concurrentRun } from '../config/util';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class DependenceService {
|
export default class DependenceService {
|
||||||
@@ -162,17 +161,20 @@ export default class DependenceService {
|
|||||||
)[dependencies[0].type as any];
|
)[dependencies[0].type as any];
|
||||||
const actionText = isInstall ? '安装' : '删除';
|
const actionText = isInstall ? '安装' : '删除';
|
||||||
const depIds = dependencies.map((x) => x.id) as number[];
|
const depIds = dependencies.map((x) => x.id) as number[];
|
||||||
const startTime = dayjs();
|
const startTime = Date.now();
|
||||||
|
|
||||||
const message = `开始${actionText}依赖 ${depNames},开始时间 ${startTime.format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)}\n\n`;
|
|
||||||
this.sockService.sendMessage({
|
this.sockService.sendMessage({
|
||||||
type: socketMessageType,
|
type: socketMessageType,
|
||||||
message,
|
message: `开始${actionText}依赖 ${depNames},开始时间 ${new Date(
|
||||||
|
startTime,
|
||||||
|
).toLocaleString()}\n\n`,
|
||||||
references: depIds,
|
references: depIds,
|
||||||
});
|
});
|
||||||
await this.updateLog(depIds, message);
|
await this.updateLog(
|
||||||
|
depIds,
|
||||||
|
`开始${actionText}依赖 ${depNames},开始时间 ${new Date(
|
||||||
|
startTime,
|
||||||
|
).toLocaleString()}\n\n`,
|
||||||
|
);
|
||||||
|
|
||||||
const cp = spawn(`${depRunCommand} ${depNames}`, { shell: '/bin/bash' });
|
const cp = spawn(`${depRunCommand} ${depNames}`, { shell: '/bin/bash' });
|
||||||
|
|
||||||
@@ -205,19 +207,23 @@ export default class DependenceService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cp.on('close', async (code) => {
|
cp.on('close', async (code) => {
|
||||||
const endTime = dayjs();
|
const endTime = Date.now();
|
||||||
const isSucceed = code === 0;
|
const isSucceed = code === 0;
|
||||||
const resultText = isSucceed ? '成功' : '失败';
|
const resultText = isSucceed ? '成功' : '失败';
|
||||||
|
|
||||||
const message = `\n依赖${actionText}${resultText},结束时间 ${endTime.format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)},耗时 ${endTime.diff(startTime, 'second')} 秒`;
|
|
||||||
this.sockService.sendMessage({
|
this.sockService.sendMessage({
|
||||||
type: socketMessageType,
|
type: socketMessageType,
|
||||||
message,
|
message: `\n依赖${actionText}${resultText},结束时间 ${new Date(
|
||||||
|
endTime,
|
||||||
|
).toLocaleString()},耗时 ${(endTime - startTime) / 1000} 秒`,
|
||||||
references: depIds,
|
references: depIds,
|
||||||
});
|
});
|
||||||
await this.updateLog(depIds, message);
|
await this.updateLog(
|
||||||
|
depIds,
|
||||||
|
`\n依赖${actionText}${resultText},结束时间 ${new Date(
|
||||||
|
endTime,
|
||||||
|
).toLocaleString()},耗时 ${(endTime - startTime) / 1000} 秒`,
|
||||||
|
);
|
||||||
|
|
||||||
let status = null;
|
let status = null;
|
||||||
if (isSucceed) {
|
if (isSucceed) {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export default class EnvService {
|
|||||||
.filter((x) => x.status !== EnvStatus.disabled)
|
.filter((x) => x.status !== EnvStatus.disabled)
|
||||||
.map('value')
|
.map('value')
|
||||||
.join('&')
|
.join('&')
|
||||||
.replace(/(\\)[^n]/g, '\\\\')
|
.replace(/(\\)[^\n]/g, '\\\\')
|
||||||
.replace(/(\\$)/, '\\\\')
|
.replace(/(\\$)/, '\\\\')
|
||||||
.replace(/"/g, '\\"')
|
.replace(/"/g, '\\"')
|
||||||
.trim();
|
.trim();
|
||||||
|
|||||||
+1
-26
@@ -90,9 +90,7 @@ export default class OpenService {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await this.find(condition);
|
const result = await this.find(condition);
|
||||||
return result
|
return result.map((x) => ({ ...x, tokens: [] }));
|
||||||
.filter((x) => x.name !== 'system')
|
|
||||||
.map((x) => ({ ...x, tokens: [] }));
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -144,27 +142,4 @@ export default class OpenService {
|
|||||||
return { code: 400, message: 'client_id或client_seret有误' };
|
return { code: 400, message: 'client_id或client_seret有误' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generateSystemToken(): Promise<{
|
|
||||||
value: string;
|
|
||||||
expiration: number;
|
|
||||||
}> {
|
|
||||||
let systemApp = (await AppModel.findOne({
|
|
||||||
where: { name: 'system' },
|
|
||||||
})) as App;
|
|
||||||
if (!systemApp) {
|
|
||||||
systemApp = await this.create({
|
|
||||||
name: 'system',
|
|
||||||
scopes: ['crons', 'system'],
|
|
||||||
} as App);
|
|
||||||
}
|
|
||||||
const { data } = await this.authToken({
|
|
||||||
client_id: systemApp.client_id,
|
|
||||||
client_secret: systemApp.client_secret,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
value: data.token,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ interface ScheduleTaskType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TaskCallbacks {
|
export interface TaskCallbacks {
|
||||||
onBefore?: (startTime: dayjs.Dayjs) => Promise<void>;
|
|
||||||
onStart?: (
|
onStart?: (
|
||||||
cp: ChildProcessWithoutNullStreams,
|
cp: ChildProcessWithoutNullStreams,
|
||||||
startTime: dayjs.Dayjs,
|
startTime: dayjs.Dayjs,
|
||||||
@@ -46,8 +45,6 @@ export default class ScheduleService {
|
|||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const startTime = dayjs();
|
const startTime = dayjs();
|
||||||
await callbacks.onBefore?.(startTime);
|
|
||||||
|
|
||||||
const cp = spawn(command, { shell: '/bin/bash' });
|
const cp = spawn(command, { shell: '/bin/bash' });
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
@@ -169,7 +166,7 @@ export default class ScheduleService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const job = new LongIntervalJob(
|
const job = new LongIntervalJob(
|
||||||
{ runImmediately: false, ...schedule },
|
{ ...schedule, runImmediately: false },
|
||||||
task,
|
task,
|
||||||
_id,
|
_id,
|
||||||
);
|
);
|
||||||
|
|||||||
+32
-34
@@ -1,11 +1,8 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
import fs from 'fs';
|
import { spawn } from 'child_process';
|
||||||
import path from 'path';
|
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import CronService from './cron';
|
import CronService from './cron';
|
||||||
import ScheduleService, { TaskCallbacks } from './schedule';
|
|
||||||
import config from '../config';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ScriptService {
|
export default class ScriptService {
|
||||||
@@ -13,43 +10,44 @@ export default class ScriptService {
|
|||||||
@Inject('logger') private logger: winston.Logger,
|
@Inject('logger') private logger: winston.Logger,
|
||||||
private sockService: SockService,
|
private sockService: SockService,
|
||||||
private cronService: CronService,
|
private cronService: CronService,
|
||||||
private scheduleService: ScheduleService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private taskCallbacks(filePath: string): TaskCallbacks {
|
public async runScript(path: string) {
|
||||||
return {
|
const cp = spawn(`task -l ${path} now`, { shell: '/bin/bash' });
|
||||||
onEnd: async (cp, endTime, diff) => {
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(filePath);
|
|
||||||
} catch (error) {}
|
|
||||||
},
|
|
||||||
onError: async (message: string) => {
|
|
||||||
this.sockService.sendMessage({
|
|
||||||
type: 'manuallyRunScript',
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onLog: async (message: string) => {
|
|
||||||
this.sockService.sendMessage({
|
|
||||||
type: 'manuallyRunScript',
|
|
||||||
message,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async runScript(filePath: string) {
|
cp.stdout.on('data', (data) => {
|
||||||
const relativePath = path.relative(config.scriptPath, filePath);
|
this.sockService.sendMessage({
|
||||||
const command = `task -l ${relativePath} now`;
|
type: 'manuallyRunScript',
|
||||||
this.scheduleService.runTask(command, this.taskCallbacks(filePath));
|
message: data.toString(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cp.stderr.on('data', (data) => {
|
||||||
|
this.sockService.sendMessage({
|
||||||
|
type: 'manuallyRunScript',
|
||||||
|
message: data.toString(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cp.on('error', (err) => {
|
||||||
|
this.sockService.sendMessage({
|
||||||
|
type: 'manuallyRunScript',
|
||||||
|
message: JSON.stringify(err),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cp.on('close', (err) => {
|
||||||
|
this.sockService.sendMessage({
|
||||||
|
type: 'manuallyRunScript',
|
||||||
|
message: `执行结束`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return { code: 200 };
|
return { code: 200 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async stopScript(filePath: string) {
|
public async stopScript(path: string) {
|
||||||
const relativePath = path.relative(config.scriptPath, filePath);
|
const err = await this.cronService.killTask(`task -l ${path} now`);
|
||||||
const err = await this.cronService.killTask(`task -l ${relativePath} now`);
|
|
||||||
|
|
||||||
const str = err ? `\n${err}` : '';
|
const str = err ? `\n${err}` : '';
|
||||||
this.sockService.sendMessage({
|
this.sockService.sendMessage({
|
||||||
type: 'manuallyRunScript',
|
type: 'manuallyRunScript',
|
||||||
|
|||||||
+5
-13
@@ -23,13 +23,6 @@ export default class SshKeyService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getConfigRegx(alias: string) {
|
|
||||||
return new RegExp(
|
|
||||||
`Host ${alias}\n.*[^StrictHostKeyChecking]*.*[\n]*.*StrictHostKeyChecking no`,
|
|
||||||
'g',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private removePrivateKeyFile(alias: string): void {
|
private removePrivateKeyFile(alias: string): void {
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(`${this.sshPath}/${alias}`);
|
fs.unlinkSync(`${this.sshPath}/${alias}`);
|
||||||
@@ -54,25 +47,24 @@ export default class SshKeyService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeSshConfig(alias: string) {
|
private removeSshConfig(config: string) {
|
||||||
try {
|
try {
|
||||||
const configRegx = this.getConfigRegx(alias);
|
|
||||||
const data = fs
|
const data = fs
|
||||||
.readFileSync(this.sshConfigFilePath, { encoding: 'utf8' })
|
.readFileSync(this.sshConfigFilePath, { encoding: 'utf8' })
|
||||||
.replace(configRegx, '')
|
.replace(config, '')
|
||||||
.replace(/\n[\n]+/g, '\n');
|
.replace(/\n\n+/, '\n\n');
|
||||||
fs.writeFileSync(this.sshConfigFilePath, data, {
|
fs.writeFileSync(this.sshConfigFilePath, data, {
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`删除ssh配置文件${alias}失败`, error);
|
this.logger.error(`删除ssh配置文件${config}失败`, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public addSSHKey(key: string, alias: string, host: string): void {
|
public addSSHKey(key: string, alias: string, host: string): void {
|
||||||
this.generatePrivateKeyFile(alias, key);
|
this.generatePrivateKeyFile(alias, key);
|
||||||
const config = this.generateSingleSshConfig(alias, host);
|
const config = this.generateSingleSshConfig(alias, host);
|
||||||
this.removeSshConfig(alias);
|
this.removeSshConfig(config);
|
||||||
this.generateSshConfig([config]);
|
this.generateSshConfig([config]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import ScheduleService, { TaskCallbacks } from './schedule';
|
|||||||
import { SimpleIntervalSchedule } from 'toad-scheduler';
|
import { SimpleIntervalSchedule } from 'toad-scheduler';
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import SshKeyService from './sshKey';
|
import SshKeyService from './sshKey';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SubscriptionService {
|
export default class SubscriptionService {
|
||||||
@@ -42,22 +41,47 @@ export default class SubscriptionService {
|
|||||||
public async list(searchText?: string): Promise<Subscription[]> {
|
public async list(searchText?: string): Promise<Subscription[]> {
|
||||||
let query = {};
|
let query = {};
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
const reg = {
|
const textArray = searchText.split(':');
|
||||||
[Op.or]: [
|
switch (textArray[0]) {
|
||||||
{ [Op.like]: `%${searchText}%` },
|
case 'name':
|
||||||
{ [Op.like]: `%${encodeURIComponent(searchText)}%` },
|
case 'command':
|
||||||
],
|
case 'schedule':
|
||||||
};
|
case 'label':
|
||||||
query = {
|
const column = textArray[0] === 'label' ? 'labels' : textArray[0];
|
||||||
[Op.or]: [
|
query = {
|
||||||
{
|
[column]: {
|
||||||
name: reg,
|
[Op.or]: [
|
||||||
},
|
{ [Op.like]: `%${textArray[1]}%` },
|
||||||
{
|
{ [Op.like]: `%${encodeURIComponent(textArray[1])}%` },
|
||||||
url: reg,
|
],
|
||||||
},
|
},
|
||||||
],
|
};
|
||||||
};
|
break;
|
||||||
|
default:
|
||||||
|
const reg = {
|
||||||
|
[Op.or]: [
|
||||||
|
{ [Op.like]: `%${searchText}%` },
|
||||||
|
{ [Op.like]: `%${encodeURIComponent(searchText)}%` },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
query = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
name: reg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
command: reg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
schedule: reg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
labels: reg,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await SubscriptionModel.findAll({
|
const result = await SubscriptionModel.findAll({
|
||||||
@@ -168,13 +192,14 @@ export default class SubscriptionService {
|
|||||||
|
|
||||||
private taskCallbacks(doc: Subscription): TaskCallbacks {
|
private taskCallbacks(doc: Subscription): TaskCallbacks {
|
||||||
return {
|
return {
|
||||||
onBefore: async (startTime) => {
|
onStart: async (cp: ChildProcessWithoutNullStreams, startTime) => {
|
||||||
const logTime = startTime.format('YYYY-MM-DD-HH-mm-ss');
|
const logTime = startTime.format('YYYY-MM-DD-HH-mm-ss');
|
||||||
const logPath = `${doc.alias}/${logTime}.log`;
|
const logPath = `${doc.alias}/${logTime}.log`;
|
||||||
await SubscriptionModel.update(
|
await SubscriptionModel.update(
|
||||||
{
|
{
|
||||||
status: SubscriptionStatus.running,
|
status: SubscriptionStatus.running,
|
||||||
log_path: logPath,
|
log_path: logPath,
|
||||||
|
pid: cp.pid,
|
||||||
},
|
},
|
||||||
{ where: { id: doc.id } },
|
{ where: { id: doc.id } },
|
||||||
);
|
);
|
||||||
@@ -195,17 +220,9 @@ export default class SubscriptionService {
|
|||||||
(error.stderr && error.stderr.toString()) || JSON.stringify(error);
|
(error.stderr && error.stderr.toString()) || JSON.stringify(error);
|
||||||
}
|
}
|
||||||
if (beforeStr) {
|
if (beforeStr) {
|
||||||
fs.appendFileSync(absolutePath, `${beforeStr}\n`);
|
fs.appendFileSync(absolutePath, `${beforeStr}\n\n`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onStart: async (cp: ChildProcessWithoutNullStreams, startTime) => {
|
|
||||||
await SubscriptionModel.update(
|
|
||||||
{
|
|
||||||
pid: cp.pid,
|
|
||||||
},
|
|
||||||
{ where: { id: doc.id } },
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onEnd: async (cp, endTime, diff) => {
|
onEnd: async (cp, endTime, diff) => {
|
||||||
const sub = await this.getDb({ id: doc.id });
|
const sub = await this.getDb({ id: doc.id });
|
||||||
const absolutePath = await this.handleLogPath(sub.log_path as string);
|
const absolutePath = await this.handleLogPath(sub.log_path as string);
|
||||||
@@ -214,7 +231,7 @@ export default class SubscriptionService {
|
|||||||
let afterStr = '';
|
let afterStr = '';
|
||||||
try {
|
try {
|
||||||
if (sub.sub_after) {
|
if (sub.sub_after) {
|
||||||
fs.appendFileSync(absolutePath, `\n\n## 执行after命令...\n\n`);
|
fs.appendFileSync(absolutePath, `\n\n## 执行after命令...\n`);
|
||||||
afterStr = await this.promiseExec(sub.sub_after);
|
afterStr = await this.promiseExec(sub.sub_after);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -269,7 +286,7 @@ export default class SubscriptionService {
|
|||||||
|
|
||||||
public async update(payload: Subscription): Promise<Subscription> {
|
public async update(payload: Subscription): Promise<Subscription> {
|
||||||
const newDoc = await this.updateDb(payload);
|
const newDoc = await this.updateDb(payload);
|
||||||
await this.handleTask(newDoc, !newDoc.is_disabled);
|
await this.handleTask(newDoc);
|
||||||
return newDoc;
|
return newDoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,14 +360,16 @@ export default class SubscriptionService {
|
|||||||
this.logger.silly(error);
|
this.logger.silly(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await this.handleTask(doc, false);
|
||||||
const command = this.formatCommand(doc);
|
const command = this.formatCommand(doc);
|
||||||
const err = await this.killTask(command);
|
const err = await this.killTask(command);
|
||||||
const absolutePath = await this.handleLogPath(doc.log_path as string);
|
const absolutePath = await this.handleLogPath(doc.log_path as string);
|
||||||
const str = err ? `\n${err}` : '';
|
const str = err ? `\n${err}` : '';
|
||||||
|
|
||||||
fs.appendFileSync(
|
fs.appendFileSync(
|
||||||
`${absolutePath}`,
|
`${absolutePath}`,
|
||||||
`${str}\n## 执行结束... ${dayjs().format('YYYY-MM-DD HH:mm:ss')} `,
|
`${str}\n## 执行结束... ${new Date()
|
||||||
|
.toLocaleString('zh', { hour12: false })
|
||||||
|
.replace(' 24:', ' 00:')} `,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { Request } from 'express';
|
|||||||
import ScheduleService from './schedule';
|
import ScheduleService from './schedule';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import dayjs from 'dayjs';
|
import got from 'got';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class UserService {
|
export default class UserService {
|
||||||
@@ -111,7 +111,7 @@ export default class UserService {
|
|||||||
});
|
});
|
||||||
await this.notificationService.notify(
|
await this.notificationService.notify(
|
||||||
'登录通知',
|
'登录通知',
|
||||||
`你于${dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')}在 ${address} ${
|
`你于${new Date(timestamp).toLocaleString()}在 ${address} ${
|
||||||
req.platform
|
req.platform
|
||||||
}端 登录成功,ip地址 ${ip}`,
|
}端 登录成功,ip地址 ${ip}`,
|
||||||
);
|
);
|
||||||
@@ -140,7 +140,7 @@ export default class UserService {
|
|||||||
});
|
});
|
||||||
await this.notificationService.notify(
|
await this.notificationService.notify(
|
||||||
'登录通知',
|
'登录通知',
|
||||||
`你于${dayjs(timestamp).format('YYYY-MM-DD HH:mm:ss')}在 ${address} ${
|
`你于${new Date(timestamp).toLocaleString()}在 ${address} ${
|
||||||
req.platform
|
req.platform
|
||||||
}端 登录失败,ip地址 ${ip}`,
|
}端 登录失败,ip地址 ${ip}`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import 'reflect-metadata';
|
|
||||||
import OpenService from './services/open';
|
|
||||||
import { Container } from 'typedi';
|
|
||||||
import LoggerInstance from './loaders/logger';
|
|
||||||
import fs from 'fs';
|
|
||||||
import config from './config';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
const tokenFile = path.join(config.configPath, 'token.json');
|
|
||||||
|
|
||||||
async function getToken() {
|
|
||||||
try {
|
|
||||||
Container.set('logger', LoggerInstance);
|
|
||||||
const openService = Container.get(OpenService);
|
|
||||||
const appToken = await openService.generateSystemToken();
|
|
||||||
console.log(appToken.value);
|
|
||||||
await writeFile({
|
|
||||||
value: appToken.value,
|
|
||||||
expiration: appToken.expiration,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeFile(data: any) {
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
fs.writeFile(tokenFile, JSON.stringify(data), { encoding: 'utf8' }, () => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getToken();
|
|
||||||
+3
-4
@@ -5,8 +5,7 @@ LABEL maintainer="${QL_MAINTAINER}"
|
|||||||
ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
|
ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
|
||||||
ARG QL_BRANCH=master
|
ARG QL_BRANCH=master
|
||||||
|
|
||||||
ENV PNPM_HOME=/root/.local/share/pnpm \
|
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules \
|
||||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
|
|
||||||
LANG=zh_CN.UTF-8 \
|
LANG=zh_CN.UTF-8 \
|
||||||
SHELL=/bin/bash \
|
SHELL=/bin/bash \
|
||||||
PS1="\u@\h:\w \$ " \
|
PS1="\u@\h:\w \$ " \
|
||||||
@@ -34,13 +33,13 @@ RUN set -x \
|
|||||||
openssh \
|
openssh \
|
||||||
py3-pip \
|
py3-pip \
|
||||||
&& rm -rf /var/cache/apk/* \
|
&& rm -rf /var/cache/apk/* \
|
||||||
&& apk update \
|
|
||||||
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
&& echo "Asia/Shanghai" > /etc/timezone \
|
&& echo "Asia/Shanghai" > /etc/timezone \
|
||||||
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
||||||
&& git config --global user.name "qinglong" \
|
&& git config --global user.name "qinglong" \
|
||||||
&& git config --global http.postBuffer 524288000 \
|
|
||||||
&& npm install -g pnpm \
|
&& npm install -g pnpm \
|
||||||
|
&& pnpm setup \
|
||||||
|
&& source ~/.bashrc \
|
||||||
&& pnpm add -g pm2 ts-node typescript tslib \
|
&& pnpm add -g pm2 ts-node typescript tslib \
|
||||||
&& git clone -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
&& git clone -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
||||||
&& cd ${QL_DIR} \
|
&& cd ${QL_DIR} \
|
||||||
|
|||||||
+10
-6
@@ -31,13 +31,17 @@
|
|||||||
"allowedVersions": {
|
"allowedVersions": {
|
||||||
"react": "17",
|
"react": "17",
|
||||||
"react-dom": "17"
|
"react-dom": "17"
|
||||||
}
|
},
|
||||||
|
"ignoreMissing": [
|
||||||
|
"monaco-editor",
|
||||||
|
"react-router"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@otplib/preset-default": "^12.0.1",
|
"@otplib/preset-default": "^12.0.1",
|
||||||
"@sentry/node": "^7.0.0",
|
"@sentry/node": "^6.18.1",
|
||||||
"@sentry/tracing": "^7.0.0",
|
"@sentry/tracing": "^6.18.1",
|
||||||
"body-parser": "^1.19.2",
|
"body-parser": "^1.19.2",
|
||||||
"celebrate": "^15.0.1",
|
"celebrate": "^15.0.1",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
@@ -59,10 +63,10 @@
|
|||||||
"nodemailer": "^6.7.2",
|
"nodemailer": "^6.7.2",
|
||||||
"p-queue": "7.2.0",
|
"p-queue": "7.2.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sequelize": "^6.20.1",
|
"sequelize": "^6.17.0",
|
||||||
"serve-handler": "^6.1.3",
|
"serve-handler": "^6.1.3",
|
||||||
"sockjs": "^0.3.24",
|
"sockjs": "^0.3.24",
|
||||||
"sqlite3": "npm:@louislam/sqlite3@^15.0.6",
|
"sqlite3": "npm:@louislam/sqlite3@^15.0.3",
|
||||||
"toad-scheduler": "^1.6.0",
|
"toad-scheduler": "^1.6.0",
|
||||||
"typedi": "^0.10.0",
|
"typedi": "^0.10.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
@@ -73,7 +77,7 @@
|
|||||||
"@ant-design/icons": "^4.7.0",
|
"@ant-design/icons": "^4.7.0",
|
||||||
"@ant-design/pro-layout": "^6.33.1",
|
"@ant-design/pro-layout": "^6.33.1",
|
||||||
"@monaco-editor/react": "^4.3.1",
|
"@monaco-editor/react": "^4.3.1",
|
||||||
"@sentry/react": "^7.0.0",
|
"@sentry/react": "^6.18.1",
|
||||||
"@types/body-parser": "^1.19.2",
|
"@types/body-parser": "^1.19.2",
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ AutoStartBot=""
|
|||||||
BotRepoUrl=""
|
BotRepoUrl=""
|
||||||
|
|
||||||
## 安装bot依赖时指定pip源,默认使用清华源,如不需要源,设置此参数为空
|
## 安装bot依赖时指定pip源,默认使用清华源,如不需要源,设置此参数为空
|
||||||
PipMirror="https://pypi.doubanio.com/simple/"
|
PipMirror="https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||||
|
|
||||||
## 通知环境变量
|
## 通知环境变量
|
||||||
## 1. Server酱
|
## 1. Server酱
|
||||||
|
|||||||
+3
-10
@@ -97,13 +97,6 @@ let IGOT_PUSH_KEY = '';
|
|||||||
let PUSH_PLUS_TOKEN = '';
|
let PUSH_PLUS_TOKEN = '';
|
||||||
let PUSH_PLUS_USER = '';
|
let PUSH_PLUS_USER = '';
|
||||||
|
|
||||||
// =======================================Cool Push设置区域=======================================
|
|
||||||
//官方文档:https://cp.xuthus.cc/docs
|
|
||||||
//QQ_SKEY: Cool Push登录授权后推送消息的调用代码Skey
|
|
||||||
//QQ_MODE: 推送模式详情请登录获取QQ_SKEY后见https://cp.xuthus.cc/feat
|
|
||||||
let QQ_SKEY = '';
|
|
||||||
let QQ_MODE = '';
|
|
||||||
|
|
||||||
//==========================云端环境变量的判断与接收=========================
|
//==========================云端环境变量的判断与接收=========================
|
||||||
if (process.env.GOTIFY_URL) {
|
if (process.env.GOTIFY_URL) {
|
||||||
GOTIFY_URL = process.env.GOTIFY_URL;
|
GOTIFY_URL = process.env.GOTIFY_URL;
|
||||||
@@ -730,9 +723,9 @@ function qywxamNotify(text, desp) {
|
|||||||
timeout,
|
timeout,
|
||||||
};
|
};
|
||||||
$.post(options_accesstoken, (err, resp, data) => {
|
$.post(options_accesstoken, (err, resp, data) => {
|
||||||
let html = desp.replace(/\n/g, '<br/>');
|
html = desp.replace(/\n/g, '<br/>');
|
||||||
let json = JSON.parse(data);
|
var json = JSON.parse(data);
|
||||||
let accesstoken = json.access_token;
|
accesstoken = json.access_token;
|
||||||
let options;
|
let options;
|
||||||
|
|
||||||
switch (QYWX_AM_AY[4]) {
|
switch (QYWX_AM_AY[4]) {
|
||||||
|
|||||||
+26
-8
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
get_token() {
|
get_token() {
|
||||||
token=$(cat $file_auth_token | jq -r .value)
|
token=$(cat $file_auth_user | jq -r .token)
|
||||||
}
|
}
|
||||||
|
|
||||||
add_cron_api() {
|
add_cron_api() {
|
||||||
@@ -17,7 +17,7 @@ add_cron_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/crons?t=$currentTimeStamp" \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
|
-H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" \
|
||||||
@@ -52,7 +52,7 @@ update_cron_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/crons?t=$currentTimeStamp" \
|
||||||
-X 'PUT' \
|
-X 'PUT' \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
@@ -84,7 +84,7 @@ update_cron_command_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/crons?t=$currentTimeStamp" \
|
||||||
-X 'PUT' \
|
-X 'PUT' \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
@@ -109,7 +109,7 @@ del_cron_api() {
|
|||||||
local ids=$1
|
local ids=$1
|
||||||
local currentTimeStamp=$(date +%s)
|
local currentTimeStamp=$(date +%s)
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/crons?t=$currentTimeStamp" \
|
||||||
-X 'DELETE' \
|
-X 'DELETE' \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
@@ -130,6 +130,24 @@ del_cron_api() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_user_info() {
|
||||||
|
local currentTimeStamp=$(date +%s)
|
||||||
|
local api=$(
|
||||||
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/user?t=$currentTimeStamp" \
|
||||||
|
-H 'Accept: */*' \
|
||||||
|
-H "Authorization: Bearer $token" \
|
||||||
|
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36' \
|
||||||
|
-H 'Referer: http://0.0.0.0:5700/crontab' \
|
||||||
|
-H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' \
|
||||||
|
--compressed
|
||||||
|
)
|
||||||
|
code=$(echo $api | jq -r .code)
|
||||||
|
if [[ $code != 200 ]]; then
|
||||||
|
echo -e "请先登录!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
update_cron() {
|
update_cron() {
|
||||||
local ids="$1"
|
local ids="$1"
|
||||||
local status="$2"
|
local status="$2"
|
||||||
@@ -139,7 +157,7 @@ update_cron() {
|
|||||||
local runningTime="${6:-0}"
|
local runningTime="${6:-0}"
|
||||||
local currentTimeStamp=$(date +%s)
|
local currentTimeStamp=$(date +%s)
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/crons/status?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/crons/status?t=$currentTimeStamp" \
|
||||||
-X 'PUT' \
|
-X 'PUT' \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
@@ -154,7 +172,7 @@ update_cron() {
|
|||||||
code=$(echo $api | jq -r .code)
|
code=$(echo $api | jq -r .code)
|
||||||
message=$(echo $api | jq -r .message)
|
message=$(echo $api | jq -r .message)
|
||||||
if [[ $code != 200 ]]; then
|
if [[ $code != 200 ]]; then
|
||||||
echo -e "\n## 更新任务状态失败(${message})\n" >> $dir_log/$log_path
|
echo -e "\n## 更新任务状态失败(${message})\n" >> $log_path
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +181,7 @@ notify_api() {
|
|||||||
local content=$2
|
local content=$2
|
||||||
local currentTimeStamp=$(date +%s)
|
local currentTimeStamp=$(date +%s)
|
||||||
local api=$(
|
local api=$(
|
||||||
curl -s --noproxy "*" "http://0.0.0.0:5600/open/system/notify?t=$currentTimeStamp" \
|
curl -s --noproxy "*" "http://0.0.0.0:5600/api/system/notify?t=$currentTimeStamp" \
|
||||||
-X 'PUT' \
|
-X 'PUT' \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "Authorization: Bearer $token" \
|
-H "Authorization: Bearer $token" \
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ check_pm2() {
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
echo -e "=====> 开始检测"
|
echo -e "=====> 开始检测"
|
||||||
npm i -g pnpm
|
|
||||||
pnpm add -g pm2
|
pnpm add -g pm2
|
||||||
copy_dep
|
copy_dep
|
||||||
check_ql
|
check_ql
|
||||||
|
|||||||
+7
-51
@@ -14,6 +14,7 @@ dir_log=$dir_data/log
|
|||||||
dir_db=$dir_data/db
|
dir_db=$dir_data/db
|
||||||
dir_dep=$dir_data/deps
|
dir_dep=$dir_data/deps
|
||||||
dir_list_tmp=$dir_log/.tmp
|
dir_list_tmp=$dir_log/.tmp
|
||||||
|
dir_code=$dir_log/code
|
||||||
dir_update_log=$dir_log/update
|
dir_update_log=$dir_log/update
|
||||||
ql_static_repo=$dir_repo/static
|
ql_static_repo=$dir_repo/static
|
||||||
|
|
||||||
@@ -24,7 +25,6 @@ file_sharecode=$dir_config/sharecode.sh
|
|||||||
file_config_user=$dir_config/config.sh
|
file_config_user=$dir_config/config.sh
|
||||||
file_auth_sample=$dir_sample/auth.sample.json
|
file_auth_sample=$dir_sample/auth.sample.json
|
||||||
file_auth_user=$dir_config/auth.json
|
file_auth_user=$dir_config/auth.json
|
||||||
file_auth_token=$dir_config/token.json
|
|
||||||
file_extra_shell=$dir_config/extra.sh
|
file_extra_shell=$dir_config/extra.sh
|
||||||
file_task_before=$dir_config/task_before.sh
|
file_task_before=$dir_config/task_before.sh
|
||||||
file_task_after=$dir_config/task_after.sh
|
file_task_after=$dir_config/task_after.sh
|
||||||
@@ -52,10 +52,12 @@ list_own_drop=$dir_list_tmp/own_drop.list
|
|||||||
link_name=(
|
link_name=(
|
||||||
task
|
task
|
||||||
ql
|
ql
|
||||||
|
notify
|
||||||
)
|
)
|
||||||
original_name=(
|
original_name=(
|
||||||
task.sh
|
task.sh
|
||||||
update.sh
|
update.sh
|
||||||
|
notify.sh
|
||||||
)
|
)
|
||||||
|
|
||||||
init_env() {
|
init_env() {
|
||||||
@@ -99,7 +101,7 @@ make_dir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
detect_termux() {
|
detect_termux() {
|
||||||
if [[ $PATH == *com.termux* ]]; then
|
if [[ ${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT} ]] || [[ $PATH == *com.termux* ]]; then
|
||||||
is_termux=1
|
is_termux=1
|
||||||
else
|
else
|
||||||
is_termux=0
|
is_termux=0
|
||||||
@@ -246,11 +248,11 @@ fix_config() {
|
|||||||
npm_install_sub() {
|
npm_install_sub() {
|
||||||
set_proxy
|
set_proxy
|
||||||
if [ $is_termux -eq 1 ]; then
|
if [ $is_termux -eq 1 ]; then
|
||||||
npm install --production --no-bin-links --registry=https://registry.npmmirror.com || npm install --production --no-bin-links
|
npm install --production --no-bin-links --registry=https://registry.npm.taobao.org || npm install --production --no-bin-links
|
||||||
elif ! type pnpm &>/dev/null; then
|
elif ! type pnpm &>/dev/null; then
|
||||||
npm install --production --registry=https://registry.npmmirror.com || npm install --production
|
npm install --production --registry=https://registry.npm.taobao.org || npm install --production
|
||||||
else
|
else
|
||||||
pnpm install --loglevel error --production --registry=https://registry.npmmirror.com || pnpm install --production --loglevel error
|
pnpm install --loglevel error --production --registry=https://registry.npm.taobao.org || pnpm install --production --loglevel error
|
||||||
fi
|
fi
|
||||||
unset_proxy
|
unset_proxy
|
||||||
}
|
}
|
||||||
@@ -378,52 +380,6 @@ reload_pm2() {
|
|||||||
pm2 start $dir_static/build/public.js -n public --source-map-support --time &>/dev/null
|
pm2 start $dir_static/build/public.js -n public --source-map-support --time &>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
diff_time() {
|
|
||||||
local format="$1"
|
|
||||||
local begin_time="$2"
|
|
||||||
local end_time="$3"
|
|
||||||
|
|
||||||
if [[ $is_macos -eq 1 ]]; then
|
|
||||||
diff_time=$(($(date -j -f "$format" "$end_time" +%s) - $(date -j -f "$format" "$begin_time" +%s)))
|
|
||||||
else
|
|
||||||
diff_time=$(($(date +%s -d "$end_time") - $(date +%s -d "$begin_time")))
|
|
||||||
fi
|
|
||||||
echo "$diff_time"
|
|
||||||
}
|
|
||||||
|
|
||||||
format_time() {
|
|
||||||
local format="$1"
|
|
||||||
local time="$2"
|
|
||||||
|
|
||||||
if [[ $is_macos -eq 1 ]]; then
|
|
||||||
echo $(date -j -f "$format" "$time" "+%Y-%m-%d %H:%M:%S")
|
|
||||||
else
|
|
||||||
echo $(date -d "$time" "+%Y-%m-%d %H:%M:%S")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
format_log_time() {
|
|
||||||
local format="$1"
|
|
||||||
local time="$2"
|
|
||||||
|
|
||||||
if [[ $is_macos -eq 1 ]]; then
|
|
||||||
echo $(date -j -f "$format" "$time" "+%Y-%m-%d-%H-%M-%S")
|
|
||||||
else
|
|
||||||
echo $(date -d "$time" "+%Y-%m-%d-%H-%M-%S")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
format_timestamp() {
|
|
||||||
local format="$1"
|
|
||||||
local time="$2"
|
|
||||||
|
|
||||||
if [[ $is_macos -eq 1 ]]; then
|
|
||||||
echo $(date -j -f "$format" "$time" "+%s")
|
|
||||||
else
|
|
||||||
echo $(date -d "$time" "+%s")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
init_env
|
init_env
|
||||||
detect_termux
|
detect_termux
|
||||||
detect_macos
|
detect_macos
|
||||||
|
|||||||
+25
-33
@@ -84,8 +84,8 @@ run_normal() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local time=$(date "+$time_format")
|
local time=$(date)
|
||||||
log_time=$(format_log_time "$time_format" "$time")
|
log_time=$(date -d "$time" "+%Y-%m-%d-%H-%M-%S")
|
||||||
log_dir_tmp="${file_param##*/}"
|
log_dir_tmp="${file_param##*/}"
|
||||||
if [[ $file_param =~ "/" ]]; then
|
if [[ $file_param =~ "/" ]]; then
|
||||||
if [[ $file_param == /* ]]; then
|
if [[ $file_param == /* ]]; then
|
||||||
@@ -99,13 +99,12 @@ run_normal() {
|
|||||||
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
||||||
log_dir="${log_dir_tmp%.*}"
|
log_dir="${log_dir_tmp%.*}"
|
||||||
log_path="$log_dir/$log_time.log"
|
log_path="$log_dir/$log_time.log"
|
||||||
cmd=">> $dir_log/$log_path 2>&1"
|
cmd="&>> $dir_log/$log_path"
|
||||||
[[ "$show_log" == "true" ]] && cmd=""
|
[[ "$show_log" == "true" ]] && cmd=""
|
||||||
make_dir "$dir_log/$log_dir"
|
make_dir "$dir_log/$log_dir"
|
||||||
|
|
||||||
local begin_time=$(format_time "$time_format" "$time")
|
local begin_time=$(date -d "$time" "+%Y-%m-%d %H:%M:%S")
|
||||||
local begin_timestamp=$(format_timestamp "$time_format" "$time")
|
local begin_timestamp=$(date -d "$time" "+%s")
|
||||||
|
|
||||||
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
||||||
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
||||||
|
|
||||||
@@ -119,13 +118,12 @@ run_normal() {
|
|||||||
cd ${relative_path}
|
cd ${relative_path}
|
||||||
file_param=${file_param/$relative_path\//}
|
file_param=${file_param/$relative_path\//}
|
||||||
fi
|
fi
|
||||||
|
eval timeout -k 10s $command_timeout_time $which_program $file_param $cmd
|
||||||
eval $timeoutCmd $which_program $file_param $cmd
|
|
||||||
|
|
||||||
eval . $file_task_after "$@" $cmd
|
eval . $file_task_after "$@" $cmd
|
||||||
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
local end_timestamp=$(date "+%s")
|
local end_timestamp=$(date "+%s")
|
||||||
local diff_time=$(expr $end_timestamp - $begin_timestamp)
|
local diff_time=$(( $end_timestamp - $begin_timestamp ))
|
||||||
[[ $id ]] && update_cron "\"$id\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time"
|
[[ $id ]] && update_cron "\"$id\"" "1" "" "$log_path" "$begin_timestamp" "$diff_time"
|
||||||
eval echo -e "\\\n\#\# 执行结束... $end_time 耗时 $diff_time 秒" $cmd
|
eval echo -e "\\\n\#\# 执行结束... $end_time 耗时 $diff_time 秒" $cmd
|
||||||
}
|
}
|
||||||
@@ -156,8 +154,8 @@ run_concurrent() {
|
|||||||
[[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr}
|
[[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr}
|
||||||
|
|
||||||
define_program "$file_param"
|
define_program "$file_param"
|
||||||
local time=$(date "+$time_format")
|
local time=$(date)
|
||||||
log_time=$(format_log_time "$time_format" "$time")
|
log_time=$(date -d "$time" "+%Y-%m-%d-%H-%M-%S")
|
||||||
log_dir_tmp="${file_param##*/}"
|
log_dir_tmp="${file_param##*/}"
|
||||||
if [[ $file_param =~ "/" ]]; then
|
if [[ $file_param =~ "/" ]]; then
|
||||||
if [[ $file_param == /* ]]; then
|
if [[ $file_param == /* ]]; then
|
||||||
@@ -171,12 +169,12 @@ run_concurrent() {
|
|||||||
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
||||||
log_dir="${log_dir_tmp%.*}"
|
log_dir="${log_dir_tmp%.*}"
|
||||||
log_path="$log_dir/$log_time.log"
|
log_path="$log_dir/$log_time.log"
|
||||||
cmd=">> $dir_log/$log_path 2>&1"
|
cmd="&>> $dir_log/$log_path"
|
||||||
[[ "$show_log" == "true" ]] && cmd=""
|
[[ "$show_log" == "true" ]] && cmd=""
|
||||||
make_dir "$dir_log/$log_dir"
|
make_dir "$dir_log/$log_dir"
|
||||||
|
|
||||||
local begin_time=$(format_time "$time_format" "$time")
|
local begin_time=$(date -d "$time" "+%Y-%m-%d %H:%M:%S")
|
||||||
local begin_timestamp=$(format_timestamp "$time_format" "$time")
|
local begin_timestamp=$(date -d "$time" "+%s")
|
||||||
|
|
||||||
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
||||||
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
||||||
@@ -198,7 +196,7 @@ run_concurrent() {
|
|||||||
for i in "${!array[@]}"; do
|
for i in "${!array[@]}"; do
|
||||||
export ${env_param}=${array[i]}
|
export ${env_param}=${array[i]}
|
||||||
single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
|
single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
|
||||||
eval $timeoutCmd $which_program $file_param &>$single_log_path &
|
timeout -k 10s $command_timeout_time $which_program $file_param &>$single_log_path &
|
||||||
done
|
done
|
||||||
|
|
||||||
wait
|
wait
|
||||||
@@ -226,8 +224,8 @@ run_designated() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
define_program "$file_param"
|
define_program "$file_param"
|
||||||
local time=$(date "+$time_format")
|
local time=$(date)
|
||||||
log_time=$(format_log_time "$time_format" "$time")
|
log_time=$(date -d "$time" "+%Y-%m-%d-%H-%M-%S")
|
||||||
log_dir_tmp="${file_param##*/}"
|
log_dir_tmp="${file_param##*/}"
|
||||||
if [[ $file_param =~ "/" ]]; then
|
if [[ $file_param =~ "/" ]]; then
|
||||||
if [[ $file_param == /* ]]; then
|
if [[ $file_param == /* ]]; then
|
||||||
@@ -241,12 +239,12 @@ run_designated() {
|
|||||||
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
||||||
log_dir="${log_dir_tmp%.*}"
|
log_dir="${log_dir_tmp%.*}"
|
||||||
log_path="$log_dir/$log_time.log"
|
log_path="$log_dir/$log_time.log"
|
||||||
cmd=">> $dir_log/$log_path 2>&1"
|
cmd="&>> $dir_log/$log_path"
|
||||||
[[ "$show_log" == "true" ]] && cmd=""
|
[[ "$show_log" == "true" ]] && cmd=""
|
||||||
make_dir "$dir_log/$log_dir"
|
make_dir "$dir_log/$log_dir"
|
||||||
|
|
||||||
local begin_time=$(format_time "$time_format" "$time")
|
local begin_time=$(date -d "$time" "+%Y-%m-%d %H:%M:%S")
|
||||||
local begin_timestamp=$(format_timestamp "$time_format" "$time")
|
local begin_timestamp=$(date -d "$time" "+%s")
|
||||||
|
|
||||||
local envs=$(eval echo "\$${env_param}")
|
local envs=$(eval echo "\$${env_param}")
|
||||||
local array=($(echo $envs | sed 's/&/ /g'))
|
local array=($(echo $envs | sed 's/&/ /g'))
|
||||||
@@ -276,7 +274,7 @@ run_designated() {
|
|||||||
cd ${relative_path}
|
cd ${relative_path}
|
||||||
file_param=${file_param/$relative_path\//}
|
file_param=${file_param/$relative_path\//}
|
||||||
fi
|
fi
|
||||||
eval $timeoutCmd $which_program $file_param $cmd
|
eval timeout -k 10s $command_timeout_time $which_program $file_param $cmd
|
||||||
|
|
||||||
eval . $file_task_after "$@" $cmd
|
eval . $file_task_after "$@" $cmd
|
||||||
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
@@ -290,8 +288,8 @@ run_designated() {
|
|||||||
run_else() {
|
run_else() {
|
||||||
local file_param="$1"
|
local file_param="$1"
|
||||||
define_program "$file_param"
|
define_program "$file_param"
|
||||||
local time=$(date "+$time_format")
|
local time=$(date)
|
||||||
log_time=$(format_log_time "$time_format" "$time")
|
log_time=$(date -d "$time" "+%Y-%m-%d-%H-%M-%S")
|
||||||
log_dir_tmp="${file_param##*/}"
|
log_dir_tmp="${file_param##*/}"
|
||||||
if [[ $file_param =~ "/" ]]; then
|
if [[ $file_param =~ "/" ]]; then
|
||||||
if [[ $file_param == /* ]]; then
|
if [[ $file_param == /* ]]; then
|
||||||
@@ -305,12 +303,12 @@ run_else() {
|
|||||||
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
[[ $log_dir_tmp_path ]] && log_dir_tmp="${log_dir_tmp_path}_${log_dir_tmp}"
|
||||||
log_dir="${log_dir_tmp%.*}"
|
log_dir="${log_dir_tmp%.*}"
|
||||||
log_path="$log_dir/$log_time.log"
|
log_path="$log_dir/$log_time.log"
|
||||||
cmd=">> $dir_log/$log_path 2>&1"
|
cmd="&>> $dir_log/$log_path"
|
||||||
[[ "$show_log" == "true" ]] && cmd=""
|
[[ "$show_log" == "true" ]] && cmd=""
|
||||||
make_dir "$dir_log/$log_dir"
|
make_dir "$dir_log/$log_dir"
|
||||||
|
|
||||||
local begin_time=$(format_time "$time_format" "$time")
|
local begin_time=$(date -d "$time" "+%Y-%m-%d %H:%M:%S")
|
||||||
local begin_timestamp=$(format_timestamp "$time_format" "$time")
|
local begin_timestamp=$(date -d "$time" "+%s")
|
||||||
|
|
||||||
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
eval echo -e "\#\# 开始执行... $begin_time\\\n" $cmd
|
||||||
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
[[ -f $task_error_log_path ]] && eval cat $task_error_log_path $cmd
|
||||||
@@ -327,7 +325,7 @@ run_else() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
shift
|
shift
|
||||||
eval $timeoutCmd $which_program "$file_param" "$@" $cmd
|
eval timeout -k 10s $command_timeout_time $which_program "$file_param" "$@" $cmd
|
||||||
|
|
||||||
eval . $file_task_after "$file_param" "$@" $cmd
|
eval . $file_task_after "$file_param" "$@" $cmd
|
||||||
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
@@ -350,12 +348,6 @@ main() {
|
|||||||
done
|
done
|
||||||
[[ "$show_log" == "true" ]] && shift $(($OPTIND - 1))
|
[[ "$show_log" == "true" ]] && shift $(($OPTIND - 1))
|
||||||
|
|
||||||
timeoutCmd=""
|
|
||||||
if type timeout &>/dev/null; then
|
|
||||||
timeoutCmd="timeout -k 10s $command_timeout_time "
|
|
||||||
fi
|
|
||||||
|
|
||||||
time_format="%Y-%m-%d %H:%M:%S"
|
|
||||||
if [[ $1 == *.js ]] || [[ $1 == *.py ]] || [[ $1 == *.sh ]] || [[ $1 == *.ts ]]; then
|
if [[ $1 == *.js ]] || [[ $1 == *.py ]] || [[ $1 == *.sh ]] || [[ $1 == *.ts ]]; then
|
||||||
case $# in
|
case $# in
|
||||||
1)
|
1)
|
||||||
|
|||||||
+9
-11
@@ -12,16 +12,14 @@ diff_cron() {
|
|||||||
local list_task="$2"
|
local list_task="$2"
|
||||||
local list_add="$3"
|
local list_add="$3"
|
||||||
local list_drop="$4"
|
local list_drop="$4"
|
||||||
if [[ -s $list_task ]] && [[ -s $list_scripts ]]; then
|
if [[ -s $list_task ]]; then
|
||||||
grep -vwf $list_task $list_scripts >$list_add
|
grep -vwf $list_task $list_scripts >$list_add
|
||||||
grep -vwf $list_scripts $list_task >$list_drop
|
elif [[ ! -s $list_task ]] && [[ -s $list_scripts ]]; then
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -s $list_task ]] && [[ -s $list_scripts ]]; then
|
|
||||||
cp -f $list_scripts $list_add
|
cp -f $list_scripts $list_add
|
||||||
fi
|
fi
|
||||||
|
if [[ -s $list_scripts ]]; then
|
||||||
if [[ ! -s $list_scripts ]] && [[ -s $list_task ]]; then
|
grep -vwf $list_scripts $list_task >$list_drop
|
||||||
|
else
|
||||||
cp -f $list_task $list_drop
|
cp -f $list_task $list_drop
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -307,6 +305,7 @@ patch_version() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 兼容pnpm@7
|
# 兼容pnpm@7
|
||||||
|
npm i -g pnpm
|
||||||
pnpm setup
|
pnpm setup
|
||||||
source ~/.bashrc
|
source ~/.bashrc
|
||||||
|
|
||||||
@@ -388,9 +387,6 @@ gen_list_repo() {
|
|||||||
local index=0
|
local index=0
|
||||||
if [[ $6 ]]; then
|
if [[ $6 ]]; then
|
||||||
file_extensions="$6"
|
file_extensions="$6"
|
||||||
if [[ $file_extensions =~ "|" ]]; then
|
|
||||||
file_extensions=$(echo $file_extensions | sed 's/|/ /g')
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
for extension in $file_extensions; do
|
for extension in $file_extensions; do
|
||||||
if [[ $index -eq 0 ]]; then
|
if [[ $index -eq 0 ]]; then
|
||||||
@@ -491,6 +487,7 @@ main() {
|
|||||||
run_extra_shell >>$log_path
|
run_extra_shell >>$log_path
|
||||||
;;
|
;;
|
||||||
repo)
|
repo)
|
||||||
|
get_user_info
|
||||||
get_uniq_path "$p2" "$p6"
|
get_uniq_path "$p2" "$p6"
|
||||||
if [[ -n $p2 ]]; then
|
if [[ -n $p2 ]]; then
|
||||||
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7"
|
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7"
|
||||||
@@ -500,6 +497,7 @@ main() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
raw)
|
raw)
|
||||||
|
get_user_info
|
||||||
get_uniq_path "$p2"
|
get_uniq_path "$p2"
|
||||||
if [[ -n $p2 ]]; then
|
if [[ -n $p2 ]]; then
|
||||||
update_raw "$p2"
|
update_raw "$p2"
|
||||||
@@ -541,7 +539,7 @@ main() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
local end_time=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
local diff_time=$(diff_time "%Y-%m-%d %H:%M:%S" "$begin_time" "$end_time")
|
local diff_time=$(($(date +%s -d "$end_time") - $(date +%s -d "$begin_time")))
|
||||||
if [[ $p1 != "repo" ]] && [[ $p1 != "raw" ]]; then
|
if [[ $p1 != "repo" ]] && [[ $p1 != "raw" ]]; then
|
||||||
echo -e "\n## 执行结束... $end_time 耗时 $diff_time 秒" >>$log_path
|
echo -e "\n## 执行结束... $end_time 耗时 $diff_time 秒" >>$log_path
|
||||||
cat $log_path
|
cat $log_path
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import {
|
|||||||
FileOutlined,
|
FileOutlined,
|
||||||
PlayCircleOutlined,
|
PlayCircleOutlined,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
FullscreenOutlined,
|
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { CrontabStatus } from './index';
|
import { CrontabStatus } from './index';
|
||||||
import { diffTime } from '@/utils/date';
|
import { diffTime } from '@/utils/date';
|
||||||
@@ -107,8 +106,7 @@ const CronDetailModal = ({
|
|||||||
glyphMargin: false,
|
glyphMargin: false,
|
||||||
wordWrap: 'on',
|
wordWrap: 'on',
|
||||||
}}
|
}}
|
||||||
onMount={(editor, monaco) => {
|
onMount={(editor) => {
|
||||||
console.log(monaco);
|
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -354,11 +352,6 @@ const CronDetailModal = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fullscreen = () => {
|
|
||||||
const editorElement = editorRef.current._domElement as HTMLElement;
|
|
||||||
editorElement.parentElement?.requestFullscreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cron && cron.id) {
|
if (cron && cron.id) {
|
||||||
setCurrentCron(cron);
|
setCurrentCron(cron);
|
||||||
@@ -536,20 +529,13 @@ const CronDetailModal = ({
|
|||||||
}}
|
}}
|
||||||
tabBarExtraContent={
|
tabBarExtraContent={
|
||||||
activeTabKey === 'script' && (
|
activeTabKey === 'script' && (
|
||||||
<>
|
<Button
|
||||||
<Button
|
type="primary"
|
||||||
type="primary"
|
style={{ marginRight: 8 }}
|
||||||
style={{ marginRight: 8 }}
|
onClick={saveFile}
|
||||||
onClick={saveFile}
|
>
|
||||||
>
|
保存
|
||||||
保存
|
</Button>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<FullscreenOutlined />}
|
|
||||||
onClick={fullscreen}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
Vendored
+1
-15
@@ -25,7 +25,7 @@ import EditNameModal from './editNameModal';
|
|||||||
import { DndProvider, useDrag, useDrop } from 'react-dnd';
|
import { DndProvider, useDrag, useDrop } from 'react-dnd';
|
||||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
import { exportJson, getTableScroll } from '@/utils/index';
|
import { getTableScroll } from '@/utils/index';
|
||||||
|
|
||||||
const { Text, Paragraph } = Typography;
|
const { Text, Paragraph } = Typography;
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
@@ -462,13 +462,6 @@ const Env = ({ headerStyle, isPhone, theme }: any) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const exportEnvs = () => {
|
|
||||||
const envs = value
|
|
||||||
.filter((x) => selectedRowIds.includes(x.id))
|
|
||||||
.map((x) => ({ value: x.value, name: x.name, remarks: x.remarks }));
|
|
||||||
exportJson('env.json', JSON.stringify(envs));
|
|
||||||
};
|
|
||||||
|
|
||||||
const modifyName = () => {
|
const modifyName = () => {
|
||||||
setIsEditNameModalVisible(true);
|
setIsEditNameModalVisible(true);
|
||||||
};
|
};
|
||||||
@@ -523,13 +516,6 @@ const Env = ({ headerStyle, isPhone, theme }: any) => {
|
|||||||
>
|
>
|
||||||
批量删除
|
批量删除
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={() => exportEnvs()}
|
|
||||||
style={{ marginLeft: 8, marginRight: 8 }}
|
|
||||||
>
|
|
||||||
批量导出
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => operateEnvs(0)}
|
onClick={() => operateEnvs(0)}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const Log = ({ headerStyle, isPhone, theme }: any) => {
|
|||||||
|
|
||||||
const getLog = (node: any) => {
|
const getLog = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}logs/${node.title}?path=${node.parent || ''}`)
|
.get(`${config.apiPrefix}logs/${node.value}?path=${node.parent || ''}`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setValue(data.data);
|
setValue(data.data);
|
||||||
});
|
});
|
||||||
@@ -113,7 +113,6 @@ const Log = ({ headerStyle, isPhone, theme }: any) => {
|
|||||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||||
treeData={data}
|
treeData={data}
|
||||||
placeholder="请选择日志"
|
placeholder="请选择日志"
|
||||||
fieldNames={{ value: 'key', label: 'title' }}
|
|
||||||
showSearch
|
showSearch
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>,
|
/>,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const EditModal = ({
|
|||||||
|
|
||||||
const getDetail = (node: any) => {
|
const getDetail = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}scripts/${node.title}?path=${node.parent || ''}`)
|
.get(`${config.apiPrefix}scripts/${node.value}?path=${node.parent || ''}`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setValue(data.data);
|
setValue(data.data);
|
||||||
});
|
});
|
||||||
@@ -74,13 +74,11 @@ const EditModal = ({
|
|||||||
|
|
||||||
const run = () => {
|
const run = () => {
|
||||||
setLog('');
|
setLog('');
|
||||||
const content = editorRef.current.getValue().replace(/\r\n/g, '\n');
|
|
||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}scripts/run`, {
|
.put(`${config.apiPrefix}scripts/run`, {
|
||||||
data: {
|
data: {
|
||||||
filename: cNode.title,
|
filename: cNode.value,
|
||||||
path: cNode.parent || '',
|
path: cNode.parent || '',
|
||||||
content,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -89,16 +87,14 @@ const EditModal = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
if (!cNode || !cNode.title) {
|
if (!cNode || !cNode.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const content = editorRef.current.getValue().replace(/\r\n/g, '\n');
|
|
||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}scripts/stop`, {
|
.put(`${config.apiPrefix}scripts/stop`, {
|
||||||
data: {
|
data: {
|
||||||
filename: cNode.title,
|
filename: cNode.value,
|
||||||
path: cNode.parent || '',
|
path: cNode.parent || '',
|
||||||
content,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -117,7 +113,8 @@ const EditModal = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_message.includes('执行结束')) {
|
if (_message === '执行结束') {
|
||||||
|
_message = '';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsRunning(false);
|
setIsRunning(false);
|
||||||
}, 300);
|
}, 300);
|
||||||
@@ -149,7 +146,6 @@ const EditModal = ({
|
|||||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||||
treeData={treeData}
|
treeData={treeData}
|
||||||
placeholder="请选择脚本文件"
|
placeholder="请选择脚本文件"
|
||||||
fieldNames={{ value: 'key', label: 'title' }}
|
|
||||||
showSearch
|
showSearch
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>
|
/>
|
||||||
@@ -247,7 +243,7 @@ const EditModal = ({
|
|||||||
content:
|
content:
|
||||||
editorRef.current &&
|
editorRef.current &&
|
||||||
editorRef.current.getValue().replace(/\r\n/g, '\n'),
|
editorRef.current.getValue().replace(/\r\n/g, '\n'),
|
||||||
filename: cNode?.title,
|
filename: cNode?.value,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SettingModal
|
<SettingModal
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import {
|
import { Modal, message, Input, Form, Select } from 'antd';
|
||||||
Modal,
|
|
||||||
message,
|
|
||||||
Input,
|
|
||||||
Form,
|
|
||||||
Select,
|
|
||||||
Upload,
|
|
||||||
Radio,
|
|
||||||
TreeSelect,
|
|
||||||
} from 'antd';
|
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import config from '@/utils/config';
|
import config from '@/utils/config';
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@@ -31,30 +21,21 @@ const EditScriptNameModal = ({
|
|||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [dirs, setDirs] = useState<any[]>([]);
|
const [dirs, setDirs] = useState<any[]>([]);
|
||||||
const [file, setFile] = useState<File>();
|
|
||||||
const [type, setType] = useState<'blank' | 'upload'>('blank');
|
|
||||||
|
|
||||||
const handleOk = async (values: any) => {
|
const handleOk = async (values: any) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
values.path = values.path || '';
|
values.path = values.path || '';
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('file', file as any);
|
|
||||||
formData.append('filename', values.filename);
|
|
||||||
formData.append('path', values.path);
|
|
||||||
formData.append('content', '');
|
|
||||||
request
|
request
|
||||||
.post(`${config.apiPrefix}scripts`, {
|
.post(`${config.apiPrefix}scripts`, {
|
||||||
data: formData,
|
data: { filename: values.filename, path: values.path, content: '' },
|
||||||
})
|
})
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
message.success('新建文件成功');
|
message.success('保存文件成功');
|
||||||
const key = values.path ? `${values.path}/` : '';
|
|
||||||
const filename = file ? file.name : values.filename;
|
|
||||||
handleCancel({
|
handleCancel({
|
||||||
filename,
|
filename: values.filename,
|
||||||
path: values.path,
|
path: values.path,
|
||||||
key: `${key}${filename}`,
|
key: `${values.path}-${values.filename}`,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
message.error(data);
|
message.error(data);
|
||||||
@@ -64,42 +45,15 @@ const EditScriptNameModal = ({
|
|||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
const beforeUpload = (file: File) => {
|
|
||||||
setFile(file);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeChange = (e) => {
|
|
||||||
setType(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDirs = (data) => {
|
|
||||||
for (const item of data) {
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
item.children = item.children
|
|
||||||
.filter((x) => x.type === 'directory')
|
|
||||||
.map((x) => ({ ...x, disabled: false }));
|
|
||||||
getDirs(item.children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const originDirs = treeData
|
|
||||||
.filter((x) => x.type === 'directory')
|
|
||||||
.map((x) => ({ ...x, disabled: false }));
|
|
||||||
const dirs = getDirs(originDirs);
|
|
||||||
setDirs(dirs);
|
|
||||||
}, [treeData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
|
const originDirs = treeData.filter((x) => x.disabled);
|
||||||
|
setDirs([{ key: '' }, ...originDirs]);
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="新建脚本"
|
title="新建文件"
|
||||||
visible={visible}
|
visible={visible}
|
||||||
forceRender
|
forceRender
|
||||||
centered
|
centered
|
||||||
@@ -119,44 +73,23 @@ const EditScriptNameModal = ({
|
|||||||
>
|
>
|
||||||
<Form form={form} layout="vertical" name="edit_name_modal">
|
<Form form={form} layout="vertical" name="edit_name_modal">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="type"
|
name="filename"
|
||||||
label="类型"
|
label="文件名"
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true, message: '请输入文件名' }]}
|
||||||
initialValue={'blank'}
|
|
||||||
>
|
>
|
||||||
<Radio.Group onChange={typeChange}>
|
<Input placeholder="请输入文件名" />
|
||||||
<Radio value="blank">空文件</Radio>
|
|
||||||
<Radio value="upload">本地上传</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{type === 'blank' && (
|
<Form.Item
|
||||||
<Form.Item
|
label="父目录"
|
||||||
name="filename"
|
name="path"
|
||||||
label="文件名"
|
initialValue={dirs && dirs.length > 0 ? dirs[0].key : ''}
|
||||||
rules={[{ required: true, message: '请输入文件名' }]}
|
>
|
||||||
>
|
<Select placeholder="请选择父目录">
|
||||||
<Input placeholder="请输入文件名" />
|
{dirs.map((x) => (
|
||||||
</Form.Item>
|
<Option value={x.key}>{x.key || '根'}</Option>
|
||||||
)}
|
))}
|
||||||
<Form.Item label="父目录" name="path">
|
</Select>
|
||||||
<TreeSelect
|
|
||||||
allowClear
|
|
||||||
treeData={dirs}
|
|
||||||
fieldNames={{ value: 'key', label: 'title' }}
|
|
||||||
placeholder="请选择父目录"
|
|
||||||
treeDefaultExpandAll
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{type === 'upload' && (
|
|
||||||
<Form.Item label="文件" name="file">
|
|
||||||
<Upload.Dragger beforeUpload={beforeUpload} maxCount={1}>
|
|
||||||
<p className="ant-upload-drag-icon">
|
|
||||||
<UploadOutlined />
|
|
||||||
</p>
|
|
||||||
<p className="ant-upload-text">点击或者拖拽文件到此区域上传</p>
|
|
||||||
</Upload.Dragger>
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
|
|
||||||
const getDetail = (node: any) => {
|
const getDetail = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}scripts/${node.title}?path=${node.parent || ''}`)
|
.get(`${config.apiPrefix}scripts/${node.value}?path=${node.parent || ''}`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setValue(data.data);
|
setValue(data.data);
|
||||||
});
|
});
|
||||||
@@ -117,6 +117,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
const obj = {
|
const obj = {
|
||||||
node: {
|
node: {
|
||||||
title: s,
|
title: s,
|
||||||
|
value: s,
|
||||||
key: p ? vkey : s,
|
key: p ? vkey : s,
|
||||||
parent: p,
|
parent: p,
|
||||||
},
|
},
|
||||||
@@ -208,7 +209,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
<>
|
<>
|
||||||
确认保存文件
|
确认保存文件
|
||||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||||
{currentNode.title}
|
{currentNode.value}
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
,保存后不可恢复
|
,保存后不可恢复
|
||||||
</>
|
</>
|
||||||
@@ -221,7 +222,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}scripts`, {
|
.put(`${config.apiPrefix}scripts`, {
|
||||||
data: {
|
data: {
|
||||||
filename: currentNode.title,
|
filename: currentNode.value,
|
||||||
path: currentNode.parent || '',
|
path: currentNode.parent || '',
|
||||||
content,
|
content,
|
||||||
},
|
},
|
||||||
@@ -261,7 +262,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
request
|
request
|
||||||
.delete(`${config.apiPrefix}scripts`, {
|
.delete(`${config.apiPrefix}scripts`, {
|
||||||
data: {
|
data: {
|
||||||
filename: currentNode.title,
|
filename: currentNode.value,
|
||||||
path: currentNode.parent || '',
|
path: currentNode.parent || '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -314,9 +315,8 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
) => {
|
) => {
|
||||||
if (filename) {
|
if (filename) {
|
||||||
const newData = [...data];
|
const newData = [...data];
|
||||||
const _file = { title: filename, key, parent: path };
|
const _file = { title: filename, key, value: filename, parent: path };
|
||||||
if (path) {
|
if (path) {
|
||||||
// TODO: 更新左侧树数据
|
|
||||||
const parentNodeIndex = newData.findIndex((x) => x.key === path);
|
const parentNodeIndex = newData.findIndex((x) => x.key === path);
|
||||||
if (parentNodeIndex !== -1) {
|
if (parentNodeIndex !== -1) {
|
||||||
const parentNode = newData[parentNodeIndex];
|
const parentNode = newData[parentNodeIndex];
|
||||||
@@ -331,7 +331,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
newData.unshift(_file);
|
newData.unshift(_file);
|
||||||
}
|
}
|
||||||
setData(newData);
|
setData(newData);
|
||||||
onSelect(_file.title, _file);
|
onSelect(_file.value, _file);
|
||||||
setIsEditing(true);
|
setIsEditing(true);
|
||||||
}
|
}
|
||||||
setIsAddFileModalVisible(false);
|
setIsAddFileModalVisible(false);
|
||||||
@@ -341,7 +341,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
request
|
request
|
||||||
.post(`${config.apiPrefix}scripts/download`, {
|
.post(`${config.apiPrefix}scripts/download`, {
|
||||||
data: {
|
data: {
|
||||||
filename: currentNode.title,
|
filename: currentNode.value,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((_data: any) => {
|
.then((_data: any) => {
|
||||||
@@ -349,7 +349,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = currentNode.title;
|
a.download = currentNode.value;
|
||||||
document.documentElement.appendChild(a);
|
document.documentElement.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.documentElement.removeChild(a);
|
document.documentElement.removeChild(a);
|
||||||
@@ -451,7 +451,6 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
|
|||||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||||
treeData={data}
|
treeData={data}
|
||||||
placeholder="请选择脚本"
|
placeholder="请选择脚本"
|
||||||
fieldNames={{ value: 'key', label: 'title' }}
|
|
||||||
showSearch
|
showSearch
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
/>,
|
/>,
|
||||||
|
|||||||
@@ -107,18 +107,12 @@ const SubscriptionModal = ({
|
|||||||
const [intervalNumber, setIntervalNumber] = useState<number>();
|
const [intervalNumber, setIntervalNumber] = useState<number>();
|
||||||
const intervalTypeChange = (type: string) => {
|
const intervalTypeChange = (type: string) => {
|
||||||
setIntervalType(type);
|
setIntervalType(type);
|
||||||
if (intervalNumber && intervalNumber > 0) {
|
onChange?.({ type, value: intervalNumber });
|
||||||
onChange?.({ type, value: intervalNumber });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const numberChange = (value: number) => {
|
const numberChange = (value: number) => {
|
||||||
setIntervalNumber(value);
|
setIntervalNumber(value);
|
||||||
if (!value) {
|
onChange?.({ type: intervalType, value });
|
||||||
onChange?.(null);
|
|
||||||
} else {
|
|
||||||
onChange?.({ type: intervalType, value });
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -204,15 +198,13 @@ const SubscriptionModal = ({
|
|||||||
] = text
|
] = text
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map((x) => x.trim().replace(/\"/g, '').replace(/\'/, ''));
|
.map((x) => x.trim().replace(/\"/g, '').replace(/\'/, ''));
|
||||||
const _type =
|
|
||||||
type === 'raw'
|
|
||||||
? 'file'
|
|
||||||
: url.startsWith('http')
|
|
||||||
? 'public-repo'
|
|
||||||
: 'private-repo';
|
|
||||||
|
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
type: _type,
|
type:
|
||||||
|
type === 'raw'
|
||||||
|
? 'file'
|
||||||
|
: url.startsWith('http')
|
||||||
|
? 'public-repo'
|
||||||
|
: 'private-repo',
|
||||||
url,
|
url,
|
||||||
whitelist,
|
whitelist,
|
||||||
blacklist,
|
blacklist,
|
||||||
@@ -221,7 +213,6 @@ const SubscriptionModal = ({
|
|||||||
extensions,
|
extensions,
|
||||||
alias: formatAlias(url, branch),
|
alias: formatAlias(url, branch),
|
||||||
});
|
});
|
||||||
setType(_type);
|
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -205,39 +205,3 @@ export function getTableScroll({
|
|||||||
let height = document.body.clientHeight - mainTop - extraHeight;
|
let height = document.body.clientHeight - mainTop - extraHeight;
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动触发点击事件
|
|
||||||
function automaticClick(elment: HTMLElement) {
|
|
||||||
const ev = document.createEvent('MouseEvents');
|
|
||||||
ev.initMouseEvent(
|
|
||||||
'click',
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
window,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
elment.dispatchEvent(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出文件
|
|
||||||
export function exportJson(name: string, data: string) {
|
|
||||||
const urlObject = window.URL || window.webkitURL || window;
|
|
||||||
const export_blob = new Blob([data]);
|
|
||||||
const createA = document.createElementNS(
|
|
||||||
'http://www.w3.org/1999/xhtml',
|
|
||||||
'a',
|
|
||||||
) as any;
|
|
||||||
createA.href = urlObject.createObjectURL(export_blob);
|
|
||||||
createA.download = name;
|
|
||||||
automaticClick(createA);
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-8
@@ -7,15 +7,9 @@ export function init() {
|
|||||||
// sentry监控 init
|
// sentry监控 init
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: 'https://3406424fb1dc4813a62d39e844a9d0ac@o1098464.ingest.sentry.io/6122818',
|
dsn: 'https://3406424fb1dc4813a62d39e844a9d0ac@o1098464.ingest.sentry.io/6122818',
|
||||||
integrations: [
|
integrations: [new Integrations.BrowserTracing()],
|
||||||
new Integrations.BrowserTracing({
|
|
||||||
shouldCreateSpanForRequest(url) {
|
|
||||||
return !url.includes('/api/ws') && !url.includes('/api/static');
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
release: version,
|
release: version,
|
||||||
tracesSampleRate: 0.1,
|
tracesSampleRate: 1.0,
|
||||||
beforeBreadcrumb(breadcrumb, hint?) {
|
beforeBreadcrumb(breadcrumb, hint?) {
|
||||||
if (breadcrumb.data && breadcrumb.data.url) {
|
if (breadcrumb.data && breadcrumb.data.url) {
|
||||||
const url = breadcrumb.data.url.replace(/token=.*/, '');
|
const url = breadcrumb.data.url.replace(/token=.*/, '');
|
||||||
|
|||||||
+7
-4
@@ -1,5 +1,8 @@
|
|||||||
export const version = '2.13.8';
|
export const version = '2.13.1';
|
||||||
export const changeLogLink = 'https://t.me/jiao_long/323';
|
export const changeLogLink = 'https://t.me/jiao_long/303';
|
||||||
export const changeLog = `2.13.8 版本说明
|
export const changeLog = `2.13.1 版本说明
|
||||||
1. 修改系统token访问逻辑,加快任务启动速度
|
1. 修复新建订阅repo命令快捷导入
|
||||||
|
2. 修复执行订阅任务含有before/after命令时,造成面板无法访问
|
||||||
|
3. 修复任务详情日志列表访问
|
||||||
|
4. 修复安装依赖造成CPU满负荷,服务器崩溃
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user