Compare commits
1334 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
32e448b6b4 | |
|
|
116bed00a5 | |
|
|
4f5bf990bf | |
|
|
0144cb855f | |
|
|
e8f9bfb5c6 | |
|
|
56b1354496 | |
|
|
8e1a89bcbe | |
|
|
4c9bfd8683 | |
|
|
ec6d84aa88 | |
|
|
05c29a2a6c | |
|
|
18ef1ea816 | |
|
|
3c574b45dc | |
|
|
0e08cc7ca4 | |
|
|
b2d832edab | |
|
|
60889185d8 | |
|
|
b95280aba2 | |
|
|
96b2c0d9b7 | |
|
|
f0efa914fe | |
|
|
edb1c614d0 | |
|
|
61c2e96aaa | |
|
|
f31e6bd1bb | |
|
|
f5805fd79e | |
|
|
55913e8707 | |
|
|
45f71a5125 | |
|
|
4218cf7cfd | |
|
|
4963454f23 | |
|
|
85cf318a94 | |
|
|
82a0eaed4a | |
|
|
f6ce55be47 | |
|
|
fd37e8b4a7 | |
|
|
d43fea60e2 | |
|
|
05075e21a3 | |
|
|
f2f6b25ed2 | |
|
|
4a5ea50a14 | |
|
|
81c1ffb07e | |
|
|
6dd8bbfc38 | |
|
|
bcb6222c61 | |
|
|
0ce40fc039 | |
|
|
0cde5c2446 | |
|
|
69714747d7 | |
|
|
83b90c3267 | |
|
|
5b19d33af9 | |
|
|
c8fd0b0470 | |
|
|
8c8d53a9cc | |
|
|
f84b77993c | |
|
|
192c0c5241 | |
|
|
92d121175d | |
|
|
d6e599d6ac | |
|
|
a4c8026265 | |
|
|
90022df5a6 | |
|
|
0699c2350a | |
|
|
fd4fe83e9f | |
|
|
4933ea6d2f | |
|
|
07ddbfeabf | |
|
|
8db4a059d9 | |
|
|
11a59e7f77 | |
|
|
f2f27c7ea3 | |
|
|
e3be485727 | |
|
|
752dd06cd9 | |
|
|
a2d0fd7057 | |
|
|
09b41e8b24 | |
|
|
40835fa733 | |
|
|
b838533558 | |
|
|
6994ee771c | |
|
|
7be8b2fbe1 | |
|
|
61bc1891c3 | |
|
|
b7f015cd07 | |
|
|
d18cd2e662 | |
|
|
5f941c6b87 | |
|
|
7d91e58594 | |
|
|
d7f58f4128 | |
|
|
52b9f43ea0 | |
|
|
ff6845f5ce | |
|
|
e4e2faa93b | |
|
|
8dd40158ec | |
|
|
64e6ae4fe4 | |
|
|
f05195d373 | |
|
|
fbeacbb026 | |
|
|
24d21eda23 | |
|
|
2cb417dab2 | |
|
|
6c89c9896a | |
|
|
705e627908 | |
|
|
049ca00930 | |
|
|
43dd9ae664 | |
|
|
8445d6a078 | |
|
|
bf58ce6067 | |
|
|
364b471d2b | |
|
|
c2deb14284 | |
|
|
2ebedeb5df | |
|
|
e4585f5dcb | |
|
|
62db29627a | |
|
|
b15106d139 | |
|
|
d7a2e80bf6 | |
|
|
e405becf9a | |
|
|
e8d8325ead | |
|
|
c21eb3507b | |
|
|
c92059d356 | |
|
|
b36ba5a16c | |
|
|
cc74bde7be | |
|
|
7358a2027d | |
|
|
21ea871ada | |
|
|
1207052749 | |
|
|
6f8a388e8e | |
|
|
03201c36e8 | |
|
|
aa7ee1aae1 | |
|
|
07f9316935 | |
|
|
5e34d68d51 | |
|
|
5a07a91b50 | |
|
|
17abf826e9 | |
|
|
eca27ed5a1 | |
|
|
466d8800fc | |
|
|
ada2cb426b | |
|
|
f67600df28 | |
|
|
10bbb27684 | |
|
|
a32da911d1 | |
|
|
6a861498ca | |
|
|
292ac30aa5 | |
|
|
1e91312f08 | |
|
|
bee73e87a5 | |
|
|
a1e2c6e1e6 | |
|
|
0bbe126125 | |
|
|
590f6a302c | |
|
|
22470677d4 | |
|
|
7040cd26c6 | |
|
|
ac1e66b4b6 | |
|
|
658ed5791b | |
|
|
ef0a29552e | |
|
|
99554659f0 | |
|
|
995eb76c0f | |
|
|
dbb312b26e | |
|
|
9b476399f0 | |
|
|
e4f70b190c | |
|
|
bb5f87658e | |
|
|
00f2db99d8 | |
|
|
e26b65ca31 | |
|
|
cda00589a4 | |
|
|
3b75d93d6b | |
|
|
10fb654d23 | |
|
|
432d5ce1be | |
|
|
f2d5545092 | |
|
|
8939e21a29 | |
|
|
b872a84a4a | |
|
|
311cb892a7 | |
|
|
fab98274b1 | |
|
|
3e8b211789 | |
|
|
c92ed66436 | |
|
|
f1233c85d7 | |
|
|
9d02f8f7e7 | |
|
|
70205922fc | |
|
|
f3d1f0afe2 | |
|
|
7ee6ad8aec | |
|
|
4ff9afac23 | |
|
|
167970e5c4 | |
|
|
29395be19a | |
|
|
da01f093f8 | |
|
|
f53515eb70 | |
|
|
84dde0dcf2 | |
|
|
df1c283335 | |
|
|
faa4bfaef3 | |
|
|
eef7ef6544 | |
|
|
22d42048ab | |
|
|
e5b905c455 | |
|
|
c64f027e66 | |
|
|
96934ca139 | |
|
|
f4c763c84d | |
|
|
8cd0d9f366 | |
|
|
6a7f727f70 | |
|
|
62381f0472 | |
|
|
2952337f15 | |
|
|
c719be609a | |
|
|
6253e41658 | |
|
|
bd0e574268 | |
|
|
6e176c807c | |
|
|
2bdf12b1e1 | |
|
|
67f2ba2aa9 | |
|
|
c105f44eb9 | |
|
|
e23a6919af | |
|
|
b362e58646 | |
|
|
db3e571af0 | |
|
|
52fe19e933 | |
|
|
7b3ab45ecc | |
|
|
e337f685bc | |
|
|
13287e02eb | |
|
|
d4a33eab94 | |
|
|
0ca327f538 | |
|
|
31bd27fcf0 | |
|
|
dcfc062c01 | |
|
|
daa8286804 | |
|
|
5a3714e9bc | |
|
|
abe1f0d63e | |
|
|
c95cb70af3 | |
|
|
47bd3c4c10 | |
|
|
1c8f55c2c1 | |
|
|
0f9558a825 | |
|
|
8a4d37e975 | |
|
|
7fbabe1a8e | |
|
|
53cd4867df | |
|
|
7aa4872cb9 | |
|
|
8fcc548d34 | |
|
|
d318b719fc | |
|
|
d6db5963d5 | |
|
|
d5f4bba084 | |
|
|
960dee7756 | |
|
|
08f775da4b | |
|
|
2a0fcdea21 | |
|
|
3f0a34e20f | |
|
|
289161b8c6 | |
|
|
47b51fe965 | |
|
|
0c0efc9455 | |
|
|
dd86447176 | |
|
|
3427223da2 | |
|
|
1959b02220 | |
|
|
acf8ea428f | |
|
|
6e476e40af | |
|
|
25d07b11cc | |
|
|
36013e6139 | |
|
|
87d3c9a93c | |
|
|
d1b3f4f397 | |
|
|
5c5961f1b4 | |
|
|
e932a7ead1 | |
|
|
20db92ecf5 | |
|
|
e1c855b091 | |
|
|
693498b877 | |
|
|
0ef403d785 | |
|
|
d8b2a9a905 | |
|
|
6df2609d1a | |
|
|
608f05b21b | |
|
|
8145485cff | |
|
|
7506ac77cb | |
|
|
5142e2d668 | |
|
|
ef1cf982e3 | |
|
|
12d550d2b6 | |
|
|
2304f95b13 | |
|
|
a4be143104 | |
|
|
0209ed0326 | |
|
|
55846c5658 | |
|
|
799815c273 | |
|
|
baa689b098 | |
|
|
e4bc44115a | |
|
|
53bb1da7a1 | |
|
|
977ceb562e | |
|
|
0264da8d7c | |
|
|
94e23ec0f8 | |
|
|
7610e138dc | |
|
|
b04c6833a3 | |
|
|
035c326071 | |
|
|
e7660d94c9 | |
|
|
5f996472e1 | |
|
|
7cbdc0eb8e | |
|
|
615aa58bea | |
|
|
de7e2f1bfc | |
|
|
41bf76a49f | |
|
|
2a2744a1bf | |
|
|
757c0eebaf | |
|
|
f60cb25245 | |
|
|
199eb3f191 | |
|
|
c1de1113c4 | |
|
|
19803715be | |
|
|
d60d0425bc | |
|
|
28387c46e2 | |
|
|
6e06a6a9e8 | |
|
|
9a60c27785 | |
|
|
4613984fb4 | |
|
|
893b29cae8 | |
|
|
b99efad19c | |
|
|
034e7ec9f0 | |
|
|
72540d01ab | |
|
|
85677a3349 | |
|
|
b5301a3632 | |
|
|
c2743f949e | |
|
|
a7350294e8 | |
|
|
6d531fb173 | |
|
|
18517b6dc5 | |
|
|
27889b0a14 | |
|
|
6bd0dc8e05 | |
|
|
248fe926c5 | |
|
|
8c6546f5d8 | |
|
|
b04eac0566 | |
|
|
6984644313 | |
|
|
174520d259 | |
|
|
e4a22fabc5 | |
|
|
d770e73e31 | |
|
|
e73877f0a2 | |
|
|
0086cc9f53 | |
|
|
2f4c975615 | |
|
|
bbfe5889ea | |
|
|
8b2177673b | |
|
|
eb0602033d | |
|
|
210d75be8e | |
|
|
ed1e7e69a8 | |
|
|
e9ebf86ac8 | |
|
|
8faea4836d | |
|
|
30f821be49 | |
|
|
3361f420c4 | |
|
|
07357a8b75 | |
|
|
c009c88a5b | |
|
|
40715336e3 | |
|
|
16ec346493 | |
|
|
a11fb3ddf7 | |
|
|
063ee7f773 | |
|
|
008a461968 | |
|
|
36f428d928 | |
|
|
871c0a115d | |
|
|
6c3f0c36ff | |
|
|
26c76deb5f | |
|
|
20e2b60370 | |
|
|
503e9c3a8e | |
|
|
cea74fec35 | |
|
|
9cca7839bc | |
|
|
8bcbdc3160 | |
|
|
a9e38fa54d | |
|
|
a5573315a1 | |
|
|
d7ed5a1f73 | |
|
|
4c9c67927b | |
|
|
4a53b718b1 | |
|
|
6f42d2e821 | |
|
|
07cc5dfa51 | |
|
|
22881ccb59 | |
|
|
c44c280b21 | |
|
|
452da5caeb | |
|
|
c78758e32d | |
|
|
4b7e9152c6 | |
|
|
e8e149719a | |
|
|
d2730a187e | |
|
|
068483ac6a | |
|
|
e597cdead4 | |
|
|
25340da2e2 | |
|
|
02375cbe7d | |
|
|
5587d39d42 | |
|
|
ae8f069cbc | |
|
|
d6f7423d59 | |
|
|
2a3981268a | |
|
|
40263f9549 | |
|
|
be8cb965e3 | |
|
|
8a92dc8257 | |
|
|
2cd634a8de | |
|
|
a23af96034 | |
|
|
78abc63c06 | |
|
|
ba9b483472 | |
|
|
a21b875402 | |
|
|
366459e8f3 | |
|
|
7414626137 | |
|
|
9ff9eb30aa | |
|
|
4d6ff66187 | |
|
|
0bc9bd2cfb | |
|
|
7cd98d6dd0 | |
|
|
6d3c988768 | |
|
|
618b81bc93 | |
|
|
16248b6e12 | |
|
|
ceba6a91f0 | |
|
|
d005057c98 | |
|
|
e4738da6fa | |
|
|
ed8834075e | |
|
|
13bba13d6a | |
|
|
e0b7910d5e | |
|
|
086458b89d | |
|
|
775d77ee6d | |
|
|
7c1fa482ba | |
|
|
7be993eb8d | |
|
|
5a9e87c60d | |
|
|
5f836d249c | |
|
|
1d0175fb87 | |
|
|
774cff9c52 | |
|
|
51251331cf | |
|
|
2b1c90d249 | |
|
|
14ca1e5c40 | |
|
|
0efa04946b | |
|
|
96286d5836 | |
|
|
07e933de5c | |
|
|
2ec5eab7bb | |
|
|
601cc1060c | |
|
|
a6bc8e342d | |
|
|
30c603a733 | |
|
|
a10d09f293 | |
|
|
5493e21bfd | |
|
|
59217e59d0 | |
|
|
03b977f5cb | |
|
|
b8a8583598 | |
|
|
4f50365ac1 | |
|
|
ee9ff26594 | |
|
|
af7339f3b0 | |
|
|
0224f58e52 | |
|
|
05ee2d0bf4 | |
|
|
54d338807e | |
|
|
4b6ed674b3 | |
|
|
32ec900f87 | |
|
|
5b160a275b | |
|
|
c6b6295b26 | |
|
|
c11ac2e565 | |
|
|
912366563b | |
|
|
61007b2905 | |
|
|
db83718aa6 | |
|
|
4c46e41525 | |
|
|
69d31e301f | |
|
|
314f0e94da | |
|
|
ff3d2134a5 | |
|
|
4a6194274a | |
|
|
bf222b392b | |
|
|
7aebe466d9 | |
|
|
777b05ce6a | |
|
|
9046b96941 | |
|
|
eb6f4c7f92 | |
|
|
d3899a8d9e | |
|
|
4315c0983d | |
|
|
3ea3edc6ba | |
|
|
dc18ca2274 | |
|
|
8fadbef031 | |
|
|
7187161621 | |
|
|
17afe54f6f | |
|
|
8ed485c28f | |
|
|
b307655251 | |
|
|
38f7ecb671 | |
|
|
f51b4f40f1 | |
|
|
1530644de5 | |
|
|
79fee39b2a | |
|
|
c44c9187a9 | |
|
|
bf2d2cbeb3 | |
|
|
1878b10daa | |
|
|
50d200d5c8 | |
|
|
1b7cead33e | |
|
|
164aa611c4 | |
|
|
8d1ef8586e | |
|
|
e4b8b0c30c | |
|
|
2c99259a37 | |
|
|
e9f9fc4b92 | |
|
|
58e58915c6 | |
|
|
007cadbecb | |
|
|
6d27c8bbc7 | |
|
|
9bad76fe22 | |
|
|
56e09726f4 | |
|
|
3a46b2231e | |
|
|
fe31918f76 | |
|
|
489ab40a8c | |
|
|
f68f4824cd | |
|
|
08fc4740d5 | |
|
|
1bbf7b8a03 | |
|
|
f100ed7cca | |
|
|
44cb080932 | |
|
|
8f1f47e60e | |
|
|
5e4c71a3aa | |
|
|
5334d8b2a5 | |
|
|
2796a96872 | |
|
|
51a5cc65c7 | |
|
|
184cc11d1c | |
|
|
5ca33901c5 | |
|
|
4ec04eda71 | |
|
|
e39f8f9127 | |
|
|
f34cd1d9b8 | |
|
|
3bf25cc829 | |
|
|
0606663fe8 | |
|
|
89719f0570 | |
|
|
6acfb0d5d9 | |
|
|
3f874d04ed | |
|
|
fba8008c81 | |
|
|
e8782ab4bf | |
|
|
4142a733b8 | |
|
|
3601972228 | |
|
|
ef41439260 | |
|
|
e037173e14 | |
|
|
a87b1c93c0 | |
|
|
0247a2d965 | |
|
|
a64d575319 | |
|
|
c7317ee5b2 | |
|
|
1710eeba98 | |
|
|
db9bd47422 | |
|
|
42c7c4fdc6 | |
|
|
c7e0292da3 | |
|
|
9d83ffab2a | |
|
|
eed4caa44f | |
|
|
27277b51d7 | |
|
|
15c7578692 | |
|
|
57da9f7ffe | |
|
|
a9c2d891bc | |
|
|
7af4a4a3b6 | |
|
|
9727c0846b | |
|
|
1312c1b20a | |
|
|
4ab671f211 | |
|
|
8abcd5dda1 | |
|
|
06edfaddb8 | |
|
|
7a72ce37e6 | |
|
|
5f55ce945b | |
|
|
61d65783d6 | |
|
|
0bcfaafb96 | |
|
|
1063cd7dcf | |
|
|
f765dbc2f6 | |
|
|
7528a595fc | |
|
|
608e7bd792 | |
|
|
b016f3a47f | |
|
|
e431e6d486 | |
|
|
b57f68ed27 | |
|
|
f63590c116 | |
|
|
47075cb6f5 | |
|
|
abd48b2172 | |
|
|
e71387b44c | |
|
|
5fb9263ff5 | |
|
|
e235b00e53 | |
|
|
c11dcc4ee8 | |
|
|
75b7f01723 | |
|
|
26dbf4f6a0 | |
|
|
14c1512a94 | |
|
|
d431e50bdf | |
|
|
dcf28440f7 | |
|
|
3111b66bdb | |
|
|
f9ba364d9f | |
|
|
5018a471b7 | |
|
|
2abe90a93c | |
|
|
1b6ca940a6 | |
|
|
4b59c590e0 | |
|
|
3283955284 | |
|
|
39bd0225b6 | |
|
|
3e3882a2af | |
|
|
48b24be2ef | |
|
|
b6090c6fcd | |
|
|
24b1aa3761 | |
|
|
da8f3b4cf8 | |
|
|
b7c8258399 | |
|
|
e1cab589f2 | |
|
|
dfe7c1a4a3 | |
|
|
2abe93d45b | |
|
|
387a3f838d | |
|
|
fe204ad7c5 | |
|
|
1b7c5258f5 | |
|
|
2a826bd5b5 | |
|
|
293513dc64 | |
|
|
e821dc6b50 | |
|
|
0e02eb24fa | |
|
|
6d3518546a | |
|
|
fc5f715a77 | |
|
|
b580af1bf3 | |
|
|
478a807ffd | |
|
|
4d55f5df17 | |
|
|
b9b2b866b2 | |
|
|
4efad1cd1b | |
|
|
f392c41f3e | |
|
|
855dfd6b5b | |
|
|
6a14c954e1 | |
|
|
e29357a612 | |
|
|
1b4c35dbd7 | |
|
|
f0c32bc34b | |
|
|
0e9d6794f3 | |
|
|
b89d0573b8 | |
|
|
0a6e493f95 | |
|
|
0f17e5c433 | |
|
|
7648eab19f | |
|
|
d0401944ea | |
|
|
322c48882e | |
|
|
74f3520693 | |
|
|
ec7f306a45 | |
|
|
2b7ac9ab98 | |
|
|
04e00e2b39 | |
|
|
5d5dde4a16 | |
|
|
e698929ca9 | |
|
|
a1c9bf1998 | |
|
|
fa52c64c92 | |
|
|
05dd2520b6 | |
|
|
6f9c272b61 | |
|
|
2ff4f51d0f | |
|
|
e4015e5257 | |
|
|
67b3a4f7e2 | |
|
|
04e7a314f8 | |
|
|
9d3f806e0d | |
|
|
b773a09938 | |
|
|
c10c3966fb | |
|
|
bcbd6322e9 | |
|
|
e58bad1ae7 | |
|
|
27a3083e80 | |
|
|
25a4b8c285 | |
|
|
4a58de4841 | |
|
|
895850128a | |
|
|
3ee4dbcfcc | |
|
|
8a78937164 | |
|
|
fd8caa01e9 | |
|
|
d2cb20024f | |
|
|
5889acf196 | |
|
|
487e6a3b3a | |
|
|
930308a16f | |
|
|
15f9c354cd | |
|
|
bb367b6620 | |
|
|
701411132d | |
|
|
e69f043cad | |
|
|
26e6bbcb6a | |
|
|
3d12a776bc | |
|
|
68200c98c9 | |
|
|
c584de2d8f | |
|
|
283d92e8aa | |
|
|
f1454d7f82 | |
|
|
bfde76cc2c | |
|
|
3026e9f158 | |
|
|
12d7c4168d | |
|
|
74f3bef334 | |
|
|
d4efa77bb6 | |
|
|
0ceb2bde2b | |
|
|
bf6ec64f15 | |
|
|
033017c0ab | |
|
|
e1c2a28752 | |
|
|
6ba25e1b4a | |
|
|
082b5d70b1 | |
|
|
3faa23b7c0 | |
|
|
9c643e7c08 | |
|
|
e6fd0c3661 | |
|
|
d95dbf235e | |
|
|
583b8b79b0 | |
|
|
243b993751 | |
|
|
73ee7bc485 | |
|
|
a1ec9a6508 | |
|
|
de6fa42721 | |
|
|
9d81ccb528 | |
|
|
9abeb6ac41 | |
|
|
5e6226a39c | |
|
|
0098b5cc2a | |
|
|
bc0a1c8fe0 | |
|
|
681fddc387 | |
|
|
d6a2d09f95 | |
|
|
926f5881ac | |
|
|
0499cd8d97 | |
|
|
223f5d6532 | |
|
|
3e37ba5f1f | |
|
|
697a989ab3 | |
|
|
e5f914277e | |
|
|
0c8a6935f2 | |
|
|
bda12d5016 | |
|
|
78eed9cd56 | |
|
|
9c92d8f87d | |
|
|
f0e4e1a1a6 | |
|
|
5ac8aea155 | |
|
|
2cf1b00b33 | |
|
|
10ac990d36 | |
|
|
ed91f217d2 | |
|
|
edfaa1210a | |
|
|
ded17a552d | |
|
|
fb480530c8 | |
|
|
832b1f4e14 | |
|
|
9116b722a4 | |
|
|
3f114ccc15 | |
|
|
f884fc927f | |
|
|
438fcc0928 | |
|
|
35a49e9462 | |
|
|
59ad2b1d5e | |
|
|
69160bf0da | |
|
|
9e994023a8 | |
|
|
d14ce06afd | |
|
|
7776b82c18 | |
|
|
1e761c7e66 | |
|
|
c6962a1f8d | |
|
|
17ab56cf53 | |
|
|
fa69ae7b49 | |
|
|
ad3d75c9f2 | |
|
|
cdccfcbf9b | |
|
|
9d30a4652c | |
|
|
c0d66fffcd | |
|
|
c7262e4c3e | |
|
|
07826c687a | |
|
|
f3aa0bc673 | |
|
|
07694e8f40 | |
|
|
08430b192f | |
|
|
9aa405c203 | |
|
|
bc96bbc9ac | |
|
|
e6500ee26a | |
|
|
a8b569a24d | |
|
|
ed0deeb230 | |
|
|
30850c1fdf | |
|
|
784cc3a10f | |
|
|
34445af291 | |
|
|
680ad3a5e0 | |
|
|
a825075dd5 | |
|
|
18f6366f2e | |
|
|
6ca8c712e3 | |
|
|
cefb14e521 | |
|
|
c27ea9d3f4 | |
|
|
80bf31dcbc | |
|
|
79ab6b558a | |
|
|
1c83adc507 | |
|
|
4b265bb193 | |
|
|
057a390bff | |
|
|
f32dd2bd07 | |
|
|
06cde445b5 | |
|
|
7a6a109a8c | |
|
|
a955d38ef1 | |
|
|
685e090f2f | |
|
|
207126847e | |
|
|
64a0a05b14 | |
|
|
5332756526 | |
|
|
260370c328 | |
|
|
707b51b247 | |
|
|
896cbb0842 | |
|
|
d59bd8b8c4 | |
|
|
ee8a9ad78b | |
|
|
509a6e1a73 | |
|
|
64c865cc70 | |
|
|
471c8825ba | |
|
|
e0523d1c2d | |
|
|
aa0c930682 | |
|
|
182c377ecb | |
|
|
3f9d0cf2ea | |
|
|
951a4d3707 | |
|
|
0139ed2a07 | |
|
|
74ec5204fe | |
|
|
7d8b7ba2d5 | |
|
|
406889ae07 | |
|
|
be47059951 | |
|
|
5fd26b2d47 | |
|
|
12f4d99dcf | |
|
|
6019db240a | |
|
|
1f0b417d9d | |
|
|
22efbd0bcf | |
|
|
5a769dbdb2 | |
|
|
63f394b0e9 | |
|
|
80ff14f88f | |
|
|
a12b54dcbf | |
|
|
d2059ee282 | |
|
|
a5d9dd8068 | |
|
|
145660138c | |
|
|
74445e76c3 | |
|
|
03c952d819 | |
|
|
8610033c26 | |
|
|
613a21edd0 | |
|
|
0c93087b58 | |
|
|
aa8e0e765d | |
|
|
b277995c64 | |
|
|
dc2a723c1b | |
|
|
ffb2d2bc87 | |
|
|
dd0c5a2bfb | |
|
|
8c1e893657 | |
|
|
5d73b1d8de | |
|
|
59a45cf5ad | |
|
|
acfb6a56bb | |
|
|
b7e20b48cb | |
|
|
4e5923a763 | |
|
|
c523be9f34 | |
|
|
ded9916649 | |
|
|
b20ad52d6a | |
|
|
e118d94b24 | |
|
|
1a46a430b6 | |
|
|
3cff281172 | |
|
|
a1ded39bb6 | |
|
|
dab0a4f0d0 | |
|
|
3039601c42 | |
|
|
5c40ca6eb8 | |
|
|
a1e7c5be0c | |
|
|
7e615f6c84 | |
|
|
c90e6f5fba | |
|
|
9b40918a35 | |
|
|
fc2b73f2a8 | |
|
|
7b3517f699 | |
|
|
510feabe4b | |
|
|
b4c27fa22b | |
|
|
b3c3759e55 | |
|
|
4ec66e6a9f | |
|
|
6b67ebb818 | |
|
|
5d41851048 | |
|
|
255799ea3a | |
|
|
8a5744f492 | |
|
|
468fa72041 | |
|
|
b4aa7232a0 | |
|
|
2b0e3546ff | |
|
|
bf1e52fd9d | |
|
|
947120d136 | |
|
|
ae7c436730 | |
|
|
3dc4cb78e5 | |
|
|
118cd15204 | |
|
|
b9c4796a27 | |
|
|
2f25abaaf2 | |
|
|
cc35627ab1 | |
|
|
adcdd046d2 | |
|
|
00392e6809 | |
|
|
d506a69290 | |
|
|
feec4f236e | |
|
|
e36334c50a | |
|
|
9f21f8816a | |
|
|
7aedaf2085 | |
|
|
895c290cbf | |
|
|
346670b197 | |
|
|
7ad0a35ba2 | |
|
|
0d0a2ecc5a | |
|
|
dc82712597 | |
|
|
9ab3a297bd | |
|
|
03174f1ead | |
|
|
a4b0a7c0bb | |
|
|
4b8d578f4d | |
|
|
b369317800 | |
|
|
d957acd899 | |
|
|
e7d791ddf0 | |
|
|
a0ada99856 | |
|
|
cdbf0e2264 | |
|
|
134e559704 | |
|
|
dd9b2cd617 | |
|
|
07e2d69ebf | |
|
|
0d65960e86 | |
|
|
e1191c56b2 | |
|
|
cec1d3adcb | |
|
|
a4c4f737a8 | |
|
|
c0c62001a9 | |
|
|
4a64a9269a | |
|
|
30278a0451 | |
|
|
f80a312b9b | |
|
|
674d236007 | |
|
|
4e211c4871 | |
|
|
43788e0590 | |
|
|
8bf5140a72 | |
|
|
3d2d88287a | |
|
|
6d5b261c7d | |
|
|
2eb5752cc1 | |
|
|
43ce484f36 | |
|
|
277d42c12b | |
|
|
2651383ab2 | |
|
|
25022bfef2 | |
|
|
98ee5e9772 | |
|
|
acbf27bc26 | |
|
|
aa62d63920 | |
|
|
31c3d4021e | |
|
|
3025017d0f | |
|
|
514ccd2c75 | |
|
|
7a8e047c6f | |
|
|
be3adb875f | |
|
|
18d80cc78e | |
|
|
b1c60695e6 | |
|
|
4a6e5a0fba | |
|
|
a9775607e0 | |
|
|
d7f7da596f | |
|
|
6c8a389f9a | |
|
|
0f3d67367a | |
|
|
49e20200f1 | |
|
|
f726bf25ce | |
|
|
7fb5382c10 | |
|
|
e75258a72b | |
|
|
ffc16b032d | |
|
|
f42b8c7a83 | |
|
|
ddbb1aa170 | |
|
|
c8b42c5b82 | |
|
|
7d1b67a8b7 | |
|
|
b09955f369 | |
|
|
e7838317d0 | |
|
|
1aa2d7a5cc | |
|
|
8b4aef15cf | |
|
|
d56d6ac5ac | |
|
|
8d165f4919 | |
|
|
44895c3d17 | |
|
|
29a30a25c2 | |
|
|
77c4a350d4 | |
|
|
a1dba1ad1c | |
|
|
ecaf13caa3 | |
|
|
58bbf6c36d | |
|
|
154b8d9db8 | |
|
|
b7aa9f3f42 | |
|
|
44df8c4c8b | |
|
|
23b98a3ef8 | |
|
|
18a7915079 | |
|
|
68b5b80299 | |
|
|
c426de4dee | |
|
|
92911e840e | |
|
|
781fd7dd1a | |
|
|
f079622e11 | |
|
|
c52ba00f4f | |
|
|
7c48bc3184 | |
|
|
91986f13f8 | |
|
|
7728ad9eb4 | |
|
|
868aed4079 | |
|
|
9627ba9e1d | |
|
|
e0e305c423 | |
|
|
ed4280379d | |
|
|
233089b3e6 | |
|
|
bb0e7bd563 | |
|
|
7bca4fcbc4 | |
|
|
1b7a735f9c | |
|
|
829dfafdaa | |
|
|
5a59670124 | |
|
|
2499685a31 | |
|
|
a3bb603382 | |
|
|
9ad3cc0b9a | |
|
|
7e259cd101 | |
|
|
3846329c82 | |
|
|
326fe6a63f | |
|
|
5321200c6e | |
|
|
82d913c7de | |
|
|
0df61a6336 | |
|
|
68a4e6de5f | |
|
|
84e447e170 | |
|
|
4fcfe890c9 | |
|
|
a3b51553fb | |
|
|
7dc982aded | |
|
|
07c3a67b70 | |
|
|
40333c6b16 | |
|
|
942e609d36 | |
|
|
9f248e97f6 | |
|
|
9c763dceab | |
|
|
92d7c18879 | |
|
|
e4919f1a62 | |
|
|
052ab8866d | |
|
|
338138a0bc | |
|
|
fedb39c9ad | |
|
|
128b35c2f6 | |
|
|
57fed227f0 | |
|
|
c3b9aa0daf | |
|
|
690a9a6281 | |
|
|
e91adcc28d | |
|
|
83981138e0 | |
|
|
c29d766cd8 | |
|
|
3ede0313f2 | |
|
|
e7248da61a | |
|
|
05638550d5 | |
|
|
004e5b8af6 | |
|
|
0544581ab9 | |
|
|
6b22fb86cb | |
|
|
6d5830a235 | |
|
|
6aed57056c | |
|
|
3f17e54cf9 | |
|
|
aea691537b | |
|
|
8c88957b69 | |
|
|
bb9d504d40 | |
|
|
30b3909fc4 | |
|
|
f72d399f9a | |
|
|
cb6ca423f8 | |
|
|
1cb1743445 | |
|
|
f24da2fc98 | |
|
|
0b85032ca8 | |
|
|
9c54c5c37d | |
|
|
59e2d4a2df | |
|
|
dc6fe4c985 | |
|
|
a8eeb652b2 | |
|
|
1af0fef99e | |
|
|
7190516a27 | |
|
|
7e34c2339f | |
|
|
12f1ff894f | |
|
|
8a9d298ffc | |
|
|
2c8365b605 | |
|
|
27f40d0357 | |
|
|
cb32d5cc90 | |
|
|
14bb9f3cba | |
|
|
0140de4546 | |
|
|
e476fe6f5d | |
|
|
897ce6e3c2 | |
|
|
6d115e602e | |
|
|
2bba8c7b73 | |
|
|
1dbc11f708 | |
|
|
f9fbdb291b | |
|
|
a3b3332fdd | |
|
|
384b58ca11 | |
|
|
52423edb24 | |
|
|
fed849beed | |
|
|
fe296cc8ba | |
|
|
6c94fe8b82 | |
|
|
febd69e2b3 | |
|
|
55512bdbec | |
|
|
22d1e5882a | |
|
|
2f24ab1692 | |
|
|
025731a04c | |
|
|
28c861c6df | |
|
|
dcbc77b403 | |
|
|
1e6b78c349 | |
|
|
4f57c28f2f | |
|
|
2a718ba4d6 | |
|
|
ca9f87bff4 | |
|
|
e517741f99 | |
|
|
d066539616 | |
|
|
5c736e96c9 | |
|
|
0307599eed | |
|
|
55da596a80 | |
|
|
6fa8c991b8 | |
|
|
51f98aa0cb | |
|
|
07042ac9b1 | |
|
|
3df553c488 | |
|
|
5426ba9d5e | |
|
|
6b9ee80ca4 | |
|
|
05b5b314ee | |
|
|
f8491c36e2 | |
|
|
06751acbf9 | |
|
|
567ab47ae9 | |
|
|
82f8dadbae | |
|
|
ca6a4b2ecf | |
|
|
9247e004d0 | |
|
|
e1e494de33 | |
|
|
3988b12e72 | |
|
|
c6bf712de4 | |
|
|
18e0a2a27d | |
|
|
6ce34b1790 | |
|
|
b5678994da | |
|
|
2aa98dcbe1 | |
|
|
96d0bd2581 | |
|
|
f826a79633 | |
|
|
c958d6ec83 | |
|
|
5cb3430791 | |
|
|
d93e43cc2c | |
|
|
47f007ba97 | |
|
|
f96328ea6b | |
|
|
2d55917f2e | |
|
|
1c6e5cf665 | |
|
|
9d316c44d2 | |
|
|
2f8422278a | |
|
|
98dd156396 | |
|
|
b65263fdd7 | |
|
|
21992c1be7 | |
|
|
d80c1d2a73 | |
|
|
55978c7f15 | |
|
|
b2012e699b | |
|
|
382d1868be | |
|
|
82df046e59 | |
|
|
4f116a6a77 | |
|
|
77d3db4cb0 | |
|
|
1155bcb22d | |
|
|
208c4a8417 | |
|
|
62a0018041 | |
|
|
f276a83956 | |
|
|
28b8f3e36f | |
|
|
56a6e940c2 | |
|
|
868edbc88c | |
|
|
b05a539970 | |
|
|
2c48aedda7 | |
|
|
87b8d032ca | |
|
|
080237cabf | |
|
|
005418e065 | |
|
|
b32111f1ab | |
|
|
25f51371f5 | |
|
|
14bad9bf20 | |
|
|
da2d0ba32f | |
|
|
0b34c3e910 | |
|
|
1557a858ea | |
|
|
9a0098cca1 | |
|
|
fe8c142cd6 | |
|
|
5346af9ab0 | |
|
|
de1979212a | |
|
|
aa0f33b5e7 | |
|
|
ecb77e2be4 | |
|
|
db9d1a7720 | |
|
|
6ad6f90968 | |
|
|
b1b0542f72 | |
|
|
7e749c25c6 | |
|
|
23bbd23032 | |
|
|
68f65cf77b | |
|
|
9b93a151fb | |
|
|
3e18ca6613 | |
|
|
a3e946b57e | |
|
|
0ebd155be4 | |
|
|
660fc42750 | |
|
|
46b08d9474 | |
|
|
9ac3ca79f8 | |
|
|
7eade0d43c | |
|
|
cf2ae2bccb | |
|
|
f9a2f9e0f4 | |
|
|
01f40d91ec | |
|
|
dd57a4fb1a | |
|
|
69cc7a4111 | |
|
|
9f5067fbad | |
|
|
c3a6f4af6a | |
|
|
ac9666db76 | |
|
|
2d064a9723 | |
|
|
01de32cc58 | |
|
|
39fdb02022 | |
|
|
e0f091819b | |
|
|
b2cbc3b28c | |
|
|
3d10d26110 | |
|
|
f4ab77f80a | |
|
|
9532ad5fcd | |
|
|
d1c5ec58df | |
|
|
509032ff8b | |
|
|
1447fc413b | |
|
|
661b6fe5d5 | |
|
|
ac97d15a7f | |
|
|
83ed5fc243 | |
|
|
39b063ff6a | |
|
|
1166be1ea0 | |
|
|
4a44e097a2 | |
|
|
2d07fcb4b4 | |
|
|
81ec67d4ea | |
|
|
3d9f48c365 | |
|
|
f600cdf527 | |
|
|
d66b5811f7 | |
|
|
af6a313d06 | |
|
|
cf211fa19c | |
|
|
e1d2d72282 | |
|
|
ee8fb0e87b | |
|
|
a6367e9453 | |
|
|
65640603d1 | |
|
|
925d2b13d8 | |
|
|
c2e425aa12 | |
|
|
538e7dcc29 | |
|
|
ad8e475bb7 | |
|
|
f5071e0c4d | |
|
|
c24758f451 | |
|
|
f83a8ff4c0 | |
|
|
e6bacada22 | |
|
|
16270ae869 | |
|
|
64f0e9d282 | |
|
|
d5d2ae1da8 | |
|
|
6dfc2a0a3d | |
|
|
0f7952b9d5 | |
|
|
fcc889ca07 | |
|
|
362374d0b7 | |
|
|
c6c71a7e70 | |
|
|
e1a38a3bd5 | |
|
|
f169eaf6cc | |
|
|
c920d3ec5b | |
|
|
ac5f45d11a | |
|
|
e4984b85f2 | |
|
|
1bd8dd00d1 | |
|
|
29ac3e21b2 | |
|
|
7acd197389 | |
|
|
025d28d80d | |
|
|
7d26bfb247 | |
|
|
2c0042c3df | |
|
|
5a7fcde102 | |
|
|
5be2aaae15 | |
|
|
1b302b9bde | |
|
|
5c7f6b7c7d | |
|
|
a1d9354de7 | |
|
|
2a6761d47e | |
|
|
18786fc669 | |
|
|
67e6aa0067 | |
|
|
12e68fab27 | |
|
|
478520572c | |
|
|
e7050f5a38 | |
|
|
79197b1977 | |
|
|
bf68719e2e | |
|
|
9b45b78ba7 | |
|
|
ca48d313a2 | |
|
|
d9fabe556c | |
|
|
12ef6d07cf | |
|
|
bed647427b | |
|
|
d408e2bf54 | |
|
|
b5cef34426 | |
|
|
129cea08ce | |
|
|
cd10f48f53 | |
|
|
a2c1bfef8f | |
|
|
47f4fce2ab | |
|
|
1c3541cc05 | |
|
|
5f05734e46 | |
|
|
e5ab665c57 | |
|
|
c3417792d9 | |
|
|
174ed02058 | |
|
|
e944409f5e | |
|
|
713ccf26e2 | |
|
|
3ee87354c8 | |
|
|
e942bcf033 | |
|
|
dea394a93d | |
|
|
54ce56564b | |
|
|
ae1d354d4c | |
|
|
20c17d6077 | |
|
|
abb951a889 | |
|
|
72a1585e26 | |
|
|
38c84fbdc6 | |
|
|
d67ff9bf2c | |
|
|
986e5bb9bd | |
|
|
ba05c28bcf | |
|
|
71ff337ee0 | |
|
|
9e2c685870 | |
|
|
75d1872b02 | |
|
|
9cf4b8935f | |
|
|
aa5d2b9fe8 | |
|
|
76b3c381c3 | |
|
|
c923dae619 | |
|
|
7b0902477d | |
|
|
126c4bc8c3 | |
|
|
a9e300d063 | |
|
|
05331eb99d | |
|
|
adbf5b05ec | |
|
|
bf6c66a77b | |
|
|
3fc965e0e7 | |
|
|
7e10d16f6c | |
|
|
d9d63cc09d | |
|
|
dcd6f2252f | |
|
|
7922cabb5b | |
|
|
900de5db80 | |
|
|
bf49b35978 | |
|
|
0df49fcfe8 | |
|
|
fcde715553 | |
|
|
08ca506cfb | |
|
|
b757c5b7b3 | |
|
|
9c927e621d | |
|
|
8ebf1504de | |
|
|
e315357dd2 | |
|
|
7b96954b2f | |
|
|
0c3cac9537 | |
|
|
2a5065420c | |
|
|
3bc161366a | |
|
|
3be95bc577 | |
|
|
8c5d7fd336 | |
|
|
d21284f325 | |
|
|
e7a0f97315 | |
|
|
2b20edeff8 | |
|
|
304da21e6d | |
|
|
8dfa1834e3 | |
|
|
d01f35deeb | |
|
|
a4da433a6d | |
|
|
fbddde13c3 | |
|
|
eb7ef55aab | |
|
|
6c47f48e06 | |
|
|
9e67d8272e | |
|
|
fbe8e6997e | |
|
|
8c912f3906 | |
|
|
8caf674f94 | |
|
|
7d94c9fcb4 | |
|
|
ff878564e4 | |
|
|
da5cca0b90 | |
|
|
e27297311c | |
|
|
5593a7e7e6 | |
|
|
a2a75a7fce | |
|
|
4ca9cb9bab | |
|
|
b743caeb6c | |
|
|
2565627e7e | |
|
|
d4096da4f5 | |
|
|
afb19d8ba6 | |
|
|
e7805c988b | |
|
|
911fb59e56 | |
|
|
080c66d12b | |
|
|
9dc5db7557 | |
|
|
370c047ff8 | |
|
|
7d6cdabc09 | |
|
|
1c235dc7f6 | |
|
|
ff67062c7f | |
|
|
91dd624048 | |
|
|
ce18a9e86d | |
|
|
d2e5bd1e43 | |
|
|
c7c7d40e4d | |
|
|
e0af01d16c | |
|
|
58673fa502 | |
|
|
a1523e3bfd | |
|
|
53fbd6c974 | |
|
|
f8165653b5 | |
|
|
2c31fc9e48 | |
|
|
1e665986a0 | |
|
|
2eec1a116c | |
|
|
fed4f1077d | |
|
|
d76c57a691 | |
|
|
90de1067d8 | |
|
|
51b8bf85aa | |
|
|
d74166f719 | |
|
|
0eeb5b8930 | |
|
|
f2b69c99e6 | |
|
|
f96aeca790 | |
|
|
27283e75c3 | |
|
|
6bc852918e | |
|
|
fd3ffcbd89 | |
|
|
ea23976fde | |
|
|
b46735fd78 | |
|
|
d4b353d8f2 | |
|
|
580ba66114 | |
|
|
77d41b279d | |
|
|
9ce273c359 | |
|
|
36738bca90 | |
|
|
dfd65fbeb8 | |
|
|
49001edac8 | |
|
|
7b4c8f89e1 | |
|
|
b1f4952cde | |
|
|
999cd996fd | |
|
|
55a4bfe70c | |
|
|
bfba5ebbfa | |
|
|
bff44efcb0 | |
|
|
7b36d1f60c | |
|
|
54e05bae60 | |
|
|
50515e1aff | |
|
|
d1b440fc0d | |
|
|
cd3dbd775b | |
|
|
36e59c99f9 | |
|
|
94aafdcf7e | |
|
|
17dd48e51d | |
|
|
1f9b26ae23 | |
|
|
79138d5d2f | |
|
|
65d01c2cee | |
|
|
202bf1ce65 | |
|
|
8a18c46b84 | |
|
|
590fe13004 | |
|
|
74834fd24e | |
|
|
ba55256630 | |
|
|
661db11765 | |
|
|
89c4659911 | |
|
|
c78802481e | |
|
|
30a7806328 | |
|
|
14c278554f | |
|
|
428d718f75 | |
|
|
8076277497 | |
|
|
7d7c052771 | |
|
|
b743bddb46 | |
|
|
8968c9730d | |
|
|
cb2232353a | |
|
|
c480d769a5 | |
|
|
a1df41ddde | |
|
|
b95aadf198 | |
|
|
4d45edbf52 | |
|
|
854b9426b9 | |
|
|
30cb122bdf | |
|
|
e16f3a9af9 | |
|
|
96d8e621e2 | |
|
|
1818af2a08 | |
|
|
efa3dbbd43 | |
|
|
f85b5202dc | |
|
|
f96113d55d | |
|
|
bddb502427 | |
|
|
c17de82c6b | |
|
|
d2930ae84f | |
|
|
9be8716776 | |
|
|
a2d95a8083 | |
|
|
7555e5aef1 | |
|
|
0bad889607 | |
|
|
7662c1eeab | |
|
|
7d6537cc8d | |
|
|
06f2fa25c0 | |
|
|
962ab735b5 | |
|
|
b8d1b54e22 | |
|
|
b90b1704cf | |
|
|
07dc3ee287 | |
|
|
27c0a440d7 | |
|
|
342eda526d | |
|
|
0145494497 | |
|
|
7329cbdceb | |
|
|
8af0afc80d | |
|
|
1f9b001648 | |
|
|
125934592c | |
|
|
d9aa73a7ad | |
|
|
ce9463569f | |
|
|
29127c07d3 | |
|
|
b180a59497 | |
|
|
8483e25250 | |
|
|
a0a12636ef | |
|
|
a2ca643a3a | |
|
|
ff10fe098e | |
|
|
72359f3b01 | |
|
|
2d58091792 | |
|
|
2ad741c4e8 | |
|
|
5d84c7fcb0 | |
|
|
d8883da034 | |
|
|
cdaa3da76a | |
|
|
bbcbf1ce9d | |
|
|
867cd57ae8 | |
|
|
0bf1717b65 | |
|
|
83a96a2327 | |
|
|
ab866e8a34 | |
|
|
5b29b2098b | |
|
|
4675691035 | |
|
|
d92be7b3a3 | |
|
|
99e85093e1 | |
|
|
49a9b3e015 | |
|
|
f48b9ff9b9 | |
|
|
9312fe6dfb | |
|
|
1790fceda9 | |
|
|
25232575e3 |
|
|
@ -0,0 +1 @@
|
||||||
|
custom: http://doc.ruoyi.vip/ruoyi/other/donate.html
|
||||||
|
|
@ -25,6 +25,8 @@ target/
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
|
|
||||||
|
### JRebel ###
|
||||||
|
rebel.xml
|
||||||
### NetBeans ###
|
### NetBeans ###
|
||||||
nbproject/private/
|
nbproject/private/
|
||||||
build/*
|
build/*
|
||||||
|
|
@ -37,6 +39,7 @@ nbdist/
|
||||||
# Others
|
# Others
|
||||||
*.log
|
*.log
|
||||||
*.xml.versionsBackup
|
*.xml.versionsBackup
|
||||||
|
*.swp
|
||||||
|
|
||||||
!*/build/*.java
|
!*/build/*.java
|
||||||
!*/build/*.html
|
!*/build/*.html
|
||||||
|
|
|
||||||
78
README.md
78
README.md
|
|
@ -1,14 +1,26 @@
|
||||||
|
<p align="center">
|
||||||
|
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-dd77653d7c9f197dd9d93684f3c8dcfbab6.png">
|
||||||
|
</p>
|
||||||
|
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.9</h1>
|
||||||
|
<h4 align="center">基于SpringBoot开发的轻量级Java快速开发框架</h4>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://gitee.com/y_project/RuoYi/stargazers"><img src="https://gitee.com/y_project/RuoYi/badge/star.svg?theme=gvp"></a>
|
||||||
|
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.7.9-brightgreen.svg"></a>
|
||||||
|
<a href="https://gitee.com/y_project/RuoYi/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## 平台简介
|
## 平台简介
|
||||||
|
|
||||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
||||||
|
|
||||||
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
|
性别男,若依是给女儿取的名字(寓意:你若不离不弃,我必生死相依)
|
||||||
|
|
||||||
若依基于hplus和inspinia两套后台系统模板开发。有需要可自行到群内下载。
|
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||||
|
|
||||||
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需Oracle版本,请移步 [RuoYi-oracle](http://doc.ruoyi.vip/#/standard/xmkz) `(不定时更新)`
|
* 前后端分离版本,请移步[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
|
||||||
|
* 感谢 [hplus](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。
|
||||||
> 阿里云通用云产品1888优惠券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof) 腾讯云通用云产品2860优惠券 :[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) `(仅限新用户)`
|
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)
|
||||||
|
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
|
|
||||||
|
|
@ -24,57 +36,67 @@
|
||||||
10. 登录日志:系统登录日志记录查询包含登录异常。
|
10. 登录日志:系统登录日志记录查询包含登录异常。
|
||||||
11. 在线用户:当前系统中活跃用户状态监控。
|
11. 在线用户:当前系统中活跃用户状态监控。
|
||||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
||||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
||||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||||
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
16. 缓存监控:对系统的缓存查询,删除、清空等操作。
|
||||||
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
17. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||||
|
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||||
|
|
||||||
## 在线体验
|
## 在线体验
|
||||||
> admin/admin123
|
|
||||||
> 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
- admin/admin123
|
||||||
|
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
||||||
|
|
||||||
演示地址:http://ruoyi.vip
|
演示地址:http://ruoyi.vip
|
||||||
|
|
||||||
文档地址:http://doc.ruoyi.vip
|
文档地址:http://doc.ruoyi.vip
|
||||||
|
|
||||||
## 演示图
|
## 演示图
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/25b5e333768d013d45a990c152dbe4d9d6e.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-42e518aa72a24d228427a1261cb3679f395.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/5ac52ccc07a59f12205948c9408791f5c5b.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-7f20dd0edba25e5187c5c4dd3ec7d3d9797.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/66f8b5b24720dabe0e11ae84bd1ad4b038e.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-2dae3d87f6a8ca05057db059cd9a411d51d.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/a46f34786bc9fc400697b6f3677be5bb3f0.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-ea4d98423471e55fba784694e45d12bd4bb.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/6010201b078dbc9e1d8c09c6a3e53f4344c.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-7f6c6e9f5873efca09bd2870ee8468b8fce.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/058928ad3a6e6de67b43d62d42dbf071355.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-c708b65f2c382a03f69fe1efa8d341e6cff.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/21acdcade5e306f2c5d7ae26993b4e6bd06.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-9ab586c47dd5c7b92bca0d727962c90e3b8.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/ad5ea3c4c2ea2e91d1f05f6cc384cbad2a1.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-ef954122a2080e02013112db21754b955c6.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/6ca845cca1701fbf71881efe4f341c82f99.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-088edb4d531e122415a1e2342bccb1a9691.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/e3aeb8fff585594f6e947218e14f2806ea1.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-f886fe19bd820c0efae82f680223cac196c.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/197ddc2fdffc27020f8624bd7ca1a971f61.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-c7a2eb71fa65d6e660294b4bccca613d638.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/a2dabea752d7d70aede20908dee0b419829.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-e60137fb0787defe613bd83331dc4755a70.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/c5699c5726b5aebde71a37bb5163d840bc2.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-7c51c1b5758f0a0f92ed3c60469b7526f9f.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/24740d59377e826d0d8664ebad66dc84abd.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-15181aed45bb2461aa97b594cbf2f86ea5f.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/bbe7fe1048d29217ba73bd3ed88d6743b55.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-83326ad52ea63f67233d126226738054d98.png"/></td>
|
||||||
<td><img src="https://oscimg.oschina.net/oscnet/5f3d39a141f21f81b90536f391b8408f1fa.jpg"/></td>
|
<td><img src="https://oscimg.oschina.net/oscnet/up-3bd6d31e913b70df00107db51d64ef81df7.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-70a2225836bc82042a6785edf6299e2586a.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-0184d6ab01fdc6667a14327fcaf8b46345d.png"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-64d8086dc2c02c8f71170290482f7640098.png"/></td>
|
||||||
|
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
## 若依交流群
|
## 若依交流群
|
||||||
|
|
||||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) 点击按钮入群。
|
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737)
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 清理生成路径。
|
echo [信息] 清理工程target生成路径。
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
|
%~d0
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
cd..
|
|
||||||
|
|
||||||
|
cd ..
|
||||||
call mvn clean
|
call mvn clean
|
||||||
|
|
||||||
cd bin
|
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 打包工程,生成jar包文件。
|
echo [信息] 打包Web工程,生成war/jar包文件。
|
||||||
echo.
|
|
||||||
pause
|
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
|
%~d0
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
cd..
|
|
||||||
|
|
||||||
|
cd ..
|
||||||
call mvn clean package -Dmaven.test.skip=true
|
call mvn clean package -Dmaven.test.skip=true
|
||||||
|
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
@echo off
|
@echo off
|
||||||
echo.
|
echo.
|
||||||
echo [信息] 运行Web工程。
|
echo [信息] 使用Jar命令运行Web工程。
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
cd %~dp0
|
cd %~dp0
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,12 @@
|
||||||
|
|
||||||
注:如对模板有特殊需求,可自行修改。编辑src/main/ resources/templates/vm目录下
|
注:如对模板有特殊需求,可自行修改。编辑src/main/ resources/templates/vm目录下
|
||||||
|
|
||||||
|
|
||||||
|
3.1.4 日志配置
|
||||||
|
编辑src/main/ resources目录下的logback.yml 文件
|
||||||
|
<property name="log.path" value="/home/ruoyi/logs" />
|
||||||
|
改为自己需要的路径
|
||||||
|
|
||||||
3.2 启动及验证
|
3.2 启动及验证
|
||||||
启动RuoYiApplication.java 出现如下图表示启动成功
|
启动RuoYiApplication.java 出现如下图表示启动成功
|
||||||
|
|
||||||
|
|
@ -48,7 +54,7 @@
|
||||||
若能正确展示登录页面,并能成功登录,登录后菜单及页面展示正常,则表明环境搭建成功。
|
若能正确展示登录页面,并能成功登录,登录后菜单及页面展示正常,则表明环境搭建成功。
|
||||||
默认密码为 admin/admin123
|
默认密码为 admin/admin123
|
||||||
|
|
||||||
演示地址:http://www.ruoyi.club
|
演示地址:http://ruoyi.vip
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
515
pom.xml
515
pom.xml
|
|
@ -1,263 +1,254 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<artifactId>ruoyi</artifactId>
|
<version>4.7.9</version>
|
||||||
<version>3.3</version>
|
|
||||||
|
<name>ruoyi</name>
|
||||||
<name>ruoyi</name>
|
<url>http://www.ruoyi.vip</url>
|
||||||
<url>http://www.ruoyi.vip</url>
|
<description>若依管理系统</description>
|
||||||
<description>若依管理系统</description>
|
|
||||||
|
<properties>
|
||||||
<properties>
|
<ruoyi.version>4.7.9</ruoyi.version>
|
||||||
<ruoyi.version>3.3</ruoyi.version>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<java.version>1.8</java.version>
|
||||||
<java.version>1.8</java.version>
|
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||||
<shiro.version>1.4.0</shiro.version>
|
<shiro.version>1.13.0</shiro.version>
|
||||||
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
|
<spring-framework.version>5.3.33</spring-framework.version>
|
||||||
<mybatis.boot.version>1.3.2</mybatis.boot.version>
|
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version>
|
||||||
<druid.version>1.1.14</druid.version>
|
<druid.version>1.2.23</druid.version>
|
||||||
<bitwalker.version>1.19</bitwalker.version>
|
<bitwalker.version>1.21</bitwalker.version>
|
||||||
<kaptcha.version>2.3.2</kaptcha.version>
|
<kaptcha.version>2.3.3</kaptcha.version>
|
||||||
<swagger.version>2.7.0</swagger.version>
|
<swagger.version>3.0.0</swagger.version>
|
||||||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
|
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
|
||||||
<oshi.version>3.9.1</oshi.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
<commons.io.version>2.5</commons.io.version>
|
<oshi.version>6.6.1</oshi.version>
|
||||||
<commons.fileupload.version>1.3.3</commons.fileupload.version>
|
<commons.io.version>2.13.0</commons.io.version>
|
||||||
<commons.beanutils.version>1.9.3</commons.beanutils.version>
|
<poi.version>4.1.2</poi.version>
|
||||||
<jsoup.version>1.11.3</jsoup.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<poi.version>3.17</poi.version>
|
</properties>
|
||||||
<velocity.version>1.7</velocity.version>
|
|
||||||
</properties>
|
<!-- 依赖声明 -->
|
||||||
|
<dependencyManagement>
|
||||||
<!-- 依赖声明 -->
|
<dependencies>
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
<!-- SpringFramework的依赖配置-->
|
||||||
|
<dependency>
|
||||||
<!-- SpringBoot的依赖配置-->
|
<groupId>org.springframework</groupId>
|
||||||
<dependency>
|
<artifactId>spring-framework-bom</artifactId>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<version>${spring-framework.version}</version>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<type>pom</type>
|
||||||
<version>2.1.1.RELEASE</version>
|
<scope>import</scope>
|
||||||
<type>pom</type>
|
</dependency>
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
<!-- SpringBoot的依赖配置-->
|
||||||
|
<dependency>
|
||||||
<!--阿里数据库连接池 -->
|
<groupId>org.springframework.boot</groupId>
|
||||||
<dependency>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
<groupId>com.alibaba</groupId>
|
<version>2.5.15</version>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<type>pom</type>
|
||||||
<version>${druid.version}</version>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--验证码 -->
|
<!-- 阿里数据库连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.penggle</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>kaptcha</artifactId>
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
<version>${kaptcha.version}</version>
|
<version>${druid.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Shiro核心框架 -->
|
<!-- 验证码 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.shiro</groupId>
|
<groupId>pro.fessional</groupId>
|
||||||
<artifactId>shiro-core</artifactId>
|
<artifactId>kaptcha</artifactId>
|
||||||
<version>${shiro.version}</version>
|
<version>${kaptcha.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Shiro使用Srping框架 -->
|
<!-- Shiro核心框架 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.shiro</groupId>
|
<groupId>org.apache.shiro</groupId>
|
||||||
<artifactId>shiro-spring</artifactId>
|
<artifactId>shiro-core</artifactId>
|
||||||
<version>${shiro.version}</version>
|
<version>${shiro.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Shiro使用EhCache缓存框架 -->
|
<!-- Shiro使用Spring框架 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.shiro</groupId>
|
<groupId>org.apache.shiro</groupId>
|
||||||
<artifactId>shiro-ehcache</artifactId>
|
<artifactId>shiro-spring</artifactId>
|
||||||
<version>${shiro.version}</version>
|
<version>${shiro.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
<!-- Shiro使用EhCache缓存框架 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.theborakompanioni</groupId>
|
<groupId>org.apache.shiro</groupId>
|
||||||
<artifactId>thymeleaf-extras-shiro</artifactId>
|
<artifactId>shiro-ehcache</artifactId>
|
||||||
<version>${thymeleaf.extras.shiro.version}</version>
|
<version>${shiro.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 解析客户端操作系统、浏览器等 -->
|
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>eu.bitwalker</groupId>
|
<groupId>com.github.theborakompanioni</groupId>
|
||||||
<artifactId>UserAgentUtils</artifactId>
|
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||||
<version>${bitwalker.version}</version>
|
<version>${thymeleaf.extras.shiro.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- pagehelper 分页插件 -->
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.pagehelper</groupId>
|
<groupId>eu.bitwalker</groupId>
|
||||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
<artifactId>UserAgentUtils</artifactId>
|
||||||
<version>${pagehelper.boot.version}</version>
|
<version>${bitwalker.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 获取系统信息 -->
|
<!-- pagehelper 分页插件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.oshi</groupId>
|
<groupId>com.github.pagehelper</groupId>
|
||||||
<artifactId>oshi-core</artifactId>
|
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||||
<version>${oshi.version}</version>
|
<version>${pagehelper.boot.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- swagger2-->
|
<!-- 获取系统信息 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>com.github.oshi</groupId>
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
<artifactId>oshi-core</artifactId>
|
||||||
<version>${swagger.version}</version>
|
<version>${oshi.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- swagger2-UI-->
|
<!-- Swagger3依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>io.springfox</groupId>
|
||||||
<artifactId>springfox-swagger-ui</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
<version>${swagger.version}</version>
|
<version>${swagger.version}</version>
|
||||||
</dependency>
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
<!--io常用工具类 -->
|
<groupId>io.swagger</groupId>
|
||||||
<dependency>
|
<artifactId>swagger-models</artifactId>
|
||||||
<groupId>commons-io</groupId>
|
</exclusion>
|
||||||
<artifactId>commons-io</artifactId>
|
</exclusions>
|
||||||
<version>${commons.io.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- io常用工具类 -->
|
||||||
<!--文件上传工具类 -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>commons-io</groupId>
|
||||||
<groupId>commons-fileupload</groupId>
|
<artifactId>commons-io</artifactId>
|
||||||
<artifactId>commons-fileupload</artifactId>
|
<version>${commons.io.version}</version>
|
||||||
<version>${commons.fileupload.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- excel工具 -->
|
||||||
<!-- 简化反射封工具类 -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>org.apache.poi</groupId>
|
||||||
<groupId>commons-beanutils</groupId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
<artifactId>commons-beanutils</artifactId>
|
<version>${poi.version}</version>
|
||||||
<version>${commons.beanutils.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- velocity代码生成使用模板 -->
|
||||||
<!-- HTML解析器 -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>org.apache.velocity</groupId>
|
||||||
<groupId>org.jsoup</groupId>
|
<artifactId>velocity-engine-core</artifactId>
|
||||||
<artifactId>jsoup</artifactId>
|
<version>${velocity.version}</version>
|
||||||
<version>${jsoup.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 阿里JSON解析器 -->
|
||||||
<!-- excel工具 -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.alibaba</groupId>
|
||||||
<groupId>org.apache.poi</groupId>
|
<artifactId>fastjson</artifactId>
|
||||||
<artifactId>poi-ooxml</artifactId>
|
<version>${fastjson.version}</version>
|
||||||
<version>${poi.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 定时任务-->
|
||||||
<!--velocity代码生成使用模板 -->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>org.apache.velocity</groupId>
|
<artifactId>ruoyi-quartz</artifactId>
|
||||||
<artifactId>velocity</artifactId>
|
<version>${ruoyi.version}</version>
|
||||||
<version>${velocity.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 代码生成-->
|
||||||
<!-- 定时任务-->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<artifactId>ruoyi-generator</artifactId>
|
||||||
<artifactId>ruoyi-quartz</artifactId>
|
<version>${ruoyi.version}</version>
|
||||||
<version>${ruoyi.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 核心模块-->
|
||||||
<!-- 代码生成-->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
<artifactId>ruoyi-generator</artifactId>
|
<version>${ruoyi.version}</version>
|
||||||
<version>${ruoyi.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 系统模块-->
|
||||||
<!-- 核心模块-->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<artifactId>ruoyi-system</artifactId>
|
||||||
<artifactId>ruoyi-framework</artifactId>
|
<version>${ruoyi.version}</version>
|
||||||
<version>${ruoyi.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
<!-- 通用工具-->
|
||||||
<!-- 系统模块-->
|
<dependency>
|
||||||
<dependency>
|
<groupId>com.ruoyi</groupId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
<artifactId>ruoyi-system</artifactId>
|
<version>${ruoyi.version}</version>
|
||||||
<version>${ruoyi.version}</version>
|
</dependency>
|
||||||
</dependency>
|
|
||||||
|
</dependencies>
|
||||||
<!-- 通用工具-->
|
</dependencyManagement>
|
||||||
<dependency>
|
|
||||||
<groupId>com.ruoyi</groupId>
|
<modules>
|
||||||
<artifactId>ruoyi-common</artifactId>
|
<module>ruoyi-admin</module>
|
||||||
<version>${ruoyi.version}</version>
|
<module>ruoyi-framework</module>
|
||||||
</dependency>
|
<module>ruoyi-system</module>
|
||||||
|
<module>ruoyi-quartz</module>
|
||||||
</dependencies>
|
<module>ruoyi-generator</module>
|
||||||
</dependencyManagement>
|
<module>ruoyi-common</module>
|
||||||
|
</modules>
|
||||||
<modules>
|
<packaging>pom</packaging>
|
||||||
<module>ruoyi-admin</module>
|
|
||||||
<module>ruoyi-framework</module>
|
|
||||||
<module>ruoyi-system</module>
|
<dependencies>
|
||||||
<module>ruoyi-quartz</module>
|
|
||||||
<module>ruoyi-generator</module>
|
</dependencies>
|
||||||
<module>ruoyi-common</module>
|
|
||||||
</modules>
|
<build>
|
||||||
<packaging>pom</packaging>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<dependencies>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
</dependencies>
|
<target>${java.version}</target>
|
||||||
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
<build>
|
</configuration>
|
||||||
<plugins>
|
</plugin>
|
||||||
<plugin>
|
</plugins>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
</build>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
<repositories>
|
||||||
<source>${java.version}</source>
|
<repository>
|
||||||
<target>${java.version}</target>
|
<id>public</id>
|
||||||
<encoding>${project.build.sourceEncoding}</encoding>
|
<name>aliyun nexus</name>
|
||||||
</configuration>
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
</plugin>
|
<releases>
|
||||||
</plugins>
|
<enabled>true</enabled>
|
||||||
</build>
|
</releases>
|
||||||
|
</repository>
|
||||||
<repositories>
|
</repositories>
|
||||||
<repository>
|
|
||||||
<id>public</id>
|
<pluginRepositories>
|
||||||
<name>aliyun nexus</name>
|
<pluginRepository>
|
||||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
<id>public</id>
|
||||||
<releases>
|
<name>aliyun nexus</name>
|
||||||
<enabled>true</enabled>
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
</releases>
|
<releases>
|
||||||
</repository>
|
<enabled>true</enabled>
|
||||||
</repositories>
|
</releases>
|
||||||
|
<snapshots>
|
||||||
<pluginRepositories>
|
<enabled>false</enabled>
|
||||||
<pluginRepository>
|
</snapshots>
|
||||||
<id>public</id>
|
</pluginRepository>
|
||||||
<name>aliyun nexus</name>
|
</pluginRepositories>
|
||||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
|
||||||
<releases>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</releases>
|
|
||||||
<snapshots>
|
|
||||||
<enabled>false</enabled>
|
|
||||||
</snapshots>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -5,18 +5,18 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>ruoyi</artifactId>
|
<artifactId>ruoyi</artifactId>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<version>3.3</version>
|
<version>4.7.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<artifactId>ruoyi-admin</artifactId>
|
<artifactId>ruoyi-admin</artifactId>
|
||||||
|
|
||||||
<description>
|
<description>
|
||||||
web服务入口
|
web服务入口
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- SpringBoot集成thymeleaf模板 -->
|
<!-- SpringBoot集成thymeleaf模板 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|
@ -24,42 +24,49 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- spring-boot-devtools -->
|
<!-- spring-boot-devtools -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-devtools</artifactId>
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- swagger2-->
|
<!-- swagger3-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>io.springfox</groupId>
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- swagger2-UI-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox</groupId>
|
|
||||||
<artifactId>springfox-swagger-ui</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 核心模块-->
|
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-models</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Mysql驱动包 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 核心模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-framework</artifactId>
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 定时任务-->
|
<!-- 定时任务-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-quartz</artifactId>
|
<artifactId>ruoyi-quartz</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 代码生成-->
|
<!-- 代码生成-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-generator</artifactId>
|
<artifactId>ruoyi-generator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
@ -67,9 +74,10 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>2.5.15</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
|
|
@ -84,11 +92,44 @@
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
<warName>${artifactId}</warName>
|
<warName>${project.artifactId}</warName>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- YUI Compressor (CSS/JS压缩)
|
||||||
|
<plugin>
|
||||||
|
<groupId>net.alchim31.maven</groupId>
|
||||||
|
<artifactId>yuicompressor-maven-plugin</artifactId>
|
||||||
|
<version>1.5.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compress</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<jswarn>false</jswarn>
|
||||||
|
<nosuffix>true</nosuffix>
|
||||||
|
<linebreakpos>50000</linebreakpos>
|
||||||
|
<sourceDirectory>src/main/resources/static</sourceDirectory>
|
||||||
|
<force>true</force>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.js</include>
|
||||||
|
<include>**/*.css</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*.min.js</exclude>
|
||||||
|
<exclude>**/*.min.css</exclude>
|
||||||
|
<exclude>**/fileinput.js</exclude>
|
||||||
|
<exclude>**/validate/**</exclude>
|
||||||
|
<exclude>**/bootstrap-table/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin> -->
|
||||||
</plugins>
|
</plugins>
|
||||||
<finalName>${artifactId}</finalName>
|
<finalName>${project.artifactId}</finalName>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.ruoyi;
|
package com.ruoyi;
|
||||||
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
|
@ -11,7 +10,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||||
@MapperScan("com.ruoyi.*.mapper")
|
|
||||||
public class RuoYiApplication
|
public class RuoYiApplication
|
||||||
{
|
{
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
package com.ruoyi.web.controller.common;
|
package com.ruoyi.web.controller.common;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.util.ArrayList;
|
||||||
import java.net.URLEncoder;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.config.Global;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.config.ServerConfig;
|
import com.ruoyi.common.config.ServerConfig;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||||
|
|
@ -25,40 +28,36 @@ import com.ruoyi.common.utils.file.FileUtils;
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
|
@RequestMapping("/common")
|
||||||
public class CommonController
|
public class CommonController
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传路径
|
|
||||||
*/
|
|
||||||
public static final String UPLOAD_PATH = "/profile/upload/";
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ServerConfig serverConfig;
|
private ServerConfig serverConfig;
|
||||||
|
|
||||||
|
private static final String FILE_DELIMETER = ",";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用下载请求
|
* 通用下载请求
|
||||||
*
|
*
|
||||||
* @param fileName 文件名称
|
* @param fileName 文件名称
|
||||||
* @param delete 是否删除
|
* @param delete 是否删除
|
||||||
*/
|
*/
|
||||||
@GetMapping("common/download")
|
@GetMapping("/download")
|
||||||
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
|
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!FileUtils.isValidFilename(fileName))
|
if (!FileUtils.checkAllowDownload(fileName))
|
||||||
{
|
{
|
||||||
throw new Exception(StringUtils.format(" 文件名称({})非法,不允许下载。 ", fileName));
|
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
|
||||||
}
|
}
|
||||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||||
String filePath = Global.getDownloadPath() + fileName;
|
String filePath = RuoYiConfig.getDownloadPath() + fileName;
|
||||||
|
|
||||||
response.setCharacterEncoding("utf-8");
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||||
response.setContentType("multipart/form-data");
|
FileUtils.setAttachmentResponseHeader(response, realFileName);
|
||||||
response.setHeader("Content-Disposition",
|
|
||||||
"attachment;fileName=" + setFileDownloadHeader(request, realFileName));
|
|
||||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||||
if (delete)
|
if (delete)
|
||||||
{
|
{
|
||||||
|
|
@ -72,22 +71,24 @@ public class CommonController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用上传请求
|
* 通用上传请求(单个)
|
||||||
*/
|
*/
|
||||||
@PostMapping("/common/upload")
|
@PostMapping("/upload")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult uploadFile(MultipartFile file) throws Exception
|
public AjaxResult uploadFile(MultipartFile file) throws Exception
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 上传文件路径
|
// 上传文件路径
|
||||||
String filePath = Global.getUploadPath();
|
String filePath = RuoYiConfig.getUploadPath();
|
||||||
// 上传并返回新文件名称
|
// 上传并返回新文件名称
|
||||||
String fileName = FileUploadUtils.upload(filePath, file);
|
String fileName = FileUploadUtils.upload(filePath, file);
|
||||||
String url = serverConfig.getUrl() + UPLOAD_PATH + fileName;
|
String url = serverConfig.getUrl() + fileName;
|
||||||
AjaxResult ajax = AjaxResult.success();
|
AjaxResult ajax = AjaxResult.success();
|
||||||
ajax.put("fileName", fileName);
|
|
||||||
ajax.put("url", url);
|
ajax.put("url", url);
|
||||||
|
ajax.put("fileName", fileName);
|
||||||
|
ajax.put("newFileName", FileUtils.getName(fileName));
|
||||||
|
ajax.put("originalFilename", file.getOriginalFilename());
|
||||||
return ajax;
|
return ajax;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
@ -96,31 +97,70 @@ public class CommonController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
|
/**
|
||||||
|
* 通用上传请求(多个)
|
||||||
|
*/
|
||||||
|
@PostMapping("/uploads")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
|
||||||
{
|
{
|
||||||
final String agent = request.getHeader("USER-AGENT");
|
try
|
||||||
String filename = fileName;
|
|
||||||
if (agent.contains("MSIE"))
|
|
||||||
{
|
{
|
||||||
// IE浏览器
|
// 上传文件路径
|
||||||
filename = URLEncoder.encode(filename, "utf-8");
|
String filePath = RuoYiConfig.getUploadPath();
|
||||||
filename = filename.replace("+", " ");
|
List<String> urls = new ArrayList<String>();
|
||||||
|
List<String> fileNames = new ArrayList<String>();
|
||||||
|
List<String> newFileNames = new ArrayList<String>();
|
||||||
|
List<String> originalFilenames = new ArrayList<String>();
|
||||||
|
for (MultipartFile file : files)
|
||||||
|
{
|
||||||
|
// 上传并返回新文件名称
|
||||||
|
String fileName = FileUploadUtils.upload(filePath, file);
|
||||||
|
String url = serverConfig.getUrl() + fileName;
|
||||||
|
urls.add(url);
|
||||||
|
fileNames.add(fileName);
|
||||||
|
newFileNames.add(FileUtils.getName(fileName));
|
||||||
|
originalFilenames.add(file.getOriginalFilename());
|
||||||
|
}
|
||||||
|
AjaxResult ajax = AjaxResult.success();
|
||||||
|
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
|
||||||
|
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
|
||||||
|
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
|
||||||
|
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
|
||||||
|
return ajax;
|
||||||
}
|
}
|
||||||
else if (agent.contains("Firefox"))
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// 火狐浏览器
|
return AjaxResult.error(e.getMessage());
|
||||||
filename = new String(fileName.getBytes(), "ISO8859-1");
|
|
||||||
}
|
}
|
||||||
else if (agent.contains("Chrome"))
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地资源通用下载
|
||||||
|
*/
|
||||||
|
@GetMapping("/download/resource")
|
||||||
|
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// google浏览器
|
if (!FileUtils.checkAllowDownload(resource))
|
||||||
filename = URLEncoder.encode(filename, "utf-8");
|
{
|
||||||
|
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
|
||||||
|
}
|
||||||
|
// 本地资源路径
|
||||||
|
String localPath = RuoYiConfig.getProfile();
|
||||||
|
// 数据库资源地址
|
||||||
|
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
|
||||||
|
// 下载名称
|
||||||
|
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
|
||||||
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||||
|
FileUtils.setAttachmentResponseHeader(response, downloadName);
|
||||||
|
FileUtils.writeBytes(downloadPath, response.getOutputStream());
|
||||||
}
|
}
|
||||||
else
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// 其它浏览器
|
log.error("下载文件失败", e);
|
||||||
filename = URLEncoder.encode(filename, "utf-8");
|
|
||||||
}
|
}
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.ruoyi.web.controller.demo.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模态窗口
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/demo/modal")
|
||||||
|
public class DemoDialogController
|
||||||
|
{
|
||||||
|
private String prefix = "demo/modal";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模态窗口
|
||||||
|
*/
|
||||||
|
@GetMapping("/dialog")
|
||||||
|
public String dialog()
|
||||||
|
{
|
||||||
|
return prefix + "/dialog";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹层组件
|
||||||
|
*/
|
||||||
|
@GetMapping("/layer")
|
||||||
|
public String layer()
|
||||||
|
{
|
||||||
|
return prefix + "/layer";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单
|
||||||
|
*/
|
||||||
|
@GetMapping("/form")
|
||||||
|
public String form()
|
||||||
|
{
|
||||||
|
return prefix + "/form";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
@GetMapping("/table")
|
||||||
|
public String table()
|
||||||
|
{
|
||||||
|
return prefix + "/table";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格check
|
||||||
|
*/
|
||||||
|
@GetMapping("/check")
|
||||||
|
public String check()
|
||||||
|
{
|
||||||
|
return prefix + "/table/check";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格radio
|
||||||
|
*/
|
||||||
|
@GetMapping("/radio")
|
||||||
|
public String radio()
|
||||||
|
{
|
||||||
|
return prefix + "/table/radio";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格回传父窗体
|
||||||
|
*/
|
||||||
|
@GetMapping("/parent")
|
||||||
|
public String parent()
|
||||||
|
{
|
||||||
|
return prefix + "/table/parent";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多层窗口frame1
|
||||||
|
*/
|
||||||
|
@GetMapping("/frame1")
|
||||||
|
public String frame1()
|
||||||
|
{
|
||||||
|
return prefix + "/table/frame1";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多层窗口frame2
|
||||||
|
*/
|
||||||
|
@GetMapping("/frame2")
|
||||||
|
public String frame2()
|
||||||
|
{
|
||||||
|
return prefix + "/table/frame2";
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.ruoyi.web.controller.demo.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图标相关
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/demo/icon")
|
||||||
|
public class DemoIconController
|
||||||
|
{
|
||||||
|
private String prefix = "demo/icon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FontAwesome图标
|
||||||
|
*/
|
||||||
|
@GetMapping("/fontawesome")
|
||||||
|
public String fontAwesome()
|
||||||
|
{
|
||||||
|
return prefix + "/fontawesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Glyphicons图标
|
||||||
|
*/
|
||||||
|
@GetMapping("/glyphicons")
|
||||||
|
public String glyphicons()
|
||||||
|
{
|
||||||
|
return prefix + "/glyphicons";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,326 @@
|
||||||
|
package com.ruoyi.web.controller.demo.controller;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.PageDomain;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.page.TableSupport;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.web.controller.demo.domain.CustomerModel;
|
||||||
|
import com.ruoyi.web.controller.demo.domain.UserOperateModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作控制
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/demo/operate")
|
||||||
|
public class DemoOperateController extends BaseController
|
||||||
|
{
|
||||||
|
private String prefix = "demo/operate";
|
||||||
|
|
||||||
|
private final static Map<Integer, UserOperateModel> users = new LinkedHashMap<Integer, UserOperateModel>();
|
||||||
|
{
|
||||||
|
users.put(1, new UserOperateModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0"));
|
||||||
|
users.put(2, new UserOperateModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||||
|
users.put(3, new UserOperateModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||||
|
users.put(4, new UserOperateModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||||
|
users.put(5, new UserOperateModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1"));
|
||||||
|
users.put(6, new UserOperateModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1"));
|
||||||
|
users.put(7, new UserOperateModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||||
|
users.put(8, new UserOperateModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1"));
|
||||||
|
users.put(9, new UserOperateModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1"));
|
||||||
|
users.put(10, new UserOperateModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||||
|
users.put(11, new UserOperateModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1"));
|
||||||
|
users.put(12, new UserOperateModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||||
|
users.put(13, new UserOperateModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1"));
|
||||||
|
users.put(14, new UserOperateModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1"));
|
||||||
|
users.put(15, new UserOperateModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||||
|
users.put(16, new UserOperateModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1"));
|
||||||
|
users.put(17, new UserOperateModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1"));
|
||||||
|
users.put(18, new UserOperateModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1"));
|
||||||
|
users.put(19, new UserOperateModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1"));
|
||||||
|
users.put(20, new UserOperateModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1"));
|
||||||
|
users.put(21, new UserOperateModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1"));
|
||||||
|
users.put(22, new UserOperateModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1"));
|
||||||
|
users.put(23, new UserOperateModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1"));
|
||||||
|
users.put(24, new UserOperateModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1"));
|
||||||
|
users.put(25, new UserOperateModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||||
|
users.put(26, new UserOperateModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
@GetMapping("/table")
|
||||||
|
public String table()
|
||||||
|
{
|
||||||
|
return prefix + "/table";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他
|
||||||
|
*/
|
||||||
|
@GetMapping("/other")
|
||||||
|
public String other()
|
||||||
|
{
|
||||||
|
return prefix + "/other";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询数据
|
||||||
|
*/
|
||||||
|
@PostMapping("/list")
|
||||||
|
@ResponseBody
|
||||||
|
public TableDataInfo list(UserOperateModel userModel)
|
||||||
|
{
|
||||||
|
TableDataInfo rspData = new TableDataInfo();
|
||||||
|
List<UserOperateModel> userList = new ArrayList<UserOperateModel>(users.values());
|
||||||
|
// 查询条件过滤
|
||||||
|
if (StringUtils.isNotEmpty(userModel.getSearchValue()))
|
||||||
|
{
|
||||||
|
userList.clear();
|
||||||
|
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue().getUserName().equals(userModel.getSearchValue()))
|
||||||
|
{
|
||||||
|
userList.add(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(userModel.getUserName()))
|
||||||
|
{
|
||||||
|
userList.clear();
|
||||||
|
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue().getUserName().equals(userModel.getUserName()))
|
||||||
|
{
|
||||||
|
userList.add(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||||
|
if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize())
|
||||||
|
{
|
||||||
|
rspData.setRows(userList);
|
||||||
|
rspData.setTotal(userList.size());
|
||||||
|
return rspData;
|
||||||
|
}
|
||||||
|
Integer pageNum = (pageDomain.getPageNum() - 1) * 10;
|
||||||
|
Integer pageSize = pageDomain.getPageNum() * 10;
|
||||||
|
if (pageSize > userList.size())
|
||||||
|
{
|
||||||
|
pageSize = userList.size();
|
||||||
|
}
|
||||||
|
rspData.setRows(userList.subList(pageNum, pageSize));
|
||||||
|
rspData.setTotal(userList.size());
|
||||||
|
return rspData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增用户
|
||||||
|
*/
|
||||||
|
@GetMapping("/add")
|
||||||
|
public String add(ModelMap mmap)
|
||||||
|
{
|
||||||
|
return prefix + "/add";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增保存用户
|
||||||
|
*/
|
||||||
|
@PostMapping("/add")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult addSave(UserOperateModel user)
|
||||||
|
{
|
||||||
|
Integer userId = users.size() + 1;
|
||||||
|
user.setUserId(userId);
|
||||||
|
return AjaxResult.success(users.put(userId, user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增保存主子表信息
|
||||||
|
*/
|
||||||
|
@PostMapping("/customer/add")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult addSave(CustomerModel customerModel)
|
||||||
|
{
|
||||||
|
System.out.println(customerModel.toString());
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户
|
||||||
|
*/
|
||||||
|
@GetMapping("/edit/{userId}")
|
||||||
|
public String edit(@PathVariable("userId") Integer userId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("user", users.get(userId));
|
||||||
|
return prefix + "/edit";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改保存用户
|
||||||
|
*/
|
||||||
|
@PostMapping("/edit")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult editSave(UserOperateModel user)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(users.put(user.getUserId(), user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出
|
||||||
|
*/
|
||||||
|
@PostMapping("/export")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult export(UserOperateModel user)
|
||||||
|
{
|
||||||
|
List<UserOperateModel> list = new ArrayList<UserOperateModel>(users.values());
|
||||||
|
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||||
|
return util.exportExcel(list, "用户数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载模板
|
||||||
|
*/
|
||||||
|
@GetMapping("/importTemplate")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult importTemplate()
|
||||||
|
{
|
||||||
|
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||||
|
return util.importTemplateExcel("用户数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入数据
|
||||||
|
*/
|
||||||
|
@PostMapping("/importData")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
|
||||||
|
{
|
||||||
|
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class);
|
||||||
|
List<UserOperateModel> userList = util.importExcel(file.getInputStream());
|
||||||
|
String message = importUser(userList, updateSupport);
|
||||||
|
return AjaxResult.success(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户
|
||||||
|
*/
|
||||||
|
@PostMapping("/remove")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult remove(String ids)
|
||||||
|
{
|
||||||
|
Integer[] userIds = Convert.toIntArray(ids);
|
||||||
|
for (Integer userId : userIds)
|
||||||
|
{
|
||||||
|
users.remove(userId);
|
||||||
|
}
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看详细
|
||||||
|
*/
|
||||||
|
@GetMapping("/detail/{userId}")
|
||||||
|
public String detail(@PathVariable("userId") Integer userId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("user", users.get(userId));
|
||||||
|
return prefix + "/detail";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/clean")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult clean()
|
||||||
|
{
|
||||||
|
users.clear();
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入用户数据
|
||||||
|
*
|
||||||
|
* @param userList 用户数据列表
|
||||||
|
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public String importUser(List<UserOperateModel> userList, Boolean isUpdateSupport)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNull(userList) || userList.size() == 0)
|
||||||
|
{
|
||||||
|
throw new ServiceException("导入用户数据不能为空!");
|
||||||
|
}
|
||||||
|
int successNum = 0;
|
||||||
|
int failureNum = 0;
|
||||||
|
StringBuilder successMsg = new StringBuilder();
|
||||||
|
StringBuilder failureMsg = new StringBuilder();
|
||||||
|
for (UserOperateModel user : userList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 验证是否存在这个用户
|
||||||
|
boolean userFlag = false;
|
||||||
|
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet())
|
||||||
|
{
|
||||||
|
if (entry.getValue().getUserName().equals(user.getUserName()))
|
||||||
|
{
|
||||||
|
userFlag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!userFlag)
|
||||||
|
{
|
||||||
|
Integer userId = users.size() + 1;
|
||||||
|
user.setUserId(userId);
|
||||||
|
users.put(userId, user);
|
||||||
|
successNum++;
|
||||||
|
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 导入成功");
|
||||||
|
}
|
||||||
|
else if (isUpdateSupport)
|
||||||
|
{
|
||||||
|
users.put(user.getUserId(), user);
|
||||||
|
successNum++;
|
||||||
|
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 更新成功");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
failureNum++;
|
||||||
|
failureMsg.append("<br/>" + failureNum + "、用户 " + user.getUserName() + " 已存在");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
failureNum++;
|
||||||
|
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
|
||||||
|
failureMsg.append(msg + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failureNum > 0)
|
||||||
|
{
|
||||||
|
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||||
|
throw new ServiceException(failureMsg.toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
|
||||||
|
}
|
||||||
|
return successMsg.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.ruoyi.web.controller.demo.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报表
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/demo/report")
|
||||||
|
public class DemoReportController
|
||||||
|
{
|
||||||
|
private String prefix = "demo/report";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百度ECharts
|
||||||
|
*/
|
||||||
|
@GetMapping("/echarts")
|
||||||
|
public String echarts()
|
||||||
|
{
|
||||||
|
return prefix + "/echarts";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图表插件
|
||||||
|
*/
|
||||||
|
@GetMapping("/peity")
|
||||||
|
public String peity()
|
||||||
|
{
|
||||||
|
return prefix + "/peity";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线状图插件
|
||||||
|
*/
|
||||||
|
@GetMapping("/sparkline")
|
||||||
|
public String sparkline()
|
||||||
|
{
|
||||||
|
return prefix + "/sparkline";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图表组合
|
||||||
|
*/
|
||||||
|
@GetMapping("/metrics")
|
||||||
|
public String metrics()
|
||||||
|
{
|
||||||
|
return prefix + "/metrics";
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,116 @@
|
||||||
|
package com.ruoyi.web.controller.demo.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户测试信息
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class CustomerModel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 客户姓名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户手机
|
||||||
|
*/
|
||||||
|
private String phonenumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户性别
|
||||||
|
*/
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户生日
|
||||||
|
*/
|
||||||
|
private String birthday;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户描述
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品信息
|
||||||
|
*/
|
||||||
|
private List<GoodsModel> goods;
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhonenumber()
|
||||||
|
{
|
||||||
|
return phonenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhonenumber(String phonenumber)
|
||||||
|
{
|
||||||
|
this.phonenumber = phonenumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getSex()
|
||||||
|
{
|
||||||
|
return sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSex(String sex)
|
||||||
|
{
|
||||||
|
this.sex = sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBirthday()
|
||||||
|
{
|
||||||
|
return birthday;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBirthday(String birthday)
|
||||||
|
{
|
||||||
|
this.birthday = birthday;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark()
|
||||||
|
{
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark)
|
||||||
|
{
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GoodsModel> getGoods()
|
||||||
|
{
|
||||||
|
return goods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoods(List<GoodsModel> goods)
|
||||||
|
{
|
||||||
|
this.goods = goods;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("name", getName())
|
||||||
|
.append("phonenumber", getPhonenumber())
|
||||||
|
.append("sex", getSex())
|
||||||
|
.append("birthday", getBirthday())
|
||||||
|
.append("goods", getGoods())
|
||||||
|
.append("remark", getRemark())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.ruoyi.web.controller.demo.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品测试信息
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class GoodsModel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 商品名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品重量
|
||||||
|
*/
|
||||||
|
private Integer weight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品价格
|
||||||
|
*/
|
||||||
|
private Double price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品日期
|
||||||
|
*/
|
||||||
|
private Date date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品种类
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getWeight()
|
||||||
|
{
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeight(Integer weight)
|
||||||
|
{
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getPrice()
|
||||||
|
{
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrice(Double price)
|
||||||
|
{
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate()
|
||||||
|
{
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date)
|
||||||
|
{
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("name", getName())
|
||||||
|
.append("weight", getWeight())
|
||||||
|
.append("price", getPrice())
|
||||||
|
.append("date", getDate())
|
||||||
|
.append("type", getType())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.ruoyi.web.controller.demo.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import com.ruoyi.common.annotation.Excel;
|
||||||
|
import com.ruoyi.common.annotation.Excel.Type;
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
|
||||||
|
public class UserOperateModel extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private int userId;
|
||||||
|
|
||||||
|
@Excel(name = "用户编号")
|
||||||
|
private String userCode;
|
||||||
|
|
||||||
|
@Excel(name = "用户姓名")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
|
||||||
|
private String userSex;
|
||||||
|
|
||||||
|
@Excel(name = "用户手机")
|
||||||
|
private String userPhone;
|
||||||
|
|
||||||
|
@Excel(name = "用户邮箱")
|
||||||
|
private String userEmail;
|
||||||
|
|
||||||
|
@Excel(name = "用户余额")
|
||||||
|
private double userBalance;
|
||||||
|
|
||||||
|
@Excel(name = "用户状态", readConverterExp = "0=正常,1=停用")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
public UserOperateModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserOperateModel(int userId, String userCode, String userName, String userSex, String userPhone,
|
||||||
|
String userEmail, double userBalance, String status)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
this.userCode = userCode;
|
||||||
|
this.userName = userName;
|
||||||
|
this.userSex = userSex;
|
||||||
|
this.userPhone = userPhone;
|
||||||
|
this.userEmail = userEmail;
|
||||||
|
this.userBalance = userBalance;
|
||||||
|
this.status = status;
|
||||||
|
this.createTime = DateUtils.getNowDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserId()
|
||||||
|
{
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(int userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserCode()
|
||||||
|
{
|
||||||
|
return userCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserCode(String userCode)
|
||||||
|
{
|
||||||
|
this.userCode = userCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName()
|
||||||
|
{
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserName(String userName)
|
||||||
|
{
|
||||||
|
this.userName = userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserSex()
|
||||||
|
{
|
||||||
|
return userSex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSex(String userSex)
|
||||||
|
{
|
||||||
|
this.userSex = userSex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserPhone()
|
||||||
|
{
|
||||||
|
return userPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserPhone(String userPhone)
|
||||||
|
{
|
||||||
|
this.userPhone = userPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserEmail()
|
||||||
|
{
|
||||||
|
return userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserEmail(String userEmail)
|
||||||
|
{
|
||||||
|
this.userEmail = userEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUserBalance()
|
||||||
|
{
|
||||||
|
return userBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserBalance(double userBalance)
|
||||||
|
{
|
||||||
|
this.userBalance = userBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus()
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status)
|
||||||
|
{
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getCreateTime()
|
||||||
|
{
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCreateTime(Date createTime)
|
||||||
|
{
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.framework.web.service.CacheService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存监控
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/monitor/cache")
|
||||||
|
public class CacheController extends BaseController
|
||||||
|
{
|
||||||
|
private String prefix = "monitor/cache";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CacheService cacheService;
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@GetMapping()
|
||||||
|
public String cache(ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("cacheNames", cacheService.getCacheNames());
|
||||||
|
return prefix + "/cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@PostMapping("/getNames")
|
||||||
|
public String getCacheNames(String fragment, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("cacheNames", cacheService.getCacheNames());
|
||||||
|
return prefix + "/cache::" + fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@PostMapping("/getKeys")
|
||||||
|
public String getCacheKeys(String fragment, String cacheName, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("cacheName", cacheName);
|
||||||
|
mmap.put("cacheKeys", cacheService.getCacheKeys(cacheName));
|
||||||
|
return prefix + "/cache::" + fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@PostMapping("/getValue")
|
||||||
|
public String getCacheValue(String fragment, String cacheName, String cacheKey, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("cacheName", cacheName);
|
||||||
|
mmap.put("cacheKey", cacheKey);
|
||||||
|
mmap.put("cacheValue", cacheService.getCacheValue(cacheName, cacheKey));
|
||||||
|
return prefix + "/cache::" + fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@PostMapping("/clearCacheName")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult clearCacheName(String cacheName, ModelMap mmap)
|
||||||
|
{
|
||||||
|
cacheService.clearCacheName(cacheName);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@PostMapping("/clearCacheKey")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult clearCacheKey(String cacheName, String cacheKey, ModelMap mmap)
|
||||||
|
{
|
||||||
|
cacheService.clearCacheKey(cacheName, cacheKey);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:cache:view")
|
||||||
|
@GetMapping("/clearAll")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult clearAll(ModelMap mmap)
|
||||||
|
{
|
||||||
|
cacheService.clearAll();
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,12 +15,12 @@ import com.ruoyi.common.core.controller.BaseController;
|
||||||
@RequestMapping("/monitor/data")
|
@RequestMapping("/monitor/data")
|
||||||
public class DruidController extends BaseController
|
public class DruidController extends BaseController
|
||||||
{
|
{
|
||||||
private String prefix = "/monitor/druid";
|
private String prefix = "/druid";
|
||||||
|
|
||||||
@RequiresPermissions("monitor:data:view")
|
@RequiresPermissions("monitor:data:view")
|
||||||
@GetMapping()
|
@GetMapping()
|
||||||
public String index()
|
public String index()
|
||||||
{
|
{
|
||||||
return redirect(prefix + "/index");
|
return redirect(prefix + "/index.html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.ruoyi.web.controller.monitor;
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
|
@ -31,6 +32,9 @@ public class SysLogininforController extends BaseController
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysLogininforService logininforService;
|
private ISysLogininforService logininforService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysPasswordService passwordService;
|
||||||
|
|
||||||
@RequiresPermissions("monitor:logininfor:view")
|
@RequiresPermissions("monitor:logininfor:view")
|
||||||
@GetMapping()
|
@GetMapping()
|
||||||
public String logininfor()
|
public String logininfor()
|
||||||
|
|
@ -48,7 +52,7 @@ public class SysLogininforController extends BaseController
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log(title = "登陆日志", businessType = BusinessType.EXPORT)
|
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
|
||||||
@RequiresPermissions("monitor:logininfor:export")
|
@RequiresPermissions("monitor:logininfor:export")
|
||||||
@PostMapping("/export")
|
@PostMapping("/export")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
|
|
@ -56,11 +60,11 @@ public class SysLogininforController extends BaseController
|
||||||
{
|
{
|
||||||
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
|
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
|
||||||
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
|
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
|
||||||
return util.exportExcel(list, "登陆日志");
|
return util.exportExcel(list, "登录日志");
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("monitor:logininfor:remove")
|
@RequiresPermissions("monitor:logininfor:remove")
|
||||||
@Log(title = "登陆日志", businessType = BusinessType.DELETE)
|
@Log(title = "登录日志", businessType = BusinessType.DELETE)
|
||||||
@PostMapping("/remove")
|
@PostMapping("/remove")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
|
|
@ -69,7 +73,7 @@ public class SysLogininforController extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("monitor:logininfor:remove")
|
@RequiresPermissions("monitor:logininfor:remove")
|
||||||
@Log(title = "登陆日志", businessType = BusinessType.CLEAN)
|
@Log(title = "登录日志", businessType = BusinessType.CLEAN)
|
||||||
@PostMapping("/clean")
|
@PostMapping("/clean")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult clean()
|
public AjaxResult clean()
|
||||||
|
|
@ -77,4 +81,14 @@ public class SysLogininforController extends BaseController
|
||||||
logininforService.cleanLogininfor();
|
logininforService.cleanLogininfor();
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("monitor:logininfor:unlock")
|
||||||
|
@Log(title = "账户解锁", businessType = BusinessType.OTHER)
|
||||||
|
@PostMapping("/unlock")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult unlock(String loginName)
|
||||||
|
{
|
||||||
|
passwordService.clearLoginRecordCache(loginName);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ public class SysOperlogController extends BaseController
|
||||||
return util.exportExcel(list, "操作日志");
|
return util.exportExcel(list, "操作日志");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Log(title = "操作日志", businessType = BusinessType.DELETE)
|
||||||
@RequiresPermissions("monitor:operlog:remove")
|
@RequiresPermissions("monitor:operlog:remove")
|
||||||
@PostMapping("/remove")
|
@PostMapping("/remove")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
package com.ruoyi.web.controller.monitor;
|
package com.ruoyi.web.controller.monitor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.enums.OnlineStatus;
|
import com.ruoyi.common.enums.OnlineStatus;
|
||||||
|
import com.ruoyi.common.utils.ShiroUtils;
|
||||||
import com.ruoyi.framework.shiro.session.OnlineSession;
|
import com.ruoyi.framework.shiro.session.OnlineSession;
|
||||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysUserOnline;
|
import com.ruoyi.system.domain.SysUserOnline;
|
||||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||||
|
|
||||||
|
|
@ -55,13 +56,13 @@ public class SysUserOnlineController extends BaseController
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("monitor:online:batchForceLogout")
|
@RequiresPermissions(value = { "monitor:online:batchForceLogout", "monitor:online:forceLogout" }, logical = Logical.OR)
|
||||||
@Log(title = "在线用户", businessType = BusinessType.FORCE)
|
@Log(title = "在线用户", businessType = BusinessType.FORCE)
|
||||||
@PostMapping("/batchForceLogout")
|
@PostMapping("/batchForceLogout")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult batchForceLogout(@RequestParam("ids[]") String[] ids)
|
public AjaxResult batchForceLogout(String ids)
|
||||||
{
|
{
|
||||||
for (String sessionId : ids)
|
for (String sessionId : Convert.toStrArray(ids))
|
||||||
{
|
{
|
||||||
SysUserOnline online = userOnlineService.selectOnlineById(sessionId);
|
SysUserOnline online = userOnlineService.selectOnlineById(sessionId);
|
||||||
if (online == null)
|
if (online == null)
|
||||||
|
|
@ -75,40 +76,13 @@ public class SysUserOnlineController extends BaseController
|
||||||
}
|
}
|
||||||
if (sessionId.equals(ShiroUtils.getSessionId()))
|
if (sessionId.equals(ShiroUtils.getSessionId()))
|
||||||
{
|
{
|
||||||
return error("当前登陆用户无法强退");
|
return error("当前登录用户无法强退");
|
||||||
}
|
}
|
||||||
onlineSession.setStatus(OnlineStatus.off_line);
|
onlineSessionDAO.delete(onlineSession);
|
||||||
onlineSessionDAO.update(onlineSession);
|
|
||||||
online.setStatus(OnlineStatus.off_line);
|
online.setStatus(OnlineStatus.off_line);
|
||||||
userOnlineService.saveOnline(online);
|
userOnlineService.saveOnline(online);
|
||||||
|
userOnlineService.removeUserCache(online.getLoginName(), sessionId);
|
||||||
}
|
}
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("monitor:online:forceLogout")
|
|
||||||
@Log(title = "在线用户", businessType = BusinessType.FORCE)
|
|
||||||
@PostMapping("/forceLogout")
|
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult forceLogout(String sessionId)
|
|
||||||
{
|
|
||||||
SysUserOnline online = userOnlineService.selectOnlineById(sessionId);
|
|
||||||
if (sessionId.equals(ShiroUtils.getSessionId()))
|
|
||||||
{
|
|
||||||
return error("当前登陆用户无法强退");
|
|
||||||
}
|
|
||||||
if (online == null)
|
|
||||||
{
|
|
||||||
return error("用户已下线");
|
|
||||||
}
|
|
||||||
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
|
|
||||||
if (onlineSession == null)
|
|
||||||
{
|
|
||||||
return error("用户已下线");
|
|
||||||
}
|
|
||||||
onlineSession.setStatus(OnlineStatus.off_line);
|
|
||||||
onlineSessionDAO.update(onlineSession);
|
|
||||||
online.setStatus(OnlineStatus.off_line);
|
|
||||||
userOnlineService.saveOnline(online);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -16,7 +17,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysConfig;
|
import com.ruoyi.system.domain.SysConfig;
|
||||||
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
|
|
||||||
|
|
@ -81,15 +81,20 @@ public class SysConfigController extends BaseController
|
||||||
@Log(title = "参数管理", businessType = BusinessType.INSERT)
|
@Log(title = "参数管理", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysConfig config)
|
public AjaxResult addSave(@Validated SysConfig config)
|
||||||
{
|
{
|
||||||
config.setCreateBy(ShiroUtils.getLoginName());
|
if (!configService.checkConfigKeyUnique(config))
|
||||||
|
{
|
||||||
|
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||||
|
}
|
||||||
|
config.setCreateBy(getLoginName());
|
||||||
return toAjax(configService.insertConfig(config));
|
return toAjax(configService.insertConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改参数配置
|
* 修改参数配置
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:config:edit")
|
||||||
@GetMapping("/edit/{configId}")
|
@GetMapping("/edit/{configId}")
|
||||||
public String edit(@PathVariable("configId") Long configId, ModelMap mmap)
|
public String edit(@PathVariable("configId") Long configId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -104,9 +109,13 @@ public class SysConfigController extends BaseController
|
||||||
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
|
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysConfig config)
|
public AjaxResult editSave(@Validated SysConfig config)
|
||||||
{
|
{
|
||||||
config.setUpdateBy(ShiroUtils.getLoginName());
|
if (!configService.checkConfigKeyUnique(config))
|
||||||
|
{
|
||||||
|
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
|
||||||
|
}
|
||||||
|
config.setUpdateBy(getLoginName());
|
||||||
return toAjax(configService.updateConfig(config));
|
return toAjax(configService.updateConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,7 +128,21 @@ public class SysConfigController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
{
|
{
|
||||||
return toAjax(configService.deleteConfigByIds(ids));
|
configService.deleteConfigByIds(ids);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新参数缓存
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:config:remove")
|
||||||
|
@Log(title = "参数管理", businessType = BusinessType.CLEAN)
|
||||||
|
@GetMapping("/refreshCache")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult refreshCache()
|
||||||
|
{
|
||||||
|
configService.resetConfigCache();
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -127,7 +150,7 @@ public class SysConfigController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkConfigKeyUnique")
|
@PostMapping("/checkConfigKeyUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkConfigKeyUnique(SysConfig config)
|
public boolean checkConfigKeyUnique(SysConfig config)
|
||||||
{
|
{
|
||||||
return configService.checkConfigKeyUnique(config);
|
return configService.checkConfigKeyUnique(config);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,20 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.Ztree;
|
import com.ruoyi.common.core.domain.Ztree;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysDept;
|
|
||||||
import com.ruoyi.system.domain.SysRole;
|
|
||||||
import com.ruoyi.system.service.ISysDeptService;
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,7 +43,7 @@ public class SysDeptController extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("system:dept:list")
|
@RequiresPermissions("system:dept:list")
|
||||||
@GetMapping("/list")
|
@PostMapping("/list")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<SysDept> list(SysDept dept)
|
public List<SysDept> list(SysDept dept)
|
||||||
{
|
{
|
||||||
|
|
@ -57,6 +57,10 @@ public class SysDeptController extends BaseController
|
||||||
@GetMapping("/add/{parentId}")
|
@GetMapping("/add/{parentId}")
|
||||||
public String add(@PathVariable("parentId") Long parentId, ModelMap mmap)
|
public String add(@PathVariable("parentId") Long parentId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
if (!getSysUser().isAdmin())
|
||||||
|
{
|
||||||
|
parentId = getSysUser().getDeptId();
|
||||||
|
}
|
||||||
mmap.put("dept", deptService.selectDeptById(parentId));
|
mmap.put("dept", deptService.selectDeptById(parentId));
|
||||||
return prefix + "/add";
|
return prefix + "/add";
|
||||||
}
|
}
|
||||||
|
|
@ -68,18 +72,24 @@ public class SysDeptController extends BaseController
|
||||||
@RequiresPermissions("system:dept:add")
|
@RequiresPermissions("system:dept:add")
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysDept dept)
|
public AjaxResult addSave(@Validated SysDept dept)
|
||||||
{
|
{
|
||||||
dept.setCreateBy(ShiroUtils.getLoginName());
|
if (!deptService.checkDeptNameUnique(dept))
|
||||||
|
{
|
||||||
|
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||||
|
}
|
||||||
|
dept.setCreateBy(getLoginName());
|
||||||
return toAjax(deptService.insertDept(dept));
|
return toAjax(deptService.insertDept(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改
|
* 修改部门
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:dept:edit")
|
||||||
@GetMapping("/edit/{deptId}")
|
@GetMapping("/edit/{deptId}")
|
||||||
public String edit(@PathVariable("deptId") Long deptId, ModelMap mmap)
|
public String edit(@PathVariable("deptId") Long deptId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
deptService.checkDeptDataScope(deptId);
|
||||||
SysDept dept = deptService.selectDeptById(deptId);
|
SysDept dept = deptService.selectDeptById(deptId);
|
||||||
if (StringUtils.isNotNull(dept) && 100L == deptId)
|
if (StringUtils.isNotNull(dept) && 100L == deptId)
|
||||||
{
|
{
|
||||||
|
|
@ -90,15 +100,29 @@ public class SysDeptController extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存
|
* 修改保存部门
|
||||||
*/
|
*/
|
||||||
@Log(title = "部门管理", businessType = BusinessType.UPDATE)
|
@Log(title = "部门管理", businessType = BusinessType.UPDATE)
|
||||||
@RequiresPermissions("system:dept:edit")
|
@RequiresPermissions("system:dept:edit")
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysDept dept)
|
public AjaxResult editSave(@Validated SysDept dept)
|
||||||
{
|
{
|
||||||
dept.setUpdateBy(ShiroUtils.getLoginName());
|
Long deptId = dept.getDeptId();
|
||||||
|
deptService.checkDeptDataScope(deptId);
|
||||||
|
if (!deptService.checkDeptNameUnique(dept))
|
||||||
|
{
|
||||||
|
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
|
||||||
|
}
|
||||||
|
else if (dept.getParentId().equals(deptId))
|
||||||
|
{
|
||||||
|
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
|
||||||
|
}
|
||||||
|
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
|
||||||
|
{
|
||||||
|
return AjaxResult.error("该部门包含未停用的子部门!");
|
||||||
|
}
|
||||||
|
dept.setUpdateBy(getLoginName());
|
||||||
return toAjax(deptService.updateDept(dept));
|
return toAjax(deptService.updateDept(dept));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,6 +143,7 @@ public class SysDeptController extends BaseController
|
||||||
{
|
{
|
||||||
return AjaxResult.warn("部门存在用户,不允许删除");
|
return AjaxResult.warn("部门存在用户,不允许删除");
|
||||||
}
|
}
|
||||||
|
deptService.checkDeptDataScope(deptId);
|
||||||
return toAjax(deptService.deleteDeptById(deptId));
|
return toAjax(deptService.deleteDeptById(deptId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,40 +152,36 @@ public class SysDeptController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkDeptNameUnique")
|
@PostMapping("/checkDeptNameUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkDeptNameUnique(SysDept dept)
|
public boolean checkDeptNameUnique(SysDept dept)
|
||||||
{
|
{
|
||||||
return deptService.checkDeptNameUnique(dept);
|
return deptService.checkDeptNameUnique(dept);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 选择部门树
|
* 选择部门树
|
||||||
|
*
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param excludeId 排除ID
|
||||||
*/
|
*/
|
||||||
@GetMapping("/selectDeptTree/{deptId}")
|
@GetMapping(value = { "/selectDeptTree/{deptId}", "/selectDeptTree/{deptId}/{excludeId}" })
|
||||||
public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap)
|
public String selectDeptTree(@PathVariable("deptId") Long deptId,
|
||||||
|
@PathVariable(value = "excludeId", required = false) Long excludeId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
mmap.put("dept", deptService.selectDeptById(deptId));
|
mmap.put("dept", deptService.selectDeptById(deptId));
|
||||||
|
mmap.put("excludeId", excludeId);
|
||||||
return prefix + "/tree";
|
return prefix + "/tree";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载部门列表树
|
* 加载部门列表树(排除下级)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/treeData")
|
@GetMapping("/treeData/{excludeId}")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Ztree> treeData()
|
public List<Ztree> treeDataExcludeChild(@PathVariable(value = "excludeId", required = false) Long excludeId)
|
||||||
{
|
{
|
||||||
List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
|
SysDept dept = new SysDept();
|
||||||
return ztrees;
|
dept.setExcludeId(excludeId);
|
||||||
}
|
List<Ztree> ztrees = deptService.selectDeptTreeExcludeChild(dept);
|
||||||
|
|
||||||
/**
|
|
||||||
* 加载角色部门(数据权限)列表树
|
|
||||||
*/
|
|
||||||
@GetMapping("/roleDeptTreeData")
|
|
||||||
@ResponseBody
|
|
||||||
public List<Ztree> deptTreeData(SysRole role)
|
|
||||||
{
|
|
||||||
List<Ztree> ztrees = deptService.roleDeptTreeData(role);
|
|
||||||
return ztrees;
|
return ztrees;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -13,11 +14,10 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysDictData;
|
|
||||||
import com.ruoyi.system.service.ISysDictDataService;
|
import com.ruoyi.system.service.ISysDictDataService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -79,15 +79,16 @@ public class SysDictDataController extends BaseController
|
||||||
@RequiresPermissions("system:dict:add")
|
@RequiresPermissions("system:dict:add")
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysDictData dict)
|
public AjaxResult addSave(@Validated SysDictData dict)
|
||||||
{
|
{
|
||||||
dict.setCreateBy(ShiroUtils.getLoginName());
|
dict.setCreateBy(getLoginName());
|
||||||
return toAjax(dictDataService.insertDictData(dict));
|
return toAjax(dictDataService.insertDictData(dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改字典类型
|
* 修改字典类型
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:dict:edit")
|
||||||
@GetMapping("/edit/{dictCode}")
|
@GetMapping("/edit/{dictCode}")
|
||||||
public String edit(@PathVariable("dictCode") Long dictCode, ModelMap mmap)
|
public String edit(@PathVariable("dictCode") Long dictCode, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -102,9 +103,9 @@ public class SysDictDataController extends BaseController
|
||||||
@RequiresPermissions("system:dict:edit")
|
@RequiresPermissions("system:dict:edit")
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysDictData dict)
|
public AjaxResult editSave(@Validated SysDictData dict)
|
||||||
{
|
{
|
||||||
dict.setUpdateBy(ShiroUtils.getLoginName());
|
dict.setUpdateBy(getLoginName());
|
||||||
return toAjax(dictDataService.updateDictData(dict));
|
return toAjax(dictDataService.updateDictData(dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,6 +115,7 @@ public class SysDictDataController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
{
|
{
|
||||||
return toAjax(dictDataService.deleteDictDataByIds(ids));
|
dictDataService.deleteDictDataByIds(ids);
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -13,11 +14,11 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.Ztree;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysDictType;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysDictType;
|
|
||||||
import com.ruoyi.system.service.ISysDictTypeService;
|
import com.ruoyi.system.service.ISysDictTypeService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -79,15 +80,20 @@ public class SysDictTypeController extends BaseController
|
||||||
@RequiresPermissions("system:dict:add")
|
@RequiresPermissions("system:dict:add")
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysDictType dict)
|
public AjaxResult addSave(@Validated SysDictType dict)
|
||||||
{
|
{
|
||||||
dict.setCreateBy(ShiroUtils.getLoginName());
|
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||||
|
{
|
||||||
|
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||||
|
}
|
||||||
|
dict.setCreateBy(getLoginName());
|
||||||
return toAjax(dictTypeService.insertDictType(dict));
|
return toAjax(dictTypeService.insertDictType(dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改字典类型
|
* 修改字典类型
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:dict:edit")
|
||||||
@GetMapping("/edit/{dictId}")
|
@GetMapping("/edit/{dictId}")
|
||||||
public String edit(@PathVariable("dictId") Long dictId, ModelMap mmap)
|
public String edit(@PathVariable("dictId") Long dictId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -102,9 +108,13 @@ public class SysDictTypeController extends BaseController
|
||||||
@RequiresPermissions("system:dict:edit")
|
@RequiresPermissions("system:dict:edit")
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysDictType dict)
|
public AjaxResult editSave(@Validated SysDictType dict)
|
||||||
{
|
{
|
||||||
dict.setUpdateBy(ShiroUtils.getLoginName());
|
if (!dictTypeService.checkDictTypeUnique(dict))
|
||||||
|
{
|
||||||
|
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
|
||||||
|
}
|
||||||
|
dict.setUpdateBy(getLoginName());
|
||||||
return toAjax(dictTypeService.updateDictType(dict));
|
return toAjax(dictTypeService.updateDictType(dict));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,14 +124,21 @@ public class SysDictTypeController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
{
|
{
|
||||||
try
|
dictTypeService.deleteDictTypeByIds(ids);
|
||||||
{
|
return success();
|
||||||
return toAjax(dictTypeService.deleteDictTypeByIds(ids));
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
/**
|
||||||
{
|
* 刷新字典缓存
|
||||||
return error(e.getMessage());
|
*/
|
||||||
}
|
@RequiresPermissions("system:dict:remove")
|
||||||
|
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
|
||||||
|
@GetMapping("/refreshCache")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult refreshCache()
|
||||||
|
{
|
||||||
|
dictTypeService.resetDictCache();
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -141,8 +158,31 @@ public class SysDictTypeController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkDictTypeUnique")
|
@PostMapping("/checkDictTypeUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkDictTypeUnique(SysDictType dictType)
|
public boolean checkDictTypeUnique(SysDictType dictType)
|
||||||
{
|
{
|
||||||
return dictTypeService.checkDictTypeUnique(dictType);
|
return dictTypeService.checkDictTypeUnique(dictType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择字典树
|
||||||
|
*/
|
||||||
|
@GetMapping("/selectDictTree/{columnId}/{dictType}")
|
||||||
|
public String selectDeptTree(@PathVariable("columnId") Long columnId, @PathVariable("dictType") String dictType,
|
||||||
|
ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("columnId", columnId);
|
||||||
|
mmap.put("dict", dictTypeService.selectDictTypeByType(dictType));
|
||||||
|
return prefix + "/tree";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载字典列表树
|
||||||
|
*/
|
||||||
|
@GetMapping("/treeData")
|
||||||
|
@ResponseBody
|
||||||
|
public List<Ztree> treeData()
|
||||||
|
{
|
||||||
|
List<Ztree> ztrees = dictTypeService.selectDictTree(new SysDictType());
|
||||||
|
return ztrees;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,29 @@
|
||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import com.ruoyi.common.config.Global;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.constant.ShiroConstants;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.system.domain.SysMenu;
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
import com.ruoyi.system.domain.SysUser;
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
|
import com.ruoyi.common.utils.CookieUtils;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||||
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,25 +37,142 @@ public class SysIndexController extends BaseController
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysMenuService menuService;
|
private ISysMenuService menuService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysPasswordService passwordService;
|
||||||
|
|
||||||
// 系统首页
|
// 系统首页
|
||||||
@GetMapping("/index")
|
@GetMapping("/index")
|
||||||
public String index(ModelMap mmap)
|
public String index(ModelMap mmap)
|
||||||
{
|
{
|
||||||
// 取身份信息
|
// 取身份信息
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
// 根据用户id取出菜单
|
// 根据用户id取出菜单
|
||||||
List<SysMenu> menus = menuService.selectMenusByUser(user);
|
List<SysMenu> menus = menuService.selectMenusByUser(user);
|
||||||
mmap.put("menus", menus);
|
mmap.put("menus", menus);
|
||||||
mmap.put("user", user);
|
mmap.put("user", user);
|
||||||
mmap.put("copyrightYear", Global.getCopyrightYear());
|
mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
|
||||||
return "index";
|
mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
|
||||||
|
Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true);
|
||||||
|
Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true);
|
||||||
|
mmap.put("footer", footer);
|
||||||
|
mmap.put("tagsView", tagsView);
|
||||||
|
mmap.put("mainClass", contentMainClass(footer, tagsView));
|
||||||
|
mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear());
|
||||||
|
mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled());
|
||||||
|
mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
|
||||||
|
mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
|
||||||
|
mmap.put("isMobile", ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")));
|
||||||
|
|
||||||
|
// 菜单导航显示风格
|
||||||
|
String menuStyle = configService.selectConfigByKey("sys.index.menuStyle");
|
||||||
|
// 移动端,默认使左侧导航菜单,否则取默认配置
|
||||||
|
String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle;
|
||||||
|
|
||||||
|
// 优先Cookie配置导航菜单
|
||||||
|
Cookie[] cookies = ServletUtils.getRequest().getCookies();
|
||||||
|
for (Cookie cookie : cookies)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName()))
|
||||||
|
{
|
||||||
|
indexStyle = cookie.getValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index";
|
||||||
|
return webIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 锁定屏幕
|
||||||
|
@GetMapping("/lockscreen")
|
||||||
|
public String lockscreen(ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("user", getSysUser());
|
||||||
|
ServletUtils.getSession().setAttribute(ShiroConstants.LOCK_SCREEN, true);
|
||||||
|
return "lock";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解锁屏幕
|
||||||
|
@PostMapping("/unlockscreen")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult unlockscreen(String password)
|
||||||
|
{
|
||||||
|
SysUser user = getSysUser();
|
||||||
|
if (StringUtils.isNull(user))
|
||||||
|
{
|
||||||
|
return AjaxResult.error("服务器超时,请重新登录");
|
||||||
|
}
|
||||||
|
if (passwordService.matches(user, password))
|
||||||
|
{
|
||||||
|
ServletUtils.getSession().removeAttribute(ShiroConstants.LOCK_SCREEN);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
return AjaxResult.error("密码不正确,请重新输入。");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换主题
|
||||||
|
@GetMapping("/system/switchSkin")
|
||||||
|
public String switchSkin()
|
||||||
|
{
|
||||||
|
return "skin";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换菜单
|
||||||
|
@GetMapping("/system/menuStyle/{style}")
|
||||||
|
public void menuStyle(@PathVariable String style, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
CookieUtils.setCookie(response, "nav-style", style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 系统介绍
|
// 系统介绍
|
||||||
@GetMapping("/system/main")
|
@GetMapping("/system/main")
|
||||||
public String main(ModelMap mmap)
|
public String main(ModelMap mmap)
|
||||||
{
|
{
|
||||||
mmap.put("version", Global.getVersion());
|
mmap.put("version", RuoYiConfig.getVersion());
|
||||||
return "main";
|
return "main";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// content-main class
|
||||||
|
public String contentMainClass(Boolean footer, Boolean tagsView)
|
||||||
|
{
|
||||||
|
if (!footer && !tagsView)
|
||||||
|
{
|
||||||
|
return "tagsview-footer-hide";
|
||||||
|
}
|
||||||
|
else if (!footer)
|
||||||
|
{
|
||||||
|
return "footer-hide";
|
||||||
|
}
|
||||||
|
else if (!tagsView)
|
||||||
|
{
|
||||||
|
return "tagsview-hide";
|
||||||
|
}
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查初始密码是否提醒修改
|
||||||
|
public boolean initPasswordIsModify(Date pwdUpdateDate)
|
||||||
|
{
|
||||||
|
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
|
||||||
|
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查密码是否过期
|
||||||
|
public boolean passwordIsExpiration(Date pwdUpdateDate)
|
||||||
|
{
|
||||||
|
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
|
||||||
|
if (passwordValidateDays != null && passwordValidateDays > 0)
|
||||||
|
{
|
||||||
|
if (StringUtils.isNull(pwdUpdateDate))
|
||||||
|
{
|
||||||
|
// 如果从未修改过初始密码,直接提醒过期
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Date nowDate = DateUtils.getNowDate();
|
||||||
|
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,82 @@
|
||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
import org.apache.shiro.subject.Subject;
|
import org.apache.shiro.subject.Subject;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.ui.ModelMap;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
/**
|
import com.ruoyi.common.core.text.Convert;
|
||||||
* 登录验证
|
import com.ruoyi.common.utils.ServletUtils;
|
||||||
*
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
* @author ruoyi
|
import com.ruoyi.framework.web.service.ConfigService;
|
||||||
*/
|
|
||||||
@Controller
|
/**
|
||||||
public class SysLoginController extends BaseController
|
* 登录验证
|
||||||
{
|
*
|
||||||
@GetMapping("/login")
|
* @author ruoyi
|
||||||
public String login(HttpServletRequest request, HttpServletResponse response)
|
*/
|
||||||
{
|
@Controller
|
||||||
// 如果是Ajax请求,返回Json字符串。
|
public class SysLoginController extends BaseController
|
||||||
if (ServletUtils.isAjaxRequest(request))
|
{
|
||||||
{
|
/**
|
||||||
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
|
* 是否开启记住我功能
|
||||||
}
|
*/
|
||||||
|
@Value("${shiro.rememberMe.enabled: false}")
|
||||||
return "login";
|
private boolean rememberMe;
|
||||||
}
|
|
||||||
|
@Autowired
|
||||||
@PostMapping("/login")
|
private ConfigService configService;
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
@GetMapping("/login")
|
||||||
{
|
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
|
||||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
{
|
||||||
Subject subject = SecurityUtils.getSubject();
|
// 如果是Ajax请求,返回Json字符串。
|
||||||
try
|
if (ServletUtils.isAjaxRequest(request))
|
||||||
{
|
{
|
||||||
subject.login(token);
|
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
|
||||||
return success();
|
}
|
||||||
}
|
// 是否开启记住我
|
||||||
catch (AuthenticationException e)
|
mmap.put("isRemembered", rememberMe);
|
||||||
{
|
// 是否开启用户注册
|
||||||
String msg = "用户或密码错误";
|
mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false));
|
||||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
return "login";
|
||||||
{
|
}
|
||||||
msg = e.getMessage();
|
|
||||||
}
|
@PostMapping("/login")
|
||||||
return error(msg);
|
@ResponseBody
|
||||||
}
|
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
||||||
}
|
{
|
||||||
|
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
||||||
@GetMapping("/unauth")
|
Subject subject = SecurityUtils.getSubject();
|
||||||
public String unauth()
|
try
|
||||||
{
|
{
|
||||||
return "/error/unauth";
|
subject.login(token);
|
||||||
}
|
return success();
|
||||||
}
|
}
|
||||||
|
catch (AuthenticationException e)
|
||||||
|
{
|
||||||
|
String msg = "用户或密码错误";
|
||||||
|
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||||
|
{
|
||||||
|
msg = e.getMessage();
|
||||||
|
}
|
||||||
|
return error(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/unauth")
|
||||||
|
public String unauth()
|
||||||
|
{
|
||||||
|
return "error/unauth";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -14,10 +15,11 @@ import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.Ztree;
|
import com.ruoyi.common.core.domain.Ztree;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
import com.ruoyi.common.utils.ShiroUtils;
|
||||||
import com.ruoyi.system.domain.SysMenu;
|
import com.ruoyi.framework.shiro.util.AuthorizationUtils;
|
||||||
import com.ruoyi.system.domain.SysRole;
|
|
||||||
import com.ruoyi.system.service.ISysMenuService;
|
import com.ruoyi.system.service.ISysMenuService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,11 +44,12 @@ public class SysMenuController extends BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("system:menu:list")
|
@RequiresPermissions("system:menu:list")
|
||||||
@GetMapping("/list")
|
@PostMapping("/list")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<SysMenu> list(SysMenu menu)
|
public List<SysMenu> list(SysMenu menu)
|
||||||
{
|
{
|
||||||
List<SysMenu> menuList = menuService.selectMenuList(menu);
|
Long userId = ShiroUtils.getUserId();
|
||||||
|
List<SysMenu> menuList = menuService.selectMenuList(menu, userId);
|
||||||
return menuList;
|
return menuList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +70,7 @@ public class SysMenuController extends BaseController
|
||||||
{
|
{
|
||||||
return AjaxResult.warn("菜单已分配,不允许删除");
|
return AjaxResult.warn("菜单已分配,不允许删除");
|
||||||
}
|
}
|
||||||
ShiroUtils.clearCachedAuthorizationInfo();
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(menuService.deleteMenuById(menuId));
|
return toAjax(menuService.deleteMenuById(menuId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,16 +102,21 @@ public class SysMenuController extends BaseController
|
||||||
@RequiresPermissions("system:menu:add")
|
@RequiresPermissions("system:menu:add")
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysMenu menu)
|
public AjaxResult addSave(@Validated SysMenu menu)
|
||||||
{
|
{
|
||||||
menu.setCreateBy(ShiroUtils.getLoginName());
|
if (!menuService.checkMenuNameUnique(menu))
|
||||||
ShiroUtils.clearCachedAuthorizationInfo();
|
{
|
||||||
|
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||||
|
}
|
||||||
|
menu.setCreateBy(getLoginName());
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(menuService.insertMenu(menu));
|
return toAjax(menuService.insertMenu(menu));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改菜单
|
* 修改菜单
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:menu:edit")
|
||||||
@GetMapping("/edit/{menuId}")
|
@GetMapping("/edit/{menuId}")
|
||||||
public String edit(@PathVariable("menuId") Long menuId, ModelMap mmap)
|
public String edit(@PathVariable("menuId") Long menuId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -123,10 +131,14 @@ public class SysMenuController extends BaseController
|
||||||
@RequiresPermissions("system:menu:edit")
|
@RequiresPermissions("system:menu:edit")
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysMenu menu)
|
public AjaxResult editSave(@Validated SysMenu menu)
|
||||||
{
|
{
|
||||||
menu.setUpdateBy(ShiroUtils.getLoginName());
|
if (!menuService.checkMenuNameUnique(menu))
|
||||||
ShiroUtils.clearCachedAuthorizationInfo();
|
{
|
||||||
|
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||||
|
}
|
||||||
|
menu.setUpdateBy(getLoginName());
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(menuService.updateMenu(menu));
|
return toAjax(menuService.updateMenu(menu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +156,7 @@ public class SysMenuController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkMenuNameUnique")
|
@PostMapping("/checkMenuNameUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkMenuNameUnique(SysMenu menu)
|
public boolean checkMenuNameUnique(SysMenu menu)
|
||||||
{
|
{
|
||||||
return menuService.checkMenuNameUnique(menu);
|
return menuService.checkMenuNameUnique(menu);
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +168,8 @@ public class SysMenuController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Ztree> roleMenuTreeData(SysRole role)
|
public List<Ztree> roleMenuTreeData(SysRole role)
|
||||||
{
|
{
|
||||||
List<Ztree> ztrees = menuService.roleMenuTreeData(role);
|
Long userId = ShiroUtils.getUserId();
|
||||||
|
List<Ztree> ztrees = menuService.roleMenuTreeData(role, userId);
|
||||||
return ztrees;
|
return ztrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,9 +178,10 @@ public class SysMenuController extends BaseController
|
||||||
*/
|
*/
|
||||||
@GetMapping("/menuTreeData")
|
@GetMapping("/menuTreeData")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Ztree> menuTreeData(SysRole role)
|
public List<Ztree> menuTreeData()
|
||||||
{
|
{
|
||||||
List<Ztree> ztrees = menuService.menuTreeData();
|
Long userId = ShiroUtils.getUserId();
|
||||||
|
List<Ztree> ztrees = menuService.menuTreeData(userId);
|
||||||
return ztrees;
|
return ztrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -15,7 +16,6 @@ import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysNotice;
|
import com.ruoyi.system.domain.SysNotice;
|
||||||
import com.ruoyi.system.service.ISysNoticeService;
|
import com.ruoyi.system.service.ISysNoticeService;
|
||||||
|
|
||||||
|
|
@ -69,15 +69,16 @@ public class SysNoticeController extends BaseController
|
||||||
@Log(title = "通知公告", businessType = BusinessType.INSERT)
|
@Log(title = "通知公告", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysNotice notice)
|
public AjaxResult addSave(@Validated SysNotice notice)
|
||||||
{
|
{
|
||||||
notice.setCreateBy(ShiroUtils.getLoginName());
|
notice.setCreateBy(getLoginName());
|
||||||
return toAjax(noticeService.insertNotice(notice));
|
return toAjax(noticeService.insertNotice(notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改公告
|
* 修改公告
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:notice:edit")
|
||||||
@GetMapping("/edit/{noticeId}")
|
@GetMapping("/edit/{noticeId}")
|
||||||
public String edit(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
|
public String edit(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -92,12 +93,23 @@ public class SysNoticeController extends BaseController
|
||||||
@Log(title = "通知公告", businessType = BusinessType.UPDATE)
|
@Log(title = "通知公告", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysNotice notice)
|
public AjaxResult editSave(@Validated SysNotice notice)
|
||||||
{
|
{
|
||||||
notice.setUpdateBy(ShiroUtils.getLoginName());
|
notice.setUpdateBy(getLoginName());
|
||||||
return toAjax(noticeService.updateNotice(notice));
|
return toAjax(noticeService.updateNotice(notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询公告详细
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:notice:list")
|
||||||
|
@GetMapping("/view/{noticeId}")
|
||||||
|
public String view(@PathVariable("noticeId") Long noticeId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("notice", noticeService.selectNoticeById(noticeId));
|
||||||
|
return prefix + "/view";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除公告
|
* 删除公告
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -16,7 +17,6 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysPost;
|
import com.ruoyi.system.domain.SysPost;
|
||||||
import com.ruoyi.system.service.ISysPostService;
|
import com.ruoyi.system.service.ISysPostService;
|
||||||
|
|
||||||
|
|
@ -94,15 +94,24 @@ public class SysPostController extends BaseController
|
||||||
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
|
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysPost post)
|
public AjaxResult addSave(@Validated SysPost post)
|
||||||
{
|
{
|
||||||
post.setCreateBy(ShiroUtils.getLoginName());
|
if (!postService.checkPostNameUnique(post))
|
||||||
|
{
|
||||||
|
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||||
|
}
|
||||||
|
else if (!postService.checkPostCodeUnique(post))
|
||||||
|
{
|
||||||
|
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||||
|
}
|
||||||
|
post.setCreateBy(getLoginName());
|
||||||
return toAjax(postService.insertPost(post));
|
return toAjax(postService.insertPost(post));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改岗位
|
* 修改岗位
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:post:edit")
|
||||||
@GetMapping("/edit/{postId}")
|
@GetMapping("/edit/{postId}")
|
||||||
public String edit(@PathVariable("postId") Long postId, ModelMap mmap)
|
public String edit(@PathVariable("postId") Long postId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -117,9 +126,17 @@ public class SysPostController extends BaseController
|
||||||
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
|
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysPost post)
|
public AjaxResult editSave(@Validated SysPost post)
|
||||||
{
|
{
|
||||||
post.setUpdateBy(ShiroUtils.getLoginName());
|
if (!postService.checkPostNameUnique(post))
|
||||||
|
{
|
||||||
|
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
|
||||||
|
}
|
||||||
|
else if (!postService.checkPostCodeUnique(post))
|
||||||
|
{
|
||||||
|
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
|
||||||
|
}
|
||||||
|
post.setUpdateBy(getLoginName());
|
||||||
return toAjax(postService.updatePost(post));
|
return toAjax(postService.updatePost(post));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +145,7 @@ public class SysPostController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkPostNameUnique")
|
@PostMapping("/checkPostNameUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkPostNameUnique(SysPost post)
|
public boolean checkPostNameUnique(SysPost post)
|
||||||
{
|
{
|
||||||
return postService.checkPostNameUnique(post);
|
return postService.checkPostNameUnique(post);
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +155,7 @@ public class SysPostController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkPostCodeUnique")
|
@PostMapping("/checkPostCodeUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkPostCodeUnique(SysPost post)
|
public boolean checkPostCodeUnique(SysPost post)
|
||||||
{
|
{
|
||||||
return postService.checkPostCodeUnique(post);
|
return postService.checkPostCodeUnique(post);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,17 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.config.Global;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.ShiroUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||||
|
import com.ruoyi.common.utils.file.MimeTypeUtils;
|
||||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
|
||||||
import com.ruoyi.system.domain.SysUser;
|
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -48,7 +50,7 @@ public class SysProfileController extends BaseController
|
||||||
@GetMapping()
|
@GetMapping()
|
||||||
public String profile(ModelMap mmap)
|
public String profile(ModelMap mmap)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
mmap.put("user", user);
|
mmap.put("user", user);
|
||||||
mmap.put("roleGroup", userService.selectUserRoleGroup(user.getUserId()));
|
mmap.put("roleGroup", userService.selectUserRoleGroup(user.getUserId()));
|
||||||
mmap.put("postGroup", userService.selectUserPostGroup(user.getUserId()));
|
mmap.put("postGroup", userService.selectUserPostGroup(user.getUserId()));
|
||||||
|
|
@ -59,18 +61,14 @@ public class SysProfileController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public boolean checkPassword(String password)
|
public boolean checkPassword(String password)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
if (passwordService.matches(user, password))
|
return passwordService.matches(user, password);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/resetPwd")
|
@GetMapping("/resetPwd")
|
||||||
public String resetPwd(ModelMap mmap)
|
public String resetPwd(ModelMap mmap)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||||
return prefix + "/resetPwd";
|
return prefix + "/resetPwd";
|
||||||
}
|
}
|
||||||
|
|
@ -80,22 +78,24 @@ public class SysProfileController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult resetPwd(String oldPassword, String newPassword)
|
public AjaxResult resetPwd(String oldPassword, String newPassword)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
if (StringUtils.isNotEmpty(newPassword) && passwordService.matches(user, oldPassword))
|
if (!passwordService.matches(user, oldPassword))
|
||||||
{
|
|
||||||
user.setSalt(ShiroUtils.randomSalt());
|
|
||||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
|
||||||
if (userService.resetUserPwd(user) > 0)
|
|
||||||
{
|
|
||||||
ShiroUtils.setSysUser(userService.selectUserById(user.getUserId()));
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
return error();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return error("修改密码失败,旧密码错误");
|
return error("修改密码失败,旧密码错误");
|
||||||
}
|
}
|
||||||
|
if (passwordService.matches(user, newPassword))
|
||||||
|
{
|
||||||
|
return error("新密码不能与旧密码相同");
|
||||||
|
}
|
||||||
|
user.setSalt(ShiroUtils.randomSalt());
|
||||||
|
user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||||
|
user.setPwdUpdateDate(DateUtils.getNowDate());
|
||||||
|
if (userService.resetUserPwd(user) > 0)
|
||||||
|
{
|
||||||
|
setSysUser(userService.selectUserById(user.getUserId()));
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
return error("修改密码异常,请联系管理员");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -104,7 +104,7 @@ public class SysProfileController extends BaseController
|
||||||
@GetMapping("/edit")
|
@GetMapping("/edit")
|
||||||
public String edit(ModelMap mmap)
|
public String edit(ModelMap mmap)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||||
return prefix + "/edit";
|
return prefix + "/edit";
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ public class SysProfileController extends BaseController
|
||||||
@GetMapping("/avatar")
|
@GetMapping("/avatar")
|
||||||
public String avatar(ModelMap mmap)
|
public String avatar(ModelMap mmap)
|
||||||
{
|
{
|
||||||
SysUser user = ShiroUtils.getSysUser();
|
SysUser user = getSysUser();
|
||||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||||
return prefix + "/avatar";
|
return prefix + "/avatar";
|
||||||
}
|
}
|
||||||
|
|
@ -128,14 +128,22 @@ public class SysProfileController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult update(SysUser user)
|
public AjaxResult update(SysUser user)
|
||||||
{
|
{
|
||||||
SysUser currentUser = ShiroUtils.getSysUser();
|
SysUser currentUser = getSysUser();
|
||||||
currentUser.setUserName(user.getUserName());
|
currentUser.setUserName(user.getUserName());
|
||||||
currentUser.setEmail(user.getEmail());
|
currentUser.setEmail(user.getEmail());
|
||||||
currentUser.setPhonenumber(user.getPhonenumber());
|
currentUser.setPhonenumber(user.getPhonenumber());
|
||||||
currentUser.setSex(user.getSex());
|
currentUser.setSex(user.getSex());
|
||||||
|
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
|
||||||
|
{
|
||||||
|
return error("修改用户'" + currentUser.getLoginName() + "'失败,手机号码已存在");
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
|
||||||
|
{
|
||||||
|
return error("修改用户'" + currentUser.getLoginName() + "'失败,邮箱账号已存在");
|
||||||
|
}
|
||||||
if (userService.updateUserInfo(currentUser) > 0)
|
if (userService.updateUserInfo(currentUser) > 0)
|
||||||
{
|
{
|
||||||
ShiroUtils.setSysUser(userService.selectUserById(currentUser.getUserId()));
|
setSysUser(userService.selectUserById(currentUser.getUserId()));
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
return error();
|
return error();
|
||||||
|
|
@ -149,16 +157,16 @@ public class SysProfileController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult updateAvatar(@RequestParam("avatarfile") MultipartFile file)
|
public AjaxResult updateAvatar(@RequestParam("avatarfile") MultipartFile file)
|
||||||
{
|
{
|
||||||
SysUser currentUser = ShiroUtils.getSysUser();
|
SysUser currentUser = getSysUser();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!file.isEmpty())
|
if (!file.isEmpty())
|
||||||
{
|
{
|
||||||
String avatar = FileUploadUtils.upload(Global.getAvatarPath(), file);
|
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
|
||||||
currentUser.setAvatar(avatar);
|
currentUser.setAvatar(avatar);
|
||||||
if (userService.updateUserInfo(currentUser) > 0)
|
if (userService.updateUserInfo(currentUser) > 0)
|
||||||
{
|
{
|
||||||
ShiroUtils.setSysUser(userService.selectUserById(currentUser.getUserId()));
|
setSysUser(userService.selectUserById(currentUser.getUserId()));
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.shiro.service.SysRegisterService;
|
||||||
|
import com.ruoyi.system.service.ISysConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册验证
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class SysRegisterController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private SysRegisterService registerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysConfigService configService;
|
||||||
|
|
||||||
|
@GetMapping("/register")
|
||||||
|
public String register()
|
||||||
|
{
|
||||||
|
return "register";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult ajaxRegister(SysUser user)
|
||||||
|
{
|
||||||
|
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
|
||||||
|
{
|
||||||
|
return error("当前系统没有开启注册功能!");
|
||||||
|
}
|
||||||
|
String msg = registerService.register(user);
|
||||||
|
return StringUtils.isEmpty(msg) ? success() : error(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -13,13 +14,15 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.Ztree;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
import com.ruoyi.framework.shiro.util.AuthorizationUtils;
|
||||||
import com.ruoyi.system.domain.SysRole;
|
|
||||||
import com.ruoyi.system.domain.SysUser;
|
|
||||||
import com.ruoyi.system.domain.SysUserRole;
|
import com.ruoyi.system.domain.SysUserRole;
|
||||||
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
||||||
|
|
@ -40,6 +43,9 @@ public class SysRoleController extends BaseController
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysUserService userService;
|
private ISysUserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysDeptService deptService;
|
||||||
|
|
||||||
@RequiresPermissions("system:role:view")
|
@RequiresPermissions("system:role:view")
|
||||||
@GetMapping()
|
@GetMapping()
|
||||||
public String role()
|
public String role()
|
||||||
|
|
@ -84,10 +90,18 @@ public class SysRoleController extends BaseController
|
||||||
@Log(title = "角色管理", businessType = BusinessType.INSERT)
|
@Log(title = "角色管理", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysRole role)
|
public AjaxResult addSave(@Validated SysRole role)
|
||||||
{
|
{
|
||||||
role.setCreateBy(ShiroUtils.getLoginName());
|
if (!roleService.checkRoleNameUnique(role))
|
||||||
ShiroUtils.clearCachedAuthorizationInfo();
|
{
|
||||||
|
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||||
|
}
|
||||||
|
else if (!roleService.checkRoleKeyUnique(role))
|
||||||
|
{
|
||||||
|
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||||
|
}
|
||||||
|
role.setCreateBy(getLoginName());
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(roleService.insertRole(role));
|
return toAjax(roleService.insertRole(role));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -95,9 +109,11 @@ public class SysRoleController extends BaseController
|
||||||
/**
|
/**
|
||||||
* 修改角色
|
* 修改角色
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:role:edit")
|
||||||
@GetMapping("/edit/{roleId}")
|
@GetMapping("/edit/{roleId}")
|
||||||
public String edit(@PathVariable("roleId") Long roleId, ModelMap mmap)
|
public String edit(@PathVariable("roleId") Long roleId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleDataScope(roleId);
|
||||||
mmap.put("role", roleService.selectRoleById(roleId));
|
mmap.put("role", roleService.selectRoleById(roleId));
|
||||||
return prefix + "/edit";
|
return prefix + "/edit";
|
||||||
}
|
}
|
||||||
|
|
@ -109,10 +125,20 @@ public class SysRoleController extends BaseController
|
||||||
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
|
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysRole role)
|
public AjaxResult editSave(@Validated SysRole role)
|
||||||
{
|
{
|
||||||
role.setUpdateBy(ShiroUtils.getLoginName());
|
roleService.checkRoleAllowed(role);
|
||||||
ShiroUtils.clearCachedAuthorizationInfo();
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
|
if (!roleService.checkRoleNameUnique(role))
|
||||||
|
{
|
||||||
|
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
|
||||||
|
}
|
||||||
|
else if (!roleService.checkRoleKeyUnique(role))
|
||||||
|
{
|
||||||
|
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
|
||||||
|
}
|
||||||
|
role.setUpdateBy(getLoginName());
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(roleService.updateRole(role));
|
return toAjax(roleService.updateRole(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +161,15 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult authDataScopeSave(SysRole role)
|
public AjaxResult authDataScopeSave(SysRole role)
|
||||||
{
|
{
|
||||||
return toAjax(roleService.authDataScope(role));
|
roleService.checkRoleAllowed(role);
|
||||||
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
|
role.setUpdateBy(getLoginName());
|
||||||
|
if (roleService.authDataScope(role) > 0)
|
||||||
|
{
|
||||||
|
setSysUser(userService.selectUserById(getUserId()));
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
return error();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("system:role:remove")
|
@RequiresPermissions("system:role:remove")
|
||||||
|
|
@ -144,14 +178,7 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
{
|
{
|
||||||
try
|
return toAjax(roleService.deleteRoleByIds(ids));
|
||||||
{
|
|
||||||
return toAjax(roleService.deleteRoleByIds(ids));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -159,7 +186,7 @@ public class SysRoleController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkRoleNameUnique")
|
@PostMapping("/checkRoleNameUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkRoleNameUnique(SysRole role)
|
public boolean checkRoleNameUnique(SysRole role)
|
||||||
{
|
{
|
||||||
return roleService.checkRoleNameUnique(role);
|
return roleService.checkRoleNameUnique(role);
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +196,7 @@ public class SysRoleController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkRoleKeyUnique")
|
@PostMapping("/checkRoleKeyUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkRoleKeyUnique(SysRole role)
|
public boolean checkRoleKeyUnique(SysRole role)
|
||||||
{
|
{
|
||||||
return roleService.checkRoleKeyUnique(role);
|
return roleService.checkRoleKeyUnique(role);
|
||||||
}
|
}
|
||||||
|
|
@ -192,6 +219,8 @@ public class SysRoleController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult changeStatus(SysRole role)
|
public AjaxResult changeStatus(SysRole role)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleAllowed(role);
|
||||||
|
roleService.checkRoleDataScope(role.getRoleId());
|
||||||
return toAjax(roleService.changeStatus(role));
|
return toAjax(roleService.changeStatus(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,6 +251,7 @@ public class SysRoleController extends BaseController
|
||||||
/**
|
/**
|
||||||
* 取消授权
|
* 取消授权
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:role:edit")
|
||||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||||
@PostMapping("/authUser/cancel")
|
@PostMapping("/authUser/cancel")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
|
|
@ -233,6 +263,7 @@ public class SysRoleController extends BaseController
|
||||||
/**
|
/**
|
||||||
* 批量取消授权
|
* 批量取消授权
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:role:edit")
|
||||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||||
@PostMapping("/authUser/cancelAll")
|
@PostMapping("/authUser/cancelAll")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
|
|
@ -267,11 +298,25 @@ public class SysRoleController extends BaseController
|
||||||
/**
|
/**
|
||||||
* 批量选择用户授权
|
* 批量选择用户授权
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:role:edit")
|
||||||
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
@Log(title = "角色管理", businessType = BusinessType.GRANT)
|
||||||
@PostMapping("/authUser/selectAll")
|
@PostMapping("/authUser/selectAll")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult selectAuthUserAll(Long roleId, String userIds)
|
public AjaxResult selectAuthUserAll(Long roleId, String userIds)
|
||||||
{
|
{
|
||||||
|
roleService.checkRoleDataScope(roleId);
|
||||||
return toAjax(roleService.insertAuthUsers(roleId, userIds));
|
return toAjax(roleService.insertAuthUsers(roleId, userIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载角色部门(数据权限)列表树
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:role:edit")
|
||||||
|
@GetMapping("/deptTreeData")
|
||||||
|
@ResponseBody
|
||||||
|
public List<Ztree> deptTreeData(SysRole role)
|
||||||
|
{
|
||||||
|
List<Ztree> ztrees = deptService.roleDeptTreeData(role);
|
||||||
|
return ztrees;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
@ -14,13 +17,20 @@ import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.domain.Ztree;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.core.text.Convert;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.ShiroUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||||
import com.ruoyi.framework.util.ShiroUtils;
|
import com.ruoyi.framework.shiro.util.AuthorizationUtils;
|
||||||
import com.ruoyi.system.domain.SysUser;
|
import com.ruoyi.system.service.ISysDeptService;
|
||||||
import com.ruoyi.system.service.ISysPostService;
|
import com.ruoyi.system.service.ISysPostService;
|
||||||
import com.ruoyi.system.service.ISysRoleService;
|
import com.ruoyi.system.service.ISysRoleService;
|
||||||
import com.ruoyi.system.service.ISysUserService;
|
import com.ruoyi.system.service.ISysUserService;
|
||||||
|
|
@ -41,6 +51,9 @@ public class SysUserController extends BaseController
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysRoleService roleService;
|
private ISysRoleService roleService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysDeptService deptService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysPostService postService;
|
private ISysPostService postService;
|
||||||
|
|
@ -84,8 +97,7 @@ public class SysUserController extends BaseController
|
||||||
{
|
{
|
||||||
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
|
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
|
||||||
List<SysUser> userList = util.importExcel(file.getInputStream());
|
List<SysUser> userList = util.importExcel(file.getInputStream());
|
||||||
String operName = ShiroUtils.getSysUser().getLoginName();
|
String message = userService.importUser(userList, updateSupport, getLoginName());
|
||||||
String message = userService.importUser(userList, updateSupport, operName);
|
|
||||||
return AjaxResult.success(message);
|
return AjaxResult.success(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +116,7 @@ public class SysUserController extends BaseController
|
||||||
@GetMapping("/add")
|
@GetMapping("/add")
|
||||||
public String add(ModelMap mmap)
|
public String add(ModelMap mmap)
|
||||||
{
|
{
|
||||||
mmap.put("roles", roleService.selectRoleAll());
|
mmap.put("roles", roleService.selectRoleAll().stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
mmap.put("posts", postService.selectPostAll());
|
mmap.put("posts", postService.selectPostAll());
|
||||||
return prefix + "/add";
|
return prefix + "/add";
|
||||||
}
|
}
|
||||||
|
|
@ -116,30 +128,58 @@ public class SysUserController extends BaseController
|
||||||
@Log(title = "用户管理", businessType = BusinessType.INSERT)
|
@Log(title = "用户管理", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult addSave(SysUser user)
|
public AjaxResult addSave(@Validated SysUser user)
|
||||||
{
|
{
|
||||||
if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId()))
|
deptService.checkDeptDataScope(user.getDeptId());
|
||||||
|
roleService.checkRoleDataScope(user.getRoleIds());
|
||||||
|
if (!userService.checkLoginNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("不允许修改超级管理员用户");
|
return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在");
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||||
|
{
|
||||||
|
return error("新增用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||||
|
{
|
||||||
|
return error("新增用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
|
||||||
}
|
}
|
||||||
user.setSalt(ShiroUtils.randomSalt());
|
user.setSalt(ShiroUtils.randomSalt());
|
||||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||||
user.setCreateBy(ShiroUtils.getLoginName());
|
user.setPwdUpdateDate(DateUtils.getNowDate());
|
||||||
|
user.setCreateBy(getLoginName());
|
||||||
return toAjax(userService.insertUser(user));
|
return toAjax(userService.insertUser(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改用户
|
* 修改用户
|
||||||
*/
|
*/
|
||||||
|
@RequiresPermissions("system:user:edit")
|
||||||
@GetMapping("/edit/{userId}")
|
@GetMapping("/edit/{userId}")
|
||||||
public String edit(@PathVariable("userId") Long userId, ModelMap mmap)
|
public String edit(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
userService.checkUserDataScope(userId);
|
||||||
|
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||||
mmap.put("user", userService.selectUserById(userId));
|
mmap.put("user", userService.selectUserById(userId));
|
||||||
mmap.put("roles", roleService.selectRolesByUserId(userId));
|
mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
mmap.put("posts", postService.selectPostsByUserId(userId));
|
mmap.put("posts", postService.selectPostsByUserId(userId));
|
||||||
return prefix + "/edit";
|
return prefix + "/edit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户详细
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:user:list")
|
||||||
|
@GetMapping("/view/{userId}")
|
||||||
|
public String view(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
userService.checkUserDataScope(userId);
|
||||||
|
mmap.put("user", userService.selectUserById(userId));
|
||||||
|
mmap.put("roleGroup", userService.selectUserRoleGroup(userId));
|
||||||
|
mmap.put("postGroup", userService.selectUserPostGroup(userId));
|
||||||
|
return prefix + "/view";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改保存用户
|
* 修改保存用户
|
||||||
*/
|
*/
|
||||||
|
|
@ -147,18 +187,30 @@ public class SysUserController extends BaseController
|
||||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/edit")
|
@PostMapping("/edit")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult editSave(SysUser user)
|
public AjaxResult editSave(@Validated SysUser user)
|
||||||
{
|
{
|
||||||
if (StringUtils.isNotNull(user.getUserId()) && SysUser.isAdmin(user.getUserId()))
|
userService.checkUserAllowed(user);
|
||||||
|
userService.checkUserDataScope(user.getUserId());
|
||||||
|
deptService.checkDeptDataScope(user.getDeptId());
|
||||||
|
roleService.checkRoleDataScope(user.getRoleIds());
|
||||||
|
if (!userService.checkLoginNameUnique(user))
|
||||||
{
|
{
|
||||||
return error("不允许修改超级管理员用户");
|
return error("修改用户'" + user.getLoginName() + "'失败,登录账号已存在");
|
||||||
}
|
}
|
||||||
user.setUpdateBy(ShiroUtils.getLoginName());
|
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
|
||||||
|
{
|
||||||
|
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在");
|
||||||
|
}
|
||||||
|
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
|
||||||
|
{
|
||||||
|
return error("修改用户'" + user.getLoginName() + "'失败,邮箱账号已存在");
|
||||||
|
}
|
||||||
|
user.setUpdateBy(getLoginName());
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
return toAjax(userService.updateUser(user));
|
return toAjax(userService.updateUser(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("system:user:resetPwd")
|
@RequiresPermissions("system:user:resetPwd")
|
||||||
@Log(title = "重置密码", businessType = BusinessType.UPDATE)
|
|
||||||
@GetMapping("/resetPwd/{userId}")
|
@GetMapping("/resetPwd/{userId}")
|
||||||
public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap)
|
public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||||
{
|
{
|
||||||
|
|
@ -172,9 +224,49 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult resetPwdSave(SysUser user)
|
public AjaxResult resetPwdSave(SysUser user)
|
||||||
{
|
{
|
||||||
|
userService.checkUserAllowed(user);
|
||||||
|
userService.checkUserDataScope(user.getUserId());
|
||||||
user.setSalt(ShiroUtils.randomSalt());
|
user.setSalt(ShiroUtils.randomSalt());
|
||||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||||
return toAjax(userService.resetUserPwd(user));
|
if (userService.resetUserPwd(user) > 0)
|
||||||
|
{
|
||||||
|
if (ShiroUtils.getUserId().longValue() == user.getUserId().longValue())
|
||||||
|
{
|
||||||
|
setSysUser(userService.selectUserById(user.getUserId()));
|
||||||
|
}
|
||||||
|
return success();
|
||||||
|
}
|
||||||
|
return error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进入授权角色页
|
||||||
|
*/
|
||||||
|
@GetMapping("/authRole/{userId}")
|
||||||
|
public String authRole(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
SysUser user = userService.selectUserById(userId);
|
||||||
|
// 获取用户所属的角色列表
|
||||||
|
List<SysRole> roles = roleService.selectRolesByUserId(userId);
|
||||||
|
mmap.put("user", user);
|
||||||
|
mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
|
||||||
|
return prefix + "/authRole";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户授权角色
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:user:edit")
|
||||||
|
@Log(title = "用户管理", businessType = BusinessType.GRANT)
|
||||||
|
@PostMapping("/authRole/insertAuthRole")
|
||||||
|
@ResponseBody
|
||||||
|
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
|
||||||
|
{
|
||||||
|
userService.checkUserDataScope(userId);
|
||||||
|
roleService.checkRoleDataScope(roleIds);
|
||||||
|
userService.insertUserAuth(userId, roleIds);
|
||||||
|
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresPermissions("system:user:remove")
|
@RequiresPermissions("system:user:remove")
|
||||||
|
|
@ -183,14 +275,11 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult remove(String ids)
|
public AjaxResult remove(String ids)
|
||||||
{
|
{
|
||||||
try
|
if (ArrayUtils.contains(Convert.toLongArray(ids), getUserId()))
|
||||||
{
|
{
|
||||||
return toAjax(userService.deleteUserByIds(ids));
|
return error("当前用户不能删除");
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return error(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
return toAjax(userService.deleteUserByIds(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -198,9 +287,9 @@ public class SysUserController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkLoginNameUnique")
|
@PostMapping("/checkLoginNameUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkLoginNameUnique(SysUser user)
|
public boolean checkLoginNameUnique(SysUser user)
|
||||||
{
|
{
|
||||||
return userService.checkLoginNameUnique(user.getLoginName());
|
return userService.checkLoginNameUnique(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -208,7 +297,7 @@ public class SysUserController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkPhoneUnique")
|
@PostMapping("/checkPhoneUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkPhoneUnique(SysUser user)
|
public boolean checkPhoneUnique(SysUser user)
|
||||||
{
|
{
|
||||||
return userService.checkPhoneUnique(user);
|
return userService.checkPhoneUnique(user);
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +307,7 @@ public class SysUserController extends BaseController
|
||||||
*/
|
*/
|
||||||
@PostMapping("/checkEmailUnique")
|
@PostMapping("/checkEmailUnique")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String checkEmailUnique(SysUser user)
|
public boolean checkEmailUnique(SysUser user)
|
||||||
{
|
{
|
||||||
return userService.checkEmailUnique(user);
|
return userService.checkEmailUnique(user);
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +321,33 @@ public class SysUserController extends BaseController
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public AjaxResult changeStatus(SysUser user)
|
public AjaxResult changeStatus(SysUser user)
|
||||||
{
|
{
|
||||||
|
userService.checkUserAllowed(user);
|
||||||
|
userService.checkUserDataScope(user.getUserId());
|
||||||
return toAjax(userService.changeStatus(user));
|
return toAjax(userService.changeStatus(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载部门列表树
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:user:list")
|
||||||
|
@GetMapping("/deptTreeData")
|
||||||
|
@ResponseBody
|
||||||
|
public List<Ztree> deptTreeData()
|
||||||
|
{
|
||||||
|
List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
|
||||||
|
return ztrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择部门树
|
||||||
|
*
|
||||||
|
* @param deptId 部门ID
|
||||||
|
*/
|
||||||
|
@RequiresPermissions("system:user:list")
|
||||||
|
@GetMapping("/selectDeptTree/{deptId}")
|
||||||
|
public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap)
|
||||||
|
{
|
||||||
|
mmap.put("dept", deptService.selectDeptById(deptId));
|
||||||
|
return prefix + "/deptTree";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,6 @@ public class SwaggerController extends BaseController
|
||||||
@GetMapping()
|
@GetMapping()
|
||||||
public String index()
|
public String index()
|
||||||
{
|
{
|
||||||
return redirect("/swagger-ui.html");
|
return redirect("/swagger-ui/index.html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,116 +1,152 @@
|
||||||
package com.ruoyi.web.controller.tool;
|
package com.ruoyi.web.controller.tool;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.R;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* swagger 测试方法
|
* swagger 用户测试方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Api("用户信息管理")
|
@Api("用户信息管理")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/test/*")
|
@RequestMapping("/test/user")
|
||||||
public class TestController extends BaseController
|
public class TestController extends BaseController
|
||||||
{
|
{
|
||||||
private final static List<Test> testList = new ArrayList<>();
|
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
|
||||||
{
|
{
|
||||||
testList.add(new Test("1", "admin", "admin123"));
|
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
|
||||||
testList.add(new Test("2", "ry", "admin123"));
|
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("获取列表")
|
@ApiOperation("获取用户列表")
|
||||||
@GetMapping("list")
|
@GetMapping("/list")
|
||||||
public List<Test> testList()
|
public R<List<UserEntity>> userList()
|
||||||
{
|
{
|
||||||
return testList;
|
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
|
||||||
|
return R.ok(userList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取用户详细")
|
||||||
|
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
||||||
|
@GetMapping("/{userId}")
|
||||||
|
public R<UserEntity> getUser(@PathVariable Integer userId)
|
||||||
|
{
|
||||||
|
if (!users.isEmpty() && users.containsKey(userId))
|
||||||
|
{
|
||||||
|
return R.ok(users.get(userId));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return R.fail("用户不存在");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("新增用户")
|
@ApiOperation("新增用户")
|
||||||
@PostMapping("save")
|
@ApiImplicitParams({
|
||||||
public AjaxResult save(Test test)
|
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
|
||||||
|
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
|
||||||
|
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
|
||||||
|
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
|
||||||
|
})
|
||||||
|
@PostMapping("/save")
|
||||||
|
public R<String> save(UserEntity user)
|
||||||
{
|
{
|
||||||
return testList.add(test) ? success() : error();
|
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||||
|
{
|
||||||
|
return R.fail("用户ID不能为空");
|
||||||
|
}
|
||||||
|
users.put(user.getUserId(), user);
|
||||||
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("更新用户")
|
@ApiOperation("更新用户")
|
||||||
@ApiImplicitParam(name = "Test", value = "单个用户信息", dataType = "Test")
|
@PutMapping("/update")
|
||||||
@PutMapping("update")
|
public R<String> update(@RequestBody UserEntity user)
|
||||||
public AjaxResult update(Test test)
|
|
||||||
{
|
{
|
||||||
return testList.remove(test) && testList.add(test) ? success() : error();
|
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
|
||||||
|
{
|
||||||
|
return R.fail("用户ID不能为空");
|
||||||
|
}
|
||||||
|
if (users.isEmpty() || !users.containsKey(user.getUserId()))
|
||||||
|
{
|
||||||
|
return R.fail("用户不存在");
|
||||||
|
}
|
||||||
|
users.remove(user.getUserId());
|
||||||
|
users.put(user.getUserId(), user);
|
||||||
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation("删除用户")
|
@ApiOperation("删除用户信息")
|
||||||
@ApiImplicitParam(name = "Tests", value = "单个用户信息", dataType = "Test")
|
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
|
||||||
@DeleteMapping("delete")
|
@DeleteMapping("/{userId}")
|
||||||
public AjaxResult delete(Test test)
|
public R<String> delete(@PathVariable Integer userId)
|
||||||
{
|
{
|
||||||
return testList.remove(test) ? success() : error();
|
if (!users.isEmpty() && users.containsKey(userId))
|
||||||
|
{
|
||||||
|
users.remove(userId);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return R.fail("用户不存在");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Test
|
@ApiModel(value = "UserEntity", description = "用户实体")
|
||||||
|
class UserEntity
|
||||||
{
|
{
|
||||||
private String userId;
|
@ApiModelProperty("用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户名称")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户密码")
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
public Test()
|
@ApiModelProperty("用户手机")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
public UserEntity()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Test(String userId, String username, String password)
|
public UserEntity(Integer userId, String username, String password, String mobile)
|
||||||
{
|
{
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.mobile = mobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Integer getUserId()
|
||||||
public boolean equals(Object o)
|
|
||||||
{
|
|
||||||
if (this == o)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Test test = (Test) o;
|
|
||||||
|
|
||||||
return userId != null ? userId.equals(test.userId) : test.userId == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
int result = userId != null ? userId.hashCode() : 0;
|
|
||||||
result = 31 * result + (username != null ? username.hashCode() : 0);
|
|
||||||
result = 31 * result + (password != null ? password.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUserId()
|
|
||||||
{
|
{
|
||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserId(String userId)
|
public void setUserId(Integer userId)
|
||||||
{
|
{
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
@ -134,4 +170,14 @@ class Test
|
||||||
{
|
{
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMobile()
|
||||||
|
{
|
||||||
|
return mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMobile(String mobile)
|
||||||
|
{
|
||||||
|
this.mobile = mobile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package com.ruoyi.web.core.config;
|
package com.ruoyi.web.core.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import com.ruoyi.common.config.Global;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
|
@ -10,7 +12,6 @@ import springfox.documentation.service.ApiInfo;
|
||||||
import springfox.documentation.service.Contact;
|
import springfox.documentation.service.Contact;
|
||||||
import springfox.documentation.spi.DocumentationType;
|
import springfox.documentation.spi.DocumentationType;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger2的接口配置
|
* Swagger2的接口配置
|
||||||
|
|
@ -18,21 +19,29 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableSwagger2
|
|
||||||
public class SwaggerConfig
|
public class SwaggerConfig
|
||||||
{
|
{
|
||||||
|
/** 是否开启swagger */
|
||||||
|
@Value("${swagger.enabled}")
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建API
|
* 创建API
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public Docket createRestApi()
|
public Docket createRestApi()
|
||||||
{
|
{
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.OAS_30)
|
||||||
// 详细定制
|
// 是否启用Swagger
|
||||||
|
.enable(enabled)
|
||||||
|
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
|
// 设置哪些接口暴露给Swagger展示
|
||||||
.select()
|
.select()
|
||||||
// 指定当前包路径
|
// 扫描所有有注解的api,用这种方式更灵活
|
||||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.web.controller.tool"))
|
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||||
|
// 扫描指定包中的swagger注解
|
||||||
|
//.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
|
||||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||||
.paths(PathSelectors.any())
|
.paths(PathSelectors.any())
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -45,10 +54,14 @@ public class SwaggerConfig
|
||||||
{
|
{
|
||||||
// 用ApiInfoBuilder进行定制
|
// 用ApiInfoBuilder进行定制
|
||||||
return new ApiInfoBuilder()
|
return new ApiInfoBuilder()
|
||||||
|
// 设置标题
|
||||||
.title("标题:若依管理系统_接口文档")
|
.title("标题:若依管理系统_接口文档")
|
||||||
|
// 描述
|
||||||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
|
||||||
.contact(new Contact(Global.getName(), null, null))
|
// 作者信息
|
||||||
.version("版本号:" + Global.getVersion())
|
.contact(new Contact(RuoYiConfig.getName(), null, null))
|
||||||
|
// 版本
|
||||||
|
.version("版本号:" + RuoYiConfig.getVersion())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ spring:
|
||||||
maxActive: 20
|
maxActive: 20
|
||||||
# 配置获取连接等待超时的时间
|
# 配置获取连接等待超时的时间
|
||||||
maxWait: 60000
|
maxWait: 60000
|
||||||
|
# 配置连接超时时间
|
||||||
|
connectTimeout: 30000
|
||||||
|
# 配置网络超时时间
|
||||||
|
socketTimeout: 60000
|
||||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||||
timeBetweenEvictionRunsMillis: 60000
|
timeBetweenEvictionRunsMillis: 60000
|
||||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||||
|
|
@ -41,7 +45,10 @@ spring:
|
||||||
enabled: true
|
enabled: true
|
||||||
# 设置白名单,不填则允许所有访问
|
# 设置白名单,不填则允许所有访问
|
||||||
allow:
|
allow:
|
||||||
url-pattern: /monitor/druid/*
|
url-pattern: /druid/*
|
||||||
|
# 控制台管理用户名和密码
|
||||||
|
login-username: ruoyi
|
||||||
|
login-password: 123456
|
||||||
filter:
|
filter:
|
||||||
stat:
|
stat:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
||||||
|
|
@ -3,35 +3,39 @@ ruoyi:
|
||||||
# 名称
|
# 名称
|
||||||
name: RuoYi
|
name: RuoYi
|
||||||
# 版本
|
# 版本
|
||||||
version: 3.3.0
|
version: 4.7.9
|
||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2019
|
copyrightYear: 2024
|
||||||
# 文件上传
|
# 实例演示开关
|
||||||
profile: D:/profile/
|
demoEnabled: true
|
||||||
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
|
profile: D:/ruoyi/uploadPath
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
addressEnabled: true
|
addressEnabled: false
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
server:
|
server:
|
||||||
# 服务端口
|
# 服务器的HTTP端口,默认为80
|
||||||
port: 80
|
port: 80
|
||||||
servlet:
|
servlet:
|
||||||
# 项目contextPath
|
# 应用的访问路径
|
||||||
context-path: /
|
context-path: /
|
||||||
tomcat:
|
tomcat:
|
||||||
# tomcat的URI编码
|
# tomcat的URI编码
|
||||||
uri-encoding: UTF-8
|
uri-encoding: UTF-8
|
||||||
# tomcat最大线程数,默认为200
|
# 连接数满后的排队数,默认为100
|
||||||
max-threads: 800
|
accept-count: 1000
|
||||||
# Tomcat启动初始化的线程数,默认值25
|
threads:
|
||||||
min-spare-threads: 30
|
# tomcat最大线程数,默认为200
|
||||||
|
max: 800
|
||||||
|
# Tomcat启动初始化的线程数,默认值10
|
||||||
|
min-spare: 100
|
||||||
|
|
||||||
# 日志配置
|
# 日志配置
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
com.ruoyi: debug
|
com.ruoyi: debug
|
||||||
org.springframework: WARN
|
org.springframework: warn
|
||||||
org.spring.springboot.dao: debug
|
|
||||||
|
|
||||||
# 用户配置
|
# 用户配置
|
||||||
user:
|
user:
|
||||||
|
|
@ -50,17 +54,19 @@ spring:
|
||||||
# 资源信息
|
# 资源信息
|
||||||
messages:
|
messages:
|
||||||
# 国际化资源文件路径
|
# 国际化资源文件路径
|
||||||
basename: i18n/messages
|
basename: static/i18n/messages
|
||||||
jackson:
|
jackson:
|
||||||
time-zone: GMT+8
|
time-zone: GMT+8
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
profiles:
|
profiles:
|
||||||
active: druid
|
active: druid
|
||||||
# 文件上传
|
# 文件上传
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 30MB
|
# 单个文件大小
|
||||||
max-request-size: 30MB
|
max-file-size: 10MB
|
||||||
|
# 设置总上传的文件大小
|
||||||
|
max-request-size: 20MB
|
||||||
# 服务模块
|
# 服务模块
|
||||||
devtools:
|
devtools:
|
||||||
restart:
|
restart:
|
||||||
|
|
@ -69,19 +75,18 @@ spring:
|
||||||
|
|
||||||
# MyBatis
|
# MyBatis
|
||||||
mybatis:
|
mybatis:
|
||||||
# 搜索指定包别名
|
# 搜索指定包别名
|
||||||
typeAliasesPackage: com.ruoyi
|
typeAliasesPackage: com.ruoyi.**.domain
|
||||||
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||||
# 加载全局的配置文件
|
# 加载全局的配置文件
|
||||||
configLocation: classpath:mapper/mybatis-config.xml
|
configLocation: classpath:mybatis/mybatis-config.xml
|
||||||
|
|
||||||
# PageHelper分页插件
|
# PageHelper分页插件
|
||||||
pagehelper:
|
pagehelper:
|
||||||
helperDialect: mysql
|
helperDialect: mysql
|
||||||
reasonable: true
|
|
||||||
supportMethodsArguments: true
|
supportMethodsArguments: true
|
||||||
params: count=countSql
|
params: count=countSql
|
||||||
|
|
||||||
# Shiro
|
# Shiro
|
||||||
shiro:
|
shiro:
|
||||||
|
|
@ -94,30 +99,44 @@ shiro:
|
||||||
indexUrl: /index
|
indexUrl: /index
|
||||||
# 验证码开关
|
# 验证码开关
|
||||||
captchaEnabled: true
|
captchaEnabled: true
|
||||||
# 验证码类型 math 数组计算 char 字符
|
# 验证码类型 math 数字计算 char 字符验证
|
||||||
captchaType: math
|
captchaType: math
|
||||||
cookie:
|
cookie:
|
||||||
# 设置Cookie的域名 默认空,即当前访问的域名
|
# 设置Cookie的域名 默认空,即当前访问的域名
|
||||||
domain:
|
domain:
|
||||||
# 设置cookie的有效访问路径
|
# 设置cookie的有效访问路径
|
||||||
path: /
|
path: /
|
||||||
# 设置HttpOnly属性
|
# 设置HttpOnly属性
|
||||||
httpOnly: true
|
httpOnly: true
|
||||||
# 设置Cookie的过期时间,天为单位
|
# 设置Cookie的过期时间,天为单位
|
||||||
maxAge: 30
|
maxAge: 30
|
||||||
|
# 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效)
|
||||||
|
cipherKey:
|
||||||
session:
|
session:
|
||||||
# Session超时时间(默认30分钟)
|
# Session超时时间,-1代表永不过期(默认30分钟)
|
||||||
expireTime: 30
|
expireTime: 30
|
||||||
# 同步session到数据库的周期(默认1分钟)
|
# 同步session到数据库的周期(默认1分钟)
|
||||||
dbSyncPeriod: 1
|
dbSyncPeriod: 1
|
||||||
# 相隔多久检查一次session的有效性,默认就是10分钟
|
# 相隔多久检查一次session的有效性,默认就是10分钟
|
||||||
validationInterval: 10
|
validationInterval: 10
|
||||||
|
# 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
|
||||||
|
maxSession: -1
|
||||||
|
# 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
||||||
|
kickoutAfter: false
|
||||||
|
rememberMe:
|
||||||
|
# 是否开启记住我
|
||||||
|
enabled: true
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
enabled: true
|
enabled: true
|
||||||
# 排除链接(多个用逗号分隔)
|
# 排除链接(多个用逗号分隔)
|
||||||
excludes: /system/notice/*
|
excludes: /system/notice/*
|
||||||
# 匹配链接
|
# 匹配链接
|
||||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||||
|
|
||||||
|
# Swagger配置
|
||||||
|
swagger:
|
||||||
|
# 是否开启swagger
|
||||||
|
enabled: true
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,15 @@
|
||||||
|
|
||||||
<!-- 磁盘缓存位置 -->
|
<!-- 磁盘缓存位置 -->
|
||||||
<diskStore path="java.io.tmpdir"/>
|
<diskStore path="java.io.tmpdir"/>
|
||||||
|
|
||||||
|
<!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
|
||||||
|
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
|
||||||
|
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
|
||||||
|
<!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||||
|
<!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||||
|
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
|
||||||
|
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
|
||||||
|
|
||||||
<!-- 默认缓存 -->
|
<!-- 默认缓存 -->
|
||||||
<defaultCache
|
<defaultCache
|
||||||
maxEntriesLocalHeap="1000"
|
maxEntriesLocalHeap="1000"
|
||||||
|
|
@ -20,8 +28,64 @@
|
||||||
timeToIdleSeconds="600"
|
timeToIdleSeconds="600"
|
||||||
timeToLiveSeconds="0"
|
timeToLiveSeconds="0"
|
||||||
overflowToDisk="false"
|
overflowToDisk="false"
|
||||||
statistics="true">
|
statistics="false">
|
||||||
</cache>
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统活跃用户缓存 -->
|
||||||
|
<cache name="sys-userCache"
|
||||||
|
maxEntriesLocalHeap="10000"
|
||||||
|
overflowToDisk="false"
|
||||||
|
eternal="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
timeToIdleSeconds="0"
|
||||||
|
statistics="false">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统用户授权缓存 没必要过期 -->
|
||||||
|
<cache name="sys-authCache"
|
||||||
|
maxEntriesLocalHeap="10000"
|
||||||
|
overflowToDisk="false"
|
||||||
|
eternal="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
timeToIdleSeconds="0"
|
||||||
|
memoryStoreEvictionPolicy="LRU"
|
||||||
|
statistics="false"/>
|
||||||
|
|
||||||
|
<!-- 系统缓存 -->
|
||||||
|
<cache name="sys-cache"
|
||||||
|
maxEntriesLocalHeap="1000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="true"
|
||||||
|
statistics="false">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统参数缓存 -->
|
||||||
|
<cache name="sys-config"
|
||||||
|
maxEntriesLocalHeap="1000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="true"
|
||||||
|
statistics="false">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统字典缓存 -->
|
||||||
|
<cache name="sys-dict"
|
||||||
|
maxEntriesLocalHeap="1000"
|
||||||
|
eternal="true"
|
||||||
|
overflowToDisk="true"
|
||||||
|
statistics="false">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统会话缓存 -->
|
||||||
|
<cache name="shiro-activeSessionCache"
|
||||||
|
maxEntriesLocalHeap="10000"
|
||||||
|
overflowToDisk="false"
|
||||||
|
eternal="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
timeToIdleSeconds="0"
|
||||||
|
statistics="false"/>
|
||||||
|
|
||||||
</ehcache>
|
</ehcache>
|
||||||
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<!-- 日志存放路径 -->
|
||||||
<property name="log.path" value="/home/ruoyi/logs" />
|
<property name="log.path" value="/home/ruoyi/logs" />
|
||||||
|
<!-- 日志输出格式 -->
|
||||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||||
|
|
||||||
<!-- 控制台输出 -->
|
<!-- 控制台输出 -->
|
||||||
|
|
@ -14,8 +15,9 @@
|
||||||
<!-- 系统日志输出 -->
|
<!-- 系统日志输出 -->
|
||||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>${log.path}/sys-info.log</file>
|
<file>${log.path}/sys-info.log</file>
|
||||||
|
<!-- 循环政策:基于时间创建日志文件 -->
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<!-- 按天回滚 daily -->
|
<!-- 日志文件名格式 -->
|
||||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
<!-- 日志最大的历史 60天 -->
|
<!-- 日志最大的历史 60天 -->
|
||||||
<maxHistory>60</maxHistory>
|
<maxHistory>60</maxHistory>
|
||||||
|
|
@ -24,15 +26,20 @@
|
||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<!-- 过滤的级别 -->
|
||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
|
<!-- 匹配时的操作:接收(记录) -->
|
||||||
<onMatch>ACCEPT</onMatch>
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||||
<onMismatch>DENY</onMismatch>
|
<onMismatch>DENY</onMismatch>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>${log.path}/sys-error.log</file>
|
<file>${log.path}/sys-error.log</file>
|
||||||
|
<!-- 循环政策:基于时间创建日志文件 -->
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 日志文件名格式 -->
|
||||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
<!-- 日志最大的历史 60天 -->
|
<!-- 日志最大的历史 60天 -->
|
||||||
<maxHistory>60</maxHistory>
|
<maxHistory>60</maxHistory>
|
||||||
|
|
@ -41,8 +48,11 @@
|
||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<!-- 过滤的级别 -->
|
||||||
<level>ERROR</level>
|
<level>ERROR</level>
|
||||||
|
<!-- 匹配时的操作:接收(记录) -->
|
||||||
<onMatch>ACCEPT</onMatch>
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||||
<onMismatch>DENY</onMismatch>
|
<onMismatch>DENY</onMismatch>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
@ -61,13 +71,10 @@
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- 显示形成的sql、使用的参数、结果集 -->
|
<!-- 系统模块日志级别控制 -->
|
||||||
<!--
|
|
||||||
<logger name="java.sql" level="debug" />
|
|
||||||
<logger name="org.springframework.jdbc" level="debug" />
|
|
||||||
-->
|
|
||||||
|
|
||||||
<logger name="com.ruoyi" level="info" />
|
<logger name="com.ruoyi" level="info" />
|
||||||
|
<!-- Spring日志级别控制 -->
|
||||||
|
<logger name="org.springframework" level="warn" />
|
||||||
|
|
||||||
<root level="info">
|
<root level="info">
|
||||||
<appender-ref ref="console" />
|
<appender-ref ref="console" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE configuration
|
||||||
|
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||||
|
<configuration>
|
||||||
|
<!-- 全局参数 -->
|
||||||
|
<settings>
|
||||||
|
<!-- 使全局的映射器启用或禁用缓存 -->
|
||||||
|
<setting name="cacheEnabled" value="true" />
|
||||||
|
<!-- 允许JDBC 支持自动生成主键 -->
|
||||||
|
<setting name="useGeneratedKeys" value="true" />
|
||||||
|
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
|
||||||
|
<setting name="defaultExecutorType" value="SIMPLE" />
|
||||||
|
<!-- 指定 MyBatis 所用日志的具体实现 -->
|
||||||
|
<setting name="logImpl" value="SLF4J" />
|
||||||
|
<!-- 使用驼峰命名法转换字段 -->
|
||||||
|
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
@ -0,0 +1,688 @@
|
||||||
|
/*!
|
||||||
|
* bootstrap-fileinput v5.5.2
|
||||||
|
* http://plugins.krajee.com/file-input
|
||||||
|
*
|
||||||
|
* Krajee default styling for bootstrap-fileinput.
|
||||||
|
*
|
||||||
|
* Author: Kartik Visweswaran
|
||||||
|
* Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com
|
||||||
|
*
|
||||||
|
* Licensed under the BSD-3-Clause
|
||||||
|
* https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
.file-loading input[type=file],
|
||||||
|
input[type=file].file-loading {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-no-browse {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 20%;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
font-size: 0;
|
||||||
|
opacity: 0;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-hidden,
|
||||||
|
.file-caption-icon,
|
||||||
|
.file-zoom-dialog .modal-header:before,
|
||||||
|
.file-zoom-dialog .modal-header:after,
|
||||||
|
.file-input-new .file-preview,
|
||||||
|
.file-input-new .close,
|
||||||
|
.file-input-new .glyphicon-file,
|
||||||
|
.file-input-new .fileinput-remove-button,
|
||||||
|
.file-input-new .fileinput-upload-button,
|
||||||
|
.file-input-new .no-browse .input-group-btn,
|
||||||
|
.file-input-ajax-new .fileinput-remove-button,
|
||||||
|
.file-input-ajax-new .fileinput-upload-button,
|
||||||
|
.file-input-ajax-new .no-browse .input-group-btn,
|
||||||
|
.hide-content .kv-file-content,
|
||||||
|
.is-locked .fileinput-upload-button,
|
||||||
|
.is-locked .fileinput-remove-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption .input-group {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file input[type=file],
|
||||||
|
.file-caption-icon,
|
||||||
|
.file-preview .fileinput-remove,
|
||||||
|
.krajee-default .file-thumb-progress,
|
||||||
|
.file-zoom-dialog .btn-navigate,
|
||||||
|
.file-zoom-dialog .floating-buttons {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-icon .kv-caption-icon {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input,
|
||||||
|
.file-loading:before,
|
||||||
|
.btn-file,
|
||||||
|
.file-caption,
|
||||||
|
.file-preview,
|
||||||
|
.krajee-default.file-preview-frame,
|
||||||
|
.krajee-default .file-thumbnail-footer,
|
||||||
|
.file-zoom-dialog .modal-dialog {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre,
|
||||||
|
.file-error-message ul,
|
||||||
|
.krajee-default .file-actions,
|
||||||
|
.krajee-default .file-other-error {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre,
|
||||||
|
.file-error-message ul {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-drag-handle,
|
||||||
|
.krajee-default .file-upload-indicator {
|
||||||
|
float: left;
|
||||||
|
margin-top: 10px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-thumb-progress .progress,
|
||||||
|
.file-thumb-progress .progress-bar {
|
||||||
|
font-family: Verdana, Helvetica, sans-serif;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-thumb-progress .progress,
|
||||||
|
.kv-upload-progress .progress {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-caption-info,
|
||||||
|
.krajee-default .file-size-info {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 160px;
|
||||||
|
height: 15px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-video,
|
||||||
|
.file-zoom-content > .file-object.type-flash,
|
||||||
|
.file-zoom-content > .file-object.type-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-video,
|
||||||
|
.file-zoom-content > .file-object.type-flash {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-pdf,
|
||||||
|
.file-zoom-content > .file-object.type-html,
|
||||||
|
.file-zoom-content > .file-object.type-text,
|
||||||
|
.file-zoom-content > .file-object.type-default {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-loading:before {
|
||||||
|
content: " Loading...";
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 20px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-variant: small-caps;
|
||||||
|
color: #999;
|
||||||
|
background: transparent url(loading.gif) top left no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-object {
|
||||||
|
margin: 0 0 -5px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file input[type=file] {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
text-align: right;
|
||||||
|
opacity: 0;
|
||||||
|
background: none repeat scroll 0 0 transparent;
|
||||||
|
cursor: inherit;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-file ::-ms-browse {
|
||||||
|
font-size: 10000px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible .file-caption-icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible .file-caption-name {
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible > .input-group-lg .file-caption-name {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption.icon-visible > .input-group-sm .file-caption-name {
|
||||||
|
padding-left: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-name:not(.file-caption-disabled) {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-name.file-processing {
|
||||||
|
font-style: italic;
|
||||||
|
border-color: #bbb;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-icon {
|
||||||
|
padding: 7px 5px;
|
||||||
|
left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-lg .file-caption-icon {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-sm .file-caption-icon {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message {
|
||||||
|
color: #a94442;
|
||||||
|
background-color: #f2dede;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid #ebccd1;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-error-message pre {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption-disabled {
|
||||||
|
background-color: #eee;
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .btn-xs {
|
||||||
|
padding: 1px 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .fileinput-remove {
|
||||||
|
top: 1px;
|
||||||
|
right: 1px;
|
||||||
|
line-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-image {
|
||||||
|
font: 40px Impact, Charcoal, sans-serif;
|
||||||
|
color: #008000;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame {
|
||||||
|
margin: 8px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
padding: 6px;
|
||||||
|
float: left;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame .kv-file-content {
|
||||||
|
width: 213px;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame[data-template="audio"] .kv-file-content {
|
||||||
|
width: 240px;
|
||||||
|
height: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame .file-thumbnail-footer {
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.file-preview-frame:not(.file-preview-error):hover {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||||
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-text {
|
||||||
|
color: #428bca;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-html {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-other-icon {
|
||||||
|
font-size: 6em;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-footer-buttons {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-footer-caption {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-upload-stats {
|
||||||
|
font-size: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-upload-progress .file-upload-stats {
|
||||||
|
font-size: 12px;
|
||||||
|
margin: -10px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-error {
|
||||||
|
opacity: 0.65;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-thumb-progress {
|
||||||
|
top: 37px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default.kvsortable-ghost {
|
||||||
|
background: #e1edf7;
|
||||||
|
border: 2px solid #a1abff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-other:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-upload-progress .progress {
|
||||||
|
height: 20px;
|
||||||
|
margin: 10px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-upload-progress .progress-bar {
|
||||||
|
height: 20px;
|
||||||
|
font-family: Verdana, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*noinspection CssOverwrittenProperties*/
|
||||||
|
|
||||||
|
.file-zoom-dialog .file-other-icon {
|
||||||
|
font-size: 22em;
|
||||||
|
font-size: 50vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-dialog {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-navigate {
|
||||||
|
margin: 0 0.1rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
top: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-navigate * {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .floating-buttons {
|
||||||
|
top: 5px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-kv-prev {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .btn-kv-next {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-zoom-header {
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-zoom-body {
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-zoom-description {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
color: #fff;
|
||||||
|
left: 15%;
|
||||||
|
right: 15%;
|
||||||
|
bottom: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-desc-hide {
|
||||||
|
float: right;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0 0.1rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-desc-hide:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .kv-desc-hide:focus {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-new .no-browse .form-control {
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-ajax-new .no-browse .form-control {
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-caption {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-thumb-loading {
|
||||||
|
background: transparent url(loading.gif) no-repeat scroll center center content-box !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone {
|
||||||
|
border: 1px dashed #aaa;
|
||||||
|
min-height: 260px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 12px 15px 12px 12px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone.clickable:hover {
|
||||||
|
border: 2px dashed #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone.clickable:focus {
|
||||||
|
border: 2px solid #5acde2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone .file-preview-thumbnails {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-drop-zone-title {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 1.6em;
|
||||||
|
text-align: center;
|
||||||
|
padding: 85px 10px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-highlighted {
|
||||||
|
border: 2px dashed #999 !important;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-uploading {
|
||||||
|
background: url(loading-sm.gif) no-repeat center bottom 10px;
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .modal-dialog {
|
||||||
|
min-width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .modal-content {
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-fullscreen .kv-zoom-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-buttons {
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.floating-buttons .btn-kv {
|
||||||
|
margin-left: 3px;
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-zoom-actions {
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-zoom-actions .btn-kv {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content {
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content:hover {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content .file-preview-image {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content .file-preview-video {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-image {
|
||||||
|
height: auto;
|
||||||
|
min-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-content > .file-object.type-audio {
|
||||||
|
width: auto;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.file-zoom-dialog .modal-dialog {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.file-zoom-dialog .modal-lg {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.file-preview-thumbnails {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-zoom-dialog .modal-header {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 350px) {
|
||||||
|
.krajee-default.file-preview-frame:not([data-template="audio"]) .kv-file-content {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 420px) {
|
||||||
|
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-loading[dir=rtl]:before {
|
||||||
|
background: transparent url(loading.gif) top right no-repeat;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable .file-drop-zone-title {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-sortable .file-drag-handle:hover {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-sortable .file-drag-handle {
|
||||||
|
cursor: grab;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-grabbing,
|
||||||
|
.file-grabbing * {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-grabbing .file-preview-thumbnails * {
|
||||||
|
cursor: grabbing !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-frame.sortable-chosen {
|
||||||
|
background-color: #d9edf7;
|
||||||
|
border-color: #17a2b8;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview .kv-zoom-cache {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-kv-rotate,
|
||||||
|
.kv-file-rotate {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotatable:not(.hide-rotate) .btn-kv-rotate,
|
||||||
|
.rotatable:not(.hide-rotate) .kv-file-rotate {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotatable .file-zoom-detail,
|
||||||
|
.rotatable .kv-file-content,
|
||||||
|
.rotatable .kv-file-content > :first-child {
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rotate-animate {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
13
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css
vendored
Normal file
13
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
11
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js
vendored
Normal file
11
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-fileinput/fileinput.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 847 B |
459
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css
vendored
Normal file
459
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.css
vendored
Normal file
|
|
@ -0,0 +1,459 @@
|
||||||
|
/*!
|
||||||
|
* Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select)
|
||||||
|
*
|
||||||
|
* Copyright 2012-2020 SnapAppointments, LLC
|
||||||
|
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
@-webkit-keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-o-keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select.bs-select-hidden,
|
||||||
|
.bootstrap-select > select.bs-select-hidden,
|
||||||
|
select.selectpicker {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select {
|
||||||
|
width: 220px \0;
|
||||||
|
/*IE9 and below*/
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: -webkit-inline-box;
|
||||||
|
display: -webkit-inline-flex;
|
||||||
|
display: -ms-inline-flexbox;
|
||||||
|
display: inline-flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-box-pack: justify;
|
||||||
|
-webkit-justify-content: space-between;
|
||||||
|
-ms-flex-pack: justify;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle:after {
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
.bootstrap-select > select {
|
||||||
|
position: absolute !important;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
display: block !important;
|
||||||
|
width: 0.5px !important;
|
||||||
|
height: 100% !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
border: none;
|
||||||
|
z-index: 0 !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select > select.mobile-device {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: block !important;
|
||||||
|
width: 100% !important;
|
||||||
|
z-index: 2 !important;
|
||||||
|
}
|
||||||
|
.has-error .bootstrap-select .dropdown-toggle,
|
||||||
|
.error .bootstrap-select .dropdown-toggle,
|
||||||
|
.bootstrap-select.is-invalid .dropdown-toggle,
|
||||||
|
.was-validated .bootstrap-select select:invalid + .dropdown-toggle {
|
||||||
|
border-color: #b94a48;
|
||||||
|
}
|
||||||
|
.bootstrap-select.is-valid .dropdown-toggle,
|
||||||
|
.was-validated .bootstrap-select select:valid + .dropdown-toggle {
|
||||||
|
border-color: #28a745;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
.bootstrap-select > select.mobile-device:focus + .dropdown-toggle,
|
||||||
|
.bootstrap-select .dropdown-toggle:focus {
|
||||||
|
outline: thin dotted #333333 !important;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color !important;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control.input-group-btn {
|
||||||
|
float: none;
|
||||||
|
z-index: auto;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select,
|
||||||
|
.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select:not(.input-group-btn),
|
||||||
|
.bootstrap-select[class*="col-"] {
|
||||||
|
float: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.dropdown-menu-right,
|
||||||
|
.bootstrap-select[class*="col-"].dropdown-menu-right,
|
||||||
|
.row .bootstrap-select[class*="col-"].dropdown-menu-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select,
|
||||||
|
.form-horizontal .bootstrap-select,
|
||||||
|
.form-group .bootstrap-select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.form-group-lg .bootstrap-select.form-control,
|
||||||
|
.form-group-sm .bootstrap-select.form-control {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
|
||||||
|
.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
|
||||||
|
height: 100%;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-sm .dropdown-toggle,
|
||||||
|
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-sm .dropdown-toggle {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select .form-control {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select.disabled,
|
||||||
|
.bootstrap-select > .disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.bootstrap-select.disabled:focus,
|
||||||
|
.bootstrap-select > .disabled:focus {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select.bs-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select.bs-container .dropdown-menu {
|
||||||
|
z-index: 1060;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
position: static;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-webkit-flex: 0 1 auto;
|
||||||
|
-ms-flex: 0 1 auto;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
.bs3.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
padding-right: inherit;
|
||||||
|
}
|
||||||
|
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
position: absolute;
|
||||||
|
padding-top: inherit;
|
||||||
|
padding-bottom: inherit;
|
||||||
|
padding-left: inherit;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
|
||||||
|
padding-right: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-expand {
|
||||||
|
width: 0 !important;
|
||||||
|
float: left;
|
||||||
|
opacity: 0 !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .caret {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 12px;
|
||||||
|
margin-top: -2px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.input-group .bootstrap-select.form-control .dropdown-toggle {
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select[class*="col-"] .dropdown-toggle {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu {
|
||||||
|
min-width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu > .inner:focus {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu.inner {
|
||||||
|
position: static;
|
||||||
|
float: none;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li.active small {
|
||||||
|
color: rgba(255, 255, 255, 0.5) !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li.disabled a {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a {
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a.opt {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 2.25em;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a span.check-mark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a span.text {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li small {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu .notify {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
width: 96%;
|
||||||
|
margin: 0 2%;
|
||||||
|
min-height: 26px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.9;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu .notify.fadeOut {
|
||||||
|
-webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
-o-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
}
|
||||||
|
.bootstrap-select .no-results {
|
||||||
|
padding: 3px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
margin: 0 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option {
|
||||||
|
position: static;
|
||||||
|
display: inline;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
|
||||||
|
content: '\00a0';
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .caret {
|
||||||
|
position: static;
|
||||||
|
top: auto;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
right: 15px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-tick .dropdown-menu li a span.text {
|
||||||
|
margin-right: 34px;
|
||||||
|
}
|
||||||
|
.bootstrap-select .bs-ok-default:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 0.5em;
|
||||||
|
height: 1em;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0 0.26em 0.26em 0;
|
||||||
|
-webkit-transform-style: preserve-3d;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
-ms-transform: rotate(45deg);
|
||||||
|
-o-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
|
||||||
|
z-index: 1061;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
|
||||||
|
content: '';
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 9px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
|
||||||
|
content: '';
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid white;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
|
||||||
|
bottom: auto;
|
||||||
|
top: -4px;
|
||||||
|
border-top: 7px solid rgba(204, 204, 204, 0.2);
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
|
||||||
|
bottom: auto;
|
||||||
|
top: -4px;
|
||||||
|
border-top: 6px solid white;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
|
||||||
|
right: 12px;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
|
||||||
|
right: 13px;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bs-searchbox,
|
||||||
|
.bs-actionsbox,
|
||||||
|
.bs-donebutton {
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
.bs-actionsbox {
|
||||||
|
width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bs-actionsbox .btn-group button {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.bs-donebutton {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bs-donebutton .btn-group button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bs-searchbox + .bs-actionsbox {
|
||||||
|
padding: 0 8px 4px;
|
||||||
|
}
|
||||||
|
.bs-searchbox .form-control {
|
||||||
|
margin-bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
3247
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js
vendored
Normal file
3247
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css
vendored
Normal file
6
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js
vendored
Normal file
8
ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-select/bootstrap-select.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* @author: Alec Fenichel
|
||||||
|
* @webSite: https://fenichelar.com
|
||||||
|
* @update: zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
|
autoRefresh: false,
|
||||||
|
showAutoRefresh: true,
|
||||||
|
autoRefreshInterval: 60,
|
||||||
|
autoRefreshSilent: true,
|
||||||
|
autoRefreshStatus: true,
|
||||||
|
autoRefreshFunction: null
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
autoRefresh: {
|
||||||
|
bootstrap3: 'glyphicon-time icon-time',
|
||||||
|
bootstrap5: 'bi-clock',
|
||||||
|
materialize: 'access_time',
|
||||||
|
'bootstrap-table': 'icon-clock'
|
||||||
|
}[$.fn.bootstrapTable.theme] || 'fa-clock'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.locales, {
|
||||||
|
formatAutoRefresh () {
|
||||||
|
return 'Auto Refresh'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init (...args) {
|
||||||
|
super.init(...args)
|
||||||
|
|
||||||
|
if (this.options.autoRefresh && this.options.autoRefreshStatus) {
|
||||||
|
this.setupRefreshInterval()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initToolbar (...args) {
|
||||||
|
if (this.options.autoRefresh) {
|
||||||
|
this.buttons = Object.assign(this.buttons, {
|
||||||
|
autoRefresh: {
|
||||||
|
html: `
|
||||||
|
<button class="auto-refresh ${this.constants.buttonsClass}
|
||||||
|
${this.options.autoRefreshStatus ? ` ${this.constants.classes.buttonActive}` : ''}"
|
||||||
|
type="button" name="autoRefresh" title="${this.options.formatAutoRefresh()}">
|
||||||
|
${this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh) : ''}
|
||||||
|
${this.options.showButtonText ? this.options.formatAutoRefresh() : ''}
|
||||||
|
</button>
|
||||||
|
`,
|
||||||
|
event: this.toggleAutoRefresh
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initToolbar(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleAutoRefresh () {
|
||||||
|
if (this.options.autoRefresh) {
|
||||||
|
if (this.options.autoRefreshStatus) {
|
||||||
|
clearInterval(this.options.autoRefreshFunction)
|
||||||
|
this.$toolbar.find('>.columns .auto-refresh')
|
||||||
|
.removeClass(this.constants.classes.buttonActive)
|
||||||
|
} else {
|
||||||
|
this.setupRefreshInterval()
|
||||||
|
this.$toolbar.find('>.columns .auto-refresh')
|
||||||
|
.addClass(this.constants.classes.buttonActive)
|
||||||
|
}
|
||||||
|
this.options.autoRefreshStatus = !this.options.autoRefreshStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy () {
|
||||||
|
if (this.options.autoRefresh && this.options.autoRefreshStatus) {
|
||||||
|
clearInterval(this.options.autoRefreshFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
setupRefreshInterval () {
|
||||||
|
this.options.autoRefreshFunction = setInterval(() => {
|
||||||
|
if (!this.options.autoRefresh || !this.options.autoRefreshStatus) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.refresh({ silent: this.options.autoRefreshSilent })
|
||||||
|
}, this.options.autoRefreshInterval * 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
.fixed-table-header-columns,
|
|
||||||
.fixed-table-body-columns {
|
|
||||||
position: absolute;
|
|
||||||
background-color: #fff;
|
|
||||||
display: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed-table-header-columns .table,
|
|
||||||
.fixed-table-body-columns .table {
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed-table-header-columns .table.table-no-bordered,
|
|
||||||
.fixed-table-body-columns .table.table-no-bordered {
|
|
||||||
border-right: 1px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed-table-body-columns table {
|
|
||||||
position: absolute;
|
|
||||||
animation: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap-table .table-hover > tbody > tr.hover > td {
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,606 @@
|
||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
|
var UtilsCookie = {
|
||||||
|
cookieIds: {
|
||||||
|
sortOrder: 'bs.table.sortOrder',
|
||||||
|
sortName: 'bs.table.sortName',
|
||||||
|
sortPriority: 'bs.table.sortPriority',
|
||||||
|
pageNumber: 'bs.table.pageNumber',
|
||||||
|
pageList: 'bs.table.pageList',
|
||||||
|
hiddenColumns: 'bs.table.hiddenColumns',
|
||||||
|
cardView: 'bs.table.cardView',
|
||||||
|
customView: 'bs.table.customView',
|
||||||
|
searchText: 'bs.table.searchText',
|
||||||
|
reorderColumns: 'bs.table.reorderColumns',
|
||||||
|
filterControl: 'bs.table.filterControl',
|
||||||
|
filterBy: 'bs.table.filterBy'
|
||||||
|
},
|
||||||
|
getCurrentHeader (that) {
|
||||||
|
return that.options.height ? that.$tableHeader : that.$header
|
||||||
|
},
|
||||||
|
getCurrentSearchControls (that) {
|
||||||
|
return that.options.height ? 'table select, table input' : 'select, input'
|
||||||
|
},
|
||||||
|
isCookieSupportedByBrowser () {
|
||||||
|
return navigator.cookieEnabled
|
||||||
|
},
|
||||||
|
isCookieEnabled (that, cookieName) {
|
||||||
|
return that.options.cookiesEnabled.includes(cookieName)
|
||||||
|
},
|
||||||
|
setCookie (that, cookieName, cookieValue) {
|
||||||
|
if (
|
||||||
|
!that.options.cookie ||
|
||||||
|
!UtilsCookie.isCookieEnabled(that, cookieName)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return that._storage.setItem(`${that.options.cookieIdTable}.${cookieName}`, cookieValue)
|
||||||
|
},
|
||||||
|
getCookie (that, cookieName) {
|
||||||
|
if (
|
||||||
|
!cookieName ||
|
||||||
|
!UtilsCookie.isCookieEnabled(that, cookieName)
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return that._storage.getItem(`${that.options.cookieIdTable}.${cookieName}`)
|
||||||
|
},
|
||||||
|
deleteCookie (that, cookieName) {
|
||||||
|
return that._storage.removeItem(`${that.options.cookieIdTable}.${cookieName}`)
|
||||||
|
},
|
||||||
|
calculateExpiration (cookieExpire) {
|
||||||
|
const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
|
||||||
|
|
||||||
|
cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
|
||||||
|
|
||||||
|
switch (time.toLowerCase()) {
|
||||||
|
case 's':
|
||||||
|
cookieExpire = +cookieExpire
|
||||||
|
break
|
||||||
|
case 'mi':
|
||||||
|
cookieExpire *= 60
|
||||||
|
break
|
||||||
|
case 'h':
|
||||||
|
cookieExpire = cookieExpire * 60 * 60
|
||||||
|
break
|
||||||
|
case 'd':
|
||||||
|
cookieExpire = cookieExpire * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
case 'm':
|
||||||
|
cookieExpire = cookieExpire * 30 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
case 'y':
|
||||||
|
cookieExpire = cookieExpire * 365 * 24 * 60 * 60
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
cookieExpire = undefined
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (!cookieExpire) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const d = new Date()
|
||||||
|
|
||||||
|
d.setTime(d.getTime() + cookieExpire * 1000)
|
||||||
|
return d.toGMTString()
|
||||||
|
},
|
||||||
|
initCookieFilters (that) {
|
||||||
|
setTimeout(() => {
|
||||||
|
const parsedCookieFilters = JSON.parse(
|
||||||
|
UtilsCookie.getCookie(that, UtilsCookie.cookieIds.filterControl))
|
||||||
|
|
||||||
|
if (!that._filterControlValuesLoaded && parsedCookieFilters) {
|
||||||
|
const cachedFilters = {}
|
||||||
|
const header = UtilsCookie.getCurrentHeader(that)
|
||||||
|
const searchControls = UtilsCookie.getCurrentSearchControls(that)
|
||||||
|
|
||||||
|
const applyCookieFilters = (element, filteredCookies) => {
|
||||||
|
filteredCookies.forEach(cookie => {
|
||||||
|
const value = element.value.toString()
|
||||||
|
const text = cookie.text
|
||||||
|
|
||||||
|
if (
|
||||||
|
text === '' ||
|
||||||
|
element.type === 'radio' &&
|
||||||
|
value !== text
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
element.tagName === 'INPUT' &&
|
||||||
|
element.type === 'radio' &&
|
||||||
|
value === text
|
||||||
|
) {
|
||||||
|
element.checked = true
|
||||||
|
cachedFilters[cookie.field] = text
|
||||||
|
} else if (element.tagName === 'INPUT') {
|
||||||
|
element.value = text
|
||||||
|
cachedFilters[cookie.field] = text
|
||||||
|
} else if (
|
||||||
|
element.tagName === 'SELECT' &&
|
||||||
|
that.options.filterControlContainer
|
||||||
|
) {
|
||||||
|
element.value = text
|
||||||
|
cachedFilters[cookie.field] = text
|
||||||
|
} else if (text !== '' && element.tagName === 'SELECT') {
|
||||||
|
cachedFilters[cookie.field] = text
|
||||||
|
for (const currentElement of element) {
|
||||||
|
if (currentElement.value === text) {
|
||||||
|
currentElement.selected = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const option = document.createElement('option')
|
||||||
|
|
||||||
|
option.value = text
|
||||||
|
option.text = text
|
||||||
|
element.add(option, element[1])
|
||||||
|
element.selectedIndex = 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let filterContainer = header
|
||||||
|
|
||||||
|
if (that.options.filterControlContainer) {
|
||||||
|
filterContainer = $(`${that.options.filterControlContainer}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
filterContainer.find(searchControls).each(function () {
|
||||||
|
const field = $(this).closest('[data-field]').data('field')
|
||||||
|
const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
|
||||||
|
|
||||||
|
applyCookieFilters(this, filteredCookies)
|
||||||
|
})
|
||||||
|
|
||||||
|
that.initColumnSearch(cachedFilters)
|
||||||
|
that._filterControlValuesLoaded = true
|
||||||
|
that.initServer()
|
||||||
|
}
|
||||||
|
}, 250)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
cookie: false,
|
||||||
|
cookieExpire: '2h',
|
||||||
|
cookiePath: null,
|
||||||
|
cookieDomain: null,
|
||||||
|
cookieSecure: null,
|
||||||
|
cookieSameSite: 'Lax',
|
||||||
|
cookieIdTable: '',
|
||||||
|
cookiesEnabled: [
|
||||||
|
'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority',
|
||||||
|
'bs.table.pageNumber', 'bs.table.pageList',
|
||||||
|
'bs.table.hiddenColumns', 'bs.table.searchText',
|
||||||
|
'bs.table.filterControl', 'bs.table.filterBy',
|
||||||
|
'bs.table.reorderColumns', 'bs.table.cardView', 'bs.table.customView'
|
||||||
|
],
|
||||||
|
cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
|
||||||
|
cookieCustomStorageGet: null,
|
||||||
|
cookieCustomStorageSet: null,
|
||||||
|
cookieCustomStorageDelete: null,
|
||||||
|
// internal variable
|
||||||
|
_filterControls: [],
|
||||||
|
_filterControlValuesLoaded: false,
|
||||||
|
_storage: {
|
||||||
|
setItem: undefined,
|
||||||
|
getItem: undefined,
|
||||||
|
removeItem: undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('getCookies')
|
||||||
|
$.fn.bootstrapTable.methods.push('deleteCookie')
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.utils, {
|
||||||
|
setCookie: UtilsCookie.setCookie,
|
||||||
|
getCookie: UtilsCookie.getCookie
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init () {
|
||||||
|
if (this.options.cookie) {
|
||||||
|
if (
|
||||||
|
this.options.cookieStorage === 'cookieStorage' &&
|
||||||
|
!UtilsCookie.isCookieSupportedByBrowser()
|
||||||
|
) {
|
||||||
|
throw new Error('Cookies are not enabled in this browser.')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.configureStorage()
|
||||||
|
|
||||||
|
// FilterBy logic
|
||||||
|
const filterByCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterBy)
|
||||||
|
|
||||||
|
if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) {
|
||||||
|
throw new Error('The cookie value of filterBy must be a json!')
|
||||||
|
}
|
||||||
|
|
||||||
|
let filterByCookie = {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
filterByCookie = JSON.parse(filterByCookieValue)
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Could not parse the json of the filterBy cookie!')
|
||||||
|
}
|
||||||
|
this.filterColumns = filterByCookie ? filterByCookie : {}
|
||||||
|
|
||||||
|
// FilterControl logic
|
||||||
|
this._filterControls = []
|
||||||
|
this._filterControlValuesLoaded = false
|
||||||
|
|
||||||
|
this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
|
||||||
|
this.options.cookiesEnabled.replace('[', '').replace(']', '')
|
||||||
|
.replace(/'/g, '').replace(/ /g, '').split(',') :
|
||||||
|
this.options.cookiesEnabled
|
||||||
|
|
||||||
|
if (this.options.filterControl) {
|
||||||
|
const that = this
|
||||||
|
|
||||||
|
this.$el.on('column-search.bs.table', (e, field, text) => {
|
||||||
|
let isNewField = true
|
||||||
|
|
||||||
|
for (let i = 0; i < that._filterControls.length; i++) {
|
||||||
|
if (that._filterControls[i].field === field) {
|
||||||
|
that._filterControls[i].text = text
|
||||||
|
isNewField = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNewField) {
|
||||||
|
that._filterControls.push({
|
||||||
|
field,
|
||||||
|
text
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that._filterControls))
|
||||||
|
}).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
initServer (...args) {
|
||||||
|
if (
|
||||||
|
this.options.cookie &&
|
||||||
|
this.options.filterControl &&
|
||||||
|
!this._filterControlValuesLoaded
|
||||||
|
) {
|
||||||
|
const cookie = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterControl))
|
||||||
|
|
||||||
|
if (cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.initServer(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
initTable (...args) {
|
||||||
|
super.initTable(...args)
|
||||||
|
this.initCookie()
|
||||||
|
}
|
||||||
|
|
||||||
|
onSort (...args) {
|
||||||
|
super.onSort(...args)
|
||||||
|
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.sortName === undefined || this.options.sortOrder === undefined) {
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||||
|
} else {
|
||||||
|
this.options.sortPriority = null
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||||
|
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMultipleSort (...args) {
|
||||||
|
super.onMultipleSort(...args)
|
||||||
|
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.sortPriority === undefined) {
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||||
|
} else {
|
||||||
|
this.options.sortName = undefined
|
||||||
|
this.options.sortOrder = undefined
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||||
|
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageNumber (...args) {
|
||||||
|
super.onPageNumber(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageListChange (...args) {
|
||||||
|
super.onPageListChange(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList,
|
||||||
|
this.options.pageSize === this.options.formatAllRows() ? 'all' : this.options.pageSize)
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPagePre (...args) {
|
||||||
|
super.onPagePre(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageNext (...args) {
|
||||||
|
super.onPageNext(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
_toggleColumn (...args) {
|
||||||
|
super._toggleColumn(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_toggleAllColumns (...args) {
|
||||||
|
super._toggleAllColumns(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field)))
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleView () {
|
||||||
|
super.toggleView()
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.cardView, this.options.cardView)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCustomView () {
|
||||||
|
super.toggleCustomView()
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.customView, this.customViewDefaultView)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectPage (page) {
|
||||||
|
super.selectPage(page)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch (event) {
|
||||||
|
super.onSearch(event, arguments.length > 1 ? arguments[1] : true)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.options.search) {
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
initHeader (...args) {
|
||||||
|
if (this.options.reorderableColumns && this.options.cookie) {
|
||||||
|
this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.reorderColumns))
|
||||||
|
}
|
||||||
|
super.initHeader(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistReorderColumnsState (that) {
|
||||||
|
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder))
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBy (...args) {
|
||||||
|
super.filterBy(...args)
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
|
||||||
|
}
|
||||||
|
|
||||||
|
initCookie () {
|
||||||
|
if (!this.options.cookie) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.cookieIdTable === '' || this.options.cookieExpire === '') {
|
||||||
|
console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
|
||||||
|
this.options.cookie = false // Make sure that the cookie extension is disabled
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortOrderCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortOrder)
|
||||||
|
const sortOrderNameCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortName)
|
||||||
|
let sortPriorityCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortPriority)
|
||||||
|
const pageNumberCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageNumber)
|
||||||
|
const pageListCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageList)
|
||||||
|
const searchTextCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.searchText)
|
||||||
|
const cardViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.cardView)
|
||||||
|
const customViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.customView)
|
||||||
|
const hiddenColumnsCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.hiddenColumns)
|
||||||
|
|
||||||
|
let hiddenColumnsCookie = {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
hiddenColumnsCookie = JSON.parse(hiddenColumnsCookieValue)
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Could not parse the json of the hidden columns cookie!', hiddenColumnsCookieValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sortPriorityCookie = JSON.parse(sortPriorityCookie)
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Could not parse the json of the sortPriority cookie!', sortPriorityCookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sortPriorityCookie) {
|
||||||
|
// sortOrder
|
||||||
|
this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
|
||||||
|
// sortName
|
||||||
|
this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
|
||||||
|
} else {
|
||||||
|
this.options.sortOrder = undefined
|
||||||
|
this.options.sortName = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortPriority
|
||||||
|
this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority
|
||||||
|
|
||||||
|
if (this.options.sortOrder || this.options.sortName) {
|
||||||
|
// sortPriority
|
||||||
|
this.options.sortPriority = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// pageNumber
|
||||||
|
this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
|
||||||
|
// pageSize
|
||||||
|
this.options.pageSize = pageListCookie ? pageListCookie === 'all' ?
|
||||||
|
this.options.formatAllRows() : +pageListCookie : this.options.pageSize
|
||||||
|
// searchText
|
||||||
|
if (UtilsCookie.isCookieEnabled(this, UtilsCookie.cookieIds.searchText) && this.options.searchText === '') {
|
||||||
|
this.options.searchText = searchTextCookie ? searchTextCookie : ''
|
||||||
|
}
|
||||||
|
// cardView
|
||||||
|
if (cardViewCookie !== null) {
|
||||||
|
this.options.cardView = cardViewCookie === 'true' ? cardViewCookie : false
|
||||||
|
}
|
||||||
|
this.customViewDefaultView = customViewCookie === 'true'
|
||||||
|
|
||||||
|
if (hiddenColumnsCookie) {
|
||||||
|
for (const column of this.columns) {
|
||||||
|
if (!column.switchable) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
column.visible = this.isSelectionColumn(column) ||
|
||||||
|
!hiddenColumnsCookie.includes(column.field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCookies () {
|
||||||
|
const bootstrapTable = this
|
||||||
|
const cookies = {}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(UtilsCookie.cookieIds)) {
|
||||||
|
cookies[key] = UtilsCookie.getCookie(bootstrapTable, value)
|
||||||
|
if (key === 'columns' || key === 'hiddenColumns' || key === 'sortPriority') {
|
||||||
|
cookies[key] = JSON.parse(cookies[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookies
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCookie (cookieName) {
|
||||||
|
if (!cookieName) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds[cookieName])
|
||||||
|
}
|
||||||
|
|
||||||
|
configureStorage () {
|
||||||
|
const that = this
|
||||||
|
|
||||||
|
this._storage = {}
|
||||||
|
switch (this.options.cookieStorage) {
|
||||||
|
case 'cookieStorage':
|
||||||
|
this._storage.setItem = function (cookieName, cookieValue) {
|
||||||
|
document.cookie = [
|
||||||
|
cookieName, '=', encodeURIComponent(cookieValue),
|
||||||
|
`; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
|
||||||
|
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||||
|
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
|
||||||
|
that.options.cookieSecure ? '; secure' : '',
|
||||||
|
`;SameSite=${that.options.cookieSameSite}`
|
||||||
|
].join('')
|
||||||
|
}
|
||||||
|
this._storage.getItem = function (cookieName) {
|
||||||
|
const value = `; ${document.cookie}`
|
||||||
|
const parts = value.split(`; ${cookieName}=`)
|
||||||
|
|
||||||
|
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
|
||||||
|
}
|
||||||
|
this._storage.removeItem = function (cookieName) {
|
||||||
|
document.cookie = [
|
||||||
|
encodeURIComponent(cookieName), '=',
|
||||||
|
'; expires=Thu, 01 Jan 1970 00:00:00 GMT',
|
||||||
|
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
|
||||||
|
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
|
||||||
|
`;SameSite=${that.options.cookieSameSite}`
|
||||||
|
].join('')
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'localStorage':
|
||||||
|
this._storage.setItem = function (cookieName, cookieValue) {
|
||||||
|
localStorage.setItem(cookieName, cookieValue)
|
||||||
|
}
|
||||||
|
this._storage.getItem = function (cookieName) {
|
||||||
|
return localStorage.getItem(cookieName)
|
||||||
|
}
|
||||||
|
this._storage.removeItem = function (cookieName) {
|
||||||
|
localStorage.removeItem(cookieName)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'sessionStorage':
|
||||||
|
this._storage.setItem = function (cookieName, cookieValue) {
|
||||||
|
sessionStorage.setItem(cookieName, cookieValue)
|
||||||
|
}
|
||||||
|
this._storage.getItem = function (cookieName) {
|
||||||
|
return sessionStorage.getItem(cookieName)
|
||||||
|
}
|
||||||
|
this._storage.removeItem = function (cookieName) {
|
||||||
|
sessionStorage.removeItem(cookieName)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'customStorage':
|
||||||
|
if (
|
||||||
|
!this.options.cookieCustomStorageSet ||
|
||||||
|
!this.options.cookieCustomStorageGet ||
|
||||||
|
!this.options.cookieCustomStorageDelete
|
||||||
|
) {
|
||||||
|
throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
|
||||||
|
}
|
||||||
|
|
||||||
|
this._storage.setItem = function (cookieName, cookieValue) {
|
||||||
|
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '')
|
||||||
|
}
|
||||||
|
this._storage.getItem = function (cookieName) {
|
||||||
|
return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '')
|
||||||
|
}
|
||||||
|
this._storage.removeItem = function (cookieName) {
|
||||||
|
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '')
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new Error('Storage method not supported.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
/**
|
||||||
|
* @author: Dustin Utecht
|
||||||
|
* @github: https://github.com/UtechtDustin
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
customView: false,
|
||||||
|
showCustomView: false,
|
||||||
|
customViewDefaultView: false
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
customViewOn: {
|
||||||
|
bootstrap3: 'glyphicon glyphicon-list',
|
||||||
|
bootstrap5: 'bi-list',
|
||||||
|
bootstrap4: 'fa fa-list',
|
||||||
|
semantic: 'fa fa-list',
|
||||||
|
foundation: 'fa fa-list',
|
||||||
|
bulma: 'fa fa-list',
|
||||||
|
materialize: 'list'
|
||||||
|
}[$.fn.bootstrapTable.theme] || 'fa-list',
|
||||||
|
customViewOff: {
|
||||||
|
bootstrap3: 'glyphicon glyphicon-eye-open',
|
||||||
|
bootstrap5: 'bi-grid',
|
||||||
|
bootstrap4: 'fa fa-th',
|
||||||
|
semantic: 'fa fa-th',
|
||||||
|
foundation: 'fa fa-th',
|
||||||
|
bulma: 'fa fa-th',
|
||||||
|
materialize: 'grid_on'
|
||||||
|
}[$.fn.bootstrapTable.theme] || 'fa-th'
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
onCustomViewPostBody () {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onCustomViewPreBody () {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onToggleCustomView () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.locales, {
|
||||||
|
formatToggleCustomViewOn () {
|
||||||
|
return 'Show custom view'
|
||||||
|
},
|
||||||
|
formatToggleCustomViewOff () {
|
||||||
|
return 'Hide custom view'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('toggleCustomView')
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.events, {
|
||||||
|
'custom-view-post-body.bs.table': 'onCustomViewPostBody',
|
||||||
|
'custom-view-pre-body.bs.table': 'onCustomViewPreBody',
|
||||||
|
'toggle-custom-view.bs.table': 'onToggleCustomView'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
|
||||||
|
init () {
|
||||||
|
this.customViewDefaultView = this.options.customViewDefaultView
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
initToolbar (...args) {
|
||||||
|
if (this.options.customView && this.options.showCustomView) {
|
||||||
|
this.buttons = Object.assign(this.buttons, {
|
||||||
|
customView: {
|
||||||
|
text: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
|
||||||
|
icon: this.options.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff,
|
||||||
|
event: this.toggleCustomView,
|
||||||
|
attributes: {
|
||||||
|
'aria-label': this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(),
|
||||||
|
title: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initToolbar(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
initBody () {
|
||||||
|
super.initBody()
|
||||||
|
|
||||||
|
if (!this.options.customView) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const $table = this.$el
|
||||||
|
const $customViewContainer = this.$container.find('.fixed-table-custom-view')
|
||||||
|
|
||||||
|
$table.hide()
|
||||||
|
$customViewContainer.hide()
|
||||||
|
if (!this.options.customView || !this.customViewDefaultView) {
|
||||||
|
$table.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this.getData().slice(this.pageFrom - 1, this.pageTo)
|
||||||
|
const value = Utils.calculateObjectValue(this, this.options.customView, [data], '')
|
||||||
|
|
||||||
|
this.trigger('custom-view-pre-body', data, value)
|
||||||
|
if ($customViewContainer.length === 1) {
|
||||||
|
$customViewContainer.show().html(value)
|
||||||
|
} else {
|
||||||
|
this.$tableBody.after(`<div class="fixed-table-custom-view">${value}</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.trigger('custom-view-post-body', data, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCustomView () {
|
||||||
|
this.customViewDefaultView = !this.customViewDefaultView
|
||||||
|
|
||||||
|
const icon = this.options.showButtonIcons ? this.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff : ''
|
||||||
|
const text = this.options.showButtonText ? this.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn() : ''
|
||||||
|
|
||||||
|
this.$toolbar.find('button[name="customView"]')
|
||||||
|
.html(`${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon)} ${text}`)
|
||||||
|
.attr('aria-label', text)
|
||||||
|
.attr('title', text)
|
||||||
|
|
||||||
|
this.initBody()
|
||||||
|
this.trigger('toggle-custom-view', this.customViewDefaultView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,674 @@
|
||||||
|
/*! X-editable - v1.5.3
|
||||||
|
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
||||||
|
* http://github.com/vitalets/x-editable
|
||||||
|
* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */
|
||||||
|
.editableform {
|
||||||
|
margin-bottom: 0; /* overwrites bootstrap margin */
|
||||||
|
}
|
||||||
|
|
||||||
|
.editableform .control-group {
|
||||||
|
margin-bottom: 0; /* overwrites bootstrap margin */
|
||||||
|
white-space: nowrap; /* prevent wrapping buttons on new line */
|
||||||
|
line-height: 20px; /* overwriting bootstrap line-height. See #133 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BS3 fix: stop css from breaking when the form is inside a popup and inside a form with the class .form-horizontal
|
||||||
|
See: https://github.com/vitalets/x-editable/issues/682
|
||||||
|
*/
|
||||||
|
.form-horizontal .editable-popup .editableform .form-group {
|
||||||
|
margin-left:0;
|
||||||
|
margin-right:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
BS3 width:1005 for inputs breaks editable form in popup
|
||||||
|
See: https://github.com/vitalets/x-editable/issues/393
|
||||||
|
*/
|
||||||
|
.editableform .form-control {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-buttons {
|
||||||
|
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
||||||
|
vertical-align: top;
|
||||||
|
margin-left: 7px;
|
||||||
|
/* inline-block emulation for IE7*/
|
||||||
|
zoom: 1;
|
||||||
|
*display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-buttons.editable-buttons-bottom {
|
||||||
|
display: block;
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-input {
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
||||||
|
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
|
||||||
|
white-space: normal; /* reset white-space decalred in parent*/
|
||||||
|
/* display-inline emulation for IE7*/
|
||||||
|
zoom: 1;
|
||||||
|
*display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-buttons .editable-cancel {
|
||||||
|
margin-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for jquery-ui buttons need set height to look more pretty*/
|
||||||
|
.editable-buttons button.ui-button-icon-only {
|
||||||
|
height: 24px;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editableform-loading {
|
||||||
|
background: url('loading.gif') center center no-repeat;
|
||||||
|
height: 25px;
|
||||||
|
width: auto;
|
||||||
|
min-width: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-inline .editableform-loading {
|
||||||
|
background-position: left 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-error-block {
|
||||||
|
max-width: 300px;
|
||||||
|
margin: 5px 0 0 0;
|
||||||
|
width: auto;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*add padding for jquery ui*/
|
||||||
|
.editable-error-block.ui-state-error {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- For specific types ---- */
|
||||||
|
|
||||||
|
.editableform .editable-date {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
|
||||||
|
.editable-inline .add-on .icon-th {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* checklist vertical alignment */
|
||||||
|
.editable-checklist label input[type="checkbox"],
|
||||||
|
.editable-checklist label span {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-checklist label {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set exact width of textarea to fit buttons toolbar */
|
||||||
|
.editable-wysihtml5 {
|
||||||
|
width: 566px;
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear button shown as link in date inputs */
|
||||||
|
.editable-clear {
|
||||||
|
clear: both;
|
||||||
|
font-size: 0.9em;
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IOS-style clear button for text inputs */
|
||||||
|
.editable-clear-x {
|
||||||
|
background: url('clear.png') center center no-repeat;
|
||||||
|
display: block;
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.6;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
top: 50%;
|
||||||
|
right: 6px;
|
||||||
|
margin-top: -6px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-clear-x:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-pre-wrapped {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-container.editable-popup {
|
||||||
|
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-container.popover {
|
||||||
|
width: auto; /* without this rule popover does not stretch */
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-container.editable-inline {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: auto;
|
||||||
|
/* inline-block emulation for IE7*/
|
||||||
|
zoom: 1;
|
||||||
|
*display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-container.ui-widget {
|
||||||
|
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
|
||||||
|
z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
|
||||||
|
}
|
||||||
|
.editable-click,
|
||||||
|
a.editable-click,
|
||||||
|
a.editable-click:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: dashed 1px #0088cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-click.editable-disabled,
|
||||||
|
a.editable-click.editable-disabled,
|
||||||
|
a.editable-click.editable-disabled:hover {
|
||||||
|
color: #585858;
|
||||||
|
cursor: default;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-empty, .editable-empty:hover, .editable-empty:focus{
|
||||||
|
font-style: italic;
|
||||||
|
color: #DD1144;
|
||||||
|
/* border-bottom: none; */
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-unsaved {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-unsaved:after {
|
||||||
|
/* content: '*'*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable-bg-transition {
|
||||||
|
-webkit-transition: background-color 1400ms ease-out;
|
||||||
|
-moz-transition: background-color 1400ms ease-out;
|
||||||
|
-o-transition: background-color 1400ms ease-out;
|
||||||
|
-ms-transition: background-color 1400ms ease-out;
|
||||||
|
transition: background-color 1400ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*see https://github.com/vitalets/x-editable/issues/139 */
|
||||||
|
.form-horizontal .editable
|
||||||
|
{
|
||||||
|
padding-top: 5px;
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Datepicker for Bootstrap
|
||||||
|
*
|
||||||
|
* Copyright 2012 Stefan Petre
|
||||||
|
* Improvements by Andrew Rowls
|
||||||
|
* Licensed under the Apache License v2.0
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
.datepicker {
|
||||||
|
padding: 4px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
direction: ltr;
|
||||||
|
/*.dow {
|
||||||
|
border-top: 1px solid #ddd !important;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
.datepicker-inline {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
.datepicker.datepicker-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
.datepicker.datepicker-rtl table tr td span {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid #ccc;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
top: -7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
.datepicker-dropdown:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid #ffffff;
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
.datepicker > div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.datepicker.days div.datepicker-days {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.datepicker.months div.datepicker-months {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.datepicker.years div.datepicker-years {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.datepicker table {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.datepicker td,
|
||||||
|
.datepicker th {
|
||||||
|
text-align: center;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.table-striped .datepicker table tr td,
|
||||||
|
.table-striped .datepicker table tr th {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.day:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.old,
|
||||||
|
.datepicker table tr td.new {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.disabled,
|
||||||
|
.datepicker table tr td.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today,
|
||||||
|
.datepicker table tr td.today:hover,
|
||||||
|
.datepicker table tr td.today.disabled,
|
||||||
|
.datepicker table tr td.today.disabled:hover {
|
||||||
|
background-color: #fde19a;
|
||||||
|
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
||||||
|
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
||||||
|
border-color: #fdf59a #fdf59a #fbed50;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:hover,
|
||||||
|
.datepicker table tr td.today:hover:hover,
|
||||||
|
.datepicker table tr td.today.disabled:hover,
|
||||||
|
.datepicker table tr td.today.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.today:active,
|
||||||
|
.datepicker table tr td.today:hover:active,
|
||||||
|
.datepicker table tr td.today.disabled:active,
|
||||||
|
.datepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.today.active,
|
||||||
|
.datepicker table tr td.today:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled.active,
|
||||||
|
.datepicker table tr td.today.disabled:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled,
|
||||||
|
.datepicker table tr td.today:hover.disabled,
|
||||||
|
.datepicker table tr td.today.disabled.disabled,
|
||||||
|
.datepicker table tr td.today.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.today[disabled],
|
||||||
|
.datepicker table tr td.today:hover[disabled],
|
||||||
|
.datepicker table tr td.today.disabled[disabled],
|
||||||
|
.datepicker table tr td.today.disabled:hover[disabled] {
|
||||||
|
background-color: #fdf59a;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:active,
|
||||||
|
.datepicker table tr td.today:hover:active,
|
||||||
|
.datepicker table tr td.today.disabled:active,
|
||||||
|
.datepicker table tr td.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.today.active,
|
||||||
|
.datepicker table tr td.today:hover.active,
|
||||||
|
.datepicker table tr td.today.disabled.active,
|
||||||
|
.datepicker table tr td.today.disabled:hover.active {
|
||||||
|
background-color: #fbf069 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today:hover:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.today.active:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range,
|
||||||
|
.datepicker table tr td.range:hover,
|
||||||
|
.datepicker table tr td.range.disabled,
|
||||||
|
.datepicker table tr td.range.disabled:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today,
|
||||||
|
.datepicker table tr td.range.today:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover {
|
||||||
|
background-color: #f3d17a;
|
||||||
|
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
|
||||||
|
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
||||||
|
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
|
||||||
|
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
|
||||||
|
background-image: linear-gradient(top, #f3c17a, #f3e97a);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
||||||
|
border-color: #f3e97a #f3e97a #edde34;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today:hover,
|
||||||
|
.datepicker table tr td.range.today:hover:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.range.today:active,
|
||||||
|
.datepicker table tr td.range.today:hover:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.range.today.active,
|
||||||
|
.datepicker table tr td.range.today:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled.active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled,
|
||||||
|
.datepicker table tr td.range.today:hover.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled.disabled,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.range.today[disabled],
|
||||||
|
.datepicker table tr td.range.today:hover[disabled],
|
||||||
|
.datepicker table tr td.range.today.disabled[disabled],
|
||||||
|
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
||||||
|
background-color: #f3e97a;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.range.today:active,
|
||||||
|
.datepicker table tr td.range.today:hover:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover:active,
|
||||||
|
.datepicker table tr td.range.today.active,
|
||||||
|
.datepicker table tr td.range.today:hover.active,
|
||||||
|
.datepicker table tr td.range.today.disabled.active,
|
||||||
|
.datepicker table tr td.range.today.disabled:hover.active {
|
||||||
|
background-color: #efe24b \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected,
|
||||||
|
.datepicker table tr td.selected:hover,
|
||||||
|
.datepicker table tr td.selected.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled:hover {
|
||||||
|
background-color: #9e9e9e;
|
||||||
|
background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
|
||||||
|
background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
||||||
|
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
|
||||||
|
background-image: -o-linear-gradient(top, #b3b3b3, #808080);
|
||||||
|
background-image: linear-gradient(top, #b3b3b3, #808080);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
||||||
|
border-color: #808080 #808080 #595959;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected:hover,
|
||||||
|
.datepicker table tr td.selected:hover:hover,
|
||||||
|
.datepicker table tr td.selected.disabled:hover,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.selected:active,
|
||||||
|
.datepicker table tr td.selected:hover:active,
|
||||||
|
.datepicker table tr td.selected.disabled:active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:active,
|
||||||
|
.datepicker table tr td.selected.active,
|
||||||
|
.datepicker table tr td.selected:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled.active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled,
|
||||||
|
.datepicker table tr td.selected:hover.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled.disabled,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.selected[disabled],
|
||||||
|
.datepicker table tr td.selected:hover[disabled],
|
||||||
|
.datepicker table tr td.selected.disabled[disabled],
|
||||||
|
.datepicker table tr td.selected.disabled:hover[disabled] {
|
||||||
|
background-color: #808080;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.selected:active,
|
||||||
|
.datepicker table tr td.selected:hover:active,
|
||||||
|
.datepicker table tr td.selected.disabled:active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover:active,
|
||||||
|
.datepicker table tr td.selected.active,
|
||||||
|
.datepicker table tr td.selected:hover.active,
|
||||||
|
.datepicker table tr td.selected.disabled.active,
|
||||||
|
.datepicker table tr td.selected.disabled:hover.active {
|
||||||
|
background-color: #666666 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active,
|
||||||
|
.datepicker table tr td.active:hover,
|
||||||
|
.datepicker table tr td.active.disabled,
|
||||||
|
.datepicker table tr td.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active:hover,
|
||||||
|
.datepicker table tr td.active:hover:hover,
|
||||||
|
.datepicker table tr td.active.disabled:hover,
|
||||||
|
.datepicker table tr td.active.disabled:hover:hover,
|
||||||
|
.datepicker table tr td.active:active,
|
||||||
|
.datepicker table tr td.active:hover:active,
|
||||||
|
.datepicker table tr td.active.disabled:active,
|
||||||
|
.datepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td.active.active,
|
||||||
|
.datepicker table tr td.active:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled.active,
|
||||||
|
.datepicker table tr td.active.disabled:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled,
|
||||||
|
.datepicker table tr td.active:hover.disabled,
|
||||||
|
.datepicker table tr td.active.disabled.disabled,
|
||||||
|
.datepicker table tr td.active.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td.active[disabled],
|
||||||
|
.datepicker table tr td.active:hover[disabled],
|
||||||
|
.datepicker table tr td.active.disabled[disabled],
|
||||||
|
.datepicker table tr td.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
.datepicker table tr td.active:active,
|
||||||
|
.datepicker table tr td.active:hover:active,
|
||||||
|
.datepicker table tr td.active.disabled:active,
|
||||||
|
.datepicker table tr td.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td.active.active,
|
||||||
|
.datepicker table tr td.active:hover.active,
|
||||||
|
.datepicker table tr td.active.disabled.active,
|
||||||
|
.datepicker table tr td.active.disabled:hover.active {
|
||||||
|
background-color: #003399 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span {
|
||||||
|
display: block;
|
||||||
|
width: 23%;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 54px;
|
||||||
|
float: left;
|
||||||
|
margin: 1%;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.disabled,
|
||||||
|
.datepicker table tr td span.disabled:hover {
|
||||||
|
background: none;
|
||||||
|
color: #999999;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active,
|
||||||
|
.datepicker table tr td span.active:hover,
|
||||||
|
.datepicker table tr td span.active.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled:hover {
|
||||||
|
background-color: #006dcc;
|
||||||
|
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
||||||
|
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-image: linear-gradient(top, #0088cc, #0044cc);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
||||||
|
border-color: #0044cc #0044cc #002a80;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active:hover,
|
||||||
|
.datepicker table tr td span.active:hover:hover,
|
||||||
|
.datepicker table tr td span.active.disabled:hover,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:hover,
|
||||||
|
.datepicker table tr td span.active:active,
|
||||||
|
.datepicker table tr td span.active:hover:active,
|
||||||
|
.datepicker table tr td span.active.disabled:active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td span.active.active,
|
||||||
|
.datepicker table tr td span.active:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled.active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled,
|
||||||
|
.datepicker table tr td span.active:hover.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled.disabled,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.disabled,
|
||||||
|
.datepicker table tr td span.active[disabled],
|
||||||
|
.datepicker table tr td span.active:hover[disabled],
|
||||||
|
.datepicker table tr td span.active.disabled[disabled],
|
||||||
|
.datepicker table tr td span.active.disabled:hover[disabled] {
|
||||||
|
background-color: #0044cc;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.active:active,
|
||||||
|
.datepicker table tr td span.active:hover:active,
|
||||||
|
.datepicker table tr td span.active.disabled:active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover:active,
|
||||||
|
.datepicker table tr td span.active.active,
|
||||||
|
.datepicker table tr td span.active:hover.active,
|
||||||
|
.datepicker table tr td span.active.disabled.active,
|
||||||
|
.datepicker table tr td span.active.disabled:hover.active {
|
||||||
|
background-color: #003399 \9;
|
||||||
|
}
|
||||||
|
.datepicker table tr td span.old,
|
||||||
|
.datepicker table tr td span.new {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.datepicker th.datepicker-switch {
|
||||||
|
width: 145px;
|
||||||
|
}
|
||||||
|
.datepicker thead tr:first-child th,
|
||||||
|
.datepicker tfoot tr th {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.datepicker thead tr:first-child th:hover,
|
||||||
|
.datepicker tfoot tr th:hover {
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
.datepicker .cw {
|
||||||
|
font-size: 10px;
|
||||||
|
width: 12px;
|
||||||
|
padding: 0 2px 0 5px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.datepicker thead tr:first-child th.cw {
|
||||||
|
cursor: default;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.input-append.date .add-on i,
|
||||||
|
.input-prepend.date .add-on i {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
.input-daterange input {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.input-daterange input:first-child {
|
||||||
|
-webkit-border-radius: 3px 0 0 3px;
|
||||||
|
-moz-border-radius: 3px 0 0 3px;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
}
|
||||||
|
.input-daterange input:last-child {
|
||||||
|
-webkit-border-radius: 0 3px 3px 0;
|
||||||
|
-moz-border-radius: 0 3px 3px 0;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
||||||
|
.input-daterange .add-on {
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
min-width: 16px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 4px 5px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 0 #ffffff;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-left: -5px;
|
||||||
|
margin-right: -5px;
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,146 +1,189 @@
|
||||||
/**
|
/* eslint-disable no-unused-vars */
|
||||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
/**
|
||||||
* extensions: https://github.com/vitalets/x-editable
|
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||||
*/
|
* extensions: https://github.com/vitalets/x-editable
|
||||||
|
*/
|
||||||
(function($) {
|
|
||||||
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
'use strict';
|
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, {
|
||||||
$.extend($.fn.bootstrapTable.defaults, {
|
editable: true,
|
||||||
editable: true,
|
onEditableInit () {
|
||||||
onEditableInit: function() {
|
return false
|
||||||
return false;
|
},
|
||||||
},
|
onEditableSave (field, row, rowIndex, oldValue, $el) {
|
||||||
onEditableSave: function(field, row, oldValue, $el) {
|
return false
|
||||||
return false;
|
},
|
||||||
},
|
onEditableShown (field, row, $el, editable) {
|
||||||
onEditableShown: function(field, row, $el, editable) {
|
return false
|
||||||
return false;
|
},
|
||||||
},
|
onEditableHidden (field, row, $el, reason) {
|
||||||
onEditableHidden: function(field, row, $el, reason) {
|
return false
|
||||||
return false;
|
}
|
||||||
}
|
})
|
||||||
});
|
|
||||||
|
$.extend($.fn.bootstrapTable.columnDefaults, {
|
||||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
alwaysUseFormatter: false
|
||||||
'editable-init.bs.table': 'onEditableInit',
|
})
|
||||||
'editable-save.bs.table': 'onEditableSave',
|
|
||||||
'editable-shown.bs.table': 'onEditableShown',
|
$.extend($.fn.bootstrapTable.events, {
|
||||||
'editable-hidden.bs.table': 'onEditableHidden'
|
'editable-init.bs.table': 'onEditableInit',
|
||||||
});
|
'editable-save.bs.table': 'onEditableSave',
|
||||||
|
'editable-shown.bs.table': 'onEditableShown',
|
||||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
'editable-hidden.bs.table': 'onEditableHidden'
|
||||||
_initTable = BootstrapTable.prototype.initTable,
|
})
|
||||||
_initBody = BootstrapTable.prototype.initBody;
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
BootstrapTable.prototype.initTable = function() {
|
initTable () {
|
||||||
var that = this;
|
super.initTable()
|
||||||
_initTable.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
if (!this.options.editable) {
|
||||||
if (!this.options.editable) {
|
return
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
this.editedCells = []
|
||||||
$.each(this.columns, function(i, column) {
|
$.each(this.columns, (i, column) => {
|
||||||
if (!column.editable) {
|
if (!column.editable) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var editableOptions = {},
|
const editableOptions = {}
|
||||||
editableDataMarkup = [],
|
const editableDataMarkup = []
|
||||||
editableDataPrefix = 'editable-';
|
const editableDataPrefix = 'editable-'
|
||||||
|
const processDataOptions = (key, value) => {
|
||||||
var processDataOptions = function(key, value) {
|
// Replace camel case with dashes.
|
||||||
// Replace camel case with dashes.
|
const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`)
|
||||||
var dashKey = key.replace(/([A-Z])/g, function($1) {
|
|
||||||
return "-" + $1.toLowerCase();
|
if (dashKey.indexOf(editableDataPrefix) === 0) {
|
||||||
});
|
editableOptions[dashKey.replace(editableDataPrefix, 'data-')] = value
|
||||||
if (dashKey.slice(0, editableDataPrefix.length) == editableDataPrefix) {
|
}
|
||||||
var dataKey = dashKey.replace(editableDataPrefix, 'data-');
|
}
|
||||||
editableOptions[dataKey] = value;
|
|
||||||
}
|
$.each(this.options, processDataOptions)
|
||||||
};
|
|
||||||
|
column.formatter = column.formatter || (value => value)
|
||||||
$.each(that.options, processDataOptions);
|
column._formatter = column._formatter ? column._formatter : column.formatter
|
||||||
|
column.formatter = (value, row, index, field) => {
|
||||||
column.formatter = column.formatter || function(value, row, index) {
|
let result = Utils.calculateObjectValue(column, column._formatter, [value, row, index], value)
|
||||||
return value;
|
|
||||||
};
|
result = typeof result === 'undefined' || result === null ? this.options.undefinedText : result
|
||||||
column._formatter = column._formatter ? column._formatter : column.formatter;
|
if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) {
|
||||||
column.formatter = function(value, row, index) {
|
const uniqueId = Utils.getItemField(row, this.options.uniqueId, false)
|
||||||
var result = column._formatter ? column._formatter(value, row, index) : value;
|
|
||||||
|
if ($.inArray(column.field + uniqueId, this.editedCells) !== -1) {
|
||||||
$.each(column, processDataOptions);
|
result = value
|
||||||
|
}
|
||||||
$.each(editableOptions, function(key, value) {
|
}
|
||||||
editableDataMarkup.push(' ' + key + '="' + value + '"');
|
|
||||||
});
|
$.each(column, processDataOptions)
|
||||||
|
|
||||||
var _dont_edit_formatter = false;
|
$.each(editableOptions, (key, value) => {
|
||||||
if (column.editable.hasOwnProperty('noeditFormatter')) {
|
editableDataMarkup.push(` ${key}="${value}"`)
|
||||||
_dont_edit_formatter = column.editable.noeditFormatter(value, row, index);
|
})
|
||||||
}
|
|
||||||
|
let noEditFormatter = false
|
||||||
if (_dont_edit_formatter === false) {
|
const editableOpts = Utils.calculateObjectValue(column,
|
||||||
return ['<a href="javascript:void(0)"',
|
column.editable, [index, row], {})
|
||||||
' data-name="' + column.field + '"',
|
|
||||||
' data-pk="' + row[that.options.idField] + '"',
|
if (editableOpts.hasOwnProperty('noEditFormatter')) {
|
||||||
' data-value="' + result + '"',
|
noEditFormatter = editableOpts.noEditFormatter(value, row, index, field)
|
||||||
editableDataMarkup.join(''),
|
}
|
||||||
'>' + '</a>'
|
|
||||||
].join('');
|
if (noEditFormatter === false) {
|
||||||
} else {
|
return `<a href="javascript:void(0)"
|
||||||
return _dont_edit_formatter;
|
data-name="${column.field}"
|
||||||
}
|
data-pk="${row[this.options.idField]}"
|
||||||
|
data-value="${result}"
|
||||||
};
|
${editableDataMarkup.join('')}></a>`
|
||||||
});
|
}
|
||||||
};
|
return noEditFormatter
|
||||||
|
}
|
||||||
BootstrapTable.prototype.initBody = function() {
|
})
|
||||||
var that = this;
|
}
|
||||||
_initBody.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
initBody (fixedScroll) {
|
||||||
if (!this.options.editable) {
|
super.initBody(fixedScroll)
|
||||||
return;
|
|
||||||
}
|
if (!this.options.editable) {
|
||||||
|
return
|
||||||
$.each(this.columns, function(i, column) {
|
}
|
||||||
if (!column.editable) {
|
|
||||||
return;
|
$.each(this.columns, (i, column) => {
|
||||||
}
|
if (!column.editable) {
|
||||||
|
return
|
||||||
that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
|
}
|
||||||
.off('save').on('save', function(e, params) {
|
|
||||||
var data = that.getData(),
|
const data = this.getData({ escape: true })
|
||||||
index = $(this).parents('tr[data-index]').data('index'),
|
const $field = this.$body.find(`a[data-name="${column.field}"]`)
|
||||||
row = data[index],
|
|
||||||
oldValue = row[column.field];
|
$field.each((i, element) => {
|
||||||
|
const $element = $(element)
|
||||||
$(this).data('value', params.submitValue);
|
const $tr = $element.closest('tr')
|
||||||
row[column.field] = params.submitValue;
|
const index = $tr.data('index')
|
||||||
that.trigger('editable-save', column.field, row, oldValue, $(this));
|
const row = data[index]
|
||||||
that.resetFooter();
|
|
||||||
});
|
const editableOpts = Utils.calculateObjectValue(column,
|
||||||
that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
|
column.editable, [index, row, $element], {})
|
||||||
.off('shown').on('shown', function(e, editable) {
|
|
||||||
var data = that.getData(),
|
$element.editable(editableOpts)
|
||||||
index = $(this).parents('tr[data-index]').data('index'),
|
})
|
||||||
row = data[index];
|
|
||||||
|
$field.off('save').on('save', ({ currentTarget }, { submitValue }) => {
|
||||||
that.trigger('editable-shown', column.field, row, $(this), editable);
|
const $this = $(currentTarget)
|
||||||
});
|
const data = this.getData()
|
||||||
that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable)
|
const rowIndex = $this.parents('tr[data-index]').data('index')
|
||||||
.off('hidden').on('hidden', function(e, reason) {
|
const row = data[rowIndex]
|
||||||
var data = that.getData(),
|
const oldValue = row[column.field]
|
||||||
index = $(this).parents('tr[data-index]').data('index'),
|
|
||||||
row = data[index];
|
if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) {
|
||||||
|
const uniqueId = Utils.getItemField(row, this.options.uniqueId, false)
|
||||||
that.trigger('editable-hidden', column.field, row, $(this), reason);
|
|
||||||
});
|
if ($.inArray(column.field + uniqueId, this.editedCells) === -1) {
|
||||||
});
|
this.editedCells.push(column.field + uniqueId)
|
||||||
this.trigger('editable-init');
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
})(jQuery);
|
submitValue = Utils.escapeHTML(submitValue)
|
||||||
|
$this.data('value', submitValue)
|
||||||
|
row[column.field] = submitValue
|
||||||
|
this.trigger('editable-save', column.field, row, rowIndex, oldValue, $this)
|
||||||
|
this.initBody()
|
||||||
|
})
|
||||||
|
|
||||||
|
$field.off('shown').on('shown', ({ currentTarget }, editable) => {
|
||||||
|
const $this = $(currentTarget)
|
||||||
|
const data = this.getData()
|
||||||
|
const rowIndex = $this.parents('tr[data-index]').data('index')
|
||||||
|
const row = data[rowIndex]
|
||||||
|
|
||||||
|
this.trigger('editable-shown', column.field, row, $this, editable)
|
||||||
|
})
|
||||||
|
|
||||||
|
$field.off('hidden').on('hidden', ({ currentTarget }, reason) => {
|
||||||
|
const $this = $(currentTarget)
|
||||||
|
const data = this.getData()
|
||||||
|
const rowIndex = $this.parents('tr[data-index]').data('index')
|
||||||
|
const row = data[rowIndex]
|
||||||
|
|
||||||
|
this.trigger('editable-hidden', column.field, row, $this, reason)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.trigger('editable-init')
|
||||||
|
}
|
||||||
|
|
||||||
|
getData (params) {
|
||||||
|
const data = super.getData(params)
|
||||||
|
|
||||||
|
if (params && params.escape) {
|
||||||
|
for (const row of data) {
|
||||||
|
for (const [key, value] of Object.entries(row)) {
|
||||||
|
if (typeof(value) !== "number") {
|
||||||
|
row[key] = Utils.unescapeHTML(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/*
|
|
||||||
* bootstrap-table - v1.11.0 - 2016-07-02
|
|
||||||
* https://github.com/wenzhixin/bootstrap-table
|
|
||||||
* Copyright (c) 2016 zhixin wen
|
|
||||||
* Licensed MIT License
|
|
||||||
*/
|
|
||||||
!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{editable:!0,onEditableInit:function(){return!1},onEditableSave:function(){return!1},onEditableShown:function(){return!1},onEditableHidden:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"editable-init.bs.table":"onEditableInit","editable-save.bs.table":"onEditableSave","editable-shown.bs.table":"onEditableShown","editable-hidden.bs.table":"onEditableHidden"});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initTable,d=b.prototype.initBody;b.prototype.initTable=function(){var b=this;c.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&a.each(this.columns,function(c,d){if(d.editable){var e={},f=[],g="editable-",h=function(a,b){var c=a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()});if(c.slice(0,g.length)==g){var d=c.replace(g,"data-");e[d]=b}};a.each(b.options,h),d.formatter=d.formatter||function(a){return a},d._formatter=d._formatter?d._formatter:d.formatter,d.formatter=function(c,g,i){var j=d._formatter?d._formatter(c,g,i):c;a.each(d,h),a.each(e,function(a,b){f.push(" "+a+'="'+b+'"')});var k=!1;return d.editable.hasOwnProperty("noeditFormatter")&&(k=d.editable.noeditFormatter(c,g,i)),k===!1?['<a href="javascript:void(0)"',' data-name="'+d.field+'"',' data-pk="'+g[b.options.idField]+'"',' data-value="'+j+'"',f.join(""),"></a>"].join(""):k}}})},b.prototype.initBody=function(){var b=this;d.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&(a.each(this.columns,function(c,d){d.editable&&(b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("save").on("save",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g],i=h[d.field];a(this).data("value",e.submitValue),h[d.field]=e.submitValue,b.trigger("editable-save",d.field,h,i,a(this)),b.resetFooter()}),b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("shown").on("shown",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g];b.trigger("editable-shown",d.field,h,a(this),e)}),b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("hidden").on("hidden",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g];b.trigger("editable-hidden",d.field,h,a(this),e)}))}),this.trigger("editable-init"))}}(jQuery);
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 244 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,119 +1,335 @@
|
||||||
/**
|
/**
|
||||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||||
* extensions: https://github.com/kayalshri/tableExport.jquery.plugin
|
* extensions: https://github.com/hhurz/tableExport.jquery.plugin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function ($) {
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
'use strict';
|
|
||||||
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
const TYPE_NAME = {
|
||||||
|
json: 'JSON',
|
||||||
var TYPE_NAME = {
|
xml: 'XML',
|
||||||
csv: 'CSV',
|
png: 'PNG',
|
||||||
txt: 'TXT',
|
csv: 'CSV',
|
||||||
doc: 'Word',
|
txt: 'TXT',
|
||||||
excel: 'Excel'
|
sql: 'SQL',
|
||||||
};
|
doc: 'MS-Word',
|
||||||
|
excel: 'MS-Excel',
|
||||||
$.extend($.fn.bootstrapTable.defaults, {
|
xlsx: 'MS-Excel (OpenXML)',
|
||||||
showExport: false,
|
powerpoint: 'MS-Powerpoint',
|
||||||
exportDataType: 'all', // basic, all, selected
|
pdf: 'PDF'
|
||||||
exportTypes: ['csv', 'txt', 'doc', 'excel'],
|
}
|
||||||
exportOptions: {
|
|
||||||
ignoreColumn: [0] //忽略列索引
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
}
|
showExport: false,
|
||||||
});
|
exportDataType: 'basic', // basic, all, selected
|
||||||
|
exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
|
||||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
exportOptions: {},
|
||||||
export: 'glyphicon glyphicon-save'
|
exportFooter: false
|
||||||
});
|
})
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.locales, {
|
Object.assign($.fn.bootstrapTable.columnDefaults, {
|
||||||
formatExport: function () {
|
forceExport: false,
|
||||||
return 'Export data';
|
forceHide: false
|
||||||
}
|
})
|
||||||
});
|
|
||||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
export: {
|
||||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
bootstrap3: 'glyphicon-export icon-share',
|
||||||
_initToolbar = BootstrapTable.prototype.initToolbar;
|
bootstrap5: 'bi-download',
|
||||||
|
materialize: 'file_download',
|
||||||
BootstrapTable.prototype.initToolbar = function () {
|
'bootstrap-table': 'icon-download'
|
||||||
this.showToolbar = this.options.showExport;
|
}[$.fn.bootstrapTable.theme] || 'fa-download'
|
||||||
|
})
|
||||||
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
Object.assign($.fn.bootstrapTable.locales, {
|
||||||
if (this.options.showExport) {
|
formatExport () {
|
||||||
var that = this,
|
return 'Export data'
|
||||||
$btnGroup = this.$toolbar.find('>.btn-group'),
|
}
|
||||||
$export = $btnGroup.find('div.export');
|
})
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
if (!$export.length) {
|
|
||||||
$export = $([
|
$.fn.bootstrapTable.methods.push('exportTable')
|
||||||
'<div class="export btn-group">',
|
|
||||||
'<button class="btn' +
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
sprintf(' btn-%s', this.options.buttonsClass) +
|
// eslint-disable-next-line no-unused-vars
|
||||||
sprintf(' btn-%s', this.options.iconSize) +
|
onExportSaved (exportedRows) {
|
||||||
' dropdown-toggle" ' +
|
return false
|
||||||
'title="' + this.options.formatExport() + '" ' +
|
},
|
||||||
'data-toggle="dropdown" type="button">',
|
onExportStarted () {
|
||||||
sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.export),
|
return false
|
||||||
'<span class="caret"></span>',
|
}
|
||||||
'</button>',
|
})
|
||||||
'<ul class="dropdown-menu" role="menu">',
|
|
||||||
'</ul>',
|
Object.assign($.fn.bootstrapTable.events, {
|
||||||
'</div>'].join('')).appendTo($btnGroup);
|
'export-saved.bs.table': 'onExportSaved',
|
||||||
|
'export-started.bs.table': 'onExportStarted'
|
||||||
var $menu = $export.find('.dropdown-menu'),
|
})
|
||||||
exportTypes = this.options.exportTypes;
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
if (typeof this.options.exportTypes === 'string') {
|
initToolbar (...args) {
|
||||||
var types = this.options.exportTypes.slice(1, -1).replace(/ /g, '').split(',');
|
const o = this.options
|
||||||
|
let exportTypes = o.exportTypes
|
||||||
exportTypes = [];
|
|
||||||
$.each(types, function (i, value) {
|
this.showToolbar = this.showToolbar || o.showExport
|
||||||
exportTypes.push(value.slice(1, -1));
|
|
||||||
});
|
if (this.options.showExport) {
|
||||||
}
|
|
||||||
$.each(exportTypes, function (i, type) {
|
if (typeof exportTypes === 'string') {
|
||||||
if (TYPE_NAME.hasOwnProperty(type)) {
|
const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',')
|
||||||
$menu.append(['<li data-type="' + type + '">',
|
|
||||||
'<a href="javascript:void(0)">',
|
exportTypes = types.map(t => t.slice(1, -1))
|
||||||
TYPE_NAME[type],
|
}
|
||||||
'</a>',
|
|
||||||
'</li>'].join(''));
|
if (typeof o.exportOptions === 'string') {
|
||||||
}
|
o.exportOptions = Utils.calculateObjectValue(null, o.exportOptions)
|
||||||
});
|
}
|
||||||
|
|
||||||
$menu.find('li').click(function () {
|
this.$export = this.$toolbar.find('>.columns div.export')
|
||||||
var type = $(this).data('type'),
|
if (this.$export.length) {
|
||||||
doExport = function () {
|
this.updateExportButton()
|
||||||
that.$el.tableExport($.extend({}, that.options.exportOptions, {
|
return
|
||||||
type: type,
|
}
|
||||||
escape: false
|
|
||||||
}));
|
this.buttons = Object.assign(this.buttons, {
|
||||||
};
|
export: {
|
||||||
|
html:
|
||||||
if (that.options.exportDataType === 'all' && that.options.pagination) {
|
() => {
|
||||||
that.$el.one(that.options.sidePagination === 'server' ? 'post-body.bs.table' : 'page-change.bs.table', function () {
|
if (exportTypes.length === 1) {
|
||||||
doExport();
|
return `
|
||||||
that.togglePagination();
|
<div class="export ${this.constants.classes.buttonsDropdown}"
|
||||||
});
|
data-type="${exportTypes[0]}">
|
||||||
that.togglePagination();
|
<button class="${this.constants.buttonsClass}"
|
||||||
} else if (that.options.exportDataType === 'selected') {
|
aria-label="${o.formatExport()}"
|
||||||
//修改sidePagination属性为server无法导出选中数据
|
type="button"
|
||||||
var trs = that.$body.children();
|
title="${o.formatExport()}">
|
||||||
for (var i = 0; i < trs.length; i++) {
|
${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''}
|
||||||
var $this = $(trs[i]);
|
${o.showButtonText ? o.formatExport() : ''}
|
||||||
if(!$this.find(sprintf('[name="%s"]',that.options.selectItemName)).prop('checked')){
|
</button>
|
||||||
$this['hide']();
|
</div>
|
||||||
}}
|
`
|
||||||
doExport();
|
}
|
||||||
that.getRowsHidden(true);
|
|
||||||
} else {
|
const html = []
|
||||||
doExport();
|
|
||||||
}
|
html.push(`
|
||||||
});
|
<div class="export ${this.constants.classes.buttonsDropdown}">
|
||||||
}
|
<button class="${this.constants.buttonsClass} dropdown-toggle"
|
||||||
}
|
aria-label="${o.formatExport()}"
|
||||||
};
|
${this.constants.dataToggle}="dropdown"
|
||||||
})(jQuery);
|
type="button"
|
||||||
|
title="${o.formatExport()}">
|
||||||
|
${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''}
|
||||||
|
${o.showButtonText ? o.formatExport() : ''}
|
||||||
|
${this.constants.html.dropdownCaret}
|
||||||
|
</button>
|
||||||
|
${this.constants.html.toolbarDropdown[0]}
|
||||||
|
`)
|
||||||
|
|
||||||
|
for (const type of exportTypes) {
|
||||||
|
if (TYPE_NAME.hasOwnProperty(type)) {
|
||||||
|
const $item = $(Utils.sprintf(this.constants.html.pageDropdownItem, '', TYPE_NAME[type]))
|
||||||
|
|
||||||
|
$item.attr('data-type', type)
|
||||||
|
html.push($item.prop('outerHTML'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push(this.constants.html.toolbarDropdown[1], '</div>')
|
||||||
|
return html.join('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initToolbar(...args)
|
||||||
|
this.$export = this.$toolbar.find('>.columns div.export')
|
||||||
|
|
||||||
|
if (!this.options.showExport) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateExportButton()
|
||||||
|
let $exportButtons = this.$export.find('[data-type]')
|
||||||
|
|
||||||
|
if (exportTypes.length === 1) {
|
||||||
|
$exportButtons = this.$export
|
||||||
|
}
|
||||||
|
|
||||||
|
$exportButtons.click(e => {
|
||||||
|
e.preventDefault()
|
||||||
|
this.trigger('export-started')
|
||||||
|
this.exportTable({
|
||||||
|
type: $(e.currentTarget).data('type')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.handleToolbar()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToolbar () {
|
||||||
|
if (!this.$export) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (super.handleToolbar) {
|
||||||
|
super.handleToolbar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exportTable (options) {
|
||||||
|
const o = this.options
|
||||||
|
const stateField = this.header.stateField
|
||||||
|
const isCardView = o.cardView
|
||||||
|
|
||||||
|
const doExport = callback => {
|
||||||
|
if (stateField) {
|
||||||
|
this.hideColumn(stateField)
|
||||||
|
}
|
||||||
|
if (isCardView) {
|
||||||
|
this.toggleView()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.columns.forEach(row => {
|
||||||
|
if (row.forceHide) {
|
||||||
|
this.hideColumn(row.field)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = this.getData()
|
||||||
|
|
||||||
|
if (o.detailView && o.detailViewIcon) {
|
||||||
|
const detailViewIndex = o.detailViewAlign === 'left' ? 0 : this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options)
|
||||||
|
|
||||||
|
o.exportOptions.ignoreColumn = [detailViewIndex].concat(o.exportOptions.ignoreColumn || [])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.exportFooter && o.height) {
|
||||||
|
const $footerRow = this.$tableFooter.find('tr').first()
|
||||||
|
const footerData = {}
|
||||||
|
const footerHtml = []
|
||||||
|
|
||||||
|
$.each($footerRow.children(), (index, footerCell) => {
|
||||||
|
const footerCellHtml = $(footerCell).children('.th-inner').first().html()
|
||||||
|
|
||||||
|
footerData[this.columns[index].field] = footerCellHtml === ' ' ? null : footerCellHtml
|
||||||
|
|
||||||
|
// grab footer cell text into cell index-based array
|
||||||
|
footerHtml.push(footerCellHtml)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$body.append(this.$body.children().last()[0].outerHTML)
|
||||||
|
const $lastTableRow = this.$body.children().last()
|
||||||
|
|
||||||
|
$.each($lastTableRow.children(), (index, lastTableRowCell) => {
|
||||||
|
$(lastTableRowCell).html(footerHtml[index])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const hiddenColumns = this.getHiddenColumns()
|
||||||
|
|
||||||
|
hiddenColumns.forEach(row => {
|
||||||
|
if (row.forceExport) {
|
||||||
|
this.showColumn(row.field)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (typeof o.exportOptions.fileName === 'function') {
|
||||||
|
options.fileName = o.exportOptions.fileName()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$el.tableExport(Utils.extend({
|
||||||
|
onAfterSaveToFile: () => {
|
||||||
|
if (o.exportFooter) {
|
||||||
|
this.load(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stateField) {
|
||||||
|
this.showColumn(stateField)
|
||||||
|
}
|
||||||
|
if (isCardView) {
|
||||||
|
this.toggleView()
|
||||||
|
}
|
||||||
|
|
||||||
|
hiddenColumns.forEach(row => {
|
||||||
|
if (row.forceExport) {
|
||||||
|
this.hideColumn(row.field)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.columns.forEach(row => {
|
||||||
|
if (row.forceHide) {
|
||||||
|
this.showColumn(row.field)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (callback) callback()
|
||||||
|
}
|
||||||
|
}, o.exportOptions, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.exportDataType === 'all' && o.pagination) {
|
||||||
|
const eventName = o.sidePagination === 'server' ?
|
||||||
|
'post-body.bs.table' : 'page-change.bs.table'
|
||||||
|
const virtualScroll = this.options.virtualScroll
|
||||||
|
|
||||||
|
this.$el.one(eventName, () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const data = this.getData()
|
||||||
|
|
||||||
|
doExport(() => {
|
||||||
|
this.options.virtualScroll = virtualScroll
|
||||||
|
this.togglePagination()
|
||||||
|
})
|
||||||
|
this.trigger('export-saved', data)
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
this.options.virtualScroll = false
|
||||||
|
this.togglePagination()
|
||||||
|
} else if (o.exportDataType === 'selected') {
|
||||||
|
let data = this.getData()
|
||||||
|
let selectedData = this.getSelections()
|
||||||
|
const pagination = o.pagination
|
||||||
|
|
||||||
|
if (!selectedData.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o.sidePagination === 'server') {
|
||||||
|
data = {
|
||||||
|
total: o.totalRows,
|
||||||
|
[this.options.dataField]: data
|
||||||
|
}
|
||||||
|
selectedData = {
|
||||||
|
total: selectedData.length,
|
||||||
|
[this.options.dataField]: selectedData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.load(selectedData)
|
||||||
|
if (pagination) {
|
||||||
|
this.togglePagination()
|
||||||
|
}
|
||||||
|
doExport(() => {
|
||||||
|
if (pagination) {
|
||||||
|
this.togglePagination()
|
||||||
|
}
|
||||||
|
this.load(data)
|
||||||
|
})
|
||||||
|
this.trigger('export-saved', selectedData)
|
||||||
|
} else {
|
||||||
|
doExport()
|
||||||
|
this.trigger('export-saved', this.getData(true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSelected () {
|
||||||
|
super.updateSelected()
|
||||||
|
this.updateExportButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateExportButton () {
|
||||||
|
if (this.options.exportDataType === 'selected') {
|
||||||
|
this.$export.find('> button')
|
||||||
|
.prop('disabled', !this.getSelections().length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
tableExport.jquery.plugin
|
||||||
|
Version 1.10.24
|
||||||
|
Copyright (c) 2015-2021 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
|
||||||
|
Based on https://github.com/kayalshri/tableExport.jquery.plugin
|
||||||
|
Licensed under the MIT License
|
||||||
|
*/
|
||||||
|
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(d,k,y){d instanceof String&&(d=String(d));for(var C=d.length,v=0;v<C;v++){var R=d[v];if(k.call(y,R,v,d))return{i:v,v:R}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,k,y){d!=Array.prototype&&d!=Object.prototype&&(d[k]=y.value)};
|
||||||
|
$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(d,k,y,C){if(k){y=$jscomp.global;d=d.split(".");for(C=0;C<d.length-1;C++){var v=d[C];v in y||(y[v]={});y=y[v]}d=d[d.length-1];C=y[d];k=k(C);k!=C&&null!=k&&$jscomp.defineProperty(y,d,{configurable:!0,writable:!0,value:k})}};
|
||||||
|
$jscomp.polyfill("Array.prototype.find",function(d){return d?d:function(d,y){return $jscomp.findInternal(this,d,y).v}},"es6","es3");
|
||||||
|
(function(d){d.fn.tableExport=function(k){function y(b){var c=[];v(b,"thead").each(function(){c.push.apply(c,v(d(this),a.theadSelector).toArray())});return c}function C(b){var c=[];v(b,"tbody").each(function(){c.push.apply(c,v(d(this),a.tbodySelector).toArray())});a.tfootSelector.length&&v(b,"tfoot").each(function(){c.push.apply(c,v(d(this),a.tfootSelector).toArray())});return c}function v(b,a){var c=b[0].tagName,q=b.parents(c).length;return b.find(a).filter(function(){return q===d(this).closest(c).parents(c).length})}
|
||||||
|
function R(b){var a=[],e=0,q=0,f=0;d(b).find("thead").first().find("th").each(function(b,c){b=void 0!==d(c).attr("data-field");"undefined"!==typeof c.parentNode.rowIndex&&q!==c.parentNode.rowIndex&&(q=c.parentNode.rowIndex,e=f=0);var h=J(c);for(e+=h?h:1;f<e;)a[f]=b?d(c).attr("data-field"):f.toString(),f++});return a}function I(b){var a="undefined"!==typeof b[0].rowIndex,e=!1===a&&"undefined"!==typeof b[0].cellIndex,q=e||a?Ja(b):b.is(":visible"),f=b.attr("data-tableexport-display");e&&"none"!==f&&
|
||||||
|
"always"!==f&&(b=d(b[0].parentNode),a="undefined"!==typeof b[0].rowIndex,f=b.attr("data-tableexport-display"));a&&"none"!==f&&"always"!==f&&(f=b.closest("table").attr("data-tableexport-display"));return"none"!==f&&(!0===q||"always"===f)}function Ja(b){var a=[];V&&(a=K.filter(function(){var a=!1;this.nodeType===b[0].nodeType&&("undefined"!==typeof this.rowIndex&&this.rowIndex===b[0].rowIndex?a=!0:"undefined"!==typeof this.cellIndex&&this.cellIndex===b[0].cellIndex&&"undefined"!==typeof this.parentNode.rowIndex&&
|
||||||
|
"undefined"!==typeof b[0].parentNode.rowIndex&&this.parentNode.rowIndex===b[0].parentNode.rowIndex&&(a=!0));return a}));return!1===V||0===a.length}function ta(b,c,e){var q=!1;I(b)?0<a.ignoreColumn.length&&(-1!==d.inArray(e,a.ignoreColumn)||-1!==d.inArray(e-c,a.ignoreColumn)||S.length>e&&"undefined"!==typeof S[e]&&-1!==d.inArray(S[e],a.ignoreColumn))&&(q=!0):q=!0;return q}function E(b,c,e,q,f){if("function"===typeof f){var h=!1;"function"===typeof a.onIgnoreRow&&(h=a.onIgnoreRow(d(b),e));if(!1===h&&
|
||||||
|
(0===a.ignoreRow.length||-1===d.inArray(e,a.ignoreRow)&&-1===d.inArray(e-q,a.ignoreRow))&&I(d(b))){b=v(d(b),c);var n=b.length,l=0,u=0;b.each(function(){var b=d(this),a=J(this),c=T(this),h;d.each(G,function(){if(e>this.s.r&&e<=this.e.r&&l>=this.s.c&&l<=this.e.c)for(h=0;h<=this.e.c-this.s.c;++h)n++,u++,f(null,e,l++)});if(c||a)a=a||1,G.push({s:{r:e,c:l},e:{r:e+(c||1)-1,c:l+a-1}});!1===ta(b,n,u++)&&f(this,e,l++);if(1<a)for(h=0;h<a-1;++h)u++,f(null,e,l++)});d.each(G,function(){if(e>=this.s.r&&e<=this.e.r&&
|
||||||
|
l>=this.s.c&&l<=this.e.c)for(ea=0;ea<=this.e.c-this.s.c;++ea)f(null,e,l++)})}}}function ua(b,a,e,d){if("undefined"!==typeof d.images&&(e=d.images[e],"undefined"!==typeof e)){a=a.getBoundingClientRect();var c=b.width/b.height,h=a.width/a.height,q=b.width,l=b.height,u=19.049976/25.4,g=0;h<=c?(l=Math.min(b.height,a.height),q=a.width*l/a.height):h>c&&(q=Math.min(b.width,a.width),l=a.height*q/a.width);q*=u;l*=u;l<b.height&&(g=(b.height-l)/2);try{d.doc.addImage(e.src,b.textPos.x,b.y+g,q,l)}catch(Pa){}b.textPos.x+=
|
||||||
|
q}}function va(b,c){if("string"===a.outputMode)return b.output();if("base64"===a.outputMode)return L(b.output());if("window"===a.outputMode)window.URL=window.URL||window.webkitURL,window.open(window.URL.createObjectURL(b.output("blob")));else try{var e=b.output("blob");saveAs(e,a.fileName+".pdf")}catch(q){ka(a.fileName+".pdf","data:application/pdf"+(c?"":";base64")+",",c?b.output("blob"):b.output())}}function wa(b,a,e){var c=0;"undefined"!==typeof e&&(c=e.colspan);if(0<=c){for(var f=b.width,d=b.textPos.x,
|
||||||
|
n=a.table.columns.indexOf(a.column),l=1;l<c;l++)f+=a.table.columns[n+l].width;1<c&&("right"===b.styles.halign?d=b.textPos.x+f-b.width:"center"===b.styles.halign&&(d=b.textPos.x+(f-b.width)/2));b.width=f;b.textPos.x=d;"undefined"!==typeof e&&1<e.rowspan&&(b.height*=e.rowspan);if("middle"===b.styles.valign||"bottom"===b.styles.valign)e=("string"===typeof b.text?b.text.split(/\r\n|\r|\n/g):b.text).length||1,2<e&&(b.textPos.y-=(2-1.15)/2*a.row.styles.fontSize*(e-2)/3);return!0}return!1}function xa(b,
|
||||||
|
a,e){"undefined"!==typeof b&&null!==b&&(b.hasAttribute("data-tableexport-canvas")?(a=(new Date).getTime(),d(b).attr("data-tableexport-canvas",a),e.images[a]={url:'[data-tableexport-canvas="'+a+'"]',src:null}):"undefined"!==a&&null!=a&&a.each(function(){if(d(this).is("img")){var a=ya(this.src);e.images[a]={url:this.src,src:this.src}}xa(b,d(this).children(),e)}))}function Ka(b,a){function c(b){if(b.url)if(b.src){var c=new Image;q=++f;c.crossOrigin="Anonymous";c.onerror=c.onload=function(){if(c.complete&&
|
||||||
|
(0===c.src.indexOf("data:image/")&&(c.width=b.width||c.width||0,c.height=b.height||c.height||0),c.width+c.height)){var e=document.createElement("canvas"),d=e.getContext("2d");e.width=c.width;e.height=c.height;d.drawImage(c,0,0);b.src=e.toDataURL("image/png")}--f||a(q)};c.src=b.url}else{var e=d(b.url);e.length&&(q=++f,html2canvas(e[0]).then(function(c){b.src=c.toDataURL("image/png");--f||a(q)}))}}var q=0,f=0;if("undefined"!==typeof b.images)for(var h in b.images)b.images.hasOwnProperty(h)&&c(b.images[h]);
|
||||||
|
(b=f)||(a(q),b=void 0);return b}function za(b,c,e){c.each(function(){if(d(this).is("div")){var c=fa(M(this,"background-color"),[255,255,255]),f=fa(M(this,"border-top-color"),[0,0,0]),h=ha(this,"border-top-width",a.jspdf.unit),n=this.getBoundingClientRect(),l=this.offsetLeft*e.wScaleFactor,u=this.offsetTop*e.hScaleFactor,g=n.width*e.wScaleFactor;n=n.height*e.hScaleFactor;e.doc.setDrawColor.apply(void 0,f);e.doc.setFillColor.apply(void 0,c);e.doc.setLineWidth(h);e.doc.rect(b.x+l,b.y+u,g,n,h?"FD":"F")}else d(this).is("img")&&
|
||||||
|
(c=ya(this.src),ua(b,this,c,e));za(b,d(this).children(),e)})}function Aa(b,c,e){if("function"===typeof e.onAutotableText)e.onAutotableText(e.doc,b,c);else{var q=b.textPos.x,f=b.textPos.y,h={halign:b.styles.halign,valign:b.styles.valign};if(c.length){for(c=c[0];c.previousSibling;)c=c.previousSibling;for(var n=!1,l=!1;c;){var u=c.innerText||c.textContent||"",g=u.length&&" "===u[0]?" ":"",k=1<u.length&&" "===u[u.length-1]?" ":"";!0!==a.preserve.leadingWS&&(u=g+la(u));!0!==a.preserve.trailingWS&&(u=ma(u)+
|
||||||
|
k);d(c).is("br")&&(q=b.textPos.x,f+=e.doc.internal.getFontSize());d(c).is("b")?n=!0:d(c).is("i")&&(l=!0);(n||l)&&e.doc.setFontType(n&&l?"bolditalic":n?"bold":"italic");if(g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()){"linebreak"===b.styles.overflow&&q>b.textPos.x&&q+g>b.textPos.x+b.width&&(0<=".,!%*;:=-".indexOf(u.charAt(0))&&(k=u.charAt(0),g=e.doc.getStringUnitWidth(k)*e.doc.internal.getFontSize(),q+g<=b.textPos.x+b.width&&(e.doc.autoTableText(k,q,f,h),u=u.substring(1,u.length)),g=
|
||||||
|
e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()),q=b.textPos.x,f+=e.doc.internal.getFontSize());if("visible"!==b.styles.overflow)for(;u.length&&q+g>b.textPos.x+b.width;)u=u.substring(0,u.length-1),g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize();e.doc.autoTableText(u,q,f,h);q+=g}if(n||l)d(c).is("b")?n=!1:d(c).is("i")&&(l=!1),e.doc.setFontType(n||l?n?"bold":"italic":"normal");c=c.nextSibling}b.textPos.x=q;b.textPos.y=f}else e.doc.autoTableText(b.text,b.textPos.x,b.textPos.y,h)}}
|
||||||
|
function W(b,a,e){return null==b?"":b.toString().replace(new RegExp(null==a?"":a.toString().replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),e)}function la(b){return null==b?"":b.toString().replace(/^\s+/,"")}function ma(b){return null==b?"":b.toString().replace(/\s+$/,"")}function La(b){if(0===a.date.html.length)return!1;a.date.pattern.lastIndex=0;var c=a.date.pattern.exec(b);if(null==c)return!1;b=+c[a.date.match_y];if(0>b||8099<b)return!1;var e=1*c[a.date.match_m];c=1*c[a.date.match_d];if(!isFinite(c))return!1;
|
||||||
|
var d=new Date(b,e-1,c,0,0,0);return d.getFullYear()===b&&d.getMonth()===e-1&&d.getDate()===c?new Date(Date.UTC(b,e-1,c,0,0,0)):!1}function na(b){b=b||"0";""!==a.numbers.html.thousandsSeparator&&(b=W(b,a.numbers.html.thousandsSeparator,""));"."!==a.numbers.html.decimalMark&&(b=W(b,a.numbers.html.decimalMark,"."));return"number"===typeof b||!1!==jQuery.isNumeric(b)?b:!1}function Ma(b){-1<b.indexOf("%")?(b=na(b.replace(/%/g,"")),!1!==b&&(b/=100)):b=!1;return b}function D(b,c,e,q){var f="",h="text";
|
||||||
|
if(null!==b){var n=d(b);n.removeData("teUserDefText");if(n[0].hasAttribute("data-tableexport-canvas"))var l="";else if(n[0].hasAttribute("data-tableexport-value"))l=(l=n.attr("data-tableexport-value"))?l+"":"",n.data("teUserDefText",1);else if(l=n.html(),"function"===typeof a.onCellHtmlData)l=a.onCellHtmlData(n,c,e,l),n.data("teUserDefText",1);else if(""!==l){b=d.parseHTML(l);var g=0,k=0;l="";d.each(b,function(){if(d(this).is("input"))l+=n.find("input").eq(g++).val();else if(d(this).is("select"))l+=
|
||||||
|
n.find("select option:selected").eq(k++).text();else if(d(this).is("br"))l+="<br>";else{if("undefined"===typeof d(this).html())l+=d(this).text();else if(void 0===jQuery().bootstrapTable||!1===d(this).hasClass("fht-cell")&&!1===d(this).hasClass("filterControl")&&0===n.parents(".detail-view").length)l+=d(this).html();if(d(this).is("a")){var b=n.find("a").attr("href")||"";f="function"===typeof a.onCellHtmlHyperlink?f+a.onCellHtmlHyperlink(n,c,e,b,l):"href"===a.htmlHyperlink?f+b:f+l;l=""}}})}if(l&&""!==
|
||||||
|
l&&!0===a.htmlContent)f=d.trim(l);else if(l&&""!==l)if(""!==n.attr("data-tableexport-cellformat")){var m=l.replace(/\n/g,"\u2028").replace(/(<\s*br([^>]*)>)/gi,"\u2060"),p=d("<div/>").html(m).contents();b=!1;m="";d.each(p.text().split("\u2028"),function(b,c){0<b&&(m+=" ");!0!==a.preserve.leadingWS&&(c=la(c));m+=!0!==a.preserve.trailingWS?ma(c):c});d.each(m.split("\u2060"),function(b,c){0<b&&(f+="\n");!0!==a.preserve.leadingWS&&(c=la(c));!0!==a.preserve.trailingWS&&(c=ma(c));f+=c.replace(/\u00AD/g,
|
||||||
|
"")});f=f.replace(/\u00A0/g," ");if("json"===a.type||"excel"===a.type&&"xmlss"===a.mso.fileFormat||!1===a.numbers.output)b=na(f),!1!==b&&(h="number",f=Number(b));else if(a.numbers.html.decimalMark!==a.numbers.output.decimalMark||a.numbers.html.thousandsSeparator!==a.numbers.output.thousandsSeparator)if(b=na(f),!1!==b){p=(""+b.substr(0>b?1:0)).split(".");1===p.length&&(p[1]="");var t=3<p[0].length?p[0].length%3:0;h="number";f=(0>b?"-":"")+(a.numbers.output.thousandsSeparator?(t?p[0].substr(0,t)+a.numbers.output.thousandsSeparator:
|
||||||
|
"")+p[0].substr(t).replace(/(\d{3})(?=\d)/g,"$1"+a.numbers.output.thousandsSeparator):p[0])+(p[1].length?a.numbers.output.decimalMark+p[1]:"")}}else f=l;!0===a.escape&&(f=escape(f));"function"===typeof a.onCellData&&(f=a.onCellData(n,c,e,f,h),n.data("teUserDefText",1))}void 0!==q&&(q.type=h);return f}function Ba(b){return 0<b.length&&!0===a.preventInjection&&0<="=+-@".indexOf(b.charAt(0))?"'"+b:b}function Na(b,a,e){return a+"-"+e.toLowerCase()}function fa(b,a){(b=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(b))&&
|
||||||
|
(a=[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]);return a}function Ca(b){var a=M(b,"text-align"),e=M(b,"font-weight"),d=M(b,"font-style"),f="";"start"===a&&(a="rtl"===M(b,"direction")?"right":"left");700<=e&&(f="bold");"italic"===d&&(f+=d);""===f&&(f="normal");a={style:{align:a,bcolor:fa(M(b,"background-color"),[255,255,255]),color:fa(M(b,"color"),[0,0,0]),fstyle:f},colspan:J(b),rowspan:T(b)};null!==b&&(b=b.getBoundingClientRect(),a.rect={width:b.width,height:b.height});return a}function J(b){var a=
|
||||||
|
d(b).attr("data-tableexport-colspan");"undefined"===typeof a&&d(b).is("[colspan]")&&(a=d(b).attr("colspan"));return parseInt(a)||0}function T(b){var a=d(b).attr("data-tableexport-rowspan");"undefined"===typeof a&&d(b).is("[rowspan]")&&(a=d(b).attr("rowspan"));return parseInt(a)||0}function M(a,c){try{return window.getComputedStyle?(c=c.replace(/([a-z])([A-Z])/,Na),window.getComputedStyle(a,null).getPropertyValue(c)):a.currentStyle?a.currentStyle[c]:a.style[c]}catch(e){}return""}function ha(a,c,e){c=
|
||||||
|
M(a,c).match(/\d+/);if(null!==c){c=c[0];a=a.parentElement;var b=document.createElement("div");b.style.overflow="hidden";b.style.visibility="hidden";a.appendChild(b);b.style.width=100+e;e=100/b.offsetWidth;a.removeChild(b);return c*e}return 0}function Oa(a){for(var b=new ArrayBuffer(a.length),e=new Uint8Array(b),d=0;d!==a.length;++d)e[d]=a.charCodeAt(d)&255;return b}function oa(a){var b=a.c,e="";for(++b;b;b=Math.floor((b-1)/26))e=String.fromCharCode((b-1)%26+65)+e;return e+(""+(a.r+1))}function pa(a,
|
||||||
|
c){if("undefined"===typeof c||"number"===typeof c)return pa(a.s,a.e);"string"!==typeof a&&(a=oa(a));"string"!==typeof c&&(c=oa(c));return a===c?a:a+":"+c}function Da(a,c){var b=Number(a);if(isFinite(b))return b;var d=1;""!==c.thousandsSeparator&&(a=a.replace(new RegExp("([\\d])"+c.thousandsSeparator+"([\\d])","g"),"$1$2"));"."!==c.decimalMark&&(a=a.replace(new RegExp("([\\d])"+c.decimalMark+"([\\d])","g"),"$1.$2"));a=a.replace(/[$]/g,"").replace(/[%]/g,function(){d*=100;return""});if(isFinite(b=Number(a)))return b/
|
||||||
|
d;a=a.replace(/[(](.*)[)]/,function(a,b){d=-d;return b});return isFinite(b=Number(a))?b/d:b}function ya(a){var b=0,d;if(0===a.length)return b;var q=0;for(d=a.length;q<d;q++){var f=a.charCodeAt(q);b=(b<<5)-b+f;b|=0}return b}function N(b,c,d,q,f,h){var e=!0;"function"===typeof a.onBeforeSaveToFile&&(e=a.onBeforeSaveToFile(b,c,d,q,f),"boolean"!==typeof e&&(e=!0));if(e)try{if(Ea=new Blob([b],{type:d+";charset="+q}),saveAs(Ea,c,!1===h),"function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(b,c)}catch(l){ka(c,
|
||||||
|
"data:"+d+(q.length?";charset="+q:"")+(f.length?";"+f:"")+",",h?"\ufeff"+b:b)}}function ka(b,c,d){var e=window.navigator.userAgent;if(!1!==b&&window.navigator.msSaveOrOpenBlob)window.navigator.msSaveOrOpenBlob(new Blob([d]),b);else if(!1!==b&&(0<e.indexOf("MSIE ")||e.match(/Trident.*rv\:11\./))){if(c=document.createElement("iframe")){document.body.appendChild(c);c.setAttribute("style","display:none");c.contentDocument.open("txt/plain","replace");c.contentDocument.write(d);c.contentDocument.close();
|
||||||
|
c.contentWindow.focus();switch(b.substr(b.lastIndexOf(".")+1)){case "doc":case "json":case "png":case "pdf":case "xls":case "xlsx":b+=".txt"}c.contentDocument.execCommand("SaveAs",!0,b);document.body.removeChild(c)}}else{var f=document.createElement("a");if(f){var h=null;f.style.display="none";!1!==b?f.download=b:f.target="_blank";"object"===typeof d?(window.URL=window.URL||window.webkitURL,e=[],e.push(d),h=window.URL.createObjectURL(new Blob(e,{type:c})),f.href=h):0<=c.toLowerCase().indexOf("base64,")?
|
||||||
|
f.href=c+L(d):f.href=c+encodeURIComponent(d);document.body.appendChild(f);if(document.createEvent)null===ia&&(ia=document.createEvent("MouseEvents")),ia.initEvent("click",!0,!1),f.dispatchEvent(ia);else if(document.createEventObject)f.fireEvent("onclick");else if("function"===typeof f.onclick)f.onclick();setTimeout(function(){h&&window.URL.revokeObjectURL(h);document.body.removeChild(f);if("function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(d,b)},100)}}}function L(a){var b,d="",q=0;if("string"===
|
||||||
|
typeof a){a=a.replace(/\x0d\x0a/g,"\n");var f="";for(b=0;b<a.length;b++){var h=a.charCodeAt(b);128>h?f+=String.fromCharCode(h):(127<h&&2048>h?f+=String.fromCharCode(h>>6|192):(f+=String.fromCharCode(h>>12|224),f+=String.fromCharCode(h>>6&63|128)),f+=String.fromCharCode(h&63|128))}a=f}for(;q<a.length;){var n=a.charCodeAt(q++);f=a.charCodeAt(q++);b=a.charCodeAt(q++);h=n>>2;n=(n&3)<<4|f>>4;var l=(f&15)<<2|b>>6;var g=b&63;isNaN(f)?l=g=64:isNaN(b)&&(g=64);d=d+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(n)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(l)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)}return d}var a={csvEnclosure:'"',csvSeparator:",",csvUseBOM:!0,date:{html:"dd/mm/yyyy"},displayTableName:!1,escape:!1,exportHiddenCells:!1,fileName:"tableExport",htmlContent:!1,htmlHyperlink:"content",ignoreColumn:[],ignoreRow:[],jsonScope:"all",jspdf:{orientation:"p",
|
||||||
|
unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},onDocCreated:null,autotable:{styles:{cellPadding:2,rowHeight:12,fontSize:8,fillColor:255,textColor:50,fontStyle:"normal",overflow:"ellipsize",halign:"inherit",valign:"middle"},headerStyles:{fillColor:[52,73,94],textColor:255,fontStyle:"bold",halign:"inherit",valign:"middle"},alternateRowStyles:{fillColor:245},tableExport:{doc:null,onAfterAutotable:null,onBeforeAutotable:null,onAutotableText:null,onTable:null,outputImages:!0}}},mso:{fileFormat:"xlshtml",
|
||||||
|
onMsoNumberFormat:null,pageFormat:"a4",pageOrientation:"portrait",rtl:!1,styles:[],worksheetName:"",xslx:{formatId:{date:14,numbers:2}}},numbers:{html:{decimalMark:".",thousandsSeparator:","},output:{decimalMark:".",thousandsSeparator:","}},onAfterSaveToFile:null,onBeforeSaveToFile:null,onCellData:null,onCellHtmlData:null,onCellHtmlHyperlink:null,onIgnoreRow:null,onTableExportBegin:null,onTableExportEnd:null,outputMode:"file",pdfmake:{enabled:!1,docDefinition:{pageSize:"A4",pageOrientation:"portrait",
|
||||||
|
styles:{header:{background:"#34495E",color:"#FFFFFF",bold:!0,alignment:"center",fillColor:"#34495E"},alternateRow:{fillColor:"#f5f5f5"}},defaultStyle:{color:"#000000",fontSize:8,font:"Roboto"}},fonts:{}},preserve:{leadingWS:!1,trailingWS:!1},preventInjection:!0,sql:{tableEnclosure:"`",columnEnclosure:"`"},tbodySelector:"tr",tfootSelector:"tr",theadSelector:"tr",tableName:"Table",type:"csv"},O={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,
|
||||||
|
595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,
|
||||||
|
161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]},B=this,ia=null,r=[],w=[],p=0,t="",S=[],G=[],Ea,K=[],V=!1;d.extend(!0,a,k);"xlsx"===a.type&&(a.mso.fileFormat=a.type,a.type="excel");"undefined"!==typeof a.excelFileFormat&&"undefined"===a.mso.fileFormat&&(a.mso.fileFormat=a.excelFileFormat);"undefined"!==typeof a.excelPageFormat&&"undefined"===a.mso.pageFormat&&
|
||||||
|
(a.mso.pageFormat=a.excelPageFormat);"undefined"!==typeof a.excelPageOrientation&&"undefined"===a.mso.pageOrientation&&(a.mso.pageOrientation=a.excelPageOrientation);"undefined"!==typeof a.excelRTL&&"undefined"===a.mso.rtl&&(a.mso.rtl=a.excelRTL);"undefined"!==typeof a.excelstyles&&"undefined"===a.mso.styles&&(a.mso.styles=a.excelstyles);"undefined"!==typeof a.onMsoNumberFormat&&"undefined"===a.mso.onMsoNumberFormat&&(a.mso.onMsoNumberFormat=a.onMsoNumberFormat);"undefined"!==typeof a.worksheetName&&
|
||||||
|
"undefined"===a.mso.worksheetName&&(a.mso.worksheetName=a.worksheetName);a.mso.pageOrientation="l"===a.mso.pageOrientation.substr(0,1)?"landscape":"portrait";a.date.html=a.date.html||"";if(a.date.html.length){k=[];k.dd="(3[01]|[12][0-9]|0?[1-9])";k.mm="(1[012]|0?[1-9])";k.yyyy="((?:1[6-9]|2[0-2])\\d{2})";k.yy="(\\d{2})";var z=a.date.html.match(/[^a-zA-Z0-9]/)[0];z=a.date.html.toLowerCase().split(z);a.date.regex="^\\s*";a.date.regex+=k[z[0]];a.date.regex+="(.)";a.date.regex+=k[z[1]];a.date.regex+=
|
||||||
|
"\\2";a.date.regex+=k[z[2]];a.date.regex+="\\s*$";a.date.pattern=new RegExp(a.date.regex,"g");k=z.indexOf("dd")+1;a.date.match_d=k+(1<k?1:0);k=z.indexOf("mm")+1;a.date.match_m=k+(1<k?1:0);k=(0<=z.indexOf("yyyy")?z.indexOf("yyyy"):z.indexOf("yy"))+1;a.date.match_y=k+(1<k?1:0)}S=R(B);if("function"===typeof a.onTableExportBegin)a.onTableExportBegin();if("csv"===a.type||"tsv"===a.type||"txt"===a.type){var P="",Z=0;G=[];p=0;var qa=function(b,c,e){b.each(function(){t="";E(this,c,p,e+b.length,function(b,
|
||||||
|
c,d){var e=t,f="";if(null!==b)if(b=D(b,c,d),c=null===b||""===b?"":b.toString(),"tsv"===a.type)b instanceof Date&&b.toLocaleString(),f=W(c,"\t"," ");else if(b instanceof Date)f=a.csvEnclosure+b.toLocaleString()+a.csvEnclosure;else if(f=Ba(c),f=W(f,a.csvEnclosure,a.csvEnclosure+a.csvEnclosure),0<=f.indexOf(a.csvSeparator)||/[\r\n ]/g.test(f))f=a.csvEnclosure+f+a.csvEnclosure;t=e+(f+("tsv"===a.type?"\t":a.csvSeparator))});t=d.trim(t).substring(0,t.length-1);0<t.length&&(0<P.length&&(P+="\n"),P+=t);p++});
|
||||||
|
return b.length};Z+=qa(d(B).find("thead").first().find(a.theadSelector),"th,td",Z);v(d(B),"tbody").each(function(){Z+=qa(v(d(this),a.tbodySelector),"td,th",Z)});a.tfootSelector.length&&qa(d(B).find("tfoot").first().find(a.tfootSelector),"td,th",Z);P+="\n";if("string"===a.outputMode)return P;if("base64"===a.outputMode)return L(P);if("window"===a.outputMode){ka(!1,"data:text/"+("csv"===a.type?"csv":"plain")+";charset=utf-8,",P);return}N(P,a.fileName+"."+a.type,"text/"+("csv"===a.type?"csv":"plain"),
|
||||||
|
"utf-8","","csv"===a.type&&a.csvUseBOM)}else if("sql"===a.type){p=0;G=[];var A="INSERT INTO "+a.sql.tableEnclosure+a.tableName+a.sql.tableEnclosure+" (";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(b,c,d){b=D(b,c,d)||"";-1<b.indexOf(a.sql.columnEnclosure)&&(b=W(b.toString(),a.sql.columnEnclosure,a.sql.columnEnclosure+a.sql.columnEnclosure));A+=a.sql.columnEnclosure+b+a.sql.columnEnclosure+","});p++;A=d.trim(A).substring(0,A.length-1)});A+=") VALUES ";w=C(d(B));d(w).each(function(){t=
|
||||||
|
"";E(this,"td,th",p,r.length+w.length,function(a,c,d){a=D(a,c,d)||"";-1<a.indexOf("'")&&(a=W(a.toString(),"'","''"));t+="'"+a+"',"});3<t.length&&(A+="("+t,A=d.trim(A).substring(0,A.length-1),A+="),");p++});A=d.trim(A).substring(0,A.length-1);A+=";";if("string"===a.outputMode)return A;if("base64"===a.outputMode)return L(A);N(A,a.fileName+".sql","application/sql","utf-8","",!1)}else if("json"===a.type){var X=[];G=[];r=y(d(B));d(r).each(function(){var a=[];E(this,"th,td",p,r.length,function(b,d,g){a.push(D(b,
|
||||||
|
d,g))});X.push(a)});var ra=[];w=C(d(B));d(w).each(function(){var a={},c=0;E(this,"td,th",p,r.length+w.length,function(b,d,f){X.length?a[X[X.length-1][c]]=D(b,d,f):a[c]=D(b,d,f);c++});!1===d.isEmptyObject(a)&&ra.push(a);p++});k="head"===a.jsonScope?JSON.stringify(X):"data"===a.jsonScope?JSON.stringify(ra):JSON.stringify({header:X,data:ra});if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".json","application/json","utf-8","base64",!1)}else if("xml"===a.type){p=
|
||||||
|
0;G=[];var Q='<?xml version="1.0" encoding="utf-8"?>';Q+="<tabledata><fields>";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(a,d,e){Q+="<field>"+D(a,d,e)+"</field>"});p++});Q+="</fields><data>";var Fa=1;w=C(d(B));d(w).each(function(){var a=1;t="";E(this,"td,th",p,r.length+w.length,function(b,d,g){t+="<column-"+a+">"+D(b,d,g)+"</column-"+a+">";a++});0<t.length&&"<column-1></column-1>"!==t&&(Q+='<row id="'+Fa+'">'+t+"</row>",Fa++);p++});Q+="</data></tabledata>";if("string"===a.outputMode)return Q;
|
||||||
|
if("base64"===a.outputMode)return L(Q);N(Q,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===a.type&&"xmlss"===a.mso.fileFormat){var sa=[],F=[];d(B).filter(function(){return I(d(this))}).each(function(){function b(a,b,c){var f=[];d(a).each(function(){var b=0,e=0;t="";E(this,"td,th",p,c+a.length,function(a,c,h){if(null!==a){var l="";c=D(a,c,h);h="String";if(!1!==jQuery.isNumeric(c))h="Number";else{var n=Ma(c);!1!==n&&(c=n,h="Number",l+=' ss:StyleID="pct1"')}"Number"!==h&&(c=
|
||||||
|
c.replace(/\n/g,"<br>"));n=J(a);a=T(a);d.each(f,function(){if(p>=this.s.r&&p<=this.e.r&&e>=this.s.c&&e<=this.e.c)for(var a=0;a<=this.e.c-this.s.c;++a)e++,b++});if(a||n)a=a||1,n=n||1,f.push({s:{r:p,c:e},e:{r:p+a-1,c:e+n-1}});1<n&&(l+=' ss:MergeAcross="'+(n-1)+'"',e+=n-1);1<a&&(l+=' ss:MergeDown="'+(a-1)+'" ss:StyleID="rsp1"');0<b&&(l+=' ss:Index="'+(e+1)+'"',b=0);t+="<Cell"+l+'><Data ss:Type="'+h+'">'+d("<div />").text(c).html()+"</Data></Cell>\r";e++}});0<t.length&&(H+='<Row ss:AutoFitHeight="0">\r'+
|
||||||
|
t+"</Row>\r");p++});return a.length}var c=d(this),e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(F.length+1):"undefined"!==typeof a.mso.worksheetName[F.length]&&(e=a.mso.worksheetName[F.length]);e.length||(e=c.find("caption").text()||"");e.length||(e="Table "+(F.length+1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));F.push(d("<div />").text(e).html());!1===a.exportHiddenCells&&(K=c.find("tr, th, td").filter(":hidden"),V=0<K.length);
|
||||||
|
p=0;S=R(this);H="<Table>\r";e=b(y(c),"th,td",0);b(C(c),"td,th",e);H+="</Table>\r";sa.push(H)});k={};z={};for(var m,aa,Y=0,ea=F.length;Y<ea;Y++)m=F[Y],aa=k[m],aa=k[m]=null==aa?1:aa+1,2===aa&&(F[z[m]]=F[z[m]].substring(0,29)+"-1"),1<k[m]?F[Y]=F[Y].substring(0,29)+"-"+k[m]:z[m]=Y;k='<?xml version="1.0" encoding="UTF-8"?>\r<?mso-application progid="Excel.Sheet"?>\r<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:o="urn:schemas-microsoft-com:office:office"\r xmlns:x="urn:schemas-microsoft-com:office:excel"\r xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:html="http://www.w3.org/TR/REC-html40">\r<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">\r <Created>'+
|
||||||
|
(new Date).toISOString()+'</Created>\r</DocumentProperties>\r<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">\r <AllowPNG/>\r</OfficeDocumentSettings>\r<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">\r <WindowHeight>9000</WindowHeight>\r <WindowWidth>13860</WindowWidth>\r <WindowTopX>0</WindowTopX>\r <WindowTopY>0</WindowTopY>\r <ProtectStructure>False</ProtectStructure>\r <ProtectWindows>False</ProtectWindows>\r</ExcelWorkbook>\r<Styles>\r <Style ss:ID="Default" ss:Name="Normal">\r <Alignment ss:Vertical="Bottom"/>\r <Borders/>\r <Font/>\r <Interior/>\r <NumberFormat/>\r <Protection/>\r </Style>\r <Style ss:ID="rsp1">\r <Alignment ss:Vertical="Center"/>\r </Style>\r <Style ss:ID="pct1">\r <NumberFormat ss:Format="Percent"/>\r </Style>\r</Styles>\r';
|
||||||
|
for(z=0;z<sa.length;z++)k+='<Worksheet ss:Name="'+F[z]+'" ss:RightToLeft="'+(a.mso.rtl?"1":"0")+'">\r'+sa[z],k=a.mso.rtl?k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">\r<DisplayRightToLeft/>\r</WorksheetOptions>\r':k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"/>\r',k+="</Worksheet>\r";k+="</Workbook>\r";if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===
|
||||||
|
a.type&&"xlsx"===a.mso.fileFormat){var ba=[],Ga=XLSX.utils.book_new();d(B).filter(function(){return I(d(this))}).each(function(){for(var b=d(this),c={},e=this.getElementsByTagName("tr"),g={s:{r:0,c:0},e:{r:0,c:0}},f=[],h,n=[],l=0,u=0,k,m,p,t,r,w=XLSX.SSF.get_table();l<e.length&&1E7>u;++l)if(k=e[l],m=!1,"function"===typeof a.onIgnoreRow&&(m=a.onIgnoreRow(d(k),l)),!0!==m&&(0===a.ignoreRow.length||-1===d.inArray(l,a.ignoreRow)&&-1===d.inArray(l-e.length,a.ignoreRow))&&!1!==I(d(k))){var y=k.children,
|
||||||
|
B=0;for(k=0;k<y.length;++k)r=y[k],t=+J(r)||1,B+=t;var z=0;for(k=m=0;k<y.length;++k)if(r=y[k],t=+J(r)||1,h=k+z,!ta(d(r),B,h+(h<m?m-h:0))){z+=t-1;for(h=0;h<f.length;++h){var v=f[h];v.s.c==m&&v.s.r<=u&&u<=v.e.r&&(m=v.e.c+1,h=-1)}(0<(p=+T(r))||1<t)&&f.push({s:{r:u,c:m},e:{r:u+(p||1)-1,c:m+t-1}});var C={type:""};h=D(r,l,k+z,C);v={t:"s",v:h};var A="";if(""!==(d(r).attr("data-tableexport-cellformat")||"")){var x=parseInt(d(r).attr("data-tableexport-xlsxformatid")||0);0===x&&"function"===typeof a.mso.xslx.formatId.numbers&&
|
||||||
|
(x=a.mso.xslx.formatId.numbers(d(r),l,k+z));0===x&&"function"===typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date(d(r),l,k+z));if(49===x||"@"===x)A="s";else if("number"===C.type||0<x&&14>x||36<x&&41>x||48===x)A="n";else if("date"===C.type||13<x&&37>x||44<x&&48>x||56===x)A="d"}else A="s";if(null!=h)if(0===h.length)v.t="z";else if(0!==h.trim().length)if("s"===A)d(r).find("a").length&&(h="href"!==a.htmlHyperlink?h:"",v={f:'=HYPERLINK("'+d(r).find("a").attr("href")+(h.length?'","'+h:"")+'")'});
|
||||||
|
else if("function"===C.type)v={f:h};else if("TRUE"===h)v={t:"b",v:!0};else if("FALSE"===h)v={t:"b",v:!1};else if("n"===A||isFinite(Da(h,a.numbers.output))){if(r=Da(h,a.numbers.output),0===x&&"function"!==typeof a.mso.xslx.formatId.numbers&&(x=a.mso.xslx.formatId.numbers),isFinite(r)||isFinite(h))v={t:"n",v:isFinite(r)?r:h,z:"string"===typeof x?x:x in w?w[x]:"0.00"}}else if(!1!==(r=La(h))||"d"===A)0===x&&"function"!==typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date),v={t:"d",v:!1!==r?r:
|
||||||
|
h,z:"string"===typeof x?x:x in w?w[x]:"m/d/yy"};c[oa({c:m,r:u})]=v;g.e.c<m&&(g.e.c=m);m+=t}++u}f.length&&(c["!merges"]=f);n.length&&(c["!rows"]=n);g.e.r=u-1;c["!ref"]=pa(g);1E7<=u&&(c["!fullref"]=pa((g.e.r=e.length-l+u-1,g)));e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(ba.length+1):"undefined"!==typeof a.mso.worksheetName[ba.length]&&(e=a.mso.worksheetName[ba.length]);e.length||(e=b.find("caption").text()||"");e.length||(e="Table "+(ba.length+
|
||||||
|
1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));ba.push(e);XLSX.utils.book_append_sheet(Ga,c,e)});k=XLSX.write(Ga,{type:"binary",bookType:a.mso.fileFormat,bookSST:!1});N(Oa(k),a.fileName+"."+a.mso.fileFormat,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","UTF-8","",!1)}else if("excel"===a.type||"xls"===a.type||"word"===a.type||"doc"===a.type){k="excel"===a.type||"xls"===a.type?"excel":"word";z="excel"===k?"xls":"doc";m='xmlns:x="urn:schemas-microsoft-com:office:'+
|
||||||
|
k+'"';var H="",ca="";d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this);""===ca&&(ca=a.mso.worksheetName||b.find("caption").text()||"Table",ca=d.trim(ca.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31)));!1===a.exportHiddenCells&&(K=b.find("tr, th, td").filter(":hidden"),V=0<K.length);p=0;G=[];S=R(this);H+="<table><thead>";r=y(b);d(r).each(function(){var b=d(this);t="";E(this,"th,td",p,r.length,function(d,c,f){if(null!==d){var e="";t+="<th";if(a.mso.styles.length){var n=document.defaultView.getComputedStyle(d,
|
||||||
|
null),l=document.defaultView.getComputedStyle(b[0],null),g;for(g in a.mso.styles){var k=n[a.mso.styles[g]];""===k&&(k=l[a.mso.styles[g]]);""!==k&&"0px none rgb(0, 0, 0)"!==k&&"rgba(0, 0, 0, 0)"!==k&&(e+=""===e?'style="':";",e+=a.mso.styles[g]+":"+k)}}""!==e&&(t+=" "+e+'"');e=J(d);0<e&&(t+=' colspan="'+e+'"');e=T(d);0<e&&(t+=' rowspan="'+e+'"');t+=">"+D(d,c,f)+"</th>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});H+="</thead><tbody>";w=C(b);d(w).each(function(){var b=d(this);t="";E(this,"td,th",p,r.length+
|
||||||
|
w.length,function(c,g,f){if(null!==c){var e=D(c,g,f),n="",l=d(c).attr("data-tableexport-msonumberformat");"undefined"===typeof l&&"function"===typeof a.mso.onMsoNumberFormat&&(l=a.mso.onMsoNumberFormat(c,g,f));"undefined"!==typeof l&&""!==l&&(n="style=\"mso-number-format:'"+l+"'");if(a.mso.styles.length){g=document.defaultView.getComputedStyle(c,null);f=document.defaultView.getComputedStyle(b[0],null);for(var k in a.mso.styles)l=g[a.mso.styles[k]],""===l&&(l=f[a.mso.styles[k]]),""!==l&&"0px none rgb(0, 0, 0)"!==
|
||||||
|
l&&"rgba(0, 0, 0, 0)"!==l&&(n+=""===n?'style="':";",n+=a.mso.styles[k]+":"+l)}t+="<td";""!==n&&(t+=" "+n+'"');n=J(c);0<n&&(t+=' colspan="'+n+'"');c=T(c);0<c&&(t+=' rowspan="'+c+'"');"string"===typeof e&&""!==e&&(e=Ba(e),e=e.replace(/\n/g,"<br>"));t+=">"+e+"</td>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});a.displayTableName&&(H+="<tr><td></td></tr><tr><td></td></tr><tr><td>"+D(d("<p>"+a.tableName+"</p>"))+"</td></tr>");H+="</tbody></table>"});m='<html xmlns:o="urn:schemas-microsoft-com:office:office" '+
|
||||||
|
m+' xmlns="http://www.w3.org/TR/REC-html40">'+('<meta http-equiv="content-type" content="application/vnd.ms-'+k+'; charset=UTF-8">')+"<head>";"excel"===k&&(m+="\x3c!--[if gte mso 9]>",m+="<xml>",m+="<x:ExcelWorkbook>",m+="<x:ExcelWorksheets>",m+="<x:ExcelWorksheet>",m+="<x:Name>",m+=ca,m+="</x:Name>",m+="<x:WorksheetOptions>",m+="<x:DisplayGridlines/>",a.mso.rtl&&(m+="<x:DisplayRightToLeft/>"),m+="</x:WorksheetOptions>",m+="</x:ExcelWorksheet>",m+="</x:ExcelWorksheets>",m+="</x:ExcelWorkbook>",m+=
|
||||||
|
"</xml>",m+="<![endif]--\x3e");m+="<style>";m+="@page { size:"+a.mso.pageOrientation+"; mso-page-orientation:"+a.mso.pageOrientation+"; }";m+="@page Section1 {size:"+O[a.mso.pageFormat][0]+"pt "+O[a.mso.pageFormat][1]+"pt";m+="; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";m+="div.Section1 {page:Section1;}";m+="@page Section2 {size:"+O[a.mso.pageFormat][1]+"pt "+O[a.mso.pageFormat][0]+"pt";m+=";mso-page-orientation:"+a.mso.pageOrientation+";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";
|
||||||
|
m+="div.Section2 {page:Section2;}";m+="br {mso-data-placement:same-cell;}";m+="</style>";m+="</head>";m+="<body>";m+='<div class="Section'+("landscape"===a.mso.pageOrientation?"2":"1")+'">';m+=H;m+="</div>";m+="</body>";m+="</html>";if("string"===a.outputMode)return m;if("base64"===a.outputMode)return L(m);N(m,a.fileName+"."+z,"application/vnd.ms-"+k,"","base64",!1)}else if("png"===a.type)html2canvas(d(B)[0]).then(function(b){b=b.toDataURL();for(var c=atob(b.substring(22)),d=new ArrayBuffer(c.length),
|
||||||
|
g=new Uint8Array(d),f=0;f<c.length;f++)g[f]=c.charCodeAt(f);if("string"===a.outputMode)return c;if("base64"===a.outputMode)return L(b);"window"===a.outputMode?window.open(b):N(d,a.fileName+".png","image/png","","",!1)});else if("pdf"===a.type)if(!0===a.pdfmake.enabled){var U={content:[]};d.extend(!0,U,a.pdfmake.docDefinition);G=[];d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this),c=[],e=[];p=0;var g=function(a,b,c){var f=0;d(a).each(function(){var a=[];E(this,b,p,c,function(c,
|
||||||
|
d,f){if("undefined"!==typeof c&&null!==c){var e=J(c),h=T(c);c={text:D(c,d,f)||" "};if(1<e||1<h)c.colSpan=e||1,c.rowSpan=h||1}else c={text:" "};0<=b.indexOf("th")&&(c.style="header");a.push(c)});for(var d=a.length;d<c;d++)a.push("");a.length&&e.push(a);f<a.length&&(f=a.length);p++});return f};r=y(b);for(var f=g(r,"th,td",r.length),h=c.length;h<f;h++)c.push("*");w=C(b);f=g(w,"td",r.length+w.length);for(h=c.length;h<f;h++)c.push("*");U.content.push({table:{headerRows:r.length?r.length:null,widths:c,
|
||||||
|
body:e},layout:{layout:"noBorders",hLineStyle:function(a,b){return 0},vLineWidth:function(a,b){return 0},hLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},vLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},fillColor:function(b,c,d){return 0===b%2?a.pdfmake.docDefinition.styles.alternateRow.fillColor:
|
||||||
|
null}},pageBreak:U.content.length?"before":void 0})});"undefined"!==typeof pdfMake&&"undefined"!==typeof pdfMake.createPdf&&(pdfMake.fonts={Roboto:{normal:"Roboto-Regular.ttf",bold:"Roboto-Medium.ttf",italics:"Roboto-Italic.ttf",bolditalics:"Roboto-MediumItalic.ttf"}},pdfMake.vfs.hasOwnProperty("Mirza-Regular.ttf")?(U.defaultStyle.font="Mirza",d.extend(!0,pdfMake.fonts,{Mirza:{normal:"Mirza-Regular.ttf",bold:"Mirza-Bold.ttf",italics:"Mirza-Medium.ttf",bolditalics:"Mirza-SemiBold.ttf"}})):pdfMake.vfs.hasOwnProperty("gbsn00lp.ttf")?
|
||||||
|
(U.defaultStyle.font="gbsn00lp",d.extend(!0,pdfMake.fonts,{gbsn00lp:{normal:"gbsn00lp.ttf",bold:"gbsn00lp.ttf",italics:"gbsn00lp.ttf",bolditalics:"gbsn00lp.ttf"}})):pdfMake.vfs.hasOwnProperty("ZCOOLXiaoWei-Regular.ttf")&&(U.defaultStyle.font="ZCOOLXiaoWei",d.extend(!0,pdfMake.fonts,{ZCOOLXiaoWei:{normal:"ZCOOLXiaoWei-Regular.ttf",bold:"ZCOOLXiaoWei-Regular.ttf",italics:"ZCOOLXiaoWei-Regular.ttf",bolditalics:"ZCOOLXiaoWei-Regular.ttf"}})),d.extend(!0,pdfMake.fonts,a.pdfmake.fonts),pdfMake.createPdf(U).getBuffer(function(b){N(b,
|
||||||
|
a.fileName+".pdf","application/pdf","","",!1)}))}else if(!1===a.jspdf.autotable){k={dim:{w:ha(d(B).first().get(0),"width","mm"),h:ha(d(B).first().get(0),"height","mm")},pagesplit:!1};var Ha=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);Ha.addHTML(d(B).first(),a.jspdf.margins.left,a.jspdf.margins.top,k,function(){va(Ha,!1)})}else{var g=a.jspdf.autotable.tableExport;if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var ja="",da="",Ia=0;d(B).each(function(){if(I(d(this))){var a=
|
||||||
|
ha(d(this).get(0),"width","pt");if(a>Ia){a>O.a0[0]&&(ja="a0",da="l");for(var c in O)O.hasOwnProperty(c)&&O[c][1]>a&&(ja=c,da="l",O[c][0]>a&&(da="p"));Ia=a}}});a.jspdf.format=""===ja?"a4":ja;a.jspdf.orientation=""===da?"w":da}if(null==g.doc&&(g.doc=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format),g.wScaleFactor=1,g.hScaleFactor=1,"function"===typeof a.jspdf.onDocCreated))a.jspdf.onDocCreated(g.doc);!0===g.outputImages&&(g.images={});"undefined"!==typeof g.images&&(d(B).filter(function(){return I(d(this))}).each(function(){var b=
|
||||||
|
0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);r=y(d(this));w=C(d(this));d(w).each(function(){E(this,"td,th",r.length+b,r.length+w.length,function(a){xa(a,d(a).children(),g)});b++})}),r=[],w=[]);Ka(g,function(){d(B).filter(function(){return I(d(this))}).each(function(){var b;p=0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);S=R(this);g.columns=[];g.rows=[];g.teCells={};if("function"===typeof g.onTable&&
|
||||||
|
!1===g.onTable(d(this),a))return!0;a.jspdf.autotable.tableExport=null;var c=d.extend(!0,{},a.jspdf.autotable);a.jspdf.autotable.tableExport=g;c.margin={};d.extend(!0,c.margin,a.jspdf.margins);c.tableExport=g;"function"!==typeof c.beforePageContent&&(c.beforePageContent=function(a){if(1===a.pageCount){var b=a.table.rows.concat(a.table.headerRow);d.each(b,function(){0<this.height&&(this.height+=(2-1.15)/2*this.styles.fontSize,a.table.height+=(2-1.15)/2*this.styles.fontSize)})}});"function"!==typeof c.createdHeaderCell&&
|
||||||
|
(c.createdHeaderCell=function(a,b){a.styles=d.extend({},b.row.styles);if("undefined"!==typeof g.columns[b.column.dataKey]){var e=g.columns[b.column.dataKey];if("undefined"!==typeof e.rect){a.contentWidth=e.rect.width;if("undefined"===typeof g.heightRatio||0===g.heightRatio){var f=b.row.raw[b.column.dataKey].rowspan?b.row.raw[b.column.dataKey].rect.height/b.row.raw[b.column.dataKey].rowspan:b.row.raw[b.column.dataKey].rect.height;g.heightRatio=a.styles.rowHeight/f}f=b.row.raw[b.column.dataKey].rect.height*
|
||||||
|
g.heightRatio;f>a.styles.rowHeight&&(a.styles.rowHeight=f)}a.styles.halign="inherit"===c.headerStyles.halign?"center":c.headerStyles.halign;a.styles.valign=c.headerStyles.valign;"undefined"!==typeof e.style&&!0!==e.style.hidden&&("inherit"===c.headerStyles.halign&&(a.styles.halign=e.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=e.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=e.style.color),"inherit"===c.styles.fontStyle&&(a.styles.fontStyle=e.style.fstyle))}});
|
||||||
|
"function"!==typeof c.createdCell&&(c.createdCell=function(a,b){b=g.teCells[b.row.index+":"+b.column.dataKey];a.styles.halign="inherit"===c.styles.halign?"center":c.styles.halign;a.styles.valign=c.styles.valign;"undefined"!==typeof b&&"undefined"!==typeof b.style&&!0!==b.style.hidden&&("inherit"===c.styles.halign&&(a.styles.halign=b.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=b.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=b.style.color),"inherit"===c.styles.fontStyle&&
|
||||||
|
(a.styles.fontStyle=b.style.fstyle))});"function"!==typeof c.drawHeaderCell&&(c.drawHeaderCell=function(a,b){var c=g.columns[b.column.dataKey];return(!0!==c.style.hasOwnProperty("hidden")||!0!==c.style.hidden)&&0<=c.rowIndex?wa(a,b,c):!1});"function"!==typeof c.drawCell&&(c.drawCell=function(a,b){var c=g.teCells[b.row.index+":"+b.column.dataKey];if(!0!==("undefined"!==typeof c&&c.isCanvas))wa(a,b,c)&&(g.doc.rect(a.x,a.y,a.width,a.height,a.styles.fillStyle),"undefined"===typeof c||"undefined"!==typeof c.hasUserDefText&&
|
||||||
|
!0===c.hasUserDefText||"undefined"===typeof c.elements||!c.elements.length?Aa(a,{},g):(b=a.height/c.rect.height,b>g.hScaleFactor&&(g.hScaleFactor=b),g.wScaleFactor=a.width/c.rect.width,b=a.textPos.y,za(a,c.elements,g),a.textPos.y=b,Aa(a,c.elements,g)));else{c=c.elements[0];var e=d(c).attr("data-tableexport-canvas"),f=c.getBoundingClientRect();a.width=f.width*g.wScaleFactor;a.height=f.height*g.hScaleFactor;b.row.height=a.height;ua(a,c,e,g)}return!1});g.headerrows=[];r=y(d(this));d(r).each(function(){b=
|
||||||
|
0;g.headerrows[p]=[];E(this,"th,td",p,r.length,function(a,c,d){var e=Ca(a);e.title=D(a,c,d);e.key=b++;e.rowIndex=p;g.headerrows[p].push(e)});p++});if(0<p)for(var e=p-1;0<=e;)d.each(g.headerrows[e],function(){var a=this;0<e&&null===this.rect&&(a=g.headerrows[e-1][this.key]);null!==a&&0<=a.rowIndex&&(!0!==a.style.hasOwnProperty("hidden")||!0!==a.style.hidden)&&g.columns.push(a)}),e=0<g.columns.length?-1:e-1;var k=0;w=[];w=C(d(this));d(w).each(function(){var a=[];b=0;E(this,"td,th",p,r.length+w.length,
|
||||||
|
function(c,e,f){if("undefined"===typeof g.columns[b]){var h={title:"",key:b,style:{hidden:!0}};g.columns.push(h)}a.push(D(c,e,f));"undefined"!==typeof c&&null!==c?(h=Ca(c),h.isCanvas=c.hasAttribute("data-tableexport-canvas"),h.elements=h.isCanvas?d(c):d(c).children(),"undefined"!==typeof d(c).data("teUserDefText")&&(h.hasUserDefText=!0)):(h=d.extend(!0,{},g.teCells[k+":"+(b-1)]),h.colspan=-1);g.teCells[k+":"+b++]=h});a.length&&(g.rows.push(a),k++);p++});if("function"===typeof g.onBeforeAutotable)g.onBeforeAutotable(d(this),
|
||||||
|
g.columns,g.rows,c);g.doc.autoTable(g.columns,g.rows,c);if("function"===typeof g.onAfterAutotable)g.onAfterAutotable(d(this),c);a.jspdf.autotable.startY=g.doc.autoTableEndPosY()+c.margin.top});va(g.doc,"undefined"!==typeof g.images&&!1===jQuery.isEmptyObject(g.images));"undefined"!==typeof g.headerrows&&(g.headerrows.length=0);"undefined"!==typeof g.columns&&(g.columns.length=0);"undefined"!==typeof g.rows&&(g.rows.length=0);delete g.doc;g.doc=null})}if("function"===typeof a.onTableExportEnd)a.onTableExportEnd();
|
||||||
|
return this}})(jQuery);
|
||||||
|
|
@ -1,92 +1,123 @@
|
||||||
/**
|
/**
|
||||||
* 基于bootstrap-table-mobile修改
|
* @author: Dennis Hernández
|
||||||
* 修正部分iPhone手机不显示卡片视图
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
* Copyright (c) 2019 ruoyi
|
*/
|
||||||
*/
|
|
||||||
!function ($) {
|
const debounce = (func, wait) => {
|
||||||
|
let timeout = 0
|
||||||
'use strict';
|
|
||||||
|
return (...args) => {
|
||||||
var resetView = function (that) {
|
const later = () => {
|
||||||
if (that.options.height || that.options.showFooter) {
|
timeout = 0
|
||||||
setTimeout(that.resetView(), 1);
|
func(...args)
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
clearTimeout(timeout)
|
||||||
// 判断是否 iphone
|
timeout = setTimeout(later, wait)
|
||||||
var isIPhone = function () {
|
}
|
||||||
var browserName = navigator.userAgent.toLowerCase();
|
}
|
||||||
return /(iPhone|iPad|iPod|iOS)/i.test(browserName);
|
|
||||||
};
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
mobileResponsive: false,
|
||||||
var changeView = function (that, width, height) {
|
minWidth: 562,
|
||||||
if (that.options.minHeight) {
|
minHeight: undefined,
|
||||||
if (checkValuesLessEqual(width, that.options.minWidth) && checkValuesLessEqual(height, that.options.minHeight)) {
|
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
|
||||||
conditionCardView(that);
|
checkOnInit: true,
|
||||||
} else if (checkValuesGreater(width, that.options.minWidth) && checkValuesGreater(height, that.options.minHeight)) {
|
columnsHidden: []
|
||||||
conditionFullView(that);
|
})
|
||||||
}
|
|
||||||
} else {
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
if (checkValuesLessEqual(width, that.options.minWidth) || isIPhone()) {
|
init (...args) {
|
||||||
conditionCardView(that);
|
super.init(...args)
|
||||||
} else if (checkValuesGreater(width, that.options.minWidth)) {
|
|
||||||
conditionFullView(that);
|
if (!this.options.mobileResponsive || !this.options.minWidth) {
|
||||||
}
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resetView(that);
|
if (this.options.minWidth < 100 && this.options.resizable) {
|
||||||
};
|
console.warn('The minWidth when the resizable extension is active should be greater or equal than 100')
|
||||||
|
this.options.minWidth = 100
|
||||||
var checkValuesLessEqual = function (currentValue, targetValue) {
|
}
|
||||||
return currentValue <= targetValue;
|
|
||||||
};
|
let old = {
|
||||||
|
width: $(window).width(),
|
||||||
var checkValuesGreater = function (currentValue, targetValue) {
|
height: $(window).height()
|
||||||
return currentValue > targetValue;
|
}
|
||||||
};
|
|
||||||
|
$(window).on('resize orientationchange', debounce(() => {
|
||||||
var conditionCardView = function (that) {
|
// reset view if height has only changed by at least the threshold.
|
||||||
changeTableView(that, false);
|
const width = $(window).width()
|
||||||
};
|
const height = $(window).height()
|
||||||
|
const $activeElement = $(document.activeElement)
|
||||||
var conditionFullView = function (that) {
|
|
||||||
changeTableView(that, true);
|
if ($activeElement.length && ['INPUT', 'SELECT', 'TEXTAREA'].includes($activeElement.prop('nodeName'))) {
|
||||||
};
|
return
|
||||||
|
}
|
||||||
var changeTableView = function (that, cardViewState) {
|
|
||||||
that.options.cardView = cardViewState;
|
if (
|
||||||
that.toggleView();
|
Math.abs(old.height - height) > this.options.heightThreshold ||
|
||||||
};
|
old.width !== width
|
||||||
|
) {
|
||||||
$.extend($.fn.bootstrapTable.defaults, {
|
this.changeView(width, height)
|
||||||
mobileResponsive: false,
|
old = {
|
||||||
minWidth: 562,
|
width,
|
||||||
minHeight: undefined,
|
height
|
||||||
checkOnInit: true,
|
}
|
||||||
toggled: false
|
}
|
||||||
});
|
}, 200))
|
||||||
|
|
||||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
if (this.options.checkOnInit) {
|
||||||
_init = BootstrapTable.prototype.init;
|
const width = $(window).width()
|
||||||
|
const height = $(window).height()
|
||||||
BootstrapTable.prototype.init = function () {
|
|
||||||
_init.apply(this, Array.prototype.slice.apply(arguments));
|
this.changeView(width, height)
|
||||||
|
old = {
|
||||||
if (!this.options.mobileResponsive) {
|
width,
|
||||||
return;
|
height
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!this.options.minWidth) {
|
}
|
||||||
return;
|
|
||||||
}
|
conditionCardView () {
|
||||||
|
this.changeTableView(false)
|
||||||
var that = this;
|
this.showHideColumns(false)
|
||||||
$(window).resize(function () {
|
}
|
||||||
changeView(that, $(this).width(), $(this).height())
|
|
||||||
});
|
conditionFullView () {
|
||||||
|
this.changeTableView(true)
|
||||||
if (this.options.checkOnInit) {
|
this.showHideColumns(true)
|
||||||
changeView(this, $(window).width(), $(window).height());
|
}
|
||||||
}
|
|
||||||
};
|
changeTableView (cardViewState) {
|
||||||
}(jQuery);
|
this.options.cardView = cardViewState
|
||||||
|
this.toggleView()
|
||||||
|
}
|
||||||
|
|
||||||
|
showHideColumns (checked) {
|
||||||
|
if (this.options.columnsHidden.length > 0) {
|
||||||
|
this.columns.forEach(column => {
|
||||||
|
if (this.options.columnsHidden.includes(column.field)) {
|
||||||
|
if (column.visible !== checked) {
|
||||||
|
this._toggleColumn(this.fieldsColumnsIndex[column.field], checked, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changeView (width, height) {
|
||||||
|
if (this.options.minHeight) {
|
||||||
|
if (width <= this.options.minWidth && height <= this.options.minHeight) {
|
||||||
|
this.conditionCardView()
|
||||||
|
} else if (width > this.options.minWidth && height > this.options.minHeight) {
|
||||||
|
this.conditionFullView()
|
||||||
|
}
|
||||||
|
} else if (width <= this.options.minWidth) {
|
||||||
|
this.conditionCardView()
|
||||||
|
} else if (width > this.options.minWidth) {
|
||||||
|
this.conditionFullView()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.resetView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,312 @@
|
||||||
|
/**
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Utils = $.fn.bootstrapTable.utils
|
||||||
|
|
||||||
|
function printPageBuilderDefault (table, styles) {
|
||||||
|
return `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
${styles}
|
||||||
|
<style type="text/css" media="print">
|
||||||
|
@page {
|
||||||
|
size: auto;
|
||||||
|
margin: 25px 0 25px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style type="text/css" media="all">
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid grey;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left:20px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 94%;
|
||||||
|
margin-left: 3%;
|
||||||
|
margin-right: 3%;
|
||||||
|
}
|
||||||
|
div.bs-table-print {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<title>Print Table</title>
|
||||||
|
<body>
|
||||||
|
<p>Printed on: ${new Date} </p>
|
||||||
|
<div class="bs-table-print">${table}</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.locales, {
|
||||||
|
formatPrint () {
|
||||||
|
return 'Print'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
showPrint: false,
|
||||||
|
printAsFilteredAndSortedOnUI: true,
|
||||||
|
printSortColumn: undefined,
|
||||||
|
printSortOrder: 'asc',
|
||||||
|
printStyles: [],
|
||||||
|
printPageBuilder (table, styles) {
|
||||||
|
return printPageBuilderDefault(table, styles)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.columnDefaults, {
|
||||||
|
printFilter: undefined,
|
||||||
|
printIgnore: false,
|
||||||
|
printFormatter: undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults.icons, {
|
||||||
|
print: {
|
||||||
|
bootstrap3: 'glyphicon-print icon-share',
|
||||||
|
bootstrap5: 'bi-printer',
|
||||||
|
'bootstrap-table': 'icon-printer'
|
||||||
|
}[$.fn.bootstrapTable.theme] || 'fa-print'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init (...args) {
|
||||||
|
super.init(...args)
|
||||||
|
|
||||||
|
if (!this.options.showPrint) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mergedCells = []
|
||||||
|
}
|
||||||
|
|
||||||
|
initToolbar (...args) {
|
||||||
|
this.showToolbar = this.showToolbar || this.options.showPrint
|
||||||
|
|
||||||
|
if (this.options.showPrint) {
|
||||||
|
this.buttons = Object.assign(this.buttons, {
|
||||||
|
print: {
|
||||||
|
text: this.options.formatPrint(),
|
||||||
|
icon: this.options.icons.print,
|
||||||
|
event: () => {
|
||||||
|
this.doPrint(this.options.printAsFilteredAndSortedOnUI ? this.getData() : this.options.data.slice(0))
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
'aria-label': this.options.formatPrint(),
|
||||||
|
title: this.options.formatPrint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initToolbar(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeCells (options) {
|
||||||
|
super.mergeCells(options)
|
||||||
|
|
||||||
|
if (!this.options.showPrint) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let col = this.getVisibleFields().indexOf(options.field)
|
||||||
|
|
||||||
|
if (Utils.hasDetailViewIcon(this.options)) {
|
||||||
|
col += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mergedCells.push({
|
||||||
|
row: options.index,
|
||||||
|
col,
|
||||||
|
rowspan: options.rowspan || 1,
|
||||||
|
colspan: options.colspan || 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
doPrint (data) {
|
||||||
|
const canPrint = column => {
|
||||||
|
return !column.printIgnore && column.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatValue = (row, i, column) => {
|
||||||
|
const value_ = Utils.getItemField(row, column.field, this.options.escape, column.escape)
|
||||||
|
const value = Utils.calculateObjectValue(column,
|
||||||
|
column.printFormatter || column.formatter,
|
||||||
|
[value_, row, i], value_)
|
||||||
|
|
||||||
|
return typeof value === 'undefined' || value === null ?
|
||||||
|
this.options.undefinedText : value
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildTable = (data, columnsArray) => {
|
||||||
|
const dir = this.$el.attr('dir') || 'ltr'
|
||||||
|
const html = [`<table dir="${dir}"><thead>`]
|
||||||
|
|
||||||
|
for (const columns of columnsArray) {
|
||||||
|
html.push('<tr>')
|
||||||
|
for (let h = 0; h < columns.length; h++) {
|
||||||
|
if (canPrint(columns[h])) {
|
||||||
|
html.push(
|
||||||
|
`<th
|
||||||
|
${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
|
||||||
|
${Utils.sprintf(' colspan="%s"', columns[h].colspan)}
|
||||||
|
>${columns[h].title}</th>`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html.push('</tr>')
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</thead><tbody>')
|
||||||
|
|
||||||
|
const notRender = []
|
||||||
|
|
||||||
|
if (this.mergedCells) {
|
||||||
|
for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
||||||
|
const currentMergedCell = this.mergedCells[mc]
|
||||||
|
|
||||||
|
for (let rs = 0; rs < currentMergedCell.rowspan; rs++) {
|
||||||
|
const row = currentMergedCell.row + rs
|
||||||
|
|
||||||
|
for (let cs = 0; cs < currentMergedCell.colspan; cs++) {
|
||||||
|
const col = currentMergedCell.col + cs
|
||||||
|
|
||||||
|
notRender.push(`${row},${col}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
html.push('<tr>')
|
||||||
|
|
||||||
|
const columns = columnsArray.flat(1)
|
||||||
|
|
||||||
|
columns.sort((c1, c2) => {
|
||||||
|
return c1.colspanIndex - c2.colspanIndex
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let j = 0; j < columns.length; j++) {
|
||||||
|
if (columns[j].colspanGroup > 0) continue
|
||||||
|
|
||||||
|
let rowspan = 0
|
||||||
|
let colspan = 0
|
||||||
|
|
||||||
|
if (this.mergedCells) {
|
||||||
|
for (let mc = 0; mc < this.mergedCells.length; mc++) {
|
||||||
|
const currentMergedCell = this.mergedCells[mc]
|
||||||
|
|
||||||
|
if (currentMergedCell.col === j && currentMergedCell.row === i) {
|
||||||
|
rowspan = currentMergedCell.rowspan
|
||||||
|
colspan = currentMergedCell.colspan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
canPrint(columns[j]) &&
|
||||||
|
(
|
||||||
|
!notRender.includes(`${i},${j}`) ||
|
||||||
|
rowspan > 0 && colspan > 0
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (rowspan > 0 && colspan > 0) {
|
||||||
|
html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>')
|
||||||
|
} else {
|
||||||
|
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</tr>')
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</tbody>')
|
||||||
|
if (this.options.showFooter) {
|
||||||
|
html.push('<footer><tr>')
|
||||||
|
|
||||||
|
for (const columns of columnsArray) {
|
||||||
|
for (let h = 0; h < columns.length; h++) {
|
||||||
|
if (canPrint(columns)) {
|
||||||
|
const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr'))
|
||||||
|
const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '')
|
||||||
|
|
||||||
|
html.push(`<th>${footerValue}</th>`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push('</tr></footer>')
|
||||||
|
}
|
||||||
|
html.push('</table>')
|
||||||
|
return html.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortRows = (data, colName, sortOrder) => {
|
||||||
|
if (!colName) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
let reverse = sortOrder !== 'asc'
|
||||||
|
|
||||||
|
reverse = -(+reverse || -1)
|
||||||
|
return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName]))
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterRow = (row, filters) => {
|
||||||
|
for (let index = 0; index < filters.length; ++index) {
|
||||||
|
if (row[filters[index].colName] !== filters[index].value) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterRows = (data, filters) => data.filter(row => filterRow(row, filters))
|
||||||
|
const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
|
||||||
|
colName: col.field,
|
||||||
|
value: col.printFilter
|
||||||
|
}))
|
||||||
|
|
||||||
|
data = filterRows(data, getColumnFilters(this.options.columns))
|
||||||
|
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
|
||||||
|
const table = buildTable(data, this.options.columns)
|
||||||
|
const newWin = window.open('')
|
||||||
|
const printStyles = typeof this.options.printStyles === 'string' ?
|
||||||
|
this.options.printStyles.replace(/\[|\]| /g, '').toLowerCase().split(',') :
|
||||||
|
this.options.printStyles
|
||||||
|
const styles = printStyles.map(it =>
|
||||||
|
`<link rel="stylesheet" href="${it}" />`).join('')
|
||||||
|
|
||||||
|
const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder,
|
||||||
|
[table, styles], printPageBuilderDefault(table, styles))
|
||||||
|
const startPrint = () => {
|
||||||
|
newWin.focus()
|
||||||
|
newWin.print()
|
||||||
|
newWin.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
newWin.document.write(calculatedPrintPage)
|
||||||
|
newWin.document.close()
|
||||||
|
|
||||||
|
if (printStyles.length) {
|
||||||
|
const links = document.getElementsByTagName('link')
|
||||||
|
const lastLink = links[links.length - 1]
|
||||||
|
|
||||||
|
lastLink.onload = startPrint
|
||||||
|
} else {
|
||||||
|
startPrint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @update: https://github.com/wenzhixin
|
||||||
|
* @version: v1.2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
$.akottr.dragtable.prototype._restoreState = function (persistObj) {
|
||||||
|
let i = 0
|
||||||
|
|
||||||
|
for (const [field, value] of Object.entries(persistObj)) {
|
||||||
|
const $th = this.originalTable.el.find(`th[data-field="${field}"]`)
|
||||||
|
|
||||||
|
if (!$th.length) {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
this.originalTable.startIndex = $th.prevAll().length + 1
|
||||||
|
this.originalTable.endIndex = parseInt(value, 10) + 1 - i
|
||||||
|
this._bubbleCols()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
|
||||||
|
const filterFn = () => {
|
||||||
|
if (!Array.prototype.filter) {
|
||||||
|
Array.prototype.filter = function (fun/* , thisArg*/) {
|
||||||
|
if (this === undefined || this === null) {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
|
||||||
|
const t = Object(this)
|
||||||
|
const len = t.length >>> 0
|
||||||
|
|
||||||
|
if (typeof fun !== 'function') {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = []
|
||||||
|
const thisArg = arguments.length >= 2 ? arguments[1] : undefined
|
||||||
|
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
if (i in t) {
|
||||||
|
const val = t[i]
|
||||||
|
|
||||||
|
// NOTE: Technically this should Object.defineProperty at
|
||||||
|
// the next index, as push can be affected by
|
||||||
|
// properties on Object.prototype and Array.prototype.
|
||||||
|
// But this method's new, and collisions should be
|
||||||
|
// rare, so use the more-compatible alternative.
|
||||||
|
if (fun.call(thisArg, val, i, t)) {
|
||||||
|
res.push(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
reorderableColumns: false,
|
||||||
|
maxMovingRows: 10,
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
onReorderColumn (headerFields) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
dragaccept: null
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.events, {
|
||||||
|
'reorder-column.bs.table': 'onReorderColumn'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.fn.bootstrapTable.methods.push('orderColumns')
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
initHeader (...args) {
|
||||||
|
super.initHeader(...args)
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeColumnsReorderable()
|
||||||
|
}
|
||||||
|
|
||||||
|
_toggleColumn (...args) {
|
||||||
|
super._toggleColumn(...args)
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeColumnsReorderable()
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleView (...args) {
|
||||||
|
super.toggleView(...args)
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.cardView) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeColumnsReorderable()
|
||||||
|
}
|
||||||
|
|
||||||
|
resetView (...args) {
|
||||||
|
super.resetView(...args)
|
||||||
|
|
||||||
|
if (!this.options.reorderableColumns) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.makeColumnsReorderable()
|
||||||
|
}
|
||||||
|
|
||||||
|
makeColumnsReorderable (order = null) {
|
||||||
|
try {
|
||||||
|
$(this.$el).dragtable('destroy')
|
||||||
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
$(this.$el).dragtable({
|
||||||
|
maxMovingRows: this.options.maxMovingRows,
|
||||||
|
dragaccept: this.options.dragaccept,
|
||||||
|
clickDelay: 200,
|
||||||
|
dragHandle: '.th-inner',
|
||||||
|
restoreState: order ? order : this.columnsSortOrder,
|
||||||
|
beforeStop: table => {
|
||||||
|
const sortOrder = {}
|
||||||
|
|
||||||
|
table.el.find('th').each((i, el) => {
|
||||||
|
sortOrder[$(el).data('field')] = i
|
||||||
|
})
|
||||||
|
|
||||||
|
this.columnsSortOrder = sortOrder
|
||||||
|
if (this.options.cookie) {
|
||||||
|
this.persistReorderColumnsState(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ths = []
|
||||||
|
const formatters = []
|
||||||
|
const columns = []
|
||||||
|
let columnsHidden = []
|
||||||
|
let columnIndex = -1
|
||||||
|
const optionsColumns = []
|
||||||
|
|
||||||
|
this.$header.find('th:not(.detail)').each((i, el) => {
|
||||||
|
ths.push($(el).data('field'))
|
||||||
|
formatters.push($(el).data('formatter'))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Exist columns not shown
|
||||||
|
if (ths.length < this.columns.length) {
|
||||||
|
columnsHidden = this.columns.filter(column => !column.visible)
|
||||||
|
for (let i = 0; i < columnsHidden.length; i++) {
|
||||||
|
ths.push(columnsHidden[i].field)
|
||||||
|
formatters.push(columnsHidden[i].formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < ths.length; i++) {
|
||||||
|
columnIndex = this.fieldsColumnsIndex[ths[i]]
|
||||||
|
if (columnIndex !== -1) {
|
||||||
|
this.fieldsColumnsIndex[ths[i]] = i
|
||||||
|
this.columns[columnIndex].fieldIndex = i
|
||||||
|
columns.push(this.columns[columnIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.columns = columns
|
||||||
|
|
||||||
|
filterFn() // Support <IE9
|
||||||
|
$.each(this.columns, (i, column) => {
|
||||||
|
let found = false
|
||||||
|
const field = column.field
|
||||||
|
|
||||||
|
this.options.columns[0].filter(item => {
|
||||||
|
if (!found && item['field'] === field) {
|
||||||
|
optionsColumns.push(item)
|
||||||
|
found = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.options.columns[0] = optionsColumns
|
||||||
|
|
||||||
|
this.header.fields = ths
|
||||||
|
this.header.formatters = formatters
|
||||||
|
this.initHeader()
|
||||||
|
this.initToolbar()
|
||||||
|
this.initSearchText()
|
||||||
|
this.initBody()
|
||||||
|
this.resetView()
|
||||||
|
this.trigger('reorder-column', ths)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
orderColumns (order) {
|
||||||
|
this.columnsSortOrder = order
|
||||||
|
this.makeColumnsReorderable()
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,145 @@
|
||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @update zhixin wen <wenzhixin2010@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
const rowAttr = (row, index) => ({
|
||||||
|
id: `customId_${index}`
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
reorderableRows: false,
|
||||||
|
onDragStyle: null,
|
||||||
|
onDropStyle: null,
|
||||||
|
onDragClass: 'reorder-rows-on-drag-class',
|
||||||
|
dragHandle: '>tbody>tr>td:not(.bs-checkbox)',
|
||||||
|
useRowAttrFunc: false,
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
onReorderRowsDrag (row) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
onReorderRowsDrop (row) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
onReorderRow (newData) {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
onDragStop () {},
|
||||||
|
onAllowDrop () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.events, {
|
||||||
|
'reorder-row.bs.table': 'onReorderRow'
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
init (...args) {
|
||||||
|
if (!this.options.reorderableRows) {
|
||||||
|
super.init(...args)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.useRowAttrFunc) {
|
||||||
|
this.options.rowAttributes = rowAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPostBody = this.options.onPostBody
|
||||||
|
|
||||||
|
this.options.onPostBody = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.makeRowsReorderable()
|
||||||
|
onPostBody.call(this.options, this.options.data)
|
||||||
|
}, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
super.init(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
makeRowsReorderable () {
|
||||||
|
this.$el.tableDnD({
|
||||||
|
onDragStyle: this.options.onDragStyle,
|
||||||
|
onDropStyle: this.options.onDropStyle,
|
||||||
|
onDragClass: this.options.onDragClass,
|
||||||
|
onAllowDrop: (hoveredRow, draggedRow) => this.onAllowDrop(hoveredRow, draggedRow),
|
||||||
|
onDragStop: (table, draggedRow) => this.onDragStop(table, draggedRow),
|
||||||
|
onDragStart: (table, droppedRow) => this.onDropStart(table, droppedRow),
|
||||||
|
onDrop: (table, droppedRow) => this.onDrop(table, droppedRow),
|
||||||
|
dragHandle: this.options.dragHandle
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropStart (table, draggingTd) {
|
||||||
|
this.$draggingTd = $(draggingTd).css('cursor', 'move')
|
||||||
|
this.draggingIndex = $(this.$draggingTd.parent()).data('index')
|
||||||
|
// Call the user defined function
|
||||||
|
this.options.onReorderRowsDrag(this.data[this.draggingIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
onDragStop (table, draggedRow) {
|
||||||
|
const rowIndexDraggedRow = $(draggedRow).data('index')
|
||||||
|
const draggedRowItem = this.data[rowIndexDraggedRow]
|
||||||
|
|
||||||
|
this.options.onDragStop(table, draggedRowItem, draggedRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
onAllowDrop (hoveredRow, draggedRow) {
|
||||||
|
const rowIndexDraggedRow = $(draggedRow).data('index')
|
||||||
|
const rowIndexHoveredRow = $(hoveredRow).data('index')
|
||||||
|
const draggedRowItem = this.data[rowIndexDraggedRow]
|
||||||
|
const hoveredRowItem = this.data[rowIndexHoveredRow]
|
||||||
|
|
||||||
|
return this.options.onAllowDrop(hoveredRowItem, draggedRowItem, hoveredRow, draggedRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
onDrop (table) {
|
||||||
|
this.$draggingTd.css('cursor', '')
|
||||||
|
const pageNum = this.options.pageNumber
|
||||||
|
const pageSize = this.options.pageSize
|
||||||
|
const newData = []
|
||||||
|
|
||||||
|
for (let i = 0; i < table.tBodies[0].rows.length; i++) {
|
||||||
|
const $tr = $(table.tBodies[0].rows[i])
|
||||||
|
|
||||||
|
newData.push(this.data[$tr.data('index')])
|
||||||
|
$tr.data('index', i)
|
||||||
|
}
|
||||||
|
|
||||||
|
const draggingRow = this.data[this.draggingIndex]
|
||||||
|
const droppedIndex = newData.indexOf(this.data[this.draggingIndex])
|
||||||
|
const droppedRow = this.data[droppedIndex]
|
||||||
|
const index = (pageNum - 1) * pageSize + this.options.data.indexOf(this.data[droppedIndex])
|
||||||
|
|
||||||
|
this.options.data.splice(this.options.data.indexOf(draggingRow), 1)
|
||||||
|
this.options.data.splice(index, 0, draggingRow)
|
||||||
|
|
||||||
|
this.initSearch()
|
||||||
|
|
||||||
|
if (this.options.sidePagination === 'server') {
|
||||||
|
this.data = [...this.options.data]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the user defined function
|
||||||
|
this.options.onReorderRowsDrop(droppedRow)
|
||||||
|
|
||||||
|
// Call the event reorder-row
|
||||||
|
this.trigger('reorder-row', newData, draggingRow, droppedRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
initSearch () {
|
||||||
|
this.ignoreInitSort = true
|
||||||
|
super.initSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
initSort () {
|
||||||
|
if (this.ignoreInitSort) {
|
||||||
|
this.ignoreInitSort = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initSort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,603 @@
|
||||||
|
/**
|
||||||
|
* TableDnD plug-in for JQuery, allows you to drag and drop table rows
|
||||||
|
* You can set up various options to control how the system will work
|
||||||
|
* Copyright (c) Denis Howlett <denish@isocra.com>
|
||||||
|
* License: MIT.
|
||||||
|
* See https://github.com/isocra/TableDnD
|
||||||
|
*/
|
||||||
|
!function ($, window, document, undefined) {
|
||||||
|
|
||||||
|
var startEvent = 'touchstart mousedown',
|
||||||
|
moveEvent = 'touchmove mousemove',
|
||||||
|
endEvent = 'touchend mouseup';
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
function parseStyle(css) {
|
||||||
|
var objMap = {},
|
||||||
|
parts = css.match(/([^;:]+)/g) || [];
|
||||||
|
while (parts.length)
|
||||||
|
objMap[parts.shift()] = parts.shift().trim();
|
||||||
|
|
||||||
|
return objMap;
|
||||||
|
}
|
||||||
|
$('table').each(function () {
|
||||||
|
if ($(this).data('table') === 'dnd') {
|
||||||
|
|
||||||
|
$(this).tableDnD({
|
||||||
|
onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null,
|
||||||
|
onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null,
|
||||||
|
onDragClass: $(this).data('ondragclass') === undefined && "tDnD_whileDrag" || $(this).data('ondragclass'),
|
||||||
|
onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null,
|
||||||
|
onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null,
|
||||||
|
onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')),
|
||||||
|
scrollAmount: $(this).data('scrollamount') || 5,
|
||||||
|
sensitivity: $(this).data('sensitivity') || 10,
|
||||||
|
hierarchyLevel: $(this).data('hierarchylevel') || 0,
|
||||||
|
indentArtifact: $(this).data('indentartifact') || '<div class="indent"> </div>',
|
||||||
|
autoWidthAdjust: $(this).data('autowidthadjust') || true,
|
||||||
|
autoCleanRelations: $(this).data('autocleanrelations') || true,
|
||||||
|
jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t',
|
||||||
|
serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/,
|
||||||
|
serializeParamName: $(this).data('serializeparamname') || false,
|
||||||
|
dragHandle: $(this).data('draghandle') || null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
jQuery.tableDnD = {
|
||||||
|
/** Keep hold of the current table being dragged */
|
||||||
|
currentTable: null,
|
||||||
|
/** Keep hold of the current drag object if any */
|
||||||
|
dragObject: null,
|
||||||
|
/** The current mouse offset */
|
||||||
|
mouseOffset: null,
|
||||||
|
/** Remember the old value of X and Y so that we don't do too much processing */
|
||||||
|
oldX: 0,
|
||||||
|
oldY: 0,
|
||||||
|
|
||||||
|
/** Actually build the structure */
|
||||||
|
build: function(options) {
|
||||||
|
// Set up the defaults if any
|
||||||
|
|
||||||
|
this.each(function() {
|
||||||
|
// This is bound to each matching table, set up the defaults and override with user options
|
||||||
|
this.tableDnDConfig = $.extend({
|
||||||
|
onDragStyle: null,
|
||||||
|
onDropStyle: null,
|
||||||
|
// Add in the default class for whileDragging
|
||||||
|
onDragClass: "tDnD_whileDrag",
|
||||||
|
onDrop: null,
|
||||||
|
onDragStart: null,
|
||||||
|
onDragStop: null,
|
||||||
|
scrollAmount: 5,
|
||||||
|
/** Sensitivity setting will throttle the trigger rate for movement detection */
|
||||||
|
sensitivity: 10,
|
||||||
|
/** Hierarchy level to support parent child. 0 switches this functionality off */
|
||||||
|
hierarchyLevel: 0,
|
||||||
|
/** The html artifact to prepend the first cell with as indentation */
|
||||||
|
indentArtifact: '<div class="indent"> </div>',
|
||||||
|
/** Automatically adjust width of first cell */
|
||||||
|
autoWidthAdjust: true,
|
||||||
|
/** Automatic clean-up to ensure relationship integrity */
|
||||||
|
autoCleanRelations: true,
|
||||||
|
/** Specify a number (4) as number of spaces or any indent string for JSON.stringify */
|
||||||
|
jsonPretifySeparator: '\t',
|
||||||
|
/** The regular expression to use to trim row IDs */
|
||||||
|
serializeRegexp: /[^\-]*$/,
|
||||||
|
/** If you want to specify another parameter name instead of the table ID */
|
||||||
|
serializeParamName: false,
|
||||||
|
/** If you give the name of a class here, then only Cells with this class will be draggable */
|
||||||
|
dragHandle: null
|
||||||
|
}, options || {});
|
||||||
|
|
||||||
|
// Now make the rows draggable
|
||||||
|
$.tableDnD.makeDraggable(this);
|
||||||
|
// Prepare hierarchy support
|
||||||
|
this.tableDnDConfig.hierarchyLevel
|
||||||
|
&& $.tableDnD.makeIndented(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Don't break the chain
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
makeIndented: function (table) {
|
||||||
|
var config = table.tableDnDConfig,
|
||||||
|
rows = table.rows,
|
||||||
|
firstCell = $(rows).first().find('td:first')[0],
|
||||||
|
indentLevel = 0,
|
||||||
|
cellWidth = 0,
|
||||||
|
longestCell,
|
||||||
|
tableStyle;
|
||||||
|
|
||||||
|
if ($(table).hasClass('indtd'))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
tableStyle = $(table).addClass('indtd').attr('style');
|
||||||
|
$(table).css({whiteSpace: "nowrap"});
|
||||||
|
|
||||||
|
for (var w = 0; w < rows.length; w++) {
|
||||||
|
if (cellWidth < $(rows[w]).find('td:first').text().length) {
|
||||||
|
cellWidth = $(rows[w]).find('td:first').text().length;
|
||||||
|
longestCell = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(firstCell).css({width: 'auto'});
|
||||||
|
for (w = 0; w < config.hierarchyLevel; w++)
|
||||||
|
$(rows[longestCell]).find('td:first').prepend(config.indentArtifact);
|
||||||
|
firstCell && $(firstCell).css({width: firstCell.offsetWidth});
|
||||||
|
tableStyle && $(table).css(tableStyle);
|
||||||
|
|
||||||
|
for (w = 0; w < config.hierarchyLevel; w++)
|
||||||
|
$(rows[longestCell]).find('td:first').children(':first').remove();
|
||||||
|
|
||||||
|
config.hierarchyLevel
|
||||||
|
&& $(rows).each(function () {
|
||||||
|
indentLevel = $(this).data('level') || 0;
|
||||||
|
indentLevel <= config.hierarchyLevel
|
||||||
|
&& $(this).data('level', indentLevel)
|
||||||
|
|| $(this).data('level', 0);
|
||||||
|
for (var i = 0; i < $(this).data('level'); i++)
|
||||||
|
$(this).find('td:first').prepend(config.indentArtifact);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
/** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
|
||||||
|
makeDraggable: function(table) {
|
||||||
|
var config = table.tableDnDConfig;
|
||||||
|
|
||||||
|
config.dragHandle
|
||||||
|
// We only need to add the event to the specified cells
|
||||||
|
&& $(config.dragHandle, table).each(function() {
|
||||||
|
if (! $(this).hasClass("nodrag")) {
|
||||||
|
// The cell is bound to "this"
|
||||||
|
$(this).bind(startEvent, function(e) {
|
||||||
|
if (e.target.tagName === "TD" && event.target.className !== "nodrag") {
|
||||||
|
$.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// For backwards compatibility, we add the event to the whole row
|
||||||
|
// get all the rows as a wrapped set
|
||||||
|
|| $(table.rows).each(function() {
|
||||||
|
// Iterate through each row, the row is bound to "this"
|
||||||
|
if (! $(this).hasClass("nodrag")) {
|
||||||
|
$(this).bind(startEvent, function(e) {
|
||||||
|
if (e.target.tagName === "TD" && event.target.className !== "nodrag") {
|
||||||
|
$.tableDnD.initialiseDrag(this, table, this, e, config);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).css("cursor", "move"); // Store the tableDnD object
|
||||||
|
} else {
|
||||||
|
$(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
currentOrder: function() {
|
||||||
|
var rows = this.currentTable.rows;
|
||||||
|
return $.map(rows, function (val) {
|
||||||
|
return ($(val).data('level') + val.id).replace(/\s/g, '');
|
||||||
|
}).join('');
|
||||||
|
},
|
||||||
|
initialiseDrag: function(dragObject, table, target, e, config) {
|
||||||
|
this.dragObject = dragObject;
|
||||||
|
this.currentTable = table;
|
||||||
|
this.mouseOffset = this.getMouseOffset(target, e);
|
||||||
|
this.originalOrder = this.currentOrder();
|
||||||
|
|
||||||
|
// Now we need to capture the mouse up and mouse move event
|
||||||
|
// We can use bind so that we don't interfere with other event handlers
|
||||||
|
$(document)
|
||||||
|
.bind(moveEvent, this.mousemove)
|
||||||
|
.bind(endEvent, this.mouseup);
|
||||||
|
|
||||||
|
// Call the onDragStart method if there is one
|
||||||
|
config.onDragStart
|
||||||
|
&& config.onDragStart(table, target);
|
||||||
|
},
|
||||||
|
updateTables: function() {
|
||||||
|
this.each(function() {
|
||||||
|
// this is now bound to each matching table
|
||||||
|
if (this.tableDnDConfig)
|
||||||
|
$.tableDnD.makeDraggable(this);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** Get the mouse coordinates from the event (allowing for browser differences) */
|
||||||
|
mouseCoords: function(e) {
|
||||||
|
if (e.originalEvent.changedTouches)
|
||||||
|
return {
|
||||||
|
x: e.originalEvent.changedTouches[0].clientX,
|
||||||
|
y: e.originalEvent.changedTouches[0].clientY
|
||||||
|
};
|
||||||
|
|
||||||
|
if(e.pageX || e.pageY)
|
||||||
|
return {
|
||||||
|
x: e.pageX,
|
||||||
|
y: e.pageY
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: e.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||||
|
y: e.clientY + document.body.scrollTop - document.body.clientTop
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/** Given a target element and a mouse eent, get the mouse offset from that element.
|
||||||
|
To do this we need the element's position and the mouse position */
|
||||||
|
getMouseOffset: function(target, e) {
|
||||||
|
var mousePos,
|
||||||
|
docPos;
|
||||||
|
|
||||||
|
e = e || window.event;
|
||||||
|
|
||||||
|
docPos = this.getPosition(target);
|
||||||
|
mousePos = this.mouseCoords(e);
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: mousePos.x - docPos.x,
|
||||||
|
y: mousePos.y - docPos.y
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/** Get the position of an element by going up the DOM tree and adding up all the offsets */
|
||||||
|
getPosition: function(element) {
|
||||||
|
var left = 0,
|
||||||
|
top = 0;
|
||||||
|
|
||||||
|
// Safari fix -- thanks to Luis Chato for this!
|
||||||
|
// Safari 2 doesn't correctly grab the offsetTop of a table row
|
||||||
|
// this is detailed here:
|
||||||
|
// http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
|
||||||
|
// the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
|
||||||
|
// note that firefox will return a text node as a first child, so designing a more thorough
|
||||||
|
// solution may need to take that into account, for now this seems to work in firefox, safari, ie
|
||||||
|
if (element.offsetHeight === 0)
|
||||||
|
element = element.firstChild; // a table cell
|
||||||
|
|
||||||
|
while (element.offsetParent) {
|
||||||
|
left += element.offsetLeft;
|
||||||
|
top += element.offsetTop;
|
||||||
|
element = element.offsetParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
left += element.offsetLeft;
|
||||||
|
top += element.offsetTop;
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: left,
|
||||||
|
y: top
|
||||||
|
};
|
||||||
|
},
|
||||||
|
autoScroll: function (mousePos) {
|
||||||
|
var config = this.currentTable.tableDnDConfig,
|
||||||
|
yOffset = window.pageYOffset,
|
||||||
|
windowHeight = window.innerHeight
|
||||||
|
? window.innerHeight
|
||||||
|
: document.documentElement.clientHeight
|
||||||
|
? document.documentElement.clientHeight
|
||||||
|
: document.body.clientHeight;
|
||||||
|
|
||||||
|
// Windows version
|
||||||
|
// yOffset=document.body.scrollTop;
|
||||||
|
if (document.all)
|
||||||
|
if (typeof document.compatMode !== 'undefined'
|
||||||
|
&& document.compatMode !== 'BackCompat')
|
||||||
|
yOffset = document.documentElement.scrollTop;
|
||||||
|
else if (typeof document.body !== 'undefined')
|
||||||
|
yOffset = document.body.scrollTop;
|
||||||
|
|
||||||
|
mousePos.y - yOffset < config.scrollAmount
|
||||||
|
&& window.scrollBy(0, - config.scrollAmount)
|
||||||
|
|| windowHeight - (mousePos.y - yOffset) < config.scrollAmount
|
||||||
|
&& window.scrollBy(0, config.scrollAmount);
|
||||||
|
|
||||||
|
},
|
||||||
|
moveVerticle: function (moving, currentRow) {
|
||||||
|
|
||||||
|
if (0 !== moving.vertical
|
||||||
|
// If we're over a row then move the dragged row to there so that the user sees the
|
||||||
|
// effect dynamically
|
||||||
|
&& currentRow
|
||||||
|
&& this.dragObject !== currentRow
|
||||||
|
&& this.dragObject.parentNode === currentRow.parentNode)
|
||||||
|
0 > moving.vertical
|
||||||
|
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling)
|
||||||
|
|| 0 < moving.vertical
|
||||||
|
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow);
|
||||||
|
|
||||||
|
},
|
||||||
|
moveHorizontal: function (moving, currentRow) {
|
||||||
|
var config = this.currentTable.tableDnDConfig,
|
||||||
|
currentLevel;
|
||||||
|
|
||||||
|
if (!config.hierarchyLevel
|
||||||
|
|| 0 === moving.horizontal
|
||||||
|
// We only care if moving left or right on the current row
|
||||||
|
|| !currentRow
|
||||||
|
|| this.dragObject !== currentRow)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
currentLevel = $(currentRow).data('level');
|
||||||
|
|
||||||
|
0 < moving.horizontal
|
||||||
|
&& currentLevel > 0
|
||||||
|
&& $(currentRow).find('td:first').children(':first').remove()
|
||||||
|
&& $(currentRow).data('level', --currentLevel);
|
||||||
|
|
||||||
|
0 > moving.horizontal
|
||||||
|
&& currentLevel < config.hierarchyLevel
|
||||||
|
&& $(currentRow).prev().data('level') >= currentLevel
|
||||||
|
&& $(currentRow).children(':first').prepend(config.indentArtifact)
|
||||||
|
&& $(currentRow).data('level', ++currentLevel);
|
||||||
|
|
||||||
|
},
|
||||||
|
mousemove: function(e) {
|
||||||
|
var dragObj = $($.tableDnD.dragObject),
|
||||||
|
config = $.tableDnD.currentTable.tableDnDConfig,
|
||||||
|
currentRow,
|
||||||
|
mousePos,
|
||||||
|
moving,
|
||||||
|
x,
|
||||||
|
y;
|
||||||
|
|
||||||
|
e && e.preventDefault();
|
||||||
|
|
||||||
|
if (!$.tableDnD.dragObject)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// prevent touch device screen scrolling
|
||||||
|
e.type === 'touchmove'
|
||||||
|
&& event.preventDefault(); // TODO verify this is event and not really e
|
||||||
|
|
||||||
|
// update the style to show we're dragging
|
||||||
|
config.onDragClass
|
||||||
|
&& dragObj.addClass(config.onDragClass)
|
||||||
|
|| dragObj.css(config.onDragStyle);
|
||||||
|
|
||||||
|
mousePos = $.tableDnD.mouseCoords(e);
|
||||||
|
x = mousePos.x - $.tableDnD.mouseOffset.x;
|
||||||
|
y = mousePos.y - $.tableDnD.mouseOffset.y;
|
||||||
|
|
||||||
|
// auto scroll the window
|
||||||
|
$.tableDnD.autoScroll(mousePos);
|
||||||
|
|
||||||
|
currentRow = $.tableDnD.findDropTargetRow(dragObj, y);
|
||||||
|
moving = $.tableDnD.findDragDirection(x, y);
|
||||||
|
|
||||||
|
$.tableDnD.moveVerticle(moving, currentRow);
|
||||||
|
$.tableDnD.moveHorizontal(moving, currentRow);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
findDragDirection: function (x,y) {
|
||||||
|
var sensitivity = this.currentTable.tableDnDConfig.sensitivity,
|
||||||
|
oldX = this.oldX,
|
||||||
|
oldY = this.oldY,
|
||||||
|
xMin = oldX - sensitivity,
|
||||||
|
xMax = oldX + sensitivity,
|
||||||
|
yMin = oldY - sensitivity,
|
||||||
|
yMax = oldY + sensitivity,
|
||||||
|
moving = {
|
||||||
|
horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1,
|
||||||
|
vertical : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// update the old value
|
||||||
|
if (moving.horizontal !== 0)
|
||||||
|
this.oldX = x;
|
||||||
|
if (moving.vertical !== 0)
|
||||||
|
this.oldY = y;
|
||||||
|
|
||||||
|
return moving;
|
||||||
|
},
|
||||||
|
/** We're only worried about the y position really, because we can only move rows up and down */
|
||||||
|
findDropTargetRow: function(draggedRow, y) {
|
||||||
|
var rowHeight = 0,
|
||||||
|
rows = this.currentTable.rows,
|
||||||
|
config = this.currentTable.tableDnDConfig,
|
||||||
|
rowY = 0,
|
||||||
|
row = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
row = rows[i];
|
||||||
|
rowY = this.getPosition(row).y;
|
||||||
|
rowHeight = parseInt(row.offsetHeight) / 2;
|
||||||
|
if (row.offsetHeight === 0) {
|
||||||
|
rowY = this.getPosition(row.firstChild).y;
|
||||||
|
rowHeight = parseInt(row.firstChild.offsetHeight) / 2;
|
||||||
|
}
|
||||||
|
// Because we always have to insert before, we need to offset the height a bit
|
||||||
|
if (y > (rowY - rowHeight) && y < (rowY + rowHeight))
|
||||||
|
// that's the row we're over
|
||||||
|
// If it's the same as the current row, ignore it
|
||||||
|
if (draggedRow.is(row)
|
||||||
|
|| (config.onAllowDrop
|
||||||
|
&& !config.onAllowDrop(draggedRow, row))
|
||||||
|
// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
|
||||||
|
|| $(row).hasClass("nodrop"))
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
processMouseup: function() {
|
||||||
|
if (!this.currentTable || !this.dragObject)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var config = this.currentTable.tableDnDConfig,
|
||||||
|
droppedRow = this.dragObject,
|
||||||
|
parentLevel = 0,
|
||||||
|
myLevel = 0;
|
||||||
|
|
||||||
|
// Unbind the event handlers
|
||||||
|
$(document)
|
||||||
|
.unbind(moveEvent, this.mousemove)
|
||||||
|
.unbind(endEvent, this.mouseup);
|
||||||
|
|
||||||
|
config.hierarchyLevel
|
||||||
|
&& config.autoCleanRelations
|
||||||
|
&& $(this.currentTable.rows).first().find('td:first').children().each(function () {
|
||||||
|
myLevel = $(this).parents('tr:first').data('level');
|
||||||
|
myLevel
|
||||||
|
&& $(this).parents('tr:first').data('level', --myLevel)
|
||||||
|
&& $(this).remove();
|
||||||
|
})
|
||||||
|
&& config.hierarchyLevel > 1
|
||||||
|
&& $(this.currentTable.rows).each(function () {
|
||||||
|
myLevel = $(this).data('level');
|
||||||
|
if (myLevel > 1) {
|
||||||
|
parentLevel = $(this).prev().data('level');
|
||||||
|
while (myLevel > parentLevel + 1) {
|
||||||
|
$(this).find('td:first').children(':first').remove();
|
||||||
|
$(this).data('level', --myLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// If we have a dragObject, then we need to release it,
|
||||||
|
// The row will already have been moved to the right place so we just reset stuff
|
||||||
|
config.onDragClass
|
||||||
|
&& $(droppedRow).removeClass(config.onDragClass)
|
||||||
|
|| $(droppedRow).css(config.onDropStyle);
|
||||||
|
|
||||||
|
this.dragObject = null;
|
||||||
|
// Call the onDrop method if there is one
|
||||||
|
config.onDrop
|
||||||
|
&& this.originalOrder !== this.currentOrder()
|
||||||
|
&& $(droppedRow).hide().fadeIn('fast')
|
||||||
|
&& config.onDrop(this.currentTable, droppedRow);
|
||||||
|
|
||||||
|
// Call the onDragStop method if there is one
|
||||||
|
config.onDragStop
|
||||||
|
&& config.onDragStop(this.currentTable, droppedRow);
|
||||||
|
|
||||||
|
this.currentTable = null; // let go of the table too
|
||||||
|
},
|
||||||
|
mouseup: function(e) {
|
||||||
|
e && e.preventDefault();
|
||||||
|
$.tableDnD.processMouseup();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
jsonize: function(pretify) {
|
||||||
|
var table = this.currentTable;
|
||||||
|
if (pretify)
|
||||||
|
return JSON.stringify(
|
||||||
|
this.tableData(table),
|
||||||
|
null,
|
||||||
|
table.tableDnDConfig.jsonPretifySeparator
|
||||||
|
);
|
||||||
|
return JSON.stringify(this.tableData(table));
|
||||||
|
},
|
||||||
|
serialize: function() {
|
||||||
|
return $.param(this.tableData(this.currentTable));
|
||||||
|
},
|
||||||
|
serializeTable: function(table) {
|
||||||
|
var result = "";
|
||||||
|
var paramName = table.tableDnDConfig.serializeParamName || table.id;
|
||||||
|
var rows = table.rows;
|
||||||
|
for (var i=0; i<rows.length; i++) {
|
||||||
|
if (result.length > 0) result += "&";
|
||||||
|
var rowId = rows[i].id;
|
||||||
|
if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
|
||||||
|
rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
|
||||||
|
result += paramName + '[]=' + rowId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
serializeTables: function() {
|
||||||
|
var result = [];
|
||||||
|
$('table').each(function() {
|
||||||
|
this.id && result.push($.param($.tableDnD.tableData(this)));
|
||||||
|
});
|
||||||
|
return result.join('&');
|
||||||
|
},
|
||||||
|
tableData: function (table) {
|
||||||
|
var config = table.tableDnDConfig,
|
||||||
|
previousIDs = [],
|
||||||
|
currentLevel = 0,
|
||||||
|
indentLevel = 0,
|
||||||
|
rowID = null,
|
||||||
|
data = {},
|
||||||
|
getSerializeRegexp,
|
||||||
|
paramName,
|
||||||
|
currentID,
|
||||||
|
rows;
|
||||||
|
|
||||||
|
if (!table)
|
||||||
|
table = this.currentTable;
|
||||||
|
if (!table || !table.rows || !table.rows.length)
|
||||||
|
return {error: { code: 500, message: "Not a valid table."}};
|
||||||
|
if (!table.id && !config.serializeParamName)
|
||||||
|
return {error: { code: 500, message: "No serializable unique id provided."}};
|
||||||
|
|
||||||
|
rows = config.autoCleanRelations
|
||||||
|
&& table.rows
|
||||||
|
|| $.makeArray(table.rows);
|
||||||
|
paramName = config.serializeParamName || table.id;
|
||||||
|
currentID = paramName;
|
||||||
|
|
||||||
|
getSerializeRegexp = function (rowId) {
|
||||||
|
if (rowId && config && config.serializeRegexp)
|
||||||
|
return rowId.match(config.serializeRegexp)[0];
|
||||||
|
return rowId;
|
||||||
|
};
|
||||||
|
|
||||||
|
data[currentID] = [];
|
||||||
|
!config.autoCleanRelations
|
||||||
|
&& $(rows[0]).data('level')
|
||||||
|
&& rows.unshift({id: 'undefined'});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (var i=0; i < rows.length; i++) {
|
||||||
|
if (config.hierarchyLevel) {
|
||||||
|
indentLevel = $(rows[i]).data('level') || 0;
|
||||||
|
if (indentLevel === 0) {
|
||||||
|
currentID = paramName;
|
||||||
|
previousIDs = [];
|
||||||
|
}
|
||||||
|
else if (indentLevel > currentLevel) {
|
||||||
|
previousIDs.push([currentID, currentLevel]);
|
||||||
|
currentID = getSerializeRegexp(rows[i-1].id);
|
||||||
|
}
|
||||||
|
else if (indentLevel < currentLevel) {
|
||||||
|
for (var h = 0; h < previousIDs.length; h++) {
|
||||||
|
if (previousIDs[h][1] === indentLevel)
|
||||||
|
currentID = previousIDs[h][0];
|
||||||
|
if (previousIDs[h][1] >= currentLevel)
|
||||||
|
previousIDs[h][1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentLevel = indentLevel;
|
||||||
|
|
||||||
|
if (!$.isArray(data[currentID]))
|
||||||
|
data[currentID] = [];
|
||||||
|
rowID = getSerializeRegexp(rows[i].id);
|
||||||
|
rowID && data[currentID].push(rowID);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rowID = getSerializeRegexp(rows[i].id);
|
||||||
|
rowID && data[currentID].push(rowID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jQuery.fn.extend(
|
||||||
|
{
|
||||||
|
tableDnD : $.tableDnD.build,
|
||||||
|
tableDnDUpdate : $.tableDnD.updateTables,
|
||||||
|
tableDnDSerialize : $.proxy($.tableDnD.serialize, $.tableDnD),
|
||||||
|
tableDnDSerializeAll : $.tableDnD.serializeTables,
|
||||||
|
tableDnDData : $.proxy($.tableDnD.tableData, $.tableDnD)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}(jQuery, window, window.document);
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* @author: Dennis Hernández
|
||||||
|
* @version: v2.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
const isInit = that => that.$el.data('resizableColumns') !== undefined
|
||||||
|
|
||||||
|
const initResizable = that => {
|
||||||
|
if (
|
||||||
|
that.options.resizable &&
|
||||||
|
!that.options.cardView &&
|
||||||
|
!isInit(that) &&
|
||||||
|
that.$el.is(':visible')
|
||||||
|
) {
|
||||||
|
that.$el.resizableColumns({
|
||||||
|
store: window.store
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const destroy = that => {
|
||||||
|
if (isInit(that)) {
|
||||||
|
that.$el.data('resizableColumns').destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reInitResizable = that => {
|
||||||
|
destroy(that)
|
||||||
|
initResizable(that)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign($.fn.bootstrapTable.defaults, {
|
||||||
|
resizable: false
|
||||||
|
})
|
||||||
|
|
||||||
|
$.BootstrapTable = class extends $.BootstrapTable {
|
||||||
|
|
||||||
|
initBody (...args) {
|
||||||
|
super.initBody(...args)
|
||||||
|
|
||||||
|
this.$el.off('column-switch.bs.table page-change.bs.table')
|
||||||
|
.on('column-switch.bs.table page-change.bs.table', () => {
|
||||||
|
reInitResizable(this)
|
||||||
|
})
|
||||||
|
|
||||||
|
reInitResizable(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleView (...args) {
|
||||||
|
super.toggleView(...args)
|
||||||
|
|
||||||
|
if (this.options.resizable && this.options.cardView) {
|
||||||
|
// Destroy the plugin
|
||||||
|
destroy(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetView (...args) {
|
||||||
|
super.resetView(...args)
|
||||||
|
|
||||||
|
if (this.options.resizable) {
|
||||||
|
// because in fitHeader function, we use setTimeout(func, 100);
|
||||||
|
setTimeout(() => {
|
||||||
|
initResizable(this)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,211 +0,0 @@
|
||||||
/**
|
|
||||||
* @author: aperez <aperez@datadec.es>
|
|
||||||
* @version: v2.0.0
|
|
||||||
*
|
|
||||||
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
|
|
||||||
*/
|
|
||||||
|
|
||||||
!function($) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var firstLoad = false;
|
|
||||||
|
|
||||||
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
|
||||||
|
|
||||||
var showAvdSearch = function(pColumns, searchTitle, searchText, that) {
|
|
||||||
if (!$("#avdSearchModal" + "_" + that.options.idTable).hasClass("modal")) {
|
|
||||||
var vModal = sprintf("<div id=\"avdSearchModal%s\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">", "_" + that.options.idTable);
|
|
||||||
vModal += "<div class=\"modal-dialog modal-xs\">";
|
|
||||||
vModal += " <div class=\"modal-content\">";
|
|
||||||
vModal += " <div class=\"modal-header\">";
|
|
||||||
vModal += " <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" >×</button>";
|
|
||||||
vModal += sprintf(" <h4 class=\"modal-title\">%s</h4>", searchTitle);
|
|
||||||
vModal += " </div>";
|
|
||||||
vModal += " <div class=\"modal-body modal-body-custom\">";
|
|
||||||
vModal += sprintf(" <div class=\"container-fluid\" id=\"avdSearchModalContent%s\" style=\"padding-right: 0px;padding-left: 0px;\" >", "_" + that.options.idTable);
|
|
||||||
vModal += " </div>";
|
|
||||||
vModal += " </div>";
|
|
||||||
vModal += " </div>";
|
|
||||||
vModal += " </div>";
|
|
||||||
vModal += "</div>";
|
|
||||||
|
|
||||||
$("body").append($(vModal));
|
|
||||||
|
|
||||||
var vFormAvd = createFormAvd(pColumns, searchText, that),
|
|
||||||
timeoutId = 0;;
|
|
||||||
|
|
||||||
$('#avdSearchModalContent' + "_" + that.options.idTable).append(vFormAvd.join(''));
|
|
||||||
|
|
||||||
$('#' + that.options.idForm).off('keyup blur', 'input').on('keyup blur', 'input', function (event) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
timeoutId = setTimeout(function () {
|
|
||||||
that.onColumnAdvancedSearch(event);
|
|
||||||
}, that.options.searchTimeOut);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#btnCloseAvd" + "_" + that.options.idTable).click(function() {
|
|
||||||
$("#avdSearchModal" + "_" + that.options.idTable).modal('hide');
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#avdSearchModal" + "_" + that.options.idTable).modal();
|
|
||||||
} else {
|
|
||||||
$("#avdSearchModal" + "_" + that.options.idTable).modal();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var createFormAvd = function(pColumns, searchText, that) {
|
|
||||||
var htmlForm = [];
|
|
||||||
htmlForm.push(sprintf('<form class="form-horizontal" id="%s" action="%s" >', that.options.idForm, that.options.actionForm));
|
|
||||||
for (var i in pColumns) {
|
|
||||||
var vObjCol = pColumns[i];
|
|
||||||
if (!vObjCol.checkbox && vObjCol.visible && vObjCol.searchable) {
|
|
||||||
htmlForm.push('<div class="form-group">');
|
|
||||||
htmlForm.push(sprintf('<label class="col-sm-4 control-label">%s</label>', vObjCol.title));
|
|
||||||
htmlForm.push('<div class="col-sm-6">');
|
|
||||||
htmlForm.push(sprintf('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">', vObjCol.field, vObjCol.title, vObjCol.field));
|
|
||||||
htmlForm.push('</div>');
|
|
||||||
htmlForm.push('</div>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlForm.push('<div class="form-group">');
|
|
||||||
htmlForm.push('<div class="col-sm-offset-9 col-sm-3">');
|
|
||||||
htmlForm.push(sprintf('<button type="button" id="btnCloseAvd%s" class="btn btn-default" >%s</button>', "_" + that.options.idTable, searchText));
|
|
||||||
htmlForm.push('</div>');
|
|
||||||
htmlForm.push('</div>');
|
|
||||||
htmlForm.push('</form>');
|
|
||||||
|
|
||||||
return htmlForm;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.defaults, {
|
|
||||||
advancedSearch: false,
|
|
||||||
idForm: 'advancedSearch',
|
|
||||||
actionForm: '',
|
|
||||||
idTable: undefined,
|
|
||||||
onColumnAdvancedSearch: function (field, text) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
|
||||||
advancedSearchIcon: 'glyphicon-chevron-down'
|
|
||||||
});
|
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
|
||||||
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
|
|
||||||
});
|
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.locales, {
|
|
||||||
formatAdvancedSearch: function() {
|
|
||||||
return 'Advanced search';
|
|
||||||
},
|
|
||||||
formatAdvancedCloseButton: function() {
|
|
||||||
return "Close";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
|
||||||
|
|
||||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
|
||||||
_initToolbar = BootstrapTable.prototype.initToolbar,
|
|
||||||
_load = BootstrapTable.prototype.load,
|
|
||||||
_initSearch = BootstrapTable.prototype.initSearch;
|
|
||||||
|
|
||||||
BootstrapTable.prototype.initToolbar = function() {
|
|
||||||
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
|
||||||
if (!this.options.search) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.options.advancedSearch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.options.idTable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var that = this,
|
|
||||||
html = [];
|
|
||||||
|
|
||||||
html.push(sprintf('<div class="columns columns-%s btn-group pull-%s" role="group">', this.options.buttonsAlign, this.options.buttonsAlign));
|
|
||||||
html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="advancedSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatAdvancedSearch()));
|
|
||||||
html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.advancedSearchIcon))
|
|
||||||
html.push('</button></div>');
|
|
||||||
|
|
||||||
that.$toolbar.prepend(html.join(''));
|
|
||||||
|
|
||||||
that.$toolbar.find('button[name="advancedSearch"]')
|
|
||||||
.off('click').on('click', function() {
|
|
||||||
showAvdSearch(that.columns, that.options.formatAdvancedSearch(), that.options.formatAdvancedCloseButton(), that);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
BootstrapTable.prototype.load = function(data) {
|
|
||||||
_load.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
|
||||||
if (!this.options.advancedSearch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof this.options.idTable === 'undefined') {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!firstLoad) {
|
|
||||||
var height = parseInt($(".bootstrap-table").height());
|
|
||||||
height += 10;
|
|
||||||
$("#" + this.options.idTable).bootstrapTable("resetView", {height: height});
|
|
||||||
firstLoad = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BootstrapTable.prototype.initSearch = function () {
|
|
||||||
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
|
||||||
|
|
||||||
if (!this.options.advancedSearch) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var that = this;
|
|
||||||
var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
|
|
||||||
|
|
||||||
this.data = fp ? $.grep(this.data, function (item, i) {
|
|
||||||
for (var key in fp) {
|
|
||||||
var fval = fp[key].toLowerCase();
|
|
||||||
var value = item[key];
|
|
||||||
value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
|
|
||||||
that.header.formatters[$.inArray(key, that.header.fields)],
|
|
||||||
[value, item, i], value);
|
|
||||||
|
|
||||||
if (!($.inArray(key, that.header.fields) !== -1 &&
|
|
||||||
(typeof value === 'string' || typeof value === 'number') &&
|
|
||||||
(value + '').toLowerCase().indexOf(fval) !== -1)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}) : this.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
BootstrapTable.prototype.onColumnAdvancedSearch = function (event) {
|
|
||||||
var text = $.trim($(event.currentTarget).val());
|
|
||||||
var $field = $(event.currentTarget)[0].id;
|
|
||||||
|
|
||||||
if ($.isEmptyObject(this.filterColumnsPartial)) {
|
|
||||||
this.filterColumnsPartial = {};
|
|
||||||
}
|
|
||||||
if (text) {
|
|
||||||
this.filterColumnsPartial[$field] = text;
|
|
||||||
} else {
|
|
||||||
delete this.filterColumnsPartial[$field];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.options.pageNumber = 1;
|
|
||||||
this.onSearch(event);
|
|
||||||
this.updatePagination();
|
|
||||||
this.trigger('column-advanced-search', $field, text);
|
|
||||||
};
|
|
||||||
}(jQuery);
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/*
|
|
||||||
* bootstrap-table - v1.11.0 - 2016-07-02
|
|
||||||
* https://github.com/wenzhixin/bootstrap-table
|
|
||||||
* Copyright (c) 2016 zhixin wen
|
|
||||||
* Licensed MIT License
|
|
||||||
*/
|
|
||||||
!function(a){"use strict";var b=!1,c=a.fn.bootstrapTable.utils.sprintf,d=function(b,d,f,g){if(a("#avdSearchModal_"+g.options.idTable).hasClass("modal"))a("#avdSearchModal_"+g.options.idTable).modal();else{var h=c('<div id="avdSearchModal%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">',"_"+g.options.idTable);h+='<div class="modal-dialog modal-xs">',h+=' <div class="modal-content">',h+=' <div class="modal-header">',h+=' <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >×</button>',h+=c(' <h4 class="modal-title">%s</h4>',d),h+=" </div>",h+=' <div class="modal-body modal-body-custom">',h+=c(' <div class="container-fluid" id="avdSearchModalContent%s" style="padding-right: 0px;padding-left: 0px;" >',"_"+g.options.idTable),h+=" </div>",h+=" </div>",h+=" </div>",h+=" </div>",h+="</div>",a("body").append(a(h));var i=e(b,f,g),j=0;a("#avdSearchModalContent_"+g.options.idTable).append(i.join("")),a("#"+g.options.idForm).off("keyup blur","input").on("keyup blur","input",function(a){clearTimeout(j),j=setTimeout(function(){g.onColumnAdvancedSearch(a)},g.options.searchTimeOut)}),a("#btnCloseAvd_"+g.options.idTable).click(function(){a("#avdSearchModal_"+g.options.idTable).modal("hide")}),a("#avdSearchModal_"+g.options.idTable).modal()}},e=function(a,b,d){var e=[];e.push(c('<form class="form-horizontal" id="%s" action="%s" >',d.options.idForm,d.options.actionForm));for(var f in a){var g=a[f];!g.checkbox&&g.visible&&g.searchable&&(e.push('<div class="form-group">'),e.push(c('<label class="col-sm-4 control-label">%s</label>',g.title)),e.push('<div class="col-sm-6">'),e.push(c('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">',g.field,g.title,g.field)),e.push("</div>"),e.push("</div>"))}return e.push('<div class="form-group">'),e.push('<div class="col-sm-offset-9 col-sm-3">'),e.push(c('<button type="button" id="btnCloseAvd%s" class="btn btn-default" >%s</button>',"_"+d.options.idTable,b)),e.push("</div>"),e.push("</div>"),e.push("</form>"),e};a.extend(a.fn.bootstrapTable.defaults,{advancedSearch:!1,idForm:"advancedSearch",actionForm:"",idTable:void 0,onColumnAdvancedSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{advancedSearchIcon:"glyphicon-chevron-down"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-advanced-search.bs.table":"onColumnAdvancedSearch"}),a.extend(a.fn.bootstrapTable.locales,{formatAdvancedSearch:function(){return"Advanced search"},formatAdvancedCloseButton:function(){return"Close"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var f=a.fn.bootstrapTable.Constructor,g=f.prototype.initToolbar,h=f.prototype.load,i=f.prototype.initSearch;f.prototype.initToolbar=function(){if(g.apply(this,Array.prototype.slice.apply(arguments)),this.options.search&&this.options.advancedSearch&&this.options.idTable){var a=this,b=[];b.push(c('<div class="columns columns-%s btn-group pull-%s" role="group">',this.options.buttonsAlign,this.options.buttonsAlign)),b.push(c('<button class="btn btn-default%s" type="button" name="advancedSearch" title="%s">',void 0===a.options.iconSize?"":" btn-"+a.options.iconSize,a.options.formatAdvancedSearch())),b.push(c('<i class="%s %s"></i>',a.options.iconsPrefix,a.options.icons.advancedSearchIcon)),b.push("</button></div>"),a.$toolbar.prepend(b.join("")),a.$toolbar.find('button[name="advancedSearch"]').off("click").on("click",function(){d(a.columns,a.options.formatAdvancedSearch(),a.options.formatAdvancedCloseButton(),a)})}},f.prototype.load=function(){if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.advancedSearch&&"undefined"!=typeof this.options.idTable&&!b){var c=parseInt(a(".bootstrap-table").height());c+=10,a("#"+this.options.idTable).bootstrapTable("resetView",{height:c}),b=!0}},f.prototype.initSearch=function(){if(i.apply(this,Array.prototype.slice.apply(arguments)),this.options.advancedSearch){var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(d,e){for(var f in c){var g=c[f].toLowerCase(),h=d[f];if(h=a.fn.bootstrapTable.utils.calculateObjectValue(b.header,b.header.formatters[a.inArray(f,b.header.fields)],[h,d,e],h),-1===a.inArray(f,b.header.fields)||"string"!=typeof h&&"number"!=typeof h||-1===(h+"").toLowerCase().indexOf(g))return!1}return!0}):this.data}},f.prototype.onColumnAdvancedSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget)[0].id;a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-advanced-search",d,c)}}(jQuery);
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -1,42 +1,109 @@
|
||||||
(function ($) {
|
/**
|
||||||
'use strict';
|
* Bootstrap Table Chinese translation
|
||||||
|
* Author: Zhixin Wen<wenzhixin2010@gmail.com>
|
||||||
$.fn.bootstrapTable.locales['zh-CN'] = {
|
*/
|
||||||
formatLoadingMessage: function () {
|
$.fn.bootstrapTable.locales['zh-CN'] = {
|
||||||
return '正在努力地加载数据中,请稍候……';
|
formatShowSearch: function formatShowSearch() {
|
||||||
},
|
return '隐藏/显示搜索';
|
||||||
formatRecordsPerPage: function (pageNumber) {
|
},
|
||||||
return pageNumber + ' 条记录每页';
|
formatPageGo: function formatPageGo() {
|
||||||
},
|
return '跳转';
|
||||||
formatShowingRows: function (pageFrom, pageTo, totalRows) {
|
},
|
||||||
return '第 ' + pageFrom + ' 到 ' + pageTo + ' 条,共 ' + totalRows + ' 条记录。';
|
formatCopyRows: function formatCopyRows() {
|
||||||
},
|
return '复制行';
|
||||||
formatSearch: function () {
|
},
|
||||||
return '搜索';
|
formatPrint: function formatPrint() {
|
||||||
},
|
return '打印';
|
||||||
formatNoMatches: function () {
|
},
|
||||||
return '没有找到匹配的记录';
|
formatLoadingMessage: function formatLoadingMessage() {
|
||||||
},
|
return '正在努力地加载数据中,请稍候';
|
||||||
formatPaginationSwitch: function () {
|
},
|
||||||
return '隐藏/显示分页';
|
formatRecordsPerPage: function formatRecordsPerPage(pageNumber) {
|
||||||
},
|
return "每页显示 ".concat(pageNumber, " 条记录");
|
||||||
formatRefresh: function () {
|
},
|
||||||
return '刷新';
|
formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
|
||||||
},
|
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
|
||||||
formatToggle: function () {
|
return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录(从 ").concat(totalNotFiltered, " 总记录中过滤)");
|
||||||
return '切换';
|
}
|
||||||
},
|
return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录");
|
||||||
formatColumns: function () {
|
},
|
||||||
return '列';
|
formatSRPaginationPreText: function formatSRPaginationPreText() {
|
||||||
},
|
return '上一页';
|
||||||
formatExport: function () {
|
},
|
||||||
return '导出数据';
|
formatSRPaginationPageText: function formatSRPaginationPageText(page) {
|
||||||
},
|
return "第".concat(page, "页");
|
||||||
formatClearFilters: function () {
|
},
|
||||||
return '清空过滤';
|
formatSRPaginationNextText: function formatSRPaginationNextText() {
|
||||||
}
|
return '下一页';
|
||||||
};
|
},
|
||||||
|
formatDetailPagination: function formatDetailPagination(totalRows) {
|
||||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
|
return "总共 ".concat(totalRows, " 条记录");
|
||||||
|
},
|
||||||
})(jQuery);
|
formatClearSearch: function formatClearSearch() {
|
||||||
|
return '清空过滤';
|
||||||
|
},
|
||||||
|
formatSearch: function formatSearch() {
|
||||||
|
return '搜索';
|
||||||
|
},
|
||||||
|
formatNoMatches: function formatNoMatches() {
|
||||||
|
return '没有找到匹配的记录';
|
||||||
|
},
|
||||||
|
formatPaginationSwitch: function formatPaginationSwitch() {
|
||||||
|
return '隐藏/显示分页';
|
||||||
|
},
|
||||||
|
formatPaginationSwitchDown: function formatPaginationSwitchDown() {
|
||||||
|
return '显示分页';
|
||||||
|
},
|
||||||
|
formatPaginationSwitchUp: function formatPaginationSwitchUp() {
|
||||||
|
return '隐藏分页';
|
||||||
|
},
|
||||||
|
formatRefresh: function formatRefresh() {
|
||||||
|
return '刷新';
|
||||||
|
},
|
||||||
|
formatToggle: function formatToggle() {
|
||||||
|
return '切换';
|
||||||
|
},
|
||||||
|
formatToggleOn: function formatToggleOn() {
|
||||||
|
return '显示卡片视图';
|
||||||
|
},
|
||||||
|
formatToggleOff: function formatToggleOff() {
|
||||||
|
return '隐藏卡片视图';
|
||||||
|
},
|
||||||
|
formatColumns: function formatColumns() {
|
||||||
|
return '列';
|
||||||
|
},
|
||||||
|
formatColumnsToggleAll: function formatColumnsToggleAll() {
|
||||||
|
return '切换所有';
|
||||||
|
},
|
||||||
|
formatFullscreen: function formatFullscreen() {
|
||||||
|
return '全屏';
|
||||||
|
},
|
||||||
|
formatAllRows: function formatAllRows() {
|
||||||
|
return '所有';
|
||||||
|
},
|
||||||
|
formatAutoRefresh: function formatAutoRefresh() {
|
||||||
|
return '自动刷新';
|
||||||
|
},
|
||||||
|
formatExport: function formatExport() {
|
||||||
|
return '导出数据';
|
||||||
|
},
|
||||||
|
formatJumpTo: function formatJumpTo() {
|
||||||
|
return '跳转';
|
||||||
|
},
|
||||||
|
formatAdvancedSearch: function formatAdvancedSearch() {
|
||||||
|
return '高级搜索';
|
||||||
|
},
|
||||||
|
formatAdvancedCloseButton: function formatAdvancedCloseButton() {
|
||||||
|
return '关闭';
|
||||||
|
},
|
||||||
|
formatFilterControlSwitch: function formatFilterControlSwitch() {
|
||||||
|
return '隐藏/显示过滤控制';
|
||||||
|
},
|
||||||
|
formatFilterControlSwitchHide: function formatFilterControlSwitchHide() {
|
||||||
|
return '隐藏过滤控制';
|
||||||
|
},
|
||||||
|
formatFilterControlSwitchShow: function formatFilterControlSwitchShow() {
|
||||||
|
return '显示过滤控制';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
(function($){$.fn.bootstrapTable.locales["zh-CN"]={formatLoadingMessage:function(){return"正在努力地加载数据中,请稍候……"},formatRecordsPerPage:function(pageNumber){return pageNumber+" 条记录每页"},formatShowingRows:function(pageFrom,pageTo,totalRows){return"第 "+pageFrom+" 到 "+pageTo+" 条,共 "+totalRows+" 条记录。"},formatSearch:function(){return"搜索"},formatNoMatches:function(){return"没有找到匹配的记录"},formatPaginationSwitch:function(){return"隐藏/显示分页"},formatRefresh:function(){return"刷新"},formatToggle:function(){return"切换"},formatColumns:function(){return"列"},formatExport:function(){return"导出数据"},formatClearFilters:function(){return"清空过滤"}};$.extend($.fn.bootstrapTable.defaults,$.fn.bootstrapTable.locales["zh-CN"])})(jQuery);
|
$.fn.bootstrapTable.locales["zh-CN"]={formatShowSearch:function formatShowSearch(){return"隐藏/显示搜索"},formatPageGo:function formatPageGo(){return"跳转"},formatCopyRows:function formatCopyRows(){return"复制行"},formatPrint:function formatPrint(){return"打印"},formatLoadingMessage:function formatLoadingMessage(){return"正在努力地加载数据中,请稍候"},formatRecordsPerPage:function formatRecordsPerPage(pageNumber){return"每页显示 ".concat(pageNumber," 条记录")},formatShowingRows:function formatShowingRows(pageFrom,pageTo,totalRows,totalNotFiltered){if(totalNotFiltered!==undefined&&totalNotFiltered>0&&totalNotFiltered>totalRows){return"显示第 ".concat(pageFrom," 到第 ").concat(pageTo," 条记录,总共 ").concat(totalRows," 条记录(从 ").concat(totalNotFiltered," 总记录中过滤)")}return"显示第 ".concat(pageFrom," 到第 ").concat(pageTo," 条记录,总共 ").concat(totalRows," 条记录")},formatSRPaginationPreText:function formatSRPaginationPreText(){return"上一页"},formatSRPaginationPageText:function formatSRPaginationPageText(page){return"第".concat(page,"页")},formatSRPaginationNextText:function formatSRPaginationNextText(){return"下一页"},formatDetailPagination:function formatDetailPagination(totalRows){return"总共 ".concat(totalRows," 条记录")},formatClearSearch:function formatClearSearch(){return"清空过滤"},formatSearch:function formatSearch(){return"搜索"},formatNoMatches:function formatNoMatches(){return"没有找到匹配的记录"},formatPaginationSwitch:function formatPaginationSwitch(){return"隐藏/显示分页"},formatPaginationSwitchDown:function formatPaginationSwitchDown(){return"显示分页"},formatPaginationSwitchUp:function formatPaginationSwitchUp(){return"隐藏分页"},formatRefresh:function formatRefresh(){return"刷新"},formatToggle:function formatToggle(){return"切换"},formatToggleOn:function formatToggleOn(){return"显示卡片视图"},formatToggleOff:function formatToggleOff(){return"隐藏卡片视图"},formatColumns:function formatColumns(){return"列"},formatColumnsToggleAll:function formatColumnsToggleAll(){return"切换所有"},formatFullscreen:function formatFullscreen(){return"全屏"},formatAllRows:function formatAllRows(){return"所有"},formatAutoRefresh:function formatAutoRefresh(){return"自动刷新"},formatExport:function formatExport(){return"导出数据"},formatJumpTo:function formatJumpTo(){return"跳转"},formatAdvancedSearch:function formatAdvancedSearch(){return"高级搜索"},formatAdvancedCloseButton:function formatAdvancedCloseButton(){return"关闭"},formatFilterControlSwitch:function formatFilterControlSwitch(){return"隐藏/显示过滤控制"},formatFilterControlSwitchHide:function formatFilterControlSwitchHide(){return"隐藏过滤控制"},formatFilterControlSwitchShow:function formatFilterControlSwitchShow(){return"显示过滤控制"}};$.extend($.fn.bootstrapTable.defaults,$.fn.bootstrapTable.locales["zh-CN"]);
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
.bootstrap-tree-table .treetable-indent {width:16px; height: 16px; display: inline-block; position: relative;}
|
|
||||||
.bootstrap-tree-table .treetable-expander {width:16px; height: 16px; display: inline-block; position: relative; cursor: pointer;}
|
|
||||||
.bootstrap-tree-table .treetable-selected{background: #f5f5f5 !important;}
|
|
||||||
.bootstrap-tree-table .treetable-table{border:0 !important;margin-bottom:0}
|
|
||||||
.bootstrap-tree-table .treetable-table tbody {display:block;height:auto;}
|
|
||||||
.bootstrap-tree-table .treetable-table thead, .treetable-table tbody tr {display:table;width:100%;table-layout:fixed;}
|
|
||||||
.bootstrap-tree-table .treetable-thead th{line-height:24px;border: 0 !important;border-radius: 4px;border-left:0px solid #e7eaec !important;border-bottom:1px solid #ccc!important;text-align: left;}
|
|
||||||
.bootstrap-tree-table .treetable-thead tr :first-child{border-left:0 !important}
|
|
||||||
.bootstrap-tree-table .treetable-tbody td{border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
|
|
||||||
.bootstrap-tree-table .treetable-tbody tr :first-child{border-left:0 !important}
|
|
||||||
.bootstrap-tree-table .treetable-bars .tool-left, .bootstrap-tree-table .treetable-bars .tool-right{margin-top: 10px; margin-bottom: 10px;}
|
|
||||||
.bootstrap-tree-table .treetable-bars .tool-left{float: left;}
|
|
||||||
.bootstrap-tree-table .treetable-bars .tool-right{float: right;}
|
|
||||||
.bootstrap-tree-table .treetable-bars .columns li label{display: block;padding: 3px 20px;clear: both;font-weight: 400;line-height: 1.428571429;max-width: 100%;margin-bottom: 5px;cursor:pointer;}
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
@charset "utf-8";
|
|
||||||
.container {
|
|
||||||
margin: 10px auto 0 auto;
|
|
||||||
position: relative;
|
|
||||||
font-family: 微软雅黑;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.container p {
|
|
||||||
line-height: 12px;
|
|
||||||
line-height: 0px;
|
|
||||||
height: 0px;
|
|
||||||
margin: 10px;
|
|
||||||
color: #bbb
|
|
||||||
}
|
|
||||||
.action {
|
|
||||||
width: 400px;
|
|
||||||
height: 30px;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
.cropped {
|
|
||||||
position: absolute;
|
|
||||||
left: 500px;
|
|
||||||
top: 0;
|
|
||||||
width: 200px;
|
|
||||||
border: 1px #ddd solid;
|
|
||||||
height: 440px;
|
|
||||||
padding: 4px;
|
|
||||||
box-shadow: 0px 0px 12px #ddd;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.imageBox {
|
|
||||||
position: relative;
|
|
||||||
height: 400px;
|
|
||||||
width: 400px;
|
|
||||||
border: 1px solid #aaa;
|
|
||||||
background: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
cursor: move;
|
|
||||||
box-shadow: 4px 4px 12px #B0B0B0;
|
|
||||||
}
|
|
||||||
.imageBox .thumbBox {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
margin-top: -100px;
|
|
||||||
margin-left: -100px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid rgb(102, 102, 102);
|
|
||||||
box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5);
|
|
||||||
background: none repeat scroll 0% 0% transparent;
|
|
||||||
}
|
|
||||||
.imageBox .spinner {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 400px;
|
|
||||||
background: rgba(0,0,0,0.7);
|
|
||||||
}
|
|
||||||
.Btnsty_peyton{ float: right;
|
|
||||||
width: 46px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
height: 37px;
|
|
||||||
line-height: 37px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
margin:0px 2px;
|
|
||||||
background-color: #f38e81;
|
|
||||||
border-radius: 3px;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 0px 0px 5px #B0B0B0;
|
|
||||||
border: 0px #fff solid;}
|
|
||||||
/*选择文件上传*/
|
|
||||||
.new-contentarea {
|
|
||||||
width: 165px;
|
|
||||||
overflow:hidden;
|
|
||||||
margin: 0 auto;
|
|
||||||
position:relative;float:left;
|
|
||||||
}
|
|
||||||
.new-contentarea label {
|
|
||||||
width:100%;
|
|
||||||
height:100%;
|
|
||||||
display:block;
|
|
||||||
}
|
|
||||||
.new-contentarea input[type=file] {
|
|
||||||
width:188px;
|
|
||||||
height:60px;
|
|
||||||
background:#333;
|
|
||||||
margin: 0 auto;
|
|
||||||
position:absolute;
|
|
||||||
right:50%;
|
|
||||||
margin-right:-94px;
|
|
||||||
top:0;
|
|
||||||
right/*\**/:0px\9;
|
|
||||||
margin-right/*\**/:0px\9;
|
|
||||||
width/*\**/:10px\9;
|
|
||||||
opacity:0;
|
|
||||||
filter:alpha(opacity=0);
|
|
||||||
z-index:2;
|
|
||||||
}
|
|
||||||
a.upload-img{
|
|
||||||
width:165px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
height:37px;
|
|
||||||
line-height: 37px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
background-color: #f38e81;
|
|
||||||
border-radius: 3px;
|
|
||||||
text-decoration:none;
|
|
||||||
cursor:pointer;
|
|
||||||
border: 0px #fff solid;
|
|
||||||
box-shadow: 0px 0px 5px #B0B0B0;
|
|
||||||
}
|
|
||||||
a.upload-img:hover{
|
|
||||||
background-color: #ec7e70;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tc{text-align:center;}
|
|
||||||
|
|
@ -1,136 +0,0 @@
|
||||||
"use strict";
|
|
||||||
(function (factory) {
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
define(['jquery'], factory);
|
|
||||||
} else {
|
|
||||||
factory(jQuery);
|
|
||||||
}
|
|
||||||
}(function ($) {
|
|
||||||
var cropbox = function(options, el){
|
|
||||||
var el = el || $(options.imageBox),
|
|
||||||
obj =
|
|
||||||
{
|
|
||||||
state : {},
|
|
||||||
ratio : 1,
|
|
||||||
options : options,
|
|
||||||
imageBox : el,
|
|
||||||
thumbBox : el.find(options.thumbBox),
|
|
||||||
spinner : el.find(options.spinner),
|
|
||||||
image : new Image(),
|
|
||||||
getDataURL: function ()
|
|
||||||
{
|
|
||||||
var width = this.thumbBox.width(),
|
|
||||||
height = this.thumbBox.height(),
|
|
||||||
canvas = document.createElement("canvas"),
|
|
||||||
dim = el.css('background-position').split(' '),
|
|
||||||
size = el.css('background-size').split(' '),
|
|
||||||
dx = parseInt(dim[0]) - el.width()/2 + width/2,
|
|
||||||
dy = parseInt(dim[1]) - el.height()/2 + height/2,
|
|
||||||
dw = parseInt(size[0]),
|
|
||||||
dh = parseInt(size[1]),
|
|
||||||
sh = parseInt(this.image.height),
|
|
||||||
sw = parseInt(this.image.width);
|
|
||||||
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
var context = canvas.getContext("2d");
|
|
||||||
context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
|
|
||||||
var imageData = canvas.toDataURL('image/png');
|
|
||||||
return imageData;
|
|
||||||
},
|
|
||||||
getBlob: function()
|
|
||||||
{
|
|
||||||
var imageData = this.getDataURL();
|
|
||||||
var b64 = imageData.replace('data:image/png;base64,','');
|
|
||||||
var binary = atob(b64);
|
|
||||||
var array = [];
|
|
||||||
for (var i = 0; i < binary.length; i++) {
|
|
||||||
array.push(binary.charCodeAt(i));
|
|
||||||
}
|
|
||||||
return new Blob([new Uint8Array(array)], {type: 'image/png'});
|
|
||||||
},
|
|
||||||
zoomIn: function ()
|
|
||||||
{
|
|
||||||
this.ratio*=1.1;
|
|
||||||
setBackground();
|
|
||||||
},
|
|
||||||
zoomOut: function ()
|
|
||||||
{
|
|
||||||
this.ratio*=0.9;
|
|
||||||
setBackground();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setBackground = function()
|
|
||||||
{
|
|
||||||
var w = parseInt(obj.image.width)*obj.ratio;
|
|
||||||
var h = parseInt(obj.image.height)*obj.ratio;
|
|
||||||
|
|
||||||
var pw = (el.width() - w) / 2;
|
|
||||||
var ph = (el.height() - h) / 2;
|
|
||||||
|
|
||||||
el.css({
|
|
||||||
'background-image': 'url(' + obj.image.src + ')',
|
|
||||||
'background-size': w +'px ' + h + 'px',
|
|
||||||
'background-position': pw + 'px ' + ph + 'px',
|
|
||||||
'background-repeat': 'no-repeat'});
|
|
||||||
},
|
|
||||||
imgMouseDown = function(e)
|
|
||||||
{
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
|
|
||||||
obj.state.dragable = true;
|
|
||||||
obj.state.mouseX = e.clientX;
|
|
||||||
obj.state.mouseY = e.clientY;
|
|
||||||
},
|
|
||||||
imgMouseMove = function(e)
|
|
||||||
{
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
|
|
||||||
if (obj.state.dragable)
|
|
||||||
{
|
|
||||||
var x = e.clientX - obj.state.mouseX;
|
|
||||||
var y = e.clientY - obj.state.mouseY;
|
|
||||||
|
|
||||||
var bg = el.css('background-position').split(' ');
|
|
||||||
|
|
||||||
var bgX = x + parseInt(bg[0]);
|
|
||||||
var bgY = y + parseInt(bg[1]);
|
|
||||||
|
|
||||||
el.css('background-position', bgX +'px ' + bgY + 'px');
|
|
||||||
|
|
||||||
obj.state.mouseX = e.clientX;
|
|
||||||
obj.state.mouseY = e.clientY;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
imgMouseUp = function(e)
|
|
||||||
{
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
obj.state.dragable = false;
|
|
||||||
},
|
|
||||||
zoomImage = function(e)
|
|
||||||
{
|
|
||||||
e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0 ? obj.ratio*=1.1 : obj.ratio*=0.9;
|
|
||||||
setBackground();
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.spinner.show();
|
|
||||||
obj.image.onload = function() {
|
|
||||||
obj.spinner.hide();
|
|
||||||
setBackground();
|
|
||||||
|
|
||||||
el.bind('mousedown', imgMouseDown);
|
|
||||||
el.bind('mousemove', imgMouseMove);
|
|
||||||
$(window).bind('mouseup', imgMouseUp);
|
|
||||||
el.bind('mousewheel DOMMouseScroll', zoomImage);
|
|
||||||
};
|
|
||||||
obj.image.crossOrigin = 'Anonymous';
|
|
||||||
obj.image.src = options.imgSrc;
|
|
||||||
el.on('remove', function(){$(window).unbind('mouseup', imgMouseUp)});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
jQuery.fn.cropbox = function(options){
|
|
||||||
return new cropbox(options, this);
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
@ -0,0 +1,304 @@
|
||||||
|
/*!
|
||||||
|
* Cropper.js v1.5.12
|
||||||
|
* https://fengyuanchen.github.io/cropperjs
|
||||||
|
*
|
||||||
|
* Copyright 2015-present Chen Fengyuan
|
||||||
|
* Released under the MIT license
|
||||||
|
*
|
||||||
|
* Date: 2021-06-12T08:00:11.623Z
|
||||||
|
*/
|
||||||
|
|
||||||
|
.cropper-container {
|
||||||
|
direction: ltr;
|
||||||
|
font-size: 0;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-container img {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
image-orientation: 0deg;
|
||||||
|
max-height: none !important;
|
||||||
|
max-width: none !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
min-width: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-wrap-box,
|
||||||
|
.cropper-canvas,
|
||||||
|
.cropper-drag-box,
|
||||||
|
.cropper-crop-box,
|
||||||
|
.cropper-modal {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-wrap-box,
|
||||||
|
.cropper-canvas {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-drag-box {
|
||||||
|
background-color: #fff;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-modal {
|
||||||
|
background-color: #000;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-view-box {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
outline: 1px solid #39f;
|
||||||
|
outline-color: rgba(51, 153, 255, 0.75);
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-dashed {
|
||||||
|
border: 0 dashed #eee;
|
||||||
|
display: block;
|
||||||
|
opacity: 0.5;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-dashed.dashed-h {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-top-width: 1px;
|
||||||
|
height: calc(100% / 3);
|
||||||
|
left: 0;
|
||||||
|
top: calc(100% / 3);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-dashed.dashed-v {
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
height: 100%;
|
||||||
|
left: calc(100% / 3);
|
||||||
|
top: 0;
|
||||||
|
width: calc(100% / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-center {
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
left: 50%;
|
||||||
|
opacity: 0.75;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-center::before,
|
||||||
|
.cropper-center::after {
|
||||||
|
background-color: #eee;
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-center::before {
|
||||||
|
height: 1px;
|
||||||
|
left: -3px;
|
||||||
|
top: 0;
|
||||||
|
width: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-center::after {
|
||||||
|
height: 7px;
|
||||||
|
left: 0;
|
||||||
|
top: -3px;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-face,
|
||||||
|
.cropper-line,
|
||||||
|
.cropper-point {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.1;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-face {
|
||||||
|
background-color: #fff;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line {
|
||||||
|
background-color: #39f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line.line-e {
|
||||||
|
cursor: ew-resize;
|
||||||
|
right: -3px;
|
||||||
|
top: 0;
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line.line-n {
|
||||||
|
cursor: ns-resize;
|
||||||
|
height: 5px;
|
||||||
|
left: 0;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line.line-w {
|
||||||
|
cursor: ew-resize;
|
||||||
|
left: -3px;
|
||||||
|
top: 0;
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-line.line-s {
|
||||||
|
bottom: -3px;
|
||||||
|
cursor: ns-resize;
|
||||||
|
height: 5px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point {
|
||||||
|
background-color: #39f;
|
||||||
|
height: 5px;
|
||||||
|
opacity: 0.75;
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-e {
|
||||||
|
cursor: ew-resize;
|
||||||
|
margin-top: -3px;
|
||||||
|
right: -3px;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-n {
|
||||||
|
cursor: ns-resize;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -3px;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-w {
|
||||||
|
cursor: ew-resize;
|
||||||
|
left: -3px;
|
||||||
|
margin-top: -3px;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-s {
|
||||||
|
bottom: -3px;
|
||||||
|
cursor: s-resize;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-ne {
|
||||||
|
cursor: nesw-resize;
|
||||||
|
right: -3px;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-nw {
|
||||||
|
cursor: nwse-resize;
|
||||||
|
left: -3px;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-sw {
|
||||||
|
bottom: -3px;
|
||||||
|
cursor: nesw-resize;
|
||||||
|
left: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-se {
|
||||||
|
bottom: -3px;
|
||||||
|
cursor: nwse-resize;
|
||||||
|
height: 20px;
|
||||||
|
opacity: 1;
|
||||||
|
right: -3px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.cropper-point.point-se {
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.cropper-point.point-se {
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.cropper-point.point-se {
|
||||||
|
height: 5px;
|
||||||
|
opacity: 0.75;
|
||||||
|
width: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-point.point-se::before {
|
||||||
|
background-color: #39f;
|
||||||
|
bottom: -50%;
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
height: 200%;
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: -50%;
|
||||||
|
width: 200%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-invisible {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-bg {
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-hide {
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-move {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-crop {
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cropper-disabled .cropper-drag-box,
|
||||||
|
.cropper-disabled .cropper-face,
|
||||||
|
.cropper-disabled .cropper-line,
|
||||||
|
.cropper-disabled .cropper-point {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*!
|
||||||
|
* Cropper.js v1.5.12
|
||||||
|
* https://fengyuanchen.github.io/cropperjs
|
||||||
|
*
|
||||||
|
* Copyright 2015-present Chen Fengyuan
|
||||||
|
* Released under the MIT license
|
||||||
|
*
|
||||||
|
* Date: 2021-06-12T08:00:11.623Z
|
||||||
|
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{image-orientation:0deg;display:block;height:100%;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,406 @@
|
||||||
|
/*!
|
||||||
|
* jQuery cxSelect
|
||||||
|
* @name jquery.cxselect.js
|
||||||
|
* @version 1.4.2
|
||||||
|
* @date 2017-09-26
|
||||||
|
* @author ciaoca
|
||||||
|
* @email ciaoca@gmail.com
|
||||||
|
* @site https://github.com/ciaoca/cxSelect
|
||||||
|
* @license Released under the MIT license
|
||||||
|
*/
|
||||||
|
(function(factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['jquery'], factory);
|
||||||
|
} else {
|
||||||
|
factory(window.jQuery || window.Zepto || window.$);
|
||||||
|
};
|
||||||
|
}(function($) {
|
||||||
|
var cxSelect = function() {
|
||||||
|
var self = this;
|
||||||
|
var dom, settings, callback;
|
||||||
|
|
||||||
|
// 分配参数
|
||||||
|
for (var i = 0, l = arguments.length; i < l; i++) {
|
||||||
|
if (cxSelect.isJquery(arguments[i]) || cxSelect.isZepto(arguments[i])) {
|
||||||
|
dom = arguments[i];
|
||||||
|
} else if (cxSelect.isElement(arguments[i])) {
|
||||||
|
dom = $(arguments[i]);
|
||||||
|
} else if (typeof arguments[i] === 'function') {
|
||||||
|
callback = arguments[i];
|
||||||
|
} else if (typeof arguments[i] === 'object') {
|
||||||
|
settings = arguments[i];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var api = new cxSelect.init(dom, settings);
|
||||||
|
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback(api);
|
||||||
|
};
|
||||||
|
|
||||||
|
return api;
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.isElement = function(o){
|
||||||
|
if (o && (typeof HTMLElement === 'function' || typeof HTMLElement === 'object') && o instanceof HTMLElement) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return (o && o.nodeType && o.nodeType === 1) ? true : false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.isJquery = function(o){
|
||||||
|
return (o && o.length && (typeof jQuery === 'function' || typeof jQuery === 'object') && o instanceof jQuery) ? true : false;
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.isZepto = function(o){
|
||||||
|
return (o && o.length && (typeof Zepto === 'function' || typeof Zepto === 'object') && Zepto.zepto.isZ(o)) ? true : false;
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.getIndex = function(n, required) {
|
||||||
|
return required ? n : n - 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.getData = function(data, space) {
|
||||||
|
if (typeof space === 'string' && space.length) {
|
||||||
|
space = space.split('.');
|
||||||
|
for (var i = 0, l = space.length; i < l; i++) {
|
||||||
|
data = data[space[i]];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.init = function(dom, settings) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!cxSelect.isJquery(dom) && !cxSelect.isZepto(dom)) {return};
|
||||||
|
|
||||||
|
var theSelect = {
|
||||||
|
dom: {
|
||||||
|
box: dom
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.attach = cxSelect.attach.bind(theSelect);
|
||||||
|
self.detach = cxSelect.detach.bind(theSelect);
|
||||||
|
self.setOptions = cxSelect.setOptions.bind(theSelect);
|
||||||
|
self.clear = cxSelect.clear.bind(theSelect);
|
||||||
|
|
||||||
|
theSelect.changeEvent = function() {
|
||||||
|
cxSelect.selectChange.call(theSelect, this.className);
|
||||||
|
};
|
||||||
|
|
||||||
|
theSelect.settings = $.extend({}, $.cxSelect.defaults, settings, {
|
||||||
|
url: theSelect.dom.box.data('url'),
|
||||||
|
emptyStyle: theSelect.dom.box.data('emptyStyle'),
|
||||||
|
required: theSelect.dom.box.data('required'),
|
||||||
|
firstTitle: theSelect.dom.box.data('firstTitle'),
|
||||||
|
firstValue: theSelect.dom.box.data('firstValue'),
|
||||||
|
jsonSpace: theSelect.dom.box.data('jsonSpace'),
|
||||||
|
jsonName: theSelect.dom.box.data('jsonName'),
|
||||||
|
jsonValue: theSelect.dom.box.data('jsonValue'),
|
||||||
|
jsonSub: theSelect.dom.box.data('jsonSub')
|
||||||
|
});
|
||||||
|
|
||||||
|
var _dataSelects = theSelect.dom.box.data('selects');
|
||||||
|
|
||||||
|
if (typeof _dataSelects === 'string' && _dataSelects.length) {
|
||||||
|
theSelect.settings.selects = _dataSelects.split(',');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setOptions();
|
||||||
|
self.attach();
|
||||||
|
|
||||||
|
// 使用独立接口获取数据
|
||||||
|
if (!theSelect.settings.url && !theSelect.settings.data) {
|
||||||
|
cxSelect.start.apply(theSelect);
|
||||||
|
|
||||||
|
// 设置自定义数据
|
||||||
|
} else if ($.isArray(theSelect.settings.data)) {
|
||||||
|
cxSelect.start.call(theSelect, theSelect.settings.data);
|
||||||
|
|
||||||
|
// 设置 URL,通过 Ajax 获取数据
|
||||||
|
} else if (typeof theSelect.settings.url === 'string' && theSelect.settings.url.length) {
|
||||||
|
$.getJSON(theSelect.settings.url, function(json) {
|
||||||
|
cxSelect.start.call(theSelect, json);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置参数
|
||||||
|
cxSelect.setOptions = function(opts) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (opts) {
|
||||||
|
$.extend(self.settings, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初次或重设选择器组
|
||||||
|
if (!$.isArray(self.selectArray) || !self.selectArray.length || (opts && opts.selects)) {
|
||||||
|
self.selectArray = [];
|
||||||
|
|
||||||
|
if ($.isArray(self.settings.selects) && self.settings.selects.length) {
|
||||||
|
var _tempSelect;
|
||||||
|
|
||||||
|
for (var i = 0, l = self.settings.selects.length; i < l; i++) {
|
||||||
|
_tempSelect = self.dom.box.find('select.' + self.settings.selects[i]);
|
||||||
|
|
||||||
|
if (!_tempSelect || !_tempSelect.length) {break};
|
||||||
|
|
||||||
|
self.selectArray.push(_tempSelect);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts) {
|
||||||
|
if (!$.isArray(opts.data) && typeof opts.url === 'string' && opts.url.length) {
|
||||||
|
$.getJSON(self.settings.url, function(json) {
|
||||||
|
cxSelect.start.call(self, json);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cxSelect.start.call(self, opts.data);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 绑定
|
||||||
|
cxSelect.attach = function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!self.attachStatus) {
|
||||||
|
self.dom.box.on('change', 'select', self.changeEvent);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof self.attachStatus === 'boolean') {
|
||||||
|
cxSelect.start.call(self);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.attachStatus = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除绑定
|
||||||
|
cxSelect.detach = function() {
|
||||||
|
var self = this;
|
||||||
|
self.dom.box.off('change', 'select', self.changeEvent);
|
||||||
|
self.attachStatus = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空选项
|
||||||
|
cxSelect.clear = function(index) {
|
||||||
|
var self = this;
|
||||||
|
var _style = {
|
||||||
|
display: '',
|
||||||
|
visibility: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
index = isNaN(index) ? 0 : index;
|
||||||
|
|
||||||
|
// 清空后面的 select
|
||||||
|
for (var i = index, l = self.selectArray.length; i < l; i++) {
|
||||||
|
self.selectArray[i].empty().prop('disabled', true);
|
||||||
|
|
||||||
|
if (self.settings.emptyStyle === 'none') {
|
||||||
|
_style.display = 'none';
|
||||||
|
} else if (self.settings.emptyStyle === 'hidden') {
|
||||||
|
_style.visibility = 'hidden';
|
||||||
|
};
|
||||||
|
|
||||||
|
self.selectArray[i].css(_style);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.start = function(data) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if ($.isArray(data)) {
|
||||||
|
self.settings.data = cxSelect.getData(data, self.settings.jsonSpace);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!self.selectArray.length) {return};
|
||||||
|
|
||||||
|
// 保存默认值
|
||||||
|
for (var i = 0, l = self.selectArray.length; i < l; i++) {
|
||||||
|
if (typeof self.selectArray[i].attr('data-value') !== 'string' && self.selectArray[i][0].options.length) {
|
||||||
|
self.selectArray[i].attr('data-value', self.selectArray[i].val());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (self.settings.data || (typeof self.selectArray[0].data('url') === 'string' && self.selectArray[0].data('url').length)) {
|
||||||
|
cxSelect.getOptionData.call(self, 0);
|
||||||
|
} else if (self.selectArray[0][0].options.length && typeof self.selectArray[0].attr('data-value') === 'string' && self.selectArray[0].attr('data-value').length) {
|
||||||
|
self.selectArray[0].val(self.selectArray[0].attr('data-value'));
|
||||||
|
cxSelect.getOptionData.call(self, 1);
|
||||||
|
} else {
|
||||||
|
self.selectArray[0].prop('disabled', false).css({
|
||||||
|
'display': '',
|
||||||
|
'visibility': ''
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取选项数据
|
||||||
|
cxSelect.getOptionData = function(index) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (typeof index !== 'number' || isNaN(index) || index < 0 || index >= self.selectArray.length) {return};
|
||||||
|
|
||||||
|
var _indexPrev = index - 1;
|
||||||
|
var _select = self.selectArray[index];
|
||||||
|
var _selectData;
|
||||||
|
var _valueIndex;
|
||||||
|
var _dataUrl = _select.data('url');
|
||||||
|
var _jsonSpace = typeof _select.data('jsonSpace') === 'undefined' ? self.settings.jsonSpace : _select.data('jsonSpace');
|
||||||
|
var _query = {};
|
||||||
|
var _queryName;
|
||||||
|
var _selectName;
|
||||||
|
var _selectValue;
|
||||||
|
|
||||||
|
cxSelect.clear.call(self, index);
|
||||||
|
|
||||||
|
// 使用独立接口
|
||||||
|
if (typeof _dataUrl === 'string' && _dataUrl.length) {
|
||||||
|
if (index > 0) {
|
||||||
|
for (var i = 0, j = 1; i < index; i++, j++) {
|
||||||
|
_queryName = self.selectArray[j].data('queryName');
|
||||||
|
_selectName = self.selectArray[i].attr('name');
|
||||||
|
_selectValue = self.selectArray[i].val();
|
||||||
|
|
||||||
|
if (typeof _queryName === 'string' && _queryName.length) {
|
||||||
|
_query[_queryName] = _selectValue;
|
||||||
|
} else if (typeof _selectName === 'string' && _selectName.length) {
|
||||||
|
_query[_selectName] = _selectValue;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$.getJSON(_dataUrl, _query, function(json) {
|
||||||
|
_selectData = cxSelect.getData(json, _jsonSpace);
|
||||||
|
|
||||||
|
cxSelect.buildOption.call(self, index, _selectData);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用整合数据
|
||||||
|
} else if (self.settings.data && typeof self.settings.data === 'object') {
|
||||||
|
_selectData = self.settings.data;
|
||||||
|
|
||||||
|
for (var i = 0; i < index; i++) {
|
||||||
|
_valueIndex = cxSelect.getIndex(self.selectArray[i][0].selectedIndex, typeof self.selectArray[i].data('required') === 'boolean' ? self.selectArray[i].data('required') : self.settings.required);
|
||||||
|
|
||||||
|
if (typeof _selectData[_valueIndex] === 'object' && $.isArray(_selectData[_valueIndex][self.settings.jsonSub]) && _selectData[_valueIndex][self.settings.jsonSub].length) {
|
||||||
|
_selectData = _selectData[_valueIndex][self.settings.jsonSub];
|
||||||
|
} else {
|
||||||
|
_selectData = null;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cxSelect.buildOption.call(self, index, _selectData);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建选项列表
|
||||||
|
cxSelect.buildOption = function(index, data) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var _select = self.selectArray[index];
|
||||||
|
var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required;
|
||||||
|
var _firstTitle = typeof _select.data('firstTitle') === 'undefined' ? self.settings.firstTitle : _select.data('firstTitle');
|
||||||
|
var _firstValue = typeof _select.data('firstValue') === 'undefined' ? self.settings.firstValue : _select.data('firstValue');
|
||||||
|
var _jsonName = typeof _select.data('jsonName') === 'undefined' ? self.settings.jsonName : _select.data('jsonName');
|
||||||
|
var _jsonValue = typeof _select.data('jsonValue') === 'undefined' ? self.settings.jsonValue : _select.data('jsonValue');
|
||||||
|
|
||||||
|
if (!$.isArray(data)) {return};
|
||||||
|
|
||||||
|
var _html = !_required ? '<option value="' + String(_firstValue) + '">' + String(_firstTitle) + '</option>' : '';
|
||||||
|
|
||||||
|
// 区分标题、值的数据
|
||||||
|
if (typeof _jsonName === 'string' && _jsonName.length) {
|
||||||
|
// 无值字段时使用标题作为值
|
||||||
|
if (typeof _jsonValue !== 'string' || !_jsonValue.length) {
|
||||||
|
_jsonValue = _jsonName;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0, l = data.length; i < l; i++) {
|
||||||
|
_html += '<option value="' + String(data[i][_jsonValue]) + '">' + String(data[i][_jsonName]) + '</option>';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 数组即为值的数据
|
||||||
|
} else {
|
||||||
|
for (var i = 0, l = data.length; i < l; i++) {
|
||||||
|
_html += '<option value="' + String(data[i]) + '">' + String(data[i]) + '</option>';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
_select.html(_html).prop('disabled', false).css({
|
||||||
|
'display': '',
|
||||||
|
'visibility': ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初次加载设置默认值
|
||||||
|
if (typeof _select.attr('data-value') === 'string') {
|
||||||
|
_select.val(String(_select.attr('data-value'))).removeAttr('data-value');
|
||||||
|
|
||||||
|
if (_select[0].selectedIndex < 0) {
|
||||||
|
_select[0].options[0].selected = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_required || _select[0].selectedIndex > 0) {
|
||||||
|
_select.trigger('change');
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 改变选择时的处理
|
||||||
|
cxSelect.selectChange = function(name) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (typeof name !== 'string' || !name.length) {return};
|
||||||
|
|
||||||
|
var index;
|
||||||
|
|
||||||
|
name = name.replace(/\s+/g, ',');
|
||||||
|
name = ',' + name + ',';
|
||||||
|
|
||||||
|
// 获取当前 select 位置
|
||||||
|
for (var i = 0, l = self.selectArray.length; i < l; i++) {
|
||||||
|
if (name.indexOf(',' + self.settings.selects[i] + ',') > -1) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof index === 'number' && index > -1) {
|
||||||
|
index += 1;
|
||||||
|
cxSelect.getOptionData.call(self, index);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
$.cxSelect = function() {
|
||||||
|
return cxSelect.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 默认值
|
||||||
|
$.cxSelect.defaults = {
|
||||||
|
selects: [], // 下拉选框组
|
||||||
|
url: null, // 列表数据文件路径(URL)或数组数据
|
||||||
|
data: null, // 自定义数据
|
||||||
|
emptyStyle: null, // 无数据状态显示方式
|
||||||
|
required: false, // 是否为必选
|
||||||
|
firstTitle: '请选择', // 第一个选项的标题
|
||||||
|
firstValue: '', // 第一个选项的值
|
||||||
|
jsonSpace: '', // 数据命名空间
|
||||||
|
jsonName: 'n', // 数据标题字段名称
|
||||||
|
jsonValue: '', // 数据值字段名称
|
||||||
|
jsonSub: 's' // 子集数据字段名称
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.cxSelect = function(settings, callback) {
|
||||||
|
this.each(function(i) {
|
||||||
|
$.cxSelect(this, settings, callback);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
}));
|
||||||
11
ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js
vendored
Normal file
11
ruoyi-admin/src/main/resources/static/ajax/libs/cxselect/jquery.cxselect.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
86
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css
vendored
Normal file
86
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.css
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Bootstrap Duallistbox - v3.0.9
|
||||||
|
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
|
||||||
|
* https://www.virtuosoft.eu/code/bootstrap-duallistbox/
|
||||||
|
*
|
||||||
|
* Made by István Ujj-Mészáros
|
||||||
|
* Under Apache License v2.0 License
|
||||||
|
*/
|
||||||
|
.bootstrap-duallistbox-container .buttons {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .info {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .clear1,
|
||||||
|
.bootstrap-duallistbox-container .clear2 {
|
||||||
|
display: none;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .box1.filtered .clear1,
|
||||||
|
.bootstrap-duallistbox-container .box2.filtered .clear2 {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .move,
|
||||||
|
.bootstrap-duallistbox-container .remove {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .btn-group .btn {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-duallistbox-container select {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .moveall,
|
||||||
|
.bootstrap-duallistbox-container .removeall {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container select {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .filter {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 31px;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container .filter.placeholder {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container.moveonselect .move,
|
||||||
|
.bootstrap-duallistbox-container.moveonselect .remove {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-duallistbox-container.moveonselect .moveall,
|
||||||
|
.bootstrap-duallistbox-container.moveonselect .removeall {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
844
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js
vendored
Normal file
844
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.js
vendored
Normal file
|
|
@ -0,0 +1,844 @@
|
||||||
|
/*
|
||||||
|
* Bootstrap Duallistbox - v3.0.9
|
||||||
|
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
|
||||||
|
* https://www.virtuosoft.eu/code/bootstrap-duallistbox/
|
||||||
|
*
|
||||||
|
* Made by István Ujj-Mészáros
|
||||||
|
* Under Apache License v2.0 License
|
||||||
|
*/
|
||||||
|
;(function ($, window, document, undefined) {
|
||||||
|
// Create the defaults once
|
||||||
|
var pluginName = 'bootstrapDualListbox',
|
||||||
|
defaults = {
|
||||||
|
bootstrap2Compatible: false,
|
||||||
|
filterTextClear: 'show all',
|
||||||
|
filterPlaceHolder: 'Filter',
|
||||||
|
moveSelectedLabel: 'Move selected',
|
||||||
|
moveAllLabel: 'Move all',
|
||||||
|
removeSelectedLabel: 'Remove selected',
|
||||||
|
removeAllLabel: 'Remove all',
|
||||||
|
moveOnSelect: true, // true/false (forced true on androids, see the comment later)
|
||||||
|
moveOnDoubleClick: true, // true/false (forced false on androids, cause moveOnSelect is forced to true)
|
||||||
|
preserveSelectionOnMove: false, // 'all' / 'moved' / false
|
||||||
|
selectedListLabel: false, // 'string', false
|
||||||
|
nonSelectedListLabel: false, // 'string', false
|
||||||
|
helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false
|
||||||
|
selectorMinimalHeight: 100,
|
||||||
|
showFilterInputs: true, // whether to show filter inputs
|
||||||
|
nonSelectedFilter: '', // string, filter the non selected options
|
||||||
|
selectedFilter: '', // string, filter the selected options
|
||||||
|
infoText: 'Showing all {0}', // text when all options are visible / false for no info text
|
||||||
|
infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
|
||||||
|
infoTextEmpty: 'Empty list', // when there are no options present in the list
|
||||||
|
filterOnValues: false, // filter by selector's values, boolean
|
||||||
|
sortByInputOrder: false,
|
||||||
|
eventMoveOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||||
|
eventMoveAllOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||||
|
eventRemoveOverride: false, // boolean, allows user to unbind default event behaviour and run their own instead
|
||||||
|
eventRemoveAllOverride: false // boolean, allows user to unbind default event behaviour and run their own instead
|
||||||
|
},
|
||||||
|
// Selections are invisible on android if the containing select is styled with CSS
|
||||||
|
// http://code.google.com/p/android/issues/detail?id=16922
|
||||||
|
isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
|
||||||
|
|
||||||
|
// The actual plugin constructor
|
||||||
|
function BootstrapDualListbox(element, options) {
|
||||||
|
this.element = $(element);
|
||||||
|
// jQuery has an extend method which merges the contents of two or
|
||||||
|
// more objects, storing the result in the first object. The first object
|
||||||
|
// is generally empty as we don't want to alter the default options for
|
||||||
|
// future instances of the plugin
|
||||||
|
this.settings = $.extend({}, defaults, options);
|
||||||
|
this._defaults = defaults;
|
||||||
|
this._name = pluginName;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerChangeEvent(dualListbox) {
|
||||||
|
dualListbox.element.trigger('change');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelectionStates(dualListbox) {
|
||||||
|
dualListbox.element.find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if (typeof($item.data('original-index')) === 'undefined') {
|
||||||
|
$item.data('original-index', dualListbox.elementCount++);
|
||||||
|
}
|
||||||
|
if (typeof($item.data('_selected')) === 'undefined') {
|
||||||
|
$item.data('_selected', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeSelectionState(dualListbox, original_index, selected) {
|
||||||
|
dualListbox.element.find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if ($item.data('original-index') === original_index) {
|
||||||
|
$item.prop('selected', selected);
|
||||||
|
if(selected){
|
||||||
|
$item.attr('data-sortindex', dualListbox.sortIndex);
|
||||||
|
dualListbox.sortIndex++;
|
||||||
|
} else {
|
||||||
|
$item.removeAttr('data-sortindex');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatString(s, args) {
|
||||||
|
return s.replace(/\{(\d+)\}/g, function(match, number) {
|
||||||
|
return typeof args[number] !== 'undefined' ? args[number] : match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshInfo(dualListbox) {
|
||||||
|
if (!dualListbox.settings.infoText) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var visible1 = dualListbox.elements.select1.find('option').length,
|
||||||
|
visible2 = dualListbox.elements.select2.find('option').length,
|
||||||
|
all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
|
||||||
|
all2 = dualListbox.selectedElements,
|
||||||
|
content = '';
|
||||||
|
|
||||||
|
if (all1 === 0) {
|
||||||
|
content = dualListbox.settings.infoTextEmpty;
|
||||||
|
} else if (visible1 === all1) {
|
||||||
|
content = formatString(dualListbox.settings.infoText, [visible1, all1]);
|
||||||
|
} else {
|
||||||
|
content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.elements.info1.html(content);
|
||||||
|
dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
|
||||||
|
|
||||||
|
if (all2 === 0) {
|
||||||
|
content = dualListbox.settings.infoTextEmpty;
|
||||||
|
} else if (visible2 === all2) {
|
||||||
|
content = formatString(dualListbox.settings.infoText, [visible2, all2]);
|
||||||
|
} else {
|
||||||
|
content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.elements.info2.html(content);
|
||||||
|
dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshSelects(dualListbox) {
|
||||||
|
dualListbox.selectedElements = 0;
|
||||||
|
|
||||||
|
dualListbox.elements.select1.empty();
|
||||||
|
dualListbox.elements.select2.empty();
|
||||||
|
|
||||||
|
dualListbox.element.find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if ($item.prop('selected')) {
|
||||||
|
dualListbox.selectedElements++;
|
||||||
|
dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||||
|
} else {
|
||||||
|
dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dualListbox.settings.showFilterInputs) {
|
||||||
|
filter(dualListbox, 1);
|
||||||
|
filter(dualListbox, 2);
|
||||||
|
}
|
||||||
|
refreshInfo(dualListbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filter(dualListbox, selectIndex) {
|
||||||
|
if (!dualListbox.settings.showFilterInputs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSelections(dualListbox, selectIndex);
|
||||||
|
|
||||||
|
dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
|
||||||
|
var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
|
||||||
|
allOptions = dualListbox.element.find('option'),
|
||||||
|
options = dualListbox.element;
|
||||||
|
|
||||||
|
if (selectIndex === 1) {
|
||||||
|
options = allOptions.not(':selected');
|
||||||
|
} else {
|
||||||
|
options = options.find('option:selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
options.each(function(index, item) {
|
||||||
|
var $item = $(item),
|
||||||
|
isFiltered = true;
|
||||||
|
if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
|
||||||
|
isFiltered = false;
|
||||||
|
dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
|
||||||
|
}
|
||||||
|
allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshInfo(dualListbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSelections(dualListbox, selectIndex) {
|
||||||
|
var options = dualListbox.element.find('option');
|
||||||
|
dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortOptionsByInputOrder(select){
|
||||||
|
var selectopt = select.children('option');
|
||||||
|
|
||||||
|
selectopt.sort(function(a,b){
|
||||||
|
var an = parseInt(a.getAttribute('data-sortindex')),
|
||||||
|
bn = parseInt(b.getAttribute('data-sortindex'));
|
||||||
|
|
||||||
|
if(an > bn) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(an < bn) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
selectopt.detach().appendTo(select);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortOptions(select, dualListbox) {
|
||||||
|
select.find('option').sort(function(a, b) {
|
||||||
|
return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
|
||||||
|
}).appendTo(select);
|
||||||
|
|
||||||
|
// workaround for chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1072475
|
||||||
|
refreshSelects(dualListbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSelections(dualListbox) {
|
||||||
|
dualListbox.elements.select1.find('option').each(function() {
|
||||||
|
dualListbox.element.find('option').data('_selected', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function move(dualListbox) {
|
||||||
|
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.elements.select1.find('option:selected').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if (!$item.data('filtered1')) {
|
||||||
|
changeSelectionState(dualListbox, $item.data('original-index'), true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshSelects(dualListbox);
|
||||||
|
triggerChangeEvent(dualListbox);
|
||||||
|
if(dualListbox.settings.sortByInputOrder){
|
||||||
|
sortOptionsByInputOrder(dualListbox.elements.select2);
|
||||||
|
} else {
|
||||||
|
sortOptions(dualListbox.elements.select2, dualListbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove(dualListbox) {
|
||||||
|
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.elements.select2.find('option:selected').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if (!$item.data('filtered2')) {
|
||||||
|
changeSelectionState(dualListbox, $item.data('original-index'), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshSelects(dualListbox);
|
||||||
|
triggerChangeEvent(dualListbox);
|
||||||
|
sortOptions(dualListbox.elements.select1, dualListbox);
|
||||||
|
if(dualListbox.settings.sortByInputOrder){
|
||||||
|
sortOptionsByInputOrder(dualListbox.elements.select2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveAll(dualListbox) {
|
||||||
|
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.element.find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if (!$item.data('filtered1')) {
|
||||||
|
$item.prop('selected', true);
|
||||||
|
$item.attr('data-sortindex', dualListbox.sortIndex);
|
||||||
|
dualListbox.sortIndex++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshSelects(dualListbox);
|
||||||
|
triggerChangeEvent(dualListbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAll(dualListbox) {
|
||||||
|
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 1);
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
|
||||||
|
saveSelections(dualListbox, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.element.find('option').each(function(index, item) {
|
||||||
|
var $item = $(item);
|
||||||
|
if (!$item.data('filtered2')) {
|
||||||
|
$item.prop('selected', false);
|
||||||
|
$item.removeAttr('data-sortindex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshSelects(dualListbox);
|
||||||
|
triggerChangeEvent(dualListbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindEvents(dualListbox) {
|
||||||
|
dualListbox.elements.form.submit(function(e) {
|
||||||
|
if (dualListbox.elements.filterInput1.is(':focus')) {
|
||||||
|
e.preventDefault();
|
||||||
|
dualListbox.elements.filterInput1.focusout();
|
||||||
|
} else if (dualListbox.elements.filterInput2.is(':focus')) {
|
||||||
|
e.preventDefault();
|
||||||
|
dualListbox.elements.filterInput2.focusout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
|
||||||
|
dualListbox.refresh(mustClearSelections);
|
||||||
|
});
|
||||||
|
|
||||||
|
dualListbox.elements.filterClear1.on('click', function() {
|
||||||
|
dualListbox.setNonSelectedFilter('', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
dualListbox.elements.filterClear2.on('click', function() {
|
||||||
|
dualListbox.setSelectedFilter('', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dualListbox.settings.eventMoveOverride === false) {
|
||||||
|
dualListbox.elements.moveButton.on('click', function() {
|
||||||
|
move(dualListbox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dualListbox.settings.eventMoveAllOverride === false) {
|
||||||
|
dualListbox.elements.moveAllButton.on('click', function() {
|
||||||
|
moveAll(dualListbox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dualListbox.settings.eventRemoveOverride === false) {
|
||||||
|
dualListbox.elements.removeButton.on('click', function() {
|
||||||
|
remove(dualListbox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dualListbox.settings.eventRemoveAllOverride === false) {
|
||||||
|
dualListbox.elements.removeAllButton.on('click', function() {
|
||||||
|
removeAll(dualListbox);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dualListbox.elements.filterInput1.on('change keyup', function() {
|
||||||
|
filter(dualListbox, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
dualListbox.elements.filterInput2.on('change keyup', function() {
|
||||||
|
filter(dualListbox, 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BootstrapDualListbox.prototype = {
|
||||||
|
init: function () {
|
||||||
|
// Add the custom HTML template
|
||||||
|
this.container = $('' +
|
||||||
|
'<div class="bootstrap-duallistbox-container">' +
|
||||||
|
' <div class="box1">' +
|
||||||
|
' <label></label>' +
|
||||||
|
' <span class="info-container">' +
|
||||||
|
' <span class="info"></span>' +
|
||||||
|
' <button type="button" class="btn clear1 pull-right"></button>' +
|
||||||
|
' </span>' +
|
||||||
|
' <input class="filter" type="text">' +
|
||||||
|
' <div class="btn-group buttons">' +
|
||||||
|
' <button type="button" class="btn moveall">' +
|
||||||
|
' <i></i>' +
|
||||||
|
' <i></i>' +
|
||||||
|
' </button>' +
|
||||||
|
' <button type="button" class="btn move">' +
|
||||||
|
' <i></i>' +
|
||||||
|
' </button>' +
|
||||||
|
' </div>' +
|
||||||
|
' <select multiple="multiple"></select>' +
|
||||||
|
' </div>' +
|
||||||
|
' <div class="box2">' +
|
||||||
|
' <label></label>' +
|
||||||
|
' <span class="info-container">' +
|
||||||
|
' <span class="info"></span>' +
|
||||||
|
' <button type="button" class="btn clear2 pull-right"></button>' +
|
||||||
|
' </span>' +
|
||||||
|
' <input class="filter" type="text">' +
|
||||||
|
' <div class="btn-group buttons">' +
|
||||||
|
' <button type="button" class="btn remove">' +
|
||||||
|
' <i></i>' +
|
||||||
|
' </button>' +
|
||||||
|
' <button type="button" class="btn removeall">' +
|
||||||
|
' <i></i>' +
|
||||||
|
' <i></i>' +
|
||||||
|
' </button>' +
|
||||||
|
' </div>' +
|
||||||
|
' <select multiple="multiple"></select>' +
|
||||||
|
' </div>' +
|
||||||
|
'</div>')
|
||||||
|
.insertBefore(this.element);
|
||||||
|
|
||||||
|
// Cache the inner elements
|
||||||
|
this.elements = {
|
||||||
|
originalSelect: this.element,
|
||||||
|
box1: $('.box1', this.container),
|
||||||
|
box2: $('.box2', this.container),
|
||||||
|
filterInput1: $('.box1 .filter', this.container),
|
||||||
|
filterInput2: $('.box2 .filter', this.container),
|
||||||
|
filterClear1: $('.box1 .clear1', this.container),
|
||||||
|
filterClear2: $('.box2 .clear2', this.container),
|
||||||
|
label1: $('.box1 > label', this.container),
|
||||||
|
label2: $('.box2 > label', this.container),
|
||||||
|
info1: $('.box1 .info', this.container),
|
||||||
|
info2: $('.box2 .info', this.container),
|
||||||
|
select1: $('.box1 select', this.container),
|
||||||
|
select2: $('.box2 select', this.container),
|
||||||
|
moveButton: $('.box1 .move', this.container),
|
||||||
|
removeButton: $('.box2 .remove', this.container),
|
||||||
|
moveAllButton: $('.box1 .moveall', this.container),
|
||||||
|
removeAllButton: $('.box2 .removeall', this.container),
|
||||||
|
form: $($('.box1 .filter', this.container)[0].form)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set select IDs
|
||||||
|
this.originalSelectName = this.element.attr('name') || '';
|
||||||
|
var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
|
||||||
|
select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
|
||||||
|
this.elements.select1.attr('id', select1Id);
|
||||||
|
this.elements.select2.attr('id', select2Id);
|
||||||
|
this.elements.label1.attr('for', select1Id);
|
||||||
|
this.elements.label2.attr('for', select2Id);
|
||||||
|
|
||||||
|
// Apply all settings
|
||||||
|
this.selectedElements = 0;
|
||||||
|
this.sortIndex = 0;
|
||||||
|
this.elementCount = 0;
|
||||||
|
this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
|
||||||
|
this.setFilterTextClear(this.settings.filterTextClear);
|
||||||
|
this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
|
||||||
|
this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
|
||||||
|
this.setMoveAllLabel(this.settings.moveAllLabel);
|
||||||
|
this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
|
||||||
|
this.setRemoveAllLabel(this.settings.removeAllLabel);
|
||||||
|
this.setMoveOnSelect(this.settings.moveOnSelect);
|
||||||
|
this.setMoveOnDoubleClick(this.settings.moveOnDoubleClick);
|
||||||
|
this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
|
||||||
|
this.setSelectedListLabel(this.settings.selectedListLabel);
|
||||||
|
this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
|
||||||
|
this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
|
||||||
|
this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
|
||||||
|
|
||||||
|
updateSelectionStates(this);
|
||||||
|
|
||||||
|
this.setShowFilterInputs(this.settings.showFilterInputs);
|
||||||
|
this.setNonSelectedFilter(this.settings.nonSelectedFilter);
|
||||||
|
this.setSelectedFilter(this.settings.selectedFilter);
|
||||||
|
this.setInfoText(this.settings.infoText);
|
||||||
|
this.setInfoTextFiltered(this.settings.infoTextFiltered);
|
||||||
|
this.setInfoTextEmpty(this.settings.infoTextEmpty);
|
||||||
|
this.setFilterOnValues(this.settings.filterOnValues);
|
||||||
|
this.setSortByInputOrder(this.settings.sortByInputOrder);
|
||||||
|
this.setEventMoveOverride(this.settings.eventMoveOverride);
|
||||||
|
this.setEventMoveAllOverride(this.settings.eventMoveAllOverride);
|
||||||
|
this.setEventRemoveOverride(this.settings.eventRemoveOverride);
|
||||||
|
this.setEventRemoveAllOverride(this.settings.eventRemoveAllOverride);
|
||||||
|
|
||||||
|
// Hide the original select
|
||||||
|
this.element.hide();
|
||||||
|
|
||||||
|
bindEvents(this);
|
||||||
|
refreshSelects(this);
|
||||||
|
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setBootstrap2Compatible: function(value, refresh) {
|
||||||
|
this.settings.bootstrap2Compatible = value;
|
||||||
|
if (value) {
|
||||||
|
this.container.removeClass('row').addClass('row-fluid bs2compatible');
|
||||||
|
this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
|
||||||
|
this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');
|
||||||
|
this.container.find('input, select').removeClass('form-control');
|
||||||
|
this.container.find('.btn').removeClass('btn-default');
|
||||||
|
this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');
|
||||||
|
this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');
|
||||||
|
} else {
|
||||||
|
this.container.removeClass('row-fluid bs2compatible').addClass('row');
|
||||||
|
this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
|
||||||
|
this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');
|
||||||
|
this.container.find('input, select').addClass('form-control');
|
||||||
|
this.container.find('.btn').addClass('btn-default');
|
||||||
|
this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');
|
||||||
|
this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setFilterTextClear: function(value, refresh) {
|
||||||
|
this.settings.filterTextClear = value;
|
||||||
|
this.elements.filterClear1.html(value);
|
||||||
|
this.elements.filterClear2.html(value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setFilterPlaceHolder: function(value, refresh) {
|
||||||
|
this.settings.filterPlaceHolder = value;
|
||||||
|
this.elements.filterInput1.attr('placeholder', value);
|
||||||
|
this.elements.filterInput2.attr('placeholder', value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setMoveSelectedLabel: function(value, refresh) {
|
||||||
|
this.settings.moveSelectedLabel = value;
|
||||||
|
this.elements.moveButton.attr('title', value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setMoveAllLabel: function(value, refresh) {
|
||||||
|
this.settings.moveAllLabel = value;
|
||||||
|
this.elements.moveAllButton.attr('title', value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setRemoveSelectedLabel: function(value, refresh) {
|
||||||
|
this.settings.removeSelectedLabel = value;
|
||||||
|
this.elements.removeButton.attr('title', value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setRemoveAllLabel: function(value, refresh) {
|
||||||
|
this.settings.removeAllLabel = value;
|
||||||
|
this.elements.removeAllButton.attr('title', value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setMoveOnSelect: function(value, refresh) {
|
||||||
|
if (isBuggyAndroid) {
|
||||||
|
value = true;
|
||||||
|
}
|
||||||
|
this.settings.moveOnSelect = value;
|
||||||
|
if (this.settings.moveOnSelect) {
|
||||||
|
this.container.addClass('moveonselect');
|
||||||
|
var self = this;
|
||||||
|
this.elements.select1.on('change', function() {
|
||||||
|
move(self);
|
||||||
|
});
|
||||||
|
this.elements.select2.on('change', function() {
|
||||||
|
remove(self);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.container.removeClass('moveonselect');
|
||||||
|
this.elements.select1.off('change');
|
||||||
|
this.elements.select2.off('change');
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setMoveOnDoubleClick: function(value, refresh) {
|
||||||
|
if (isBuggyAndroid) {
|
||||||
|
value = false;
|
||||||
|
}
|
||||||
|
this.settings.moveOnDoubleClick = value;
|
||||||
|
if (this.settings.moveOnDoubleClick) {
|
||||||
|
this.container.addClass('moveondoubleclick');
|
||||||
|
var self = this;
|
||||||
|
this.elements.select1.on('dblclick', function() {
|
||||||
|
move(self);
|
||||||
|
});
|
||||||
|
this.elements.select2.on('dblclick', function() {
|
||||||
|
remove(self);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.container.removeClass('moveondoubleclick');
|
||||||
|
this.elements.select1.off('dblclick');
|
||||||
|
this.elements.select2.off('dblclick');
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setPreserveSelectionOnMove: function(value, refresh) {
|
||||||
|
// We are forcing to move on select and disabling preserveSelectionOnMove on Android
|
||||||
|
if (isBuggyAndroid) {
|
||||||
|
value = false;
|
||||||
|
}
|
||||||
|
this.settings.preserveSelectionOnMove = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setSelectedListLabel: function(value, refresh) {
|
||||||
|
this.settings.selectedListLabel = value;
|
||||||
|
if (value) {
|
||||||
|
this.elements.label2.show().html(value);
|
||||||
|
} else {
|
||||||
|
this.elements.label2.hide().html(value);
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setNonSelectedListLabel: function(value, refresh) {
|
||||||
|
this.settings.nonSelectedListLabel = value;
|
||||||
|
if (value) {
|
||||||
|
this.elements.label1.show().html(value);
|
||||||
|
} else {
|
||||||
|
this.elements.label1.hide().html(value);
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setHelperSelectNamePostfix: function(value, refresh) {
|
||||||
|
this.settings.helperSelectNamePostfix = value;
|
||||||
|
if (value) {
|
||||||
|
this.elements.select1.attr('name', this.originalSelectName + value + '1');
|
||||||
|
this.elements.select2.attr('name', this.originalSelectName + value + '2');
|
||||||
|
} else {
|
||||||
|
this.elements.select1.removeAttr('name');
|
||||||
|
this.elements.select2.removeAttr('name');
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setSelectOrMinimalHeight: function(value, refresh) {
|
||||||
|
this.settings.selectorMinimalHeight = value;
|
||||||
|
var height = this.element.height();
|
||||||
|
if (this.element.height() < value) {
|
||||||
|
height = value;
|
||||||
|
}
|
||||||
|
this.elements.select1.height(height);
|
||||||
|
this.elements.select2.height(height);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setShowFilterInputs: function(value, refresh) {
|
||||||
|
if (!value) {
|
||||||
|
this.setNonSelectedFilter('');
|
||||||
|
this.setSelectedFilter('');
|
||||||
|
refreshSelects(this);
|
||||||
|
this.elements.filterInput1.hide();
|
||||||
|
this.elements.filterInput2.hide();
|
||||||
|
} else {
|
||||||
|
this.elements.filterInput1.show();
|
||||||
|
this.elements.filterInput2.show();
|
||||||
|
}
|
||||||
|
this.settings.showFilterInputs = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setNonSelectedFilter: function(value, refresh) {
|
||||||
|
if (this.settings.showFilterInputs) {
|
||||||
|
this.settings.nonSelectedFilter = value;
|
||||||
|
this.elements.filterInput1.val(value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setSelectedFilter: function(value, refresh) {
|
||||||
|
if (this.settings.showFilterInputs) {
|
||||||
|
this.settings.selectedFilter = value;
|
||||||
|
this.elements.filterInput2.val(value);
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setInfoText: function(value, refresh) {
|
||||||
|
this.settings.infoText = value;
|
||||||
|
if (value) {
|
||||||
|
this.elements.info1.show();
|
||||||
|
this.elements.info2.show();
|
||||||
|
} else {
|
||||||
|
this.elements.info1.hide();
|
||||||
|
this.elements.info2.hide();
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setInfoTextFiltered: function(value, refresh) {
|
||||||
|
this.settings.infoTextFiltered = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setInfoTextEmpty: function(value, refresh) {
|
||||||
|
this.settings.infoTextEmpty = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setFilterOnValues: function(value, refresh) {
|
||||||
|
this.settings.filterOnValues = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setSortByInputOrder: function(value, refresh){
|
||||||
|
this.settings.sortByInputOrder = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setEventMoveOverride: function(value, refresh) {
|
||||||
|
this.settings.eventMoveOverride = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setEventMoveAllOverride: function(value, refresh) {
|
||||||
|
this.settings.eventMoveAllOverride = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setEventRemoveOverride: function(value, refresh) {
|
||||||
|
this.settings.eventRemoveOverride = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
setEventRemoveAllOverride: function(value, refresh) {
|
||||||
|
this.settings.eventRemoveAllOverride = value;
|
||||||
|
if (refresh) {
|
||||||
|
refreshSelects(this);
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
|
},
|
||||||
|
getContainer: function() {
|
||||||
|
return this.container;
|
||||||
|
},
|
||||||
|
refresh: function(mustClearSelections) {
|
||||||
|
updateSelectionStates(this);
|
||||||
|
|
||||||
|
if (!mustClearSelections) {
|
||||||
|
saveSelections(this, 1);
|
||||||
|
saveSelections(this, 2);
|
||||||
|
} else {
|
||||||
|
clearSelections(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshSelects(this);
|
||||||
|
},
|
||||||
|
destroy: function() {
|
||||||
|
this.container.remove();
|
||||||
|
this.element.show();
|
||||||
|
$.data(this, 'plugin_' + pluginName, null);
|
||||||
|
return this.element;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A really lightweight plugin wrapper around the constructor,
|
||||||
|
// preventing against multiple instantiations
|
||||||
|
$.fn[ pluginName ] = function (options) {
|
||||||
|
var args = arguments;
|
||||||
|
|
||||||
|
// Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
|
||||||
|
if (options === undefined || typeof options === 'object') {
|
||||||
|
return this.each(function () {
|
||||||
|
// If this is not a select
|
||||||
|
if (!$(this).is('select')) {
|
||||||
|
$(this).find('select').each(function(index, item) {
|
||||||
|
// For each nested select, instantiate the Dual List Box
|
||||||
|
$(item).bootstrapDualListbox(options);
|
||||||
|
});
|
||||||
|
} else if (!$.data(this, 'plugin_' + pluginName)) {
|
||||||
|
// Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
|
||||||
|
|
||||||
|
// if it has no instance, create a new one, pass options to our plugin constructor,
|
||||||
|
// and store the plugin instance in the elements jQuery data object.
|
||||||
|
$.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
|
||||||
|
// treat this as a call to a public method.
|
||||||
|
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
|
||||||
|
|
||||||
|
// Cache the method call to make it possible to return a value
|
||||||
|
var returns;
|
||||||
|
|
||||||
|
this.each(function () {
|
||||||
|
var instance = $.data(this, 'plugin_' + pluginName);
|
||||||
|
// Tests that there's already a plugin-instance and checks that the requested public method exists
|
||||||
|
if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
|
||||||
|
// Call the method of our plugin instance, and pass it the supplied arguments.
|
||||||
|
returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the earlier cached method gives a value back return the value,
|
||||||
|
// otherwise return this to preserve chainability.
|
||||||
|
return returns !== undefined ? returns : this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery, window, document);
|
||||||
9
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css
vendored
Normal file
9
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.css
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Bootstrap Duallistbox - v3.0.9
|
||||||
|
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
|
||||||
|
* https://www.virtuosoft.eu/code/bootstrap-duallistbox/
|
||||||
|
*
|
||||||
|
* Made by István Ujj-Mészáros
|
||||||
|
* Under Apache License v2.0 License
|
||||||
|
*/
|
||||||
|
.bootstrap-duallistbox-container .buttons{width:100%;margin-bottom:-1px}.bootstrap-duallistbox-container label{display:block}.bootstrap-duallistbox-container .info{display:inline-block;margin-bottom:5px;font-size:11px}.bootstrap-duallistbox-container .clear1,.bootstrap-duallistbox-container .clear2{display:none;font-size:10px}.bootstrap-duallistbox-container .box1.filtered .clear1,.bootstrap-duallistbox-container .box2.filtered .clear2{display:inline-block}.bootstrap-duallistbox-container .move,.bootstrap-duallistbox-container .remove{width:60%}.bootstrap-duallistbox-container .btn-group .btn{border-bottom-left-radius:0;border-bottom-right-radius:0}.bootstrap-duallistbox-container select{border-top-left-radius:0;border-top-right-radius:0}.bootstrap-duallistbox-container .moveall,.bootstrap-duallistbox-container .removeall{width:40%}.bootstrap-duallistbox-container.bs2compatible .btn-group>.btn+.btn{margin-left:0}.bootstrap-duallistbox-container select{width:100%;height:300px;padding:0}.bootstrap-duallistbox-container .filter{display:inline-block;width:100%;height:31px;margin:0 0 5px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-duallistbox-container .filter.placeholder{color:#aaa}.bootstrap-duallistbox-container.moveonselect .move,.bootstrap-duallistbox-container.moveonselect .remove{display:none}.bootstrap-duallistbox-container.moveonselect .moveall,.bootstrap-duallistbox-container.moveonselect .removeall{width:100%}
|
||||||
10
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js
vendored
Normal file
10
ruoyi-admin/src/main/resources/static/ajax/libs/duallistbox/bootstrap-duallistbox.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,315 @@
|
||||||
|
/* The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2011 by Michael Zinsmaier and nergal.dev
|
||||||
|
Copyright (c) 2012 by Thomas Ritou
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
____________________________________________________
|
||||||
|
|
||||||
|
what it is:
|
||||||
|
____________________________________________________
|
||||||
|
|
||||||
|
curvedLines is a plugin for flot, that tries to display lines in a smoother way.
|
||||||
|
The plugin is based on nergal.dev's work https://code.google.com/p/flot/issues/detail?id=226
|
||||||
|
and further extended with a mode that forces the min/max points of the curves to be on the
|
||||||
|
points. Both modes are achieved through adding of more data points
|
||||||
|
=> 1) with large data sets you may get trouble
|
||||||
|
=> 2) if you want to display the points too, you have to plot them as 2nd data series over the lines
|
||||||
|
|
||||||
|
&& 3) consecutive x data points are not allowed to have the same value
|
||||||
|
|
||||||
|
This is version 0.5 of curvedLines so it will probably not work in every case. However
|
||||||
|
the basic form of use descirbed next works (:
|
||||||
|
|
||||||
|
Feel free to further improve the code
|
||||||
|
|
||||||
|
____________________________________________________
|
||||||
|
|
||||||
|
how to use it:
|
||||||
|
____________________________________________________
|
||||||
|
|
||||||
|
var d1 = [[5,5],[7,3],[9,12]];
|
||||||
|
|
||||||
|
var options = { series: { curvedLines: { active: true }}};
|
||||||
|
|
||||||
|
$.plot($("#placeholder"), [{data = d1, lines: { show: true}, curvedLines: {apply: true}}], options);
|
||||||
|
|
||||||
|
_____________________________________________________
|
||||||
|
|
||||||
|
options:
|
||||||
|
_____________________________________________________
|
||||||
|
|
||||||
|
active: bool true => plugin can be used
|
||||||
|
apply: bool true => series will be drawn as curved line
|
||||||
|
fit: bool true => forces the max,mins of the curve to be on the datapoints
|
||||||
|
curvePointFactor int defines how many "virtual" points are used per "real" data point to
|
||||||
|
emulate the curvedLines (points total = real points * curvePointFactor)
|
||||||
|
fitPointDist: int defines the x axis distance of the additional two points that are used
|
||||||
|
to enforce the min max condition.
|
||||||
|
|
||||||
|
+ line options (since v0.5 curved lines use flots line implementation for drawing
|
||||||
|
=> line options like fill, show ... are supported out of the box)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* v0.1 initial commit
|
||||||
|
* v0.15 negative values should work now (outcommented a negative -> 0 hook hope it does no harm)
|
||||||
|
* v0.2 added fill option (thanks to monemihir) and multi axis support (thanks to soewono effendi)
|
||||||
|
* v0.3 improved saddle handling and added basic handling of Dates
|
||||||
|
* v0.4 rewritten fill option (thomas ritou) mostly from original flot code (now fill between points rather than to graph bottom), corrected fill Opacity bug
|
||||||
|
* v0.5 rewritten instead of implementing a own draw function CurvedLines is now based on the processDatapoints flot hook (credits go to thomas ritou).
|
||||||
|
* This change breakes existing code however CurvedLines are now just many tiny straight lines to flot and therefore all flot lines options (like gradient fill,
|
||||||
|
* shadow) are now supported out of the box
|
||||||
|
* v0.6 flot 0.8 compatibility and some bug fixes
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
series : {
|
||||||
|
curvedLines : {
|
||||||
|
active : false,
|
||||||
|
apply: false,
|
||||||
|
fit : false,
|
||||||
|
curvePointFactor : 20,
|
||||||
|
fitPointDist : undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(plot) {
|
||||||
|
|
||||||
|
plot.hooks.processOptions.push(processOptions);
|
||||||
|
|
||||||
|
//if the plugin is active register processDatapoints method
|
||||||
|
function processOptions(plot, options) {
|
||||||
|
if (options.series.curvedLines.active) {
|
||||||
|
plot.hooks.processDatapoints.unshift(processDatapoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//only if the plugin is active
|
||||||
|
function processDatapoints(plot, series, datapoints) {
|
||||||
|
var nrPoints = datapoints.points.length / datapoints.pointsize;
|
||||||
|
var EPSILON = 0.5; //pretty large epsilon but save
|
||||||
|
|
||||||
|
if (series.curvedLines.apply == true && series.originSeries === undefined && nrPoints > (1 + EPSILON)) {
|
||||||
|
if (series.lines.fill) {
|
||||||
|
|
||||||
|
var pointsTop = calculateCurvePoints(datapoints, series.curvedLines, 1)
|
||||||
|
,pointsBottom = calculateCurvePoints(datapoints, series.curvedLines, 2); //flot makes sure for us that we've got a second y point if fill is true !
|
||||||
|
|
||||||
|
//Merge top and bottom curve
|
||||||
|
datapoints.pointsize = 3;
|
||||||
|
datapoints.points = [];
|
||||||
|
var j = 0;
|
||||||
|
var k = 0;
|
||||||
|
var i = 0;
|
||||||
|
var ps = 2;
|
||||||
|
while (i < pointsTop.length || j < pointsBottom.length) {
|
||||||
|
if (pointsTop[i] == pointsBottom[j]) {
|
||||||
|
datapoints.points[k] = pointsTop[i];
|
||||||
|
datapoints.points[k + 1] = pointsTop[i + 1];
|
||||||
|
datapoints.points[k + 2] = pointsBottom[j + 1];
|
||||||
|
j += ps;
|
||||||
|
i += ps;
|
||||||
|
|
||||||
|
} else if (pointsTop[i] < pointsBottom[j]) {
|
||||||
|
datapoints.points[k] = pointsTop[i];
|
||||||
|
datapoints.points[k + 1] = pointsTop[i + 1];
|
||||||
|
datapoints.points[k + 2] = k > 0 ? datapoints.points[k-1] : null;
|
||||||
|
i += ps;
|
||||||
|
} else {
|
||||||
|
datapoints.points[k] = pointsBottom[j];
|
||||||
|
datapoints.points[k + 1] = k > 1 ? datapoints.points[k-2] : null;
|
||||||
|
datapoints.points[k + 2] = pointsBottom[j + 1];
|
||||||
|
j += ps;
|
||||||
|
}
|
||||||
|
k += 3;
|
||||||
|
}
|
||||||
|
} else if (series.lines.lineWidth > 0) {
|
||||||
|
datapoints.points = calculateCurvePoints(datapoints, series.curvedLines, 1);
|
||||||
|
datapoints.pointsize = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//no real idea whats going on here code mainly from https://code.google.com/p/flot/issues/detail?id=226
|
||||||
|
//if fit option is selected additional datapoints get inserted before the curve calculations in nergal.dev s code.
|
||||||
|
function calculateCurvePoints(datapoints, curvedLinesOptions, yPos) {
|
||||||
|
|
||||||
|
var points = datapoints.points, ps = datapoints.pointsize;
|
||||||
|
var num = curvedLinesOptions.curvePointFactor * (points.length / ps);
|
||||||
|
|
||||||
|
var xdata = new Array;
|
||||||
|
var ydata = new Array;
|
||||||
|
|
||||||
|
var curX = -1;
|
||||||
|
var curY = -1;
|
||||||
|
var j = 0;
|
||||||
|
|
||||||
|
if (curvedLinesOptions.fit) {
|
||||||
|
//insert a point before and after the "real" data point to force the line
|
||||||
|
//to have a max,min at the data point.
|
||||||
|
|
||||||
|
var fpDist;
|
||||||
|
if(typeof curvedLinesOptions.fitPointDist == 'undefined') {
|
||||||
|
//estimate it
|
||||||
|
var minX = points[0];
|
||||||
|
var maxX = points[points.length-ps];
|
||||||
|
fpDist = (maxX - minX) / (500 * 100); //x range / (estimated pixel length of placeholder * factor)
|
||||||
|
} else {
|
||||||
|
//use user defined value
|
||||||
|
fpDist = curvedLinesOptions.fitPointDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < points.length; i += ps) {
|
||||||
|
|
||||||
|
var frontX;
|
||||||
|
var backX;
|
||||||
|
curX = i;
|
||||||
|
curY = i + yPos;
|
||||||
|
|
||||||
|
//add point X s
|
||||||
|
frontX = points[curX] - fpDist;
|
||||||
|
backX = points[curX] + fpDist;
|
||||||
|
|
||||||
|
var factor = 2;
|
||||||
|
while (frontX == points[curX] || backX == points[curX]) {
|
||||||
|
//inside the ulp
|
||||||
|
frontX = points[curX] - (fpDist * factor);
|
||||||
|
backX = points[curX] + (fpDist * factor);
|
||||||
|
factor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add curve points
|
||||||
|
xdata[j] = frontX;
|
||||||
|
ydata[j] = points[curY];
|
||||||
|
j++;
|
||||||
|
|
||||||
|
xdata[j] = points[curX];
|
||||||
|
ydata[j] = points[curY];
|
||||||
|
j++;
|
||||||
|
|
||||||
|
xdata[j] = backX;
|
||||||
|
ydata[j] = points[curY];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//just use the datapoints
|
||||||
|
for (var i = 0; i < points.length; i += ps) {
|
||||||
|
curX = i;
|
||||||
|
curY = i + yPos;
|
||||||
|
|
||||||
|
xdata[j] = points[curX];
|
||||||
|
ydata[j] = points[curY];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var n = xdata.length;
|
||||||
|
|
||||||
|
var y2 = new Array();
|
||||||
|
var delta = new Array();
|
||||||
|
y2[0] = 0;
|
||||||
|
y2[n - 1] = 0;
|
||||||
|
delta[0] = 0;
|
||||||
|
|
||||||
|
for (var i = 1; i < n - 1; ++i) {
|
||||||
|
var d = (xdata[i + 1] - xdata[i - 1]);
|
||||||
|
if (d == 0) {
|
||||||
|
//point before current point and after current point need some space in between
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = (xdata[i] - xdata[i - 1]) / d;
|
||||||
|
var p = s * y2[i - 1] + 2;
|
||||||
|
y2[i] = (s - 1) / p;
|
||||||
|
delta[i] = (ydata[i + 1] - ydata[i]) / (xdata[i + 1] - xdata[i]) - (ydata[i] - ydata[i - 1]) / (xdata[i] - xdata[i - 1]);
|
||||||
|
delta[i] = (6 * delta[i] / (xdata[i + 1] - xdata[i - 1]) - s * delta[i - 1]) / p;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var j = n - 2; j >= 0; --j) {
|
||||||
|
y2[j] = y2[j] * y2[j + 1] + delta[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
// xmax - xmin / #points
|
||||||
|
var step = (xdata[n - 1] - xdata[0]) / (num - 1);
|
||||||
|
|
||||||
|
var xnew = new Array;
|
||||||
|
var ynew = new Array;
|
||||||
|
var result = new Array;
|
||||||
|
|
||||||
|
xnew[0] = xdata[0];
|
||||||
|
ynew[0] = ydata[0];
|
||||||
|
|
||||||
|
result.push(xnew[0]);
|
||||||
|
result.push(ynew[0]);
|
||||||
|
|
||||||
|
for ( j = 1; j < num; ++j) {
|
||||||
|
//new x point (sampling point for the created curve)
|
||||||
|
xnew[j] = xnew[0] + j * step;
|
||||||
|
|
||||||
|
var max = n - 1;
|
||||||
|
var min = 0;
|
||||||
|
|
||||||
|
while (max - min > 1) {
|
||||||
|
var k = Math.round((max + min) / 2);
|
||||||
|
if (xdata[k] > xnew[j]) {
|
||||||
|
max = k;
|
||||||
|
} else {
|
||||||
|
min = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//found point one to the left and one to the right of generated new point
|
||||||
|
var h = (xdata[max] - xdata[min]);
|
||||||
|
|
||||||
|
if (h == 0) {
|
||||||
|
//similar to above two points from original x data need some space between them
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = (xdata[max] - xnew[j]) / h;
|
||||||
|
var b = (xnew[j] - xdata[min]) / h;
|
||||||
|
|
||||||
|
ynew[j] = a * ydata[min] + b * ydata[max] + ((a * a * a - a) * y2[min] + (b * b * b - b) * y2[max]) * (h * h) / 6;
|
||||||
|
|
||||||
|
result.push(xnew[j]);
|
||||||
|
result.push(ynew[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end init
|
||||||
|
|
||||||
|
$.plot.plugins.push({
|
||||||
|
init : init,
|
||||||
|
options : options,
|
||||||
|
name : 'curvedLines',
|
||||||
|
version : '0.5'
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue