mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	Compare commits
	
		
			1558 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ed43f0a889 | ||
| 
						 | 
					a7daed30d8 | ||
| 
						 | 
					f2598e7961 | ||
| 
						 | 
					4c848cf4cb | ||
| 
						 | 
					4d1bf7c25c | ||
| 
						 | 
					88bd127b67 | ||
| 
						 | 
					1186b86f73 | ||
| 
						 | 
					eb946e029d | ||
| 
						 | 
					9b68b27168 | ||
| 
						 | 
					5dbb255323 | ||
| 
						 | 
					cc326e36cc | ||
| 
						 | 
					bacdd8d685 | ||
| 
						 | 
					8ce96690fc | ||
| 
						 | 
					9d0d52a48c | ||
| 
						 | 
					8d0c06b5bf | ||
| 
						 | 
					245ade0d79 | ||
| 
						 | 
					8de02e285e | ||
| 
						 | 
					0005710f45 | ||
| 
						 | 
					88e09f2189 | ||
| 
						 | 
					c7e79d2681 | ||
| 
						 | 
					86223d5a6b | ||
| 
						 | 
					ce04052da3 | ||
| 
						 | 
					f91f225ba6 | ||
| 
						 | 
					2cfdb9bcda | ||
| 
						 | 
					a06f3255d0 | ||
| 
						 | 
					2affe91837 | ||
| 
						 | 
					7544ae318c | ||
| 
						 | 
					e59f04bfee | ||
| 
						 | 
					e35df6d1d2 | ||
| 
						 | 
					81dcd8b512 | ||
| 
						 | 
					8ca601dc66 | ||
| 
						 | 
					5ff7203929 | ||
| 
						 | 
					a6ef8bb938 | ||
| 
						 | 
					79fd63599a | ||
| 
						 | 
					3c89a83d6b | ||
| 
						 | 
					d45ae7ffc5 | ||
| 
						 | 
					34babcbfa5 | ||
| 
						 | 
					e5661a2cf4 | ||
| 
						 | 
					cc40f9c4ac | ||
| 
						 | 
					6e38a9e412 | ||
| 
						 | 
					481170922e | ||
| 
						 | 
					f46b8d0758 | ||
| 
						 | 
					1d43448423 | ||
| 
						 | 
					2de97fe45c | ||
| 
						 | 
					c41688831c | ||
| 
						 | 
					2a36ce4302 | ||
| 
						 | 
					f2200df15a | ||
| 
						 | 
					3b498c4939 | ||
| 
						 | 
					2cead2c5fd | ||
| 
						 | 
					23bf840684 | ||
| 
						 | 
					f8d551e226 | ||
| 
						 | 
					2e3b068341 | ||
| 
						 | 
					0d9b1c2e82 | ||
| 
						 | 
					148c7c588e | ||
| 
						 | 
					3a82fb82e8 | ||
| 
						 | 
					c319579c0b | ||
| 
						 | 
					acfa39369e | ||
| 
						 | 
					f71b8110a9 | ||
| 
						 | 
					8311454342 | ||
| 
						 | 
					ed4df16201 | ||
| 
						 | 
					2f3dbbfe32 | ||
| 
						 | 
					dc752ade25 | ||
| 
						 | 
					ebef89be62 | ||
| 
						 | 
					7d209aeb41 | ||
| 
						 | 
					e82a031dd0 | ||
| 
						 | 
					fea9fdaa5f | ||
| 
						 | 
					952cd0b4d3 | ||
| 
						 | 
					ec6704181f | ||
| 
						 | 
					3389a11933 | ||
| 
						 | 
					db0c882f1b | ||
| 
						 | 
					13d468d8cc | ||
| 
						 | 
					b6daa886e0 | ||
| 
						 | 
					1d10611172 | ||
| 
						 | 
					8a5cc7f76c | ||
| 
						 | 
					d4ab8a8e22 | ||
| 
						 | 
					8a86c5bdc5 | ||
| 
						 | 
					e9cc7c3058 | ||
| 
						 | 
					f7dd7d1e42 | ||
| 
						 | 
					71317201b8 | ||
| 
						 | 
					19ba2b4207 | ||
| 
						 | 
					cb54a9576e | ||
| 
						 | 
					7f73bfc478 | ||
| 
						 | 
					ed8d6b651a | ||
| 
						 | 
					fd2a1cb9b9 | ||
| 
						 | 
					775bd5925a | ||
| 
						 | 
					fc0a33e512 | ||
| 
						 | 
					e093b7b2ec | ||
| 
						 | 
					350e62c6cb | ||
| 
						 | 
					2c3d2e4ea3 | ||
| 
						 | 
					57bddf259a | ||
| 
						 | 
					c40b45e7bb | ||
| 
						 | 
					7b924e2482 | ||
| 
						 | 
					9699d1fedb | ||
| 
						 | 
					2004a0cc64 | ||
| 
						 | 
					11485c2538 | ||
| 
						 | 
					36b5051cbd | ||
| 
						 | 
					8b3310cd00 | ||
| 
						 | 
					788e370cc0 | ||
| 
						 | 
					c230eedbc0 | ||
| 
						 | 
					39d4efee6a | ||
| 
						 | 
					1bd9688533 | ||
| 
						 | 
					2e50b52ae8 | ||
| 
						 | 
					73e14d33fe | ||
| 
						 | 
					9dab37060b | ||
| 
						 | 
					1e69726d77 | ||
| 
						 | 
					45eec24b7f | ||
| 
						 | 
					618ba481b8 | ||
| 
						 | 
					81f488e24a | ||
| 
						 | 
					7cdeb3d3d7 | ||
| 
						 | 
					0ff533e6b5 | ||
| 
						 | 
					d785a01973 | ||
| 
						 | 
					bbbfeb59c8 | ||
| 
						 | 
					361e210583 | ||
| 
						 | 
					c7f14a8b21 | ||
| 
						 | 
					040ce14acd | ||
| 
						 | 
					cf66216f3e | ||
| 
						 | 
					adc286d25a | ||
| 
						 | 
					ad7731a0e9 | ||
| 
						 | 
					bbda70c2a0 | ||
| 
						 | 
					cbd0aca8eb | ||
| 
						 | 
					d2e18fd571 | ||
| 
						 | 
					df544f32c9 | ||
| 
						 | 
					cad98d8384 | ||
| 
						 | 
					88377e2e05 | ||
| 
						 | 
					c6324e80af | ||
| 
						 | 
					04eb841cde | ||
| 
						 | 
					2ad0299493 | ||
| 
						 | 
					0f5603aed4 | ||
| 
						 | 
					72882374be | ||
| 
						 | 
					21570cbd33 | ||
| 
						 | 
					049da896f8 | ||
| 
						 | 
					0affb8ab54 | ||
| 
						 | 
					a412b20118 | ||
| 
						 | 
					2dcfb8e3ce | ||
| 
						 | 
					c631a084f3 | ||
| 
						 | 
					022d33bc41 | ||
| 
						 | 
					47379dd702 | ||
| 
						 | 
					8c8b53e266 | ||
| 
						 | 
					9e8a58af43 | ||
| 
						 | 
					4409b96c74 | ||
| 
						 | 
					9253186c27 | ||
| 
						 | 
					b9eee8f399 | ||
| 
						 | 
					230d5e7d56 | ||
| 
						 | 
					68404f3f6e | ||
| 
						 | 
					a312794423 | ||
| 
						 | 
					98e9c11378 | ||
| 
						 | 
					d9b8dd9cc2 | ||
| 
						 | 
					f366457aa1 | ||
| 
						 | 
					311df68fa6 | ||
| 
						 | 
					c5d071dbaf | ||
| 
						 | 
					b55409bf37 | ||
| 
						 | 
					11f548b53b | ||
| 
						 | 
					d8b264a13d | ||
| 
						 | 
					77407899e8 | ||
| 
						 | 
					6296a50259 | ||
| 
						 | 
					754b138abe | ||
| 
						 | 
					811177f530 | ||
| 
						 | 
					54a45d0900 | ||
| 
						 | 
					b55d8faa67 | ||
| 
						 | 
					1ad5a526e7 | ||
| 
						 | 
					ecdb629438 | ||
| 
						 | 
					df5eb800cd | ||
| 
						 | 
					f3fa1386e7 | ||
| 
						 | 
					a31d4a92d6 | ||
| 
						 | 
					0804854175 | ||
| 
						 | 
					bb265274c5 | ||
| 
						 | 
					9895517097 | ||
| 
						 | 
					93dda236dc | ||
| 
						 | 
					8619d97749 | ||
| 
						 | 
					6762ab739a | ||
| 
						 | 
					5b43d0e29f | ||
| 
						 | 
					0662756e8c | ||
| 
						 | 
					5cd6dcff4f | ||
| 
						 | 
					0b0439b72e | ||
| 
						 | 
					0abc2e9624 | ||
| 
						 | 
					7343cdbe70 | ||
| 
						 | 
					ded82af207 | ||
| 
						 | 
					16d58bacbc | ||
| 
						 | 
					a5abbbf988 | ||
| 
						 | 
					5c040dc5cb | ||
| 
						 | 
					6c41fd1cf3 | ||
| 
						 | 
					b4cf1dbb6d | ||
| 
						 | 
					eba4c88833 | ||
| 
						 | 
					773b497761 | ||
| 
						 | 
					3832dc933d | ||
| 
						 | 
					7fd262fd8b | ||
| 
						 | 
					5e44843854 | ||
| 
						 | 
					09d72dceef | ||
| 
						 | 
					684b84a16d | ||
| 
						 | 
					35c289ab92 | ||
| 
						 | 
					b91f02f5b7 | ||
| 
						 | 
					ab7f6957b9 | ||
| 
						 | 
					b13c10ccd6 | ||
| 
						 | 
					eb23098a4d | ||
| 
						 | 
					b02ad6a0cc | ||
| 
						 | 
					2fd44be9db | ||
| 
						 | 
					fda19131ae | ||
| 
						 | 
					24d942f036 | ||
| 
						 | 
					7484b9b6a9 | ||
| 
						 | 
					9ae3e9902a | ||
| 
						 | 
					cbd50e6b3d | ||
| 
						 | 
					9a9507ce5a | ||
| 
						 | 
					46e126dff7 | ||
| 
						 | 
					56d7023e41 | ||
| 
						 | 
					0e0370f532 | ||
| 
						 | 
					025f3a9bcf | ||
| 
						 | 
					4dc8af274b | ||
| 
						 | 
					7f0661c007 | ||
| 
						 | 
					a847a1dbcc | ||
| 
						 | 
					a5ee33b559 | ||
| 
						 | 
					8f87da19ea | ||
| 
						 | 
					a2d8ff9286 | ||
| 
						 | 
					8387ec6134 | ||
| 
						 | 
					9e0fca3b54 | ||
| 
						 | 
					f8c079c651 | ||
| 
						 | 
					9b7adfdaf4 | ||
| 
						 | 
					91a61b6927 | ||
| 
						 | 
					d38fa0ec05 | ||
| 
						 | 
					d7d398763f | ||
| 
						 | 
					f6d4e23bf6 | ||
| 
						 | 
					4b07faf89a | ||
| 
						 | 
					31194414eb | ||
| 
						 | 
					d6c49b915f | ||
| 
						 | 
					b465972e7c | ||
| 
						 | 
					7a5abcd0f8 | ||
| 
						 | 
					5464dfb830 | ||
| 
						 | 
					7a97377c28 | ||
| 
						 | 
					453b8fcbb2 | ||
| 
						 | 
					2a46cdbd88 | ||
| 
						 | 
					995578c561 | ||
| 
						 | 
					f88c93b335 | ||
| 
						 | 
					edcd7c99ba | ||
| 
						 | 
					dadf05c25c | ||
| 
						 | 
					a2c43aceb1 | ||
| 
						 | 
					4bd2691422 | ||
| 
						 | 
					088002bd62 | ||
| 
						 | 
					5722ba3f6c | ||
| 
						 | 
					40aeeeced1 | ||
| 
						 | 
					6f209cad99 | ||
| 
						 | 
					db6796e740 | ||
| 
						 | 
					4382cf2217 | ||
| 
						 | 
					d93307151a | ||
| 
						 | 
					f3d800d598 | ||
| 
						 | 
					d2baaaaf7b | ||
| 
						 | 
					c203d0af46 | ||
| 
						 | 
					1f507f2d22 | ||
| 
						 | 
					5cf3287064 | ||
| 
						 | 
					57bcb5dbf6 | ||
| 
						 | 
					e803388cad | ||
| 
						 | 
					b9b76539ac | ||
| 
						 | 
					bc06550918 | ||
| 
						 | 
					61db843576 | ||
| 
						 | 
					6c6d92a776 | ||
| 
						 | 
					f8ac8c085e | ||
| 
						 | 
					7c05920e73 | ||
| 
						 | 
					2d7535012e | ||
| 
						 | 
					654944b5c7 | ||
| 
						 | 
					d2675744f4 | ||
| 
						 | 
					e20dacbfd9 | ||
| 
						 | 
					540afd839d | ||
| 
						 | 
					b34c2fd6ee | ||
| 
						 | 
					1ae44c8124 | ||
| 
						 | 
					6fb34a7717 | ||
| 
						 | 
					43982c5a36 | ||
| 
						 | 
					d8062087c7 | ||
| 
						 | 
					10f88f5458 | ||
| 
						 | 
					c79c3ee5b6 | ||
| 
						 | 
					cedb174ffd | ||
| 
						 | 
					f9d9eb2d70 | ||
| 
						 | 
					1a70cf658c | ||
| 
						 | 
					242e26abee | ||
| 
						 | 
					52d33195ec | ||
| 
						 | 
					d8b486c793 | ||
| 
						 | 
					00b6ca5dfe | ||
| 
						 | 
					9ebaf936c1 | ||
| 
						 | 
					dac463efa6 | ||
| 
						 | 
					da1b18792b | ||
| 
						 | 
					85b4adf400 | ||
| 
						 | 
					70f39cb1ee | ||
| 
						 | 
					d87dfd6397 | ||
| 
						 | 
					1496220a74 | ||
| 
						 | 
					996835d124 | ||
| 
						 | 
					f6f3db1701 | ||
| 
						 | 
					6ee3085260 | ||
| 
						 | 
					a6f6562693 | ||
| 
						 | 
					d8585d0ee7 | ||
| 
						 | 
					4761237849 | ||
| 
						 | 
					f1a09711c1 | ||
| 
						 | 
					346a3cf7f1 | ||
| 
						 | 
					c42229bc54 | ||
| 
						 | 
					317ab351ce | ||
| 
						 | 
					e1579622de | ||
| 
						 | 
					f2ff839106 | ||
| 
						 | 
					c494ab9963 | ||
| 
						 | 
					15f7d4dc47 | ||
| 
						 | 
					dd9ef8431b | ||
| 
						 | 
					e729a924d4 | ||
| 
						 | 
					aeacfea536 | ||
| 
						 | 
					43b31edb75 | ||
| 
						 | 
					8448bcdc6d | ||
| 
						 | 
					e1efdb8602 | ||
| 
						 | 
					409849db1a | ||
| 
						 | 
					9d6b0b35a3 | ||
| 
						 | 
					7f00861e68 | ||
| 
						 | 
					d2b1177580 | ||
| 
						 | 
					ef91551449 | ||
| 
						 | 
					4063b0c2dd | ||
| 
						 | 
					5117fe2958 | ||
| 
						 | 
					9ed60f22de | ||
| 
						 | 
					8498ead56c | ||
| 
						 | 
					53ae4ea6bc | ||
| 
						 | 
					4c8137daf2 | ||
| 
						 | 
					6e017c35f7 | ||
| 
						 | 
					06cda3fb18 | ||
| 
						 | 
					b38151a0bb | ||
| 
						 | 
					2790b5ddc4 | ||
| 
						 | 
					f70951d374 | ||
| 
						 | 
					9ebe1ae918 | ||
| 
						 | 
					06e6f7af0c | ||
| 
						 | 
					d6894c89ed | ||
| 
						 | 
					ebf780617a | ||
| 
						 | 
					e130475259 | ||
| 
						 | 
					115af9c402 | ||
| 
						 | 
					8b914c1091 | ||
| 
						 | 
					9c368e8e68 | ||
| 
						 | 
					700db1fc15 | ||
| 
						 | 
					35f9c0fb72 | ||
| 
						 | 
					3091241279 | ||
| 
						 | 
					56050aa650 | ||
| 
						 | 
					b5cbb58c2d | ||
| 
						 | 
					adaa93acfb | ||
| 
						 | 
					5d043078b2 | ||
| 
						 | 
					fe8db721d7 | ||
| 
						 | 
					4d02466fed | ||
| 
						 | 
					ca69c00cf4 | ||
| 
						 | 
					6733e48ea1 | ||
| 
						 | 
					dca5d69dd2 | ||
| 
						 | 
					842af57d74 | ||
| 
						 | 
					8dc92383d9 | ||
| 
						 | 
					1ae35032a5 | ||
| 
						 | 
					223ae7ae72 | ||
| 
						 | 
					87a212f093 | ||
| 
						 | 
					5952b1c90e | ||
| 
						 | 
					83ba9be342 | ||
| 
						 | 
					a1431c5cb1 | ||
| 
						 | 
					e41a58b10d | ||
| 
						 | 
					da94e89825 | ||
| 
						 | 
					0381df6b17 | ||
| 
						 | 
					31acd6b301 | ||
| 
						 | 
					3c5dfdcf57 | ||
| 
						 | 
					e0b65b857d | ||
| 
						 | 
					83395d4e2f | ||
| 
						 | 
					a6bed384d7 | ||
| 
						 | 
					afac00de33 | ||
| 
						 | 
					ee80e97578 | ||
| 
						 | 
					35fac6cc0c | ||
| 
						 | 
					e5515751fd | ||
| 
						 | 
					c9c1e5ca7f | ||
| 
						 | 
					b47e67ff30 | ||
| 
						 | 
					f5de8b9ddf | ||
| 
						 | 
					a63abbf268 | ||
| 
						 | 
					1f42bd3d22 | ||
| 
						 | 
					93c4cc2cd1 | ||
| 
						 | 
					ab4b21ff58 | ||
| 
						 | 
					83a09c475d | ||
| 
						 | 
					9d99afd159 | ||
| 
						 | 
					1858ac6b25 | ||
| 
						 | 
					78290128e7 | ||
| 
						 | 
					68193fd37f | ||
| 
						 | 
					cd9c3c3f4f | ||
| 
						 | 
					8bd023b49f | ||
| 
						 | 
					57daef9ced | ||
| 
						 | 
					fb134da091 | ||
| 
						 | 
					c1a3eaaffb | ||
| 
						 | 
					b6dbe7b5a5 | ||
| 
						 | 
					8138063bfe | ||
| 
						 | 
					4c8dc500c7 | ||
| 
						 | 
					85247991b6 | ||
| 
						 | 
					a127eaa0e9 | ||
| 
						 | 
					ebb9f15a75 | ||
| 
						 | 
					cd137bd9fc | ||
| 
						 | 
					07bde5f88a | ||
| 
						 | 
					6fffa02acf | ||
| 
						 | 
					5830c3c96d | ||
| 
						 | 
					9f2dc5c233 | ||
| 
						 | 
					ec076c1e0d | ||
| 
						 | 
					6e8ef308ed | ||
| 
						 | 
					dc48f9858b | ||
| 
						 | 
					a6b2ac5dcd | ||
| 
						 | 
					c0685b7f7f | ||
| 
						 | 
					fb2d616c57 | ||
| 
						 | 
					6ff6853082 | ||
| 
						 | 
					f8014ae969 | ||
| 
						 | 
					88ed6e25ca | ||
| 
						 | 
					1de2b7a57e | ||
| 
						 | 
					95f7ba0080 | ||
| 
						 | 
					bb73b31e6b | ||
| 
						 | 
					9ecc4475dd | ||
| 
						 | 
					f01aa37394 | ||
| 
						 | 
					0208fa14af | ||
| 
						 | 
					efa2f23510 | ||
| 
						 | 
					408155ff5c | ||
| 
						 | 
					785c7495c1 | ||
| 
						 | 
					4517dea98d | ||
| 
						 | 
					0358dc233a | ||
| 
						 | 
					e21396870f | ||
| 
						 | 
					b67f6a0fec | ||
| 
						 | 
					42d8104505 | ||
| 
						 | 
					f40a0eab23 | ||
| 
						 | 
					b6153d1aef | ||
| 
						 | 
					a2c585daa4 | ||
| 
						 | 
					5a60bf0b0a | ||
| 
						 | 
					d2e58ba46b | ||
| 
						 | 
					9dcddc7876 | ||
| 
						 | 
					b970185536 | ||
| 
						 | 
					a64a029323 | ||
| 
						 | 
					98bb1f00ee | ||
| 
						 | 
					78f4d1c85b | ||
| 
						 | 
					bf83fe568b | ||
| 
						 | 
					02f4fdb2e5 | ||
| 
						 | 
					cb61a84acb | ||
| 
						 | 
					dc56e211e6 | ||
| 
						 | 
					e4d33b7d13 | ||
| 
						 | 
					f7de561ac5 | ||
| 
						 | 
					fde624998f | ||
| 
						 | 
					6505432bf4 | ||
| 
						 | 
					7d953c1a8b | ||
| 
						 | 
					95010d4a4c | ||
| 
						 | 
					a32a931d24 | ||
| 
						 | 
					4d72fb4289 | ||
| 
						 | 
					186c04d90a | ||
| 
						 | 
					84de5a5d42 | ||
| 
						 | 
					6fe80cff6b | ||
| 
						 | 
					c542b7ac32 | ||
| 
						 | 
					3607e008a3 | ||
| 
						 | 
					5b8edbf381 | ||
| 
						 | 
					03f7bc0f3f | ||
| 
						 | 
					0c54416040 | ||
| 
						 | 
					0d188d6a39 | ||
| 
						 | 
					e95a1245c5 | ||
| 
						 | 
					a3b761f4e0 | ||
| 
						 | 
					6e0c5817d5 | ||
| 
						 | 
					e410fc8c41 | ||
| 
						 | 
					9e7141f97c | ||
| 
						 | 
					d7441edae7 | ||
| 
						 | 
					5053361a7f | ||
| 
						 | 
					91c99d305c | ||
| 
						 | 
					2c39f26de3 | ||
| 
						 | 
					a680a84d91 | ||
| 
						 | 
					390edc5e3e | ||
| 
						 | 
					663024ac7f | ||
| 
						 | 
					0e75aa6250 | ||
| 
						 | 
					693a33f660 | ||
| 
						 | 
					8af85e8066 | ||
| 
						 | 
					513bda53cd | ||
| 
						 | 
					cf7df6a14c | ||
| 
						 | 
					acbdd6365a | ||
| 
						 | 
					e781f88eca | ||
| 
						 | 
					86d16d070d | ||
| 
						 | 
					3c4c91dc7d | ||
| 
						 | 
					574837a92a | ||
| 
						 | 
					854b405d89 | ||
| 
						 | 
					7d66a5bd84 | ||
| 
						 | 
					2c7663d971 | ||
| 
						 | 
					6281ec0456 | ||
| 
						 | 
					c3faa1a925 | ||
| 
						 | 
					111db70908 | ||
| 
						 | 
					d6400e382a | ||
| 
						 | 
					8f34644692 | ||
| 
						 | 
					7135a917c5 | ||
| 
						 | 
					e2bcd943f5 | ||
| 
						 | 
					d7c855b6f5 | ||
| 
						 | 
					d2774d3706 | ||
| 
						 | 
					adfae03953 | ||
| 
						 | 
					8298a08592 | ||
| 
						 | 
					9a3111487a | ||
| 
						 | 
					0788bcfcb0 | ||
| 
						 | 
					e4fff795b8 | ||
| 
						 | 
					fd7dc204de | ||
| 
						 | 
					4e807455e0 | ||
| 
						 | 
					8c9c52417e | ||
| 
						 | 
					be51b4bf25 | ||
| 
						 | 
					5761ba4271 | ||
| 
						 | 
					9e075f5c85 | ||
| 
						 | 
					37d6cc8146 | ||
| 
						 | 
					2293822dc2 | ||
| 
						 | 
					f5bec70911 | ||
| 
						 | 
					87c53a049b | ||
| 
						 | 
					5bcd2825b6 | ||
| 
						 | 
					fc442f482d | ||
| 
						 | 
					a26c02006f | ||
| 
						 | 
					be37190c09 | ||
| 
						 | 
					036144b9ea | ||
| 
						 | 
					2f2021caaf | ||
| 
						 | 
					4a00e4c9b1 | ||
| 
						 | 
					541c2df8db | ||
| 
						 | 
					0e39f6fa2d | ||
| 
						 | 
					17f0c20242 | ||
| 
						 | 
					24be022d4c | ||
| 
						 | 
					1f41b1db02 | ||
| 
						 | 
					bd338dd934 | ||
| 
						 | 
					1920ba94b7 | ||
| 
						 | 
					ccb1449fb2 | ||
| 
						 | 
					3fb15d8ec3 | ||
| 
						 | 
					3f4d51b485 | ||
| 
						 | 
					64ce9daf88 | ||
| 
						 | 
					0a07236347 | ||
| 
						 | 
					42d602b7a8 | ||
| 
						 | 
					d4b800036c | ||
| 
						 | 
					0b0a52c699 | ||
| 
						 | 
					b289f4c1b1 | ||
| 
						 | 
					edbde96487 | ||
| 
						 | 
					2f380f0c41 | ||
| 
						 | 
					bc76319f28 | ||
| 
						 | 
					5c2313d622 | ||
| 
						 | 
					aa638475e9 | ||
| 
						 | 
					4af334f2ad | ||
| 
						 | 
					21ab56ff78 | ||
| 
						 | 
					09c4c40d4d | ||
| 
						 | 
					2cb1b84204 | ||
| 
						 | 
					d1ef8f5eb3 | ||
| 
						 | 
					39efed1710 | ||
| 
						 | 
					9a895763d5 | ||
| 
						 | 
					3950f3c869 | ||
| 
						 | 
					7347cbaedf | ||
| 
						 | 
					ba2994210c | ||
| 
						 | 
					f1a4b363c6 | ||
| 
						 | 
					a78b5b7b2a | ||
| 
						 | 
					e104f0cce5 | ||
| 
						 | 
					5d6f76d11a | ||
| 
						 | 
					99d1760b98 | ||
| 
						 | 
					4d71cfa90a | ||
| 
						 | 
					e02f692359 | ||
| 
						 | 
					9a7e66826c | ||
| 
						 | 
					77ec8d1c9a | ||
| 
						 | 
					66ce21ec29 | ||
| 
						 | 
					27e0937235 | ||
| 
						 | 
					aadb7a41cb | ||
| 
						 | 
					9b3767a954 | ||
| 
						 | 
					67e20711d4 | ||
| 
						 | 
					d1681dc18c | ||
| 
						 | 
					0c58ba5057 | ||
| 
						 | 
					34997ef3e1 | ||
| 
						 | 
					7d57725490 | ||
| 
						 | 
					0fa0070062 | ||
| 
						 | 
					851dc54b49 | ||
| 
						 | 
					9f2fe90e50 | ||
| 
						 | 
					cf2c4e02c6 | ||
| 
						 | 
					d351c59b38 | ||
| 
						 | 
					8837119aad | ||
| 
						 | 
					f9a9431958 | ||
| 
						 | 
					56d209cd20 | ||
| 
						 | 
					0936aaccea | ||
| 
						 | 
					89c1e4f91d | ||
| 
						 | 
					88b5715eae | ||
| 
						 | 
					5b05d4a123 | ||
| 
						 | 
					893ef39401 | ||
| 
						 | 
					890ad682d7 | ||
| 
						 | 
					5d367b7bf8 | ||
| 
						 | 
					b9f45057b8 | ||
| 
						 | 
					89008c28df | ||
| 
						 | 
					af7d0a3409 | ||
| 
						 | 
					1cd2eef899 | ||
| 
						 | 
					8c7b93ec4f | ||
| 
						 | 
					3f7bf545b5 | ||
| 
						 | 
					138842e9ba | ||
| 
						 | 
					07f3517b6f | ||
| 
						 | 
					1a8e2b3e63 | ||
| 
						 | 
					e57682aa53 | ||
| 
						 | 
					46287da60e | ||
| 
						 | 
					0cecbec3b3 | ||
| 
						 | 
					515657616a | ||
| 
						 | 
					be7766b5f0 | ||
| 
						 | 
					168d49fe0b | ||
| 
						 | 
					cbedec7ca6 | ||
| 
						 | 
					fb1bac2114 | ||
| 
						 | 
					d0f399a66a | ||
| 
						 | 
					e73dbd470a | ||
| 
						 | 
					e0cd5381e2 | ||
| 
						 | 
					8fe07a7e6d | ||
| 
						 | 
					4a796d0e81 | ||
| 
						 | 
					aee5d417ed | ||
| 
						 | 
					250c5ba226 | ||
| 
						 | 
					b91c848962 | ||
| 
						 | 
					027cd821a2 | ||
| 
						 | 
					e3e9fe5106 | ||
| 
						 | 
					26b0dc336a | ||
| 
						 | 
					d4475d0e8d | ||
| 
						 | 
					1c935819db | ||
| 
						 | 
					0c9398776a | ||
| 
						 | 
					aff54ab5fe | ||
| 
						 | 
					06177addf5 | ||
| 
						 | 
					9f3b91fe57 | ||
| 
						 | 
					80d25863db | ||
| 
						 | 
					cf8a7f8678 | ||
| 
						 | 
					a8d798c38a | ||
| 
						 | 
					975b84a394 | ||
| 
						 | 
					ef121fa664 | ||
| 
						 | 
					f4c1816084 | ||
| 
						 | 
					86fc709b03 | ||
| 
						 | 
					afc4f9552f | ||
| 
						 | 
					b8b58cb202 | ||
| 
						 | 
					96970ff951 | ||
| 
						 | 
					c2c0a03932 | ||
| 
						 | 
					9bc2d2981b | ||
| 
						 | 
					7cc9d17424 | ||
| 
						 | 
					bc8b5f1079 | ||
| 
						 | 
					5ec5e1a65d | ||
| 
						 | 
					1f0e742710 | ||
| 
						 | 
					801615f780 | ||
| 
						 | 
					28b9fbb4d2 | ||
| 
						 | 
					d51b77f42b | ||
| 
						 | 
					6f83ed3285 | ||
| 
						 | 
					369e4be31c | ||
| 
						 | 
					5c9fe22780 | ||
| 
						 | 
					a2843b599d | ||
| 
						 | 
					55ba098e50 | ||
| 
						 | 
					1fdd81b4fa | ||
| 
						 | 
					d4af02f600 | ||
| 
						 | 
					d7cf341eb3 | ||
| 
						 | 
					079e6f7c20 | ||
| 
						 | 
					8a930bd7d5 | ||
| 
						 | 
					2c79dc906e | ||
| 
						 | 
					1852017ecc | ||
| 
						 | 
					ca301891db | ||
| 
						 | 
					ce7536df9f | ||
| 
						 | 
					424d11896a | ||
| 
						 | 
					ae707d340b | ||
| 
						 | 
					edefee46b2 | ||
| 
						 | 
					77ac99a1d0 | ||
| 
						 | 
					918708a227 | ||
| 
						 | 
					3ba8cf4102 | ||
| 
						 | 
					73db68b08b | ||
| 
						 | 
					ecc4aa5571 | ||
| 
						 | 
					a1a13708be | ||
| 
						 | 
					c7c3da2038 | ||
| 
						 | 
					eb9f3d3772 | ||
| 
						 | 
					1a61790407 | ||
| 
						 | 
					fe98fba5b5 | ||
| 
						 | 
					ff3ad74fb4 | ||
| 
						 | 
					7cf93278d3 | ||
| 
						 | 
					1d9f2d2ce7 | ||
| 
						 | 
					f109bd4a02 | ||
| 
						 | 
					aeebf7fa95 | ||
| 
						 | 
					c57ab693e4 | ||
| 
						 | 
					af54608f62 | ||
| 
						 | 
					f2d502faf8 | ||
| 
						 | 
					6c1e146bc1 | ||
| 
						 | 
					15d5eb858c | ||
| 
						 | 
					ac1d7aa69f | ||
| 
						 | 
					da4077f3b7 | ||
| 
						 | 
					25f9f72366 | ||
| 
						 | 
					7f04327625 | ||
| 
						 | 
					dd25573ebc | ||
| 
						 | 
					d9e54388e7 | ||
| 
						 | 
					0b07780619 | ||
| 
						 | 
					48cb0a1bb1 | ||
| 
						 | 
					84f00e7cad | ||
| 
						 | 
					a46a7458e1 | ||
| 
						 | 
					c33aa5c969 | ||
| 
						 | 
					0ee5fd1ac0 | ||
| 
						 | 
					4eb8809a8a | ||
| 
						 | 
					9315417935 | ||
| 
						 | 
					1bb1b3886b | ||
| 
						 | 
					9cd4f0c332 | ||
| 
						 | 
					0d8510b8b3 | ||
| 
						 | 
					6b57a8161c | ||
| 
						 | 
					0a893d196e | ||
| 
						 | 
					a0a09c23da | ||
| 
						 | 
					1270b6717f | ||
| 
						 | 
					d1f8b2ed17 | ||
| 
						 | 
					765deae84d | ||
| 
						 | 
					686068c8ed | ||
| 
						 | 
					ec45cf04af | ||
| 
						 | 
					b9931cda30 | ||
| 
						 | 
					8a97d2717b | ||
| 
						 | 
					b80f733cdb | ||
| 
						 | 
					c6b0e61f44 | ||
| 
						 | 
					b2a927cc5e | ||
| 
						 | 
					b73324e800 | ||
| 
						 | 
					23cbed3aac | ||
| 
						 | 
					2bd6ad9963 | ||
| 
						 | 
					ea3d66fda3 | ||
| 
						 | 
					8acce4a7fc | ||
| 
						 | 
					181eaefea8 | ||
| 
						 | 
					5e73b88a8a | ||
| 
						 | 
					5e6d0b79e3 | ||
| 
						 | 
					bf362b9aba | ||
| 
						 | 
					6b0d9214a9 | ||
| 
						 | 
					9b57c67d3e | ||
| 
						 | 
					7545323eba | ||
| 
						 | 
					5eff9a50b6 | ||
| 
						 | 
					7dc33c9247 | ||
| 
						 | 
					6f48fc3c58 | ||
| 
						 | 
					8558954da7 | ||
| 
						 | 
					2ae41df23b | ||
| 
						 | 
					47b8daf69c | ||
| 
						 | 
					ef31a0de42 | ||
| 
						 | 
					8c956d681b | ||
| 
						 | 
					89eb44afbc | ||
| 
						 | 
					9d7e32fb07 | ||
| 
						 | 
					abb88d622a | ||
| 
						 | 
					1ccdd75019 | ||
| 
						 | 
					aaedafff52 | ||
| 
						 | 
					3ccf5c0e50 | ||
| 
						 | 
					f25a9832b8 | ||
| 
						 | 
					11d5e2cdbb | ||
| 
						 | 
					15f7a7db65 | ||
| 
						 | 
					aec194ba61 | ||
| 
						 | 
					63eb145772 | ||
| 
						 | 
					db5fea922f | ||
| 
						 | 
					0214d93299 | ||
| 
						 | 
					1124a203cc | ||
| 
						 | 
					e8fbf5fdbd | ||
| 
						 | 
					8fd4ae1282 | ||
| 
						 | 
					eab1b450d5 | ||
| 
						 | 
					98fc30786e | ||
| 
						 | 
					4cb8e239ae | ||
| 
						 | 
					ea781293df | ||
| 
						 | 
					0a2979360e | ||
| 
						 | 
					0c75048e70 | ||
| 
						 | 
					a07c004983 | ||
| 
						 | 
					1018a0eda6 | ||
| 
						 | 
					d1e4898924 | ||
| 
						 | 
					a46c4bf04e | ||
| 
						 | 
					d40667a798 | ||
| 
						 | 
					0eca9e7401 | ||
| 
						 | 
					b76af31155 | ||
| 
						 | 
					426aeb0a7f | ||
| 
						 | 
					8a222df60e | ||
| 
						 | 
					4c79fcb6ed | ||
| 
						 | 
					b27e55f4de | ||
| 
						 | 
					a246cd044e | ||
| 
						 | 
					880101f338 | ||
| 
						 | 
					a2d0ff1328 | ||
| 
						 | 
					5479b4db2b | ||
| 
						 | 
					da0c86dd54 | ||
| 
						 | 
					e9f29cd147 | ||
| 
						 | 
					263448faa2 | ||
| 
						 | 
					34396de03a | ||
| 
						 | 
					f6fa17a3a8 | ||
| 
						 | 
					1dceadba4c | ||
| 
						 | 
					666c80877c | ||
| 
						 | 
					4cb9aab9ce | ||
| 
						 | 
					51593aafb2 | ||
| 
						 | 
					5ced7e05f5 | ||
| 
						 | 
					b97a662f2e | ||
| 
						 | 
					9639c096ba | ||
| 
						 | 
					e4af41e89a | ||
| 
						 | 
					52e1717014 | ||
| 
						 | 
					0ced5d2eaa | ||
| 
						 | 
					ab8111bdeb | ||
| 
						 | 
					8dc23ea1ce | ||
| 
						 | 
					8a2e3d13f2 | ||
| 
						 | 
					a29a0648ad | ||
| 
						 | 
					63d471ec94 | ||
| 
						 | 
					9fa3eac3aa | ||
| 
						 | 
					a3ba78d7bd | ||
| 
						 | 
					4b07be6bfd | ||
| 
						 | 
					e320c50e49 | ||
| 
						 | 
					524ad4e6dd | ||
| 
						 | 
					e515d6f776 | ||
| 
						 | 
					c137965dec | ||
| 
						 | 
					a9e68e13a8 | ||
| 
						 | 
					77fffda10e | ||
| 
						 | 
					88fe5c641f | ||
| 
						 | 
					da0309eb09 | ||
| 
						 | 
					4e6f47d50a | ||
| 
						 | 
					7e626ea219 | ||
| 
						 | 
					8a6ccabffb | ||
| 
						 | 
					f546ba85aa | ||
| 
						 | 
					73e1d3b046 | ||
| 
						 | 
					b2c8062131 | ||
| 
						 | 
					6805a96e53 | ||
| 
						 | 
					a92667c000 | ||
| 
						 | 
					4a0619cadb | ||
| 
						 | 
					a7e16d582d | ||
| 
						 | 
					b3a4da5e4d | ||
| 
						 | 
					5ea298a238 | ||
| 
						 | 
					859c0915fb | ||
| 
						 | 
					45fd96cd0d | ||
| 
						 | 
					ffe2b3c24d | ||
| 
						 | 
					b5b8d941f3 | ||
| 
						 | 
					970561b956 | ||
| 
						 | 
					9c3b53b701 | ||
| 
						 | 
					6a69be88c5 | ||
| 
						 | 
					3a918ae8f6 | ||
| 
						 | 
					f668089e64 | ||
| 
						 | 
					af6a08398e | ||
| 
						 | 
					4d7def4311 | ||
| 
						 | 
					ae960f5220 | ||
| 
						 | 
					5be9ce1823 | ||
| 
						 | 
					5693bbe1f5 | ||
| 
						 | 
					e4267c5c56 | ||
| 
						 | 
					99dfd42372 | ||
| 
						 | 
					8d36924cb6 | ||
| 
						 | 
					80d1e28d0f | ||
| 
						 | 
					60132e9947 | ||
| 
						 | 
					940b996e2d | ||
| 
						 | 
					0055f479cb | ||
| 
						 | 
					1c41b701dd | ||
| 
						 | 
					e1e26d53e6 | ||
| 
						 | 
					f9131832c7 | ||
| 
						 | 
					ce14b5e9fb | ||
| 
						 | 
					c40aa1f950 | ||
| 
						 | 
					7d1d3d3f05 | ||
| 
						 | 
					5e6a895fef | ||
| 
						 | 
					d2fe2a7fc5 | ||
| 
						 | 
					44a8025e0f | ||
| 
						 | 
					71e392c1f9 | ||
| 
						 | 
					416088a2de | ||
| 
						 | 
					e57d11d55a | ||
| 
						 | 
					781ae8d5c8 | ||
| 
						 | 
					b01d45cf5c | ||
| 
						 | 
					4941aaa5c1 | ||
| 
						 | 
					07559a5aaa | ||
| 
						 | 
					92f030887b | ||
| 
						 | 
					9476f7f616 | ||
| 
						 | 
					cbe405f6ea | ||
| 
						 | 
					e18cf51c01 | ||
| 
						 | 
					f32813951f | ||
| 
						 | 
					7ba8fc256b | ||
| 
						 | 
					c7972aa5e6 | ||
| 
						 | 
					eaef38f79c | ||
| 
						 | 
					7414bc492e | ||
| 
						 | 
					6f14087a16 | ||
| 
						 | 
					0700c60636 | ||
| 
						 | 
					aac6e0521a | ||
| 
						 | 
					7e25a80c5b | ||
| 
						 | 
					328d4b916d | ||
| 
						 | 
					596ff28207 | ||
| 
						 | 
					70c1a37bbd | ||
| 
						 | 
					4902276921 | ||
| 
						 | 
					83cdeacaa8 | ||
| 
						 | 
					e6e2f48f7e | ||
| 
						 | 
					e316f613d0 | ||
| 
						 | 
					9a8c87a43e | ||
| 
						 | 
					67140f996b | ||
| 
						 | 
					2f5d9ced6d | ||
| 
						 | 
					3dfb116fdd | ||
| 
						 | 
					eb1047a149 | ||
| 
						 | 
					b42a8176ca | ||
| 
						 | 
					2a9beec31d | ||
| 
						 | 
					910fe6261b | ||
| 
						 | 
					0c820b96d8 | ||
| 
						 | 
					9689efedc4 | ||
| 
						 | 
					97561f428e | ||
| 
						 | 
					df0497fb58 | ||
| 
						 | 
					30f0bdc754 | ||
| 
						 | 
					c3c49a05c2 | ||
| 
						 | 
					e72b878380 | ||
| 
						 | 
					d51d8ad877 | ||
| 
						 | 
					68a616d7c7 | ||
| 
						 | 
					a0447de061 | ||
| 
						 | 
					46db06a22b | ||
| 
						 | 
					7984fdfd20 | ||
| 
						 | 
					d637f03067 | ||
| 
						 | 
					4c57c2a044 | ||
| 
						 | 
					94b09c3fc0 | ||
| 
						 | 
					de5ae4a05e | ||
| 
						 | 
					517c5705b6 | ||
| 
						 | 
					5d3e977761 | ||
| 
						 | 
					c0d430f4e5 | ||
| 
						 | 
					d910888181 | ||
| 
						 | 
					db2dfee6ae | ||
| 
						 | 
					d311d56bbf | ||
| 
						 | 
					a33898c2a0 | ||
| 
						 | 
					e6940d48e3 | ||
| 
						 | 
					3bc5ef38d3 | ||
| 
						 | 
					bac3b3a0dc | ||
| 
						 | 
					07fded4da9 | ||
| 
						 | 
					4f0a584efc | ||
| 
						 | 
					1139fb39c5 | ||
| 
						 | 
					4cd7c07344 | ||
| 
						 | 
					a854e0ca8e | ||
| 
						 | 
					de1766abde | ||
| 
						 | 
					ebd005e1b1 | ||
| 
						 | 
					9ba61037a4 | ||
| 
						 | 
					c74b878372 | ||
| 
						 | 
					01a566c794 | ||
| 
						 | 
					5362a633e6 | ||
| 
						 | 
					b2c3f45141 | ||
| 
						 | 
					d5f9b5b74a | ||
| 
						 | 
					95a2c74462 | ||
| 
						 | 
					d217ef37bf | ||
| 
						 | 
					95bea7f64a | ||
| 
						 | 
					58b63a24c2 | ||
| 
						 | 
					53c90cfc99 | ||
| 
						 | 
					2043d1f439 | ||
| 
						 | 
					61034d4dde | ||
| 
						 | 
					6605bf35a8 | ||
| 
						 | 
					b2b93e5060 | ||
| 
						 | 
					098286fcaf | ||
| 
						 | 
					a6f30412ad | ||
| 
						 | 
					b624648115 | ||
| 
						 | 
					9d1d74c022 | ||
| 
						 | 
					0c79d1a619 | ||
| 
						 | 
					1ea8eebfec | ||
| 
						 | 
					1dcc03aae0 | ||
| 
						 | 
					3be9535225 | ||
| 
						 | 
					8cad83a9dc | ||
| 
						 | 
					0488495a34 | ||
| 
						 | 
					a5eb8ce21e | ||
| 
						 | 
					1dbcd4ee6e | ||
| 
						 | 
					7e1f024d28 | ||
| 
						 | 
					4a353896e3 | ||
| 
						 | 
					eaa12de740 | ||
| 
						 | 
					0e4372b4a3 | ||
| 
						 | 
					b0c31ae486 | ||
| 
						 | 
					a43e4b8aa7 | ||
| 
						 | 
					ce3f80144a | ||
| 
						 | 
					cd33cd66ae | ||
| 
						 | 
					f2a2c2d407 | ||
| 
						 | 
					5f0481c067 | ||
| 
						 | 
					f30f3ac37b | ||
| 
						 | 
					d31ed1f2e1 | ||
| 
						 | 
					cf67d606ae | ||
| 
						 | 
					76b859f6ba | ||
| 
						 | 
					a326e301f0 | ||
| 
						 | 
					a16ae7dadc | ||
| 
						 | 
					ac47375aba | ||
| 
						 | 
					857054179c | ||
| 
						 | 
					fd5a87eedf | ||
| 
						 | 
					4770b0d3e3 | ||
| 
						 | 
					181ec4633b | ||
| 
						 | 
					dc5e5c6c08 | ||
| 
						 | 
					dcdf423d66 | ||
| 
						 | 
					1a19c3b3a5 | ||
| 
						 | 
					0a3fcfd9f4 | ||
| 
						 | 
					49ac180329 | ||
| 
						 | 
					0271aa5414 | ||
| 
						 | 
					880b3290e8 | ||
| 
						 | 
					a0364f0758 | ||
| 
						 | 
					ed693e89c9 | ||
| 
						 | 
					526957e0ac | ||
| 
						 | 
					3341eb5f2c | ||
| 
						 | 
					51fba42b83 | ||
| 
						 | 
					12f5327e0e | ||
| 
						 | 
					40f9fac1a5 | ||
| 
						 | 
					0b5e924a21 | ||
| 
						 | 
					cd312f1348 | ||
| 
						 | 
					e480f616e0 | ||
| 
						 | 
					2285a94958 | ||
| 
						 | 
					7f1356a447 | ||
| 
						 | 
					420a43cdd5 | ||
| 
						 | 
					1aab88859d | ||
| 
						 | 
					3210fce113 | ||
| 
						 | 
					0a1b026d92 | ||
| 
						 | 
					29e1bf3f2e | ||
| 
						 | 
					333a38978e | ||
| 
						 | 
					91c7b46d52 | ||
| 
						 | 
					870d51bf10 | ||
| 
						 | 
					7c0f41c785 | ||
| 
						 | 
					647d3391bb | ||
| 
						 | 
					0d24f34d83 | ||
| 
						 | 
					a68a32d9b6 | ||
| 
						 | 
					8a89054c2f | ||
| 
						 | 
					cd46d08afd | ||
| 
						 | 
					5e8ccda522 | ||
| 
						 | 
					78d0e67987 | ||
| 
						 | 
					62fc38078c | ||
| 
						 | 
					bc4f844cd8 | ||
| 
						 | 
					d73cd5ed27 | ||
| 
						 | 
					2bf3d3a9c5 | ||
| 
						 | 
					e3b64387a5 | ||
| 
						 | 
					bd0454309f | ||
| 
						 | 
					a72fa8038f | ||
| 
						 | 
					f15f8e3295 | ||
| 
						 | 
					604c671d41 | ||
| 
						 | 
					6130bebbb3 | ||
| 
						 | 
					9f944c043f | ||
| 
						 | 
					092b3214c5 | ||
| 
						 | 
					07dfef48be | ||
| 
						 | 
					e9571fc2e2 | ||
| 
						 | 
					db3a83d163 | ||
| 
						 | 
					22f7ccc11d | ||
| 
						 | 
					ea53b3faba | ||
| 
						 | 
					645ccb2f87 | ||
| 
						 | 
					b40cc02e2a | ||
| 
						 | 
					98418272ab | ||
| 
						 | 
					a32cc879cc | ||
| 
						 | 
					adf329cf1a | ||
| 
						 | 
					4bd5009ec1 | ||
| 
						 | 
					74a9b4c058 | ||
| 
						 | 
					8ee749f137 | ||
| 
						 | 
					46fa404d83 | ||
| 
						 | 
					cb8f5de5af | ||
| 
						 | 
					3c7c5380f4 | ||
| 
						 | 
					04d611e1c2 | ||
| 
						 | 
					2d813b2191 | ||
| 
						 | 
					f1bf549e0f | ||
| 
						 | 
					d3a3ad5cbd | ||
| 
						 | 
					8091a46005 | ||
| 
						 | 
					18cffc4678 | ||
| 
						 | 
					c1d01fb1e1 | ||
| 
						 | 
					4d0c84bcf5 | ||
| 
						 | 
					8db5c27d81 | ||
| 
						 | 
					2ff36d81a1 | ||
| 
						 | 
					56feff0455 | ||
| 
						 | 
					cf17bcb15c | ||
| 
						 | 
					b2d3abd9d6 | ||
| 
						 | 
					a54cb7d3e4 | ||
| 
						 | 
					00549c267f | ||
| 
						 | 
					f41bfdb8eb | ||
| 
						 | 
					ca085b9aaa | ||
| 
						 | 
					42df37bb21 | ||
| 
						 | 
					c23c986543 | ||
| 
						 | 
					2190d87dc9 | ||
| 
						 | 
					eefdba947c | ||
| 
						 | 
					b9afd55856 | ||
| 
						 | 
					147eb7a9e5 | ||
| 
						 | 
					81ab861036 | ||
| 
						 | 
					e6014dd0e9 | ||
| 
						 | 
					ac030b7275 | ||
| 
						 | 
					9370747479 | ||
| 
						 | 
					45efd9290e | ||
| 
						 | 
					96edba7eec | ||
| 
						 | 
					6751b97db9 | ||
| 
						 | 
					927b05713a | ||
| 
						 | 
					8f23ff7274 | ||
| 
						 | 
					158e883e47 | ||
| 
						 | 
					7faa364c53 | ||
| 
						 | 
					e62e8e372c | ||
| 
						 | 
					568e2a9337 | ||
| 
						 | 
					77756eb08d | ||
| 
						 | 
					8b097af195 | ||
| 
						 | 
					81ff77c2d5 | ||
| 
						 | 
					bb65cd1976 | ||
| 
						 | 
					1086c00929 | ||
| 
						 | 
					9aaa9ce8aa | ||
| 
						 | 
					cb5a6d29e2 | ||
| 
						 | 
					4d8bd8805b | ||
| 
						 | 
					d9b9f0b3d3 | ||
| 
						 | 
					c8c57b545a | ||
| 
						 | 
					d0f7a317e4 | ||
| 
						 | 
					3517a8f494 | ||
| 
						 | 
					aa9ed2e863 | ||
| 
						 | 
					075f7fc19e | ||
| 
						 | 
					ea7ea2ec59 | ||
| 
						 | 
					64b183da36 | ||
| 
						 | 
					54c6c4e547 | ||
| 
						 | 
					986b48cf36 | ||
| 
						 | 
					3bb9b03add | ||
| 
						 | 
					f05aa674ab | ||
| 
						 | 
					965bdc9986 | ||
| 
						 | 
					edce19e406 | ||
| 
						 | 
					1687f20760 | ||
| 
						 | 
					2917d335bc | ||
| 
						 | 
					329c070e05 | ||
| 
						 | 
					30e90619f5 | ||
| 
						 | 
					d53dc28b83 | ||
| 
						 | 
					3446b38cbb | ||
| 
						 | 
					f3a4104fd0 | ||
| 
						 | 
					bb793d71e7 | ||
| 
						 | 
					82e8ab2385 | ||
| 
						 | 
					c9260c4966 | ||
| 
						 | 
					587fb27484 | ||
| 
						 | 
					7f305962f2 | ||
| 
						 | 
					f6edb48df9 | ||
| 
						 | 
					e793138031 | ||
| 
						 | 
					5c2992ef16 | ||
| 
						 | 
					d734bfc34f | ||
| 
						 | 
					86d5a1d190 | ||
| 
						 | 
					cb713e32d3 | ||
| 
						 | 
					84fe0737de | ||
| 
						 | 
					4ea636366d | ||
| 
						 | 
					54f5b59c8c | ||
| 
						 | 
					657b6a9fae | ||
| 
						 | 
					6c01241b96 | ||
| 
						 | 
					961073ec96 | ||
| 
						 | 
					e2b786d97b | ||
| 
						 | 
					2fbf9ab7be | ||
| 
						 | 
					68a23c4918 | ||
| 
						 | 
					b49dbcdbbe | ||
| 
						 | 
					ee2f74dc5e | ||
| 
						 | 
					81630a096f | ||
| 
						 | 
					21780d8106 | ||
| 
						 | 
					b7b4364db2 | ||
| 
						 | 
					d9859de756 | ||
| 
						 | 
					5e6fd0d1e1 | ||
| 
						 | 
					a91d7cdd72 | ||
| 
						 | 
					d00dc3b03a | ||
| 
						 | 
					f5c69bae30 | ||
| 
						 | 
					89fe17f419 | ||
| 
						 | 
					c491257359 | ||
| 
						 | 
					8a2f988be6 | ||
| 
						 | 
					83c0b70a2d | ||
| 
						 | 
					b7082c0eb4 | ||
| 
						 | 
					61e2a07ee2 | ||
| 
						 | 
					dd5e514d92 | ||
| 
						 | 
					2532e40f9c | ||
| 
						 | 
					50236ae4e5 | ||
| 
						 | 
					04c36018d6 | ||
| 
						 | 
					1273421498 | ||
| 
						 | 
					7bd34cb1da | ||
| 
						 | 
					d99dd4b875 | ||
| 
						 | 
					c99eb98001 | ||
| 
						 | 
					a29201a248 | ||
| 
						 | 
					6f0c59d7be | ||
| 
						 | 
					844e8b2f77 | ||
| 
						 | 
					5a0a9e3a1c | ||
| 
						 | 
					a6ed5667ab | ||
| 
						 | 
					53da7140c2 | ||
| 
						 | 
					eb87229ee9 | ||
| 
						 | 
					0b852faf00 | ||
| 
						 | 
					ce9e033551 | ||
| 
						 | 
					eefe3a9c6e | ||
| 
						 | 
					06535c8eac | ||
| 
						 | 
					651867055c | ||
| 
						 | 
					8c7e49dd54 | ||
| 
						 | 
					612c4293d1 | ||
| 
						 | 
					8007b22b85 | ||
| 
						 | 
					35664d818d | ||
| 
						 | 
					aa9f2c9a3c | ||
| 
						 | 
					5764befa46 | ||
| 
						 | 
					29462b83ff | ||
| 
						 | 
					129a49a60b | ||
| 
						 | 
					0da30f4623 | ||
| 
						 | 
					69bcebdf86 | ||
| 
						 | 
					c0d749b1e2 | ||
| 
						 | 
					e6bcced213 | ||
| 
						 | 
					3706d2e1db | ||
| 
						 | 
					03bda9422d | ||
| 
						 | 
					f89b4e9336 | ||
| 
						 | 
					cd510b43b1 | ||
| 
						 | 
					0c8f727bd8 | ||
| 
						 | 
					ad18449753 | ||
| 
						 | 
					1fe08f49c7 | ||
| 
						 | 
					48b007543a | ||
| 
						 | 
					d52ece745e | ||
| 
						 | 
					0f75f789d8 | ||
| 
						 | 
					bc9098bc22 | ||
| 
						 | 
					76f1650109 | ||
| 
						 | 
					c636e6909b | ||
| 
						 | 
					b5b1b94a9d | ||
| 
						 | 
					b87aeb9b95 | ||
| 
						 | 
					5f0e4e81f0 | ||
| 
						 | 
					7306feb6ef | ||
| 
						 | 
					dccb3ac6c6 | ||
| 
						 | 
					89cd2106ed | ||
| 
						 | 
					74f991b8c5 | ||
| 
						 | 
					dcf79d9119 | ||
| 
						 | 
					911867d5a5 | ||
| 
						 | 
					3600875707 | ||
| 
						 | 
					8052d75957 | ||
| 
						 | 
					cc2624d08e | ||
| 
						 | 
					e72cfff7bb | ||
| 
						 | 
					a43e6e06e0 | ||
| 
						 | 
					dc0af0a419 | ||
| 
						 | 
					868942e202 | ||
| 
						 | 
					3fef2b68dc | ||
| 
						 | 
					404cb4c7a6 | ||
| 
						 | 
					a966b95a5b | ||
| 
						 | 
					15f05b602f | ||
| 
						 | 
					9e51d3f250 | ||
| 
						 | 
					d7ca248bc8 | ||
| 
						 | 
					3980b2f2ff | ||
| 
						 | 
					bed9fcea46 | ||
| 
						 | 
					b1b82857ba | ||
| 
						 | 
					0b09272a60 | ||
| 
						 | 
					f9129bd54e | ||
| 
						 | 
					c0f3dff0f6 | ||
| 
						 | 
					6ca8535166 | ||
| 
						 | 
					ff4a429136 | ||
| 
						 | 
					9a5cea2b23 | ||
| 
						 | 
					cd1a68f15e | ||
| 
						 | 
					a0bed51d96 | ||
| 
						 | 
					857dec38d1 | ||
| 
						 | 
					8f6484e470 | ||
| 
						 | 
					5413b37d71 | ||
| 
						 | 
					869dcf73f8 | ||
| 
						 | 
					96a34d1ad7 | ||
| 
						 | 
					26fc652d33 | ||
| 
						 | 
					766361ac83 | ||
| 
						 | 
					fc8c96399f | ||
| 
						 | 
					9bad713db5 | ||
| 
						 | 
					6f222ab02b | ||
| 
						 | 
					9bd7509e87 | ||
| 
						 | 
					e47596383a | ||
| 
						 | 
					7487c92a52 | ||
| 
						 | 
					29cc9da934 | ||
| 
						 | 
					eaeb324c74 | ||
| 
						 | 
					9f7acd4cf9 | ||
| 
						 | 
					d9a0de20f8 | ||
| 
						 | 
					eb11337f7d | ||
| 
						 | 
					d2872539e3 | ||
| 
						 | 
					1a5b024df6 | ||
| 
						 | 
					578d65dfb4 | ||
| 
						 | 
					db4c2d3dd5 | ||
| 
						 | 
					47842a1611 | ||
| 
						 | 
					f4f4cd9b1f | ||
| 
						 | 
					b7452cc281 | ||
| 
						 | 
					92653f3deb | ||
| 
						 | 
					c526ab1870 | ||
| 
						 | 
					1c7d840ff6 | ||
| 
						 | 
					8ba91fc9dd | ||
| 
						 | 
					09b03465d8 | ||
| 
						 | 
					c8d9b3f8fc | ||
| 
						 | 
					c9d19cbe56 | ||
| 
						 | 
					10ae0bce65 | ||
| 
						 | 
					7bc15245aa | ||
| 
						 | 
					cb6228800b | ||
| 
						 | 
					6ef899d000 | ||
| 
						 | 
					6353f4ff09 | ||
| 
						 | 
					fb673107f3 | ||
| 
						 | 
					bb1af390a7 | ||
| 
						 | 
					f65cd6245d | ||
| 
						 | 
					530b2a51d5 | ||
| 
						 | 
					d51e7cbb51 | ||
| 
						 | 
					f244fe1855 | ||
| 
						 | 
					293db76bd6 | ||
| 
						 | 
					5b257b2b57 | ||
| 
						 | 
					4e04f5e967 | ||
| 
						 | 
					29f0ded88b | ||
| 
						 | 
					6c4882b907 | ||
| 
						 | 
					45e6accd2a | ||
| 
						 | 
					51b19fcff4 | ||
| 
						 | 
					c4cfaab621 | ||
| 
						 | 
					8bf27bf76b | ||
| 
						 | 
					ccb132374b | ||
| 
						 | 
					c82afc8c46 | ||
| 
						 | 
					08e0ed4fc6 | ||
| 
						 | 
					261d9f8ebc | ||
| 
						 | 
					948ad86049 | ||
| 
						 | 
					ed659da488 | ||
| 
						 | 
					1294f68265 | ||
| 
						 | 
					0e771a6c1b | ||
| 
						 | 
					a8227453fc | ||
| 
						 | 
					225eda7176 | ||
| 
						 | 
					dd37247e65 | ||
| 
						 | 
					295cd3670f | ||
| 
						 | 
					e4df0c6da1 | ||
| 
						 | 
					2a421deaa3 | ||
| 
						 | 
					7b23b6db6f | ||
| 
						 | 
					5ca038d888 | ||
| 
						 | 
					caf93da26a | ||
| 
						 | 
					3454e34c7c | ||
| 
						 | 
					619a80228f | ||
| 
						 | 
					89de1beb6f | ||
| 
						 | 
					b6442b4640 | ||
| 
						 | 
					be412faf6c | ||
| 
						 | 
					fd3a699ad8 | ||
| 
						 | 
					4c99cea3e4 | ||
| 
						 | 
					1d54ef57c7 | ||
| 
						 | 
					673b225da2 | ||
| 
						 | 
					c3fe137720 | ||
| 
						 | 
					c28aa299bd | ||
| 
						 | 
					b2189ae965 | ||
| 
						 | 
					a3504dac6e | ||
| 
						 | 
					a028b566ed | ||
| 
						 | 
					ca2405c104 | ||
| 
						 | 
					08f4ae04e1 | ||
| 
						 | 
					83d69ba507 | ||
| 
						 | 
					63cb34b563 | ||
| 
						 | 
					271e42176c | ||
| 
						 | 
					e5647793ce | ||
| 
						 | 
					b87e45ce32 | ||
| 
						 | 
					903b5aebca | ||
| 
						 | 
					7492dcc9e6 | ||
| 
						 | 
					5d2b162bea | ||
| 
						 | 
					3fce90dbb9 | ||
| 
						 | 
					d40b9324ca | ||
| 
						 | 
					6875935d37 | ||
| 
						 | 
					8978012f9d | ||
| 
						 | 
					7cf4a5da87 | ||
| 
						 | 
					47b67331d4 | ||
| 
						 | 
					6e14601c7c | ||
| 
						 | 
					3546ac2854 | ||
| 
						 | 
					d600cdd8a0 | ||
| 
						 | 
					d2c6e27d07 | ||
| 
						 | 
					8041ced02d | ||
| 
						 | 
					d81056cbe7 | ||
| 
						 | 
					44e8a012e2 | ||
| 
						 | 
					30483dacfb | ||
| 
						 | 
					9d81d95700 | ||
| 
						 | 
					e6b45d4cdb | ||
| 
						 | 
					c2e28b5d94 | ||
| 
						 | 
					fef7ead0d5 | ||
| 
						 | 
					06aef0587a | ||
| 
						 | 
					bf7c259cdd | ||
| 
						 | 
					43d76e5990 | ||
| 
						 | 
					ffde310d30 | ||
| 
						 | 
					44bc7dd9a5 | ||
| 
						 | 
					9e5b64e1b7 | ||
| 
						 | 
					2599073f56 | ||
| 
						 | 
					a2d49f9981 | ||
| 
						 | 
					877a9d510b | ||
| 
						 | 
					2455d0b859 | ||
| 
						 | 
					b3c3afc2b4 | ||
| 
						 | 
					3f97d19381 | ||
| 
						 | 
					3ab3d49055 | ||
| 
						 | 
					bd89cc0287 | ||
| 
						 | 
					d365a52cd6 | ||
| 
						 | 
					5e38e054a7 | ||
| 
						 | 
					317f6d5c87 | ||
| 
						 | 
					c876776a25 | ||
| 
						 | 
					e1c7115d8c | ||
| 
						 | 
					bb4d75aff0 | ||
| 
						 | 
					c5dbd04c9c | ||
| 
						 | 
					2a8a72a085 | ||
| 
						 | 
					29c46a15f9 | ||
| 
						 | 
					aae3fe5305 | ||
| 
						 | 
					2743785aaf | ||
| 
						 | 
					abc378c727 | ||
| 
						 | 
					79fc16eeb7 | ||
| 
						 | 
					2a235917dc | ||
| 
						 | 
					c9e9341b4a | ||
| 
						 | 
					da247c61b7 | ||
| 
						 | 
					2cd2e6dd19 | ||
| 
						 | 
					e442bce607 | ||
| 
						 | 
					f7664a2d7e | ||
| 
						 | 
					8a5c8d0db5 | ||
| 
						 | 
					bcd5b713f8 | ||
| 
						 | 
					a9488ba3c9 | ||
| 
						 | 
					be13e3494a | ||
| 
						 | 
					a62d65a9b8 | ||
| 
						 | 
					44ce6774dc | ||
| 
						 | 
					b911d7f78f | ||
| 
						 | 
					4644176e26 | ||
| 
						 | 
					df6759b033 | ||
| 
						 | 
					bf8bac2bcc | ||
| 
						 | 
					37def02ee1 | ||
| 
						 | 
					09dfb25d73 | ||
| 
						 | 
					850b98337b | ||
| 
						 | 
					7f2921f26b | ||
| 
						 | 
					836017f2b9 | ||
| 
						 | 
					ed22f395ba | ||
| 
						 | 
					bcbc7c1d47 | ||
| 
						 | 
					1445d6d24a | ||
| 
						 | 
					4de4763baf | ||
| 
						 | 
					8362fe1b39 | ||
| 
						 | 
					258dc16cfd | ||
| 
						 | 
					8f8e796c77 | ||
| 
						 | 
					a39a98cda9 | ||
| 
						 | 
					90ba39593a | ||
| 
						 | 
					c3061a19a2 | ||
| 
						 | 
					e11a6163dd | ||
| 
						 | 
					1b752c35cc | ||
| 
						 | 
					8b9d3541dd | ||
| 
						 | 
					dff7d70f0a | ||
| 
						 | 
					e763381186 | ||
| 
						 | 
					d4f49b10d7 | ||
| 
						 | 
					5ba39c0086 | ||
| 
						 | 
					b5db6fe186 | ||
| 
						 | 
					8d2886e1ca | ||
| 
						 | 
					965ebd0f03 | ||
| 
						 | 
					cb306b0793 | ||
| 
						 | 
					c5dc08e082 | ||
| 
						 | 
					b00c6dd89b | ||
| 
						 | 
					2fd28ca5c8 | ||
| 
						 | 
					14a05ddaca | ||
| 
						 | 
					209654fdff | ||
| 
						 | 
					f30aa02e7c | ||
| 
						 | 
					dd4374229b | ||
| 
						 | 
					7eedf37149 | ||
| 
						 | 
					7aea32f48b | ||
| 
						 | 
					ac38f7b909 | ||
| 
						 | 
					2c3f1c28e5 | ||
| 
						 | 
					e8ee5ad691 | ||
| 
						 | 
					5322f5f707 | ||
| 
						 | 
					408f5055a9 | ||
| 
						 | 
					6bfae2652f | ||
| 
						 | 
					9036370d67 | ||
| 
						 | 
					9bc730866f | ||
| 
						 | 
					a2d3f987c0 | ||
| 
						 | 
					5a271b8fde | ||
| 
						 | 
					f43a5cb244 | ||
| 
						 | 
					bf4ac3ad7a | ||
| 
						 | 
					4f0e73ba97 | ||
| 
						 | 
					f28a91969a | ||
| 
						 | 
					ca285f5e53 | ||
| 
						 | 
					34f2552cad | ||
| 
						 | 
					c8720b1524 | ||
| 
						 | 
					4238266ea3 | ||
| 
						 | 
					230d19a7aa | ||
| 
						 | 
					d2b7843d97 | ||
| 
						 | 
					9351d47948 | ||
| 
						 | 
					bf98ee3c93 | ||
| 
						 | 
					dbba894544 | ||
| 
						 | 
					52673152cc | ||
| 
						 | 
					42295ef2ac | ||
| 
						 | 
					a8a4f2101d | ||
| 
						 | 
					f46bd8b6ba | ||
| 
						 | 
					d4e1d4ec38 | ||
| 
						 | 
					f517dc05ef | ||
| 
						 | 
					a627de02c7 | ||
| 
						 | 
					a94a0589dd | ||
| 
						 | 
					81755a280d | ||
| 
						 | 
					89d776acb5 | ||
| 
						 | 
					daf660e66d | ||
| 
						 | 
					e4020faff3 | ||
| 
						 | 
					e11b727584 | ||
| 
						 | 
					0a36a94b73 | ||
| 
						 | 
					89e7cb19b9 | ||
| 
						 | 
					fa2bdcd5ac | ||
| 
						 | 
					ea71c9b214 | ||
| 
						 | 
					c00e397405 | ||
| 
						 | 
					a2a2640d29 | ||
| 
						 | 
					7c4a104823 | ||
| 
						 | 
					7892ec5a59 | ||
| 
						 | 
					e5fd1f76db | ||
| 
						 | 
					554ebebb92 | ||
| 
						 | 
					f604cf4988 | ||
| 
						 | 
					9de0e9157a | ||
| 
						 | 
					b1be47f0a0 | ||
| 
						 | 
					6502f21072 | ||
| 
						 | 
					a9e21702aa | ||
| 
						 | 
					48fd65d7f8 | ||
| 
						 | 
					c1b0e176e5 | ||
| 
						 | 
					e2d370bd9d | ||
| 
						 | 
					2fe8291f1d | ||
| 
						 | 
					1d1732ab4a | ||
| 
						 | 
					1010ccca4d | ||
| 
						 | 
					c21ff85b57 | ||
| 
						 | 
					c3bb4d2a61 | ||
| 
						 | 
					d2b7f8ef0f | ||
| 
						 | 
					af25588b88 | ||
| 
						 | 
					7546ef649c | ||
| 
						 | 
					2a3bf1d994 | ||
| 
						 | 
					450657f871 | ||
| 
						 | 
					664192da0b | ||
| 
						 | 
					9fc3e220a7 | ||
| 
						 | 
					64f6a69d9a | ||
| 
						 | 
					16734b1d88 | ||
| 
						 | 
					31106c91fb | ||
| 
						 | 
					026a427103 | ||
| 
						 | 
					7a4f36c00e | ||
| 
						 | 
					1f3ef4ffe1 | ||
| 
						 | 
					c364836a9d | ||
| 
						 | 
					97a12075b1 | ||
| 
						 | 
					bafb1372a7 | ||
| 
						 | 
					b4f032fab4 | ||
| 
						 | 
					d36d944b3a | ||
| 
						 | 
					7af22453ba | ||
| 
						 | 
					d0c4b5bc76 | ||
| 
						 | 
					4f194aa101 | ||
| 
						 | 
					ef4bfde4a8 | ||
| 
						 | 
					65a1245a03 | ||
| 
						 | 
					486e4f8dd3 | ||
| 
						 | 
					4cfbd8a9d2 | ||
| 
						 | 
					7ab51b8960 | ||
| 
						 | 
					18cbd96280 | ||
| 
						 | 
					2cdea69719 | ||
| 
						 | 
					6c053b6266 | ||
| 
						 | 
					20eea9914e | ||
| 
						 | 
					6d3f4f5a04 | ||
| 
						 | 
					20e782eb21 | ||
| 
						 | 
					e30fa57ab4 | ||
| 
						 | 
					ef0b07d5c4 | ||
| 
						 | 
					b9b1ec8f41 | ||
| 
						 | 
					019526fbe9 | ||
| 
						 | 
					a4cd5bd424 | ||
| 
						 | 
					421593c0ba | ||
| 
						 | 
					91ad85aec1 | ||
| 
						 | 
					d1eacc1d1c | ||
| 
						 | 
					e41dd8a0f1 | ||
| 
						 | 
					5e1d4f215d | ||
| 
						 | 
					9a7bb81cd0 | ||
| 
						 | 
					321bb010cb | ||
| 
						 | 
					e24a79f87b | ||
| 
						 | 
					2dd0add3e7 | ||
| 
						 | 
					ce279ca360 | ||
| 
						 | 
					fcf606acde | ||
| 
						 | 
					084907eeca | ||
| 
						 | 
					f8487f581b | ||
| 
						 | 
					40c9559d9e | ||
| 
						 | 
					531e0ef918 | ||
| 
						 | 
					2781655b0a | ||
| 
						 | 
					64add90edd | ||
| 
						 | 
					8de93d35ed | ||
| 
						 | 
					eb844e3260 | ||
| 
						 | 
					cedd2d1daf | ||
| 
						 | 
					81d04fb31f | ||
| 
						 | 
					caba6fb01e | ||
| 
						 | 
					1c8d44b309 | ||
| 
						 | 
					984098abce | ||
| 
						 | 
					ead6da4760 | ||
| 
						 | 
					2ab96587ef | ||
| 
						 | 
					cb9c0e79eb | ||
| 
						 | 
					96d2b2d6b8 | ||
| 
						 | 
					b699b5fef5 | ||
| 
						 | 
					b374ff4d6d | ||
| 
						 | 
					149b136e0b | ||
| 
						 | 
					5389663b72 | ||
| 
						 | 
					a610c5c8c6 | ||
| 
						 | 
					874cf18566 | ||
| 
						 | 
					53cb0826bc | ||
| 
						 | 
					6904f38ea2 | ||
| 
						 | 
					223ff4ebff | ||
| 
						 | 
					d2ec3e7d9a | ||
| 
						 | 
					b00171366f | ||
| 
						 | 
					7079a4e7e4 | ||
| 
						 | 
					4e817a1109 | ||
| 
						 | 
					d185d4e4cc | ||
| 
						 | 
					3b574875cb | ||
| 
						 | 
					4d5048435c | ||
| 
						 | 
					57df7f8dfe | ||
| 
						 | 
					74b36fbd98 | ||
| 
						 | 
					8ea56d3b22 | ||
| 
						 | 
					019f585c83 | ||
| 
						 | 
					19b7f0747a | ||
| 
						 | 
					c7c9bd6b08 | ||
| 
						 | 
					b132f04f71 | ||
| 
						 | 
					2f21f293c1 | ||
| 
						 | 
					5b3c390e08 | ||
| 
						 | 
					8a93371baa | ||
| 
						 | 
					95dcae1a85 | ||
| 
						 | 
					03e2ff587e | ||
| 
						 | 
					1ea73a67ca | ||
| 
						 | 
					1d32420a27 | ||
| 
						 | 
					53dd9a35a0 | ||
| 
						 | 
					0b35927b16 | ||
| 
						 | 
					bbbe83b737 | ||
| 
						 | 
					06f06ce390 | ||
| 
						 | 
					cc4c52c998 | ||
| 
						 | 
					bd09e5b11c | ||
| 
						 | 
					181f62c15e | ||
| 
						 | 
					1ff306ff40 | ||
| 
						 | 
					c4e17ff847 | ||
| 
						 | 
					3ae5ec92a5 | ||
| 
						 | 
					2fe919b6ce | ||
| 
						 | 
					a8ab3ffd01 | ||
| 
						 | 
					f3c9a4a81c | ||
| 
						 | 
					cd0aad10b0 | ||
| 
						 | 
					da2cb61cae | ||
| 
						 | 
					e4c691fd5f | ||
| 
						 | 
					ea2e560bd9 | ||
| 
						 | 
					25321984fa | ||
| 
						 | 
					24ebc73ee5 | ||
| 
						 | 
					f5f16aac96 | ||
| 
						 | 
					13c770b6be | ||
| 
						 | 
					d1037c6c9a | ||
| 
						 | 
					6e73d8b3ab | ||
| 
						 | 
					82a2dd8732 | ||
| 
						 | 
					695cb6d76b | ||
| 
						 | 
					c9a3164a29 | ||
| 
						 | 
					6ab575cd49 | ||
| 
						 | 
					c9274307f2 | ||
| 
						 | 
					2489c46a7f | ||
| 
						 | 
					1ae369855b | ||
| 
						 | 
					1f1d4e2def | ||
| 
						 | 
					91c4253f06 | ||
| 
						 | 
					bc6db547d6 | ||
| 
						 | 
					e2de22bdce | ||
| 
						 | 
					100f6603f2 | ||
| 
						 | 
					5382a2a15e | ||
| 
						 | 
					0a9d4ea17b | ||
| 
						 | 
					f05138df62 | ||
| 
						 | 
					6e67e1a849 | ||
| 
						 | 
					76a2e7f8e5 | ||
| 
						 | 
					b082da73a1 | ||
| 
						 | 
					6976c7f386 | ||
| 
						 | 
					7702175130 | ||
| 
						 | 
					c2e43cc781 | ||
| 
						 | 
					6f6a3566ac | ||
| 
						 | 
					06442d5aa2 | ||
| 
						 | 
					0d24be4c05 | ||
| 
						 | 
					553c29ab8a | 
@@ -10,7 +10,7 @@ end_of_line = lf
 | 
			
		||||
trim_trailing_whitespace = true
 | 
			
		||||
insert_final_newline = true
 | 
			
		||||
 | 
			
		||||
[*.{json,yml}]
 | 
			
		||||
[*.{json,yml,yaml}]
 | 
			
		||||
indent_size = 2
 | 
			
		||||
 | 
			
		||||
[*.md]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								.gitee/ISSUE_TEMPLATE.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								.gitee/ISSUE_TEMPLATE.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
### 使用版本(未按照模板填写直接删除)
 | 
			
		||||
 | 
			
		||||
- jdk版本(带上尾号): 例如 1.8.0_202
 | 
			
		||||
- 框架版本(项目启动时输出的版本号): 例如 4.4.0
 | 
			
		||||
- 其他依赖版本(你觉得有必要的):
 | 
			
		||||
 | 
			
		||||
### 问题前提
 | 
			
		||||
 | 
			
		||||
> 功能不好用 不会用 是否已经看过项目文档
 | 
			
		||||
> 项目运行报错 是否已经拿着报错信息去百度 常见报错百度百度足以
 | 
			
		||||
> 是否搜索过其他issue 一些已经解决的问题 会在issue内留下解决方法
 | 
			
		||||
> 无法线上解决或者与框架无关的问题的欢迎加VIP群跟作者一对一谈
 | 
			
		||||
 | 
			
		||||
### 异常模块
 | 
			
		||||
 | 
			
		||||
> 此报错都涉及到那些系统模块
 | 
			
		||||
 | 
			
		||||
例如 ruoyi-system ruoyi-auth 等等
 | 
			
		||||
 | 
			
		||||
### 问题描述
 | 
			
		||||
 | 
			
		||||
> 越详细越容易直击问题所在
 | 
			
		||||
 | 
			
		||||
已知: XXX功能不好用 或 XXX数据不正常 等等
 | 
			
		||||
 | 
			
		||||
### 希望结果
 | 
			
		||||
 | 
			
		||||
> 想知道你觉得怎么样是正常或者合理的
 | 
			
		||||
 | 
			
		||||
希望功能可以有XXX结果 或者 XXX现象
 | 
			
		||||
 | 
			
		||||
### 重现步骤
 | 
			
		||||
 | 
			
		||||
> 作者并不知道这个问题是如何出现的
 | 
			
		||||
 | 
			
		||||
- 1
 | 
			
		||||
- 2
 | 
			
		||||
- 3
 | 
			
		||||
 | 
			
		||||
### 相关代码与报错信息(请勿发混乱格式)
 | 
			
		||||
 | 
			
		||||
> 代码可按照如下形式提供或者截图均可 越详细越好
 | 
			
		||||
> 大多数问题都是 代码编写错误问题 逻辑问题 或者用法错误等问题
 | 
			
		||||
 | 
			
		||||
```java
 | 
			
		||||
public class XXX {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										50
									
								
								.gitee/ISSUE_TEMPLATE/bug.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								.gitee/ISSUE_TEMPLATE/bug.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
name: Bug 反馈
 | 
			
		||||
description: 当你中发现了一个 Bug,导致应用崩溃或抛出异常,或者有一个组件存在问题,或者某些地方看起来不对劲。
 | 
			
		||||
title: "[Bug]: "
 | 
			
		||||
labels: ["bug"]
 | 
			
		||||
body:
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: version
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 版本
 | 
			
		||||
      description: 你当前正在使用我们软件的哪个版本(pom文件内的版本号)?
 | 
			
		||||
      value: |
 | 
			
		||||
        jdk版本(带上尾号): 例如 1.8.0
 | 
			
		||||
        框架版本(项目启动时输出的版本号): 例如 4.4.0
 | 
			
		||||
        其他依赖版本(你觉得有必要的):
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
  - type: checkboxes
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 功能不好用不会用是否已经看过项目文档?
 | 
			
		||||
      options:
 | 
			
		||||
        - label: https://plus-doc.dromara.org
 | 
			
		||||
          required: true
 | 
			
		||||
  - type: checkboxes
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 这个问题是否已经存在?
 | 
			
		||||
      options:
 | 
			
		||||
        - label: 我已经搜索过现有的问题 (https://gitee.com/dromara/RuoYi-Vue-Plus/issues)
 | 
			
		||||
          required: true
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 希望结果
 | 
			
		||||
      description: 想知道你觉得怎么样是正常或者合理的。
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
  - type: markdown
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 如何复现
 | 
			
		||||
      description: 请详细告诉我们如何复现你遇到的问题
 | 
			
		||||
      value: |
 | 
			
		||||
        如涉及代码 可提供一个最小代码示例 并使用```附上它 或者截图均可 越详细越好<br>
 | 
			
		||||
        大多数问题都是 代码编写错误问题 逻辑问题 或者用法错误等问题
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 相关代码与报错信息(请勿发混乱格式)
 | 
			
		||||
      description: 如果可以的话,上传任何关于 bug 的截图。
 | 
			
		||||
      value: |
 | 
			
		||||
        [在这里上传图片]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								.gitee/ISSUE_TEMPLATE/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.gitee/ISSUE_TEMPLATE/config.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
blank_issues_enabled: false
 | 
			
		||||
contact_links:
 | 
			
		||||
  - name: RuoYi-Vue-Plus 文档中心
 | 
			
		||||
    url: https://plus-doc.dromara.org
 | 
			
		||||
    about: 提供 RuoYi-Vue-Plus 搭建使用指南、平台基本开发使用方式、介绍、基础知识和常见问题解答
 | 
			
		||||
							
								
								
									
										43
									
								
								.gitee/ISSUE_TEMPLATE/feature.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								.gitee/ISSUE_TEMPLATE/feature.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
name: 功能建议
 | 
			
		||||
description: 对本项目提出一个功能建议
 | 
			
		||||
title: "[功能建议]: "
 | 
			
		||||
labels: ["enhancement"]
 | 
			
		||||
body:
 | 
			
		||||
  - type: markdown
 | 
			
		||||
    attributes:
 | 
			
		||||
      value: |
 | 
			
		||||
        感谢提出功能建议,我们将仔细考虑!请持续关注该issues,在加入计划后我们会有贡献者设置为负责人,同时状态成为进行中。
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: related-problem
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 你的功能建议是否和某个问题相关?
 | 
			
		||||
      description: 清晰并简洁地描述问题是什么,例如,当我...时,我总是感到困扰。
 | 
			
		||||
    validations:
 | 
			
		||||
      required: false
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: desired-solution
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 你希望看到什么解决方案?
 | 
			
		||||
      description: 清晰并简洁地描述你希望发生的事情。
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: alternatives
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 你考虑过哪些替代方案?
 | 
			
		||||
      description: 清晰并简洁地描述你考虑过的任何替代解决方案或功能。
 | 
			
		||||
    validations:
 | 
			
		||||
      required: false
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: additional-context
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 你有其他上下文或截图吗?
 | 
			
		||||
      description: 在此处添加有关功能请求的任何其他上下文或截图。
 | 
			
		||||
    validations:
 | 
			
		||||
      required: false
 | 
			
		||||
  - type: checkboxes
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: 意向参与贡献
 | 
			
		||||
      options:
 | 
			
		||||
        - label: 我有意向参与具体功能的开发实现并将代码贡献回到上游社区
 | 
			
		||||
          required: false
 | 
			
		||||
							
								
								
									
										7
									
								
								.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
### 更改目的 解决了什么问题(请提交到dev分支)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 改动逻辑 这么写的思路(让作者更好的理解你的意图)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 测试 都做了哪些测试(未经过测试不采纳)
 | 
			
		||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -25,6 +25,9 @@ target/
 | 
			
		||||
*.iml
 | 
			
		||||
*.ipr
 | 
			
		||||
 | 
			
		||||
### JRebel ###
 | 
			
		||||
rebel.xml
 | 
			
		||||
 | 
			
		||||
### NetBeans ###
 | 
			
		||||
nbproject/private/
 | 
			
		||||
build/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								.run/ruoyi-monitor-admin.run.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.run/ruoyi-monitor-admin.run.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<component name="ProjectRunConfigurationManager">
 | 
			
		||||
  <configuration default="false" name="ruoyi-monitor-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
 | 
			
		||||
    <deployment type="dockerfile">
 | 
			
		||||
      <settings>
 | 
			
		||||
        <option name="imageTag" value="ruoyi/ruoyi-monitor-admin:4.8.2" />
 | 
			
		||||
        <option name="buildOnly" value="true" />
 | 
			
		||||
        <option name="sourceFilePath" value="ruoyi-extend/ruoyi-monitor-admin/Dockerfile" />
 | 
			
		||||
      </settings>
 | 
			
		||||
    </deployment>
 | 
			
		||||
    <method v="2" />
 | 
			
		||||
  </configuration>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										12
									
								
								.run/ruoyi-server.run.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.run/ruoyi-server.run.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<component name="ProjectRunConfigurationManager">
 | 
			
		||||
  <configuration default="false" name="ruoyi-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
 | 
			
		||||
    <deployment type="dockerfile">
 | 
			
		||||
      <settings>
 | 
			
		||||
        <option name="imageTag" value="ruoyi/ruoyi-server:4.8.2" />
 | 
			
		||||
        <option name="buildOnly" value="true" />
 | 
			
		||||
        <option name="sourceFilePath" value="ruoyi-admin/Dockerfile" />
 | 
			
		||||
      </settings>
 | 
			
		||||
    </deployment>
 | 
			
		||||
    <method v="2" />
 | 
			
		||||
  </configuration>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										12
									
								
								.run/ruoyi-xxl-job-admin.run.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.run/ruoyi-xxl-job-admin.run.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
<component name="ProjectRunConfigurationManager">
 | 
			
		||||
  <configuration default="false" name="ruoyi-xxl-job-admin" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
 | 
			
		||||
    <deployment type="dockerfile">
 | 
			
		||||
      <settings>
 | 
			
		||||
        <option name="imageTag" value="ruoyi/ruoyi-xxl-job-admin:4.8.2" />
 | 
			
		||||
        <option name="buildOnly" value="true" />
 | 
			
		||||
        <option name="sourceFilePath" value="ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile" />
 | 
			
		||||
      </settings>
 | 
			
		||||
    </deployment>
 | 
			
		||||
    <method v="2" />
 | 
			
		||||
  </configuration>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										255
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										255
									
								
								README.md
									
									
									
									
									
								
							@@ -1,68 +1,126 @@
 | 
			
		||||
<img src="https://foruda.gitee.com/images/1679673773341074847/178e8451_1766278.png" width="50%" height="50%">
 | 
			
		||||
<div style="height: 10px; clear: both;"></div>
 | 
			
		||||
 | 
			
		||||
- - -
 | 
			
		||||
 | 
			
		||||
## 版本状态说明
 | 
			
		||||
 | 
			
		||||
由于 springboot 2.X 与 vue 2.X 官方均宣布停止维护, 故而 框架 4.X 版本 进入维护状态(只处理问题不更新功能)
 | 
			
		||||
 | 
			
		||||
停止维护时间预计: 2024年6-10月具体根据使用人数动态决定, 此版本已经相当稳定 即便不更新功能也不影响使用
 | 
			
		||||
 | 
			
		||||
如果依旧选择使用 jdk8 或者 jdk11 可以放心使用此版本, 如果希望使用 jdk17 或者 jdk21 可以选择使用 5.X 分支
 | 
			
		||||
 | 
			
		||||
## 平台简介
 | 
			
		||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
 | 
			
		||||
[](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
 | 
			
		||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE)
 | 
			
		||||
 | 
			
		||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
 | 
			
		||||
[](https://github.com/dromara/RuoYi-Vue-Plus)
 | 
			
		||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
 | 
			
		||||
[](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
 | 
			
		||||
<br>
 | 
			
		||||
[](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
 | 
			
		||||
[]()
 | 
			
		||||
[](https://gitee.com/dromara/RuoYi-Vue-Plus)
 | 
			
		||||
[]()
 | 
			
		||||
[]()
 | 
			
		||||
[]()
 | 
			
		||||
[]()
 | 
			
		||||
 | 
			
		||||
RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼容原框架)
 | 
			
		||||
> RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群` 场景全方位升级(不兼容原框架)
 | 
			
		||||
 | 
			
		||||
| 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 |
 | 
			
		||||
|---|---|---|---|
 | 
			
		||||
| 当前框架 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
 | 
			
		||||
| satoken分支 | RuoYi-Vue-Plus-satoken | [satoken分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/) | 使用satoken重构权限鉴权(仅供学习不推荐上生产) |
 | 
			
		||||
| 单体分支 | RuoYi-Vue-Plus-fast | [fast分支地址](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) | 单体应用结构 |
 | 
			
		||||
| 原框架 | RuoYi-Vue | [RuoYi-Vue官网](http://ruoyi.vip/) | 定期同步需要的功能 |
 | 
			
		||||
| 前端开发框架 | Vue、Element UI | [Element UI官网](https://element.eleme.cn/#/zh-CN) | |
 | 
			
		||||
| 后端开发框架 | SpringBoot | [SpringBoot官网](https://spring.io/projects/spring-boot/#learn) | |
 | 
			
		||||
| 容器框架 | Undertow | [Undertow官网](https://undertow.io/) | 基于 Netty 的高性能容器 |
 | 
			
		||||
| 权限认证框架 | Spring Security、Jwt | [SpringSecurity官网](https://spring.io/projects/spring-security#learn) | 支持多终端认证系统 |
 | 
			
		||||
| 关系数据库 | MySQL | [MySQL官网](https://dev.mysql.com/) | 适配 8.X 最低 5.7 |
 | 
			
		||||
| 缓存数据库 | Redis | [Redis官网](https://redis.io/) | 适配 6.X 最低 4.X |
 | 
			
		||||
| 数据库框架 | Mybatis-Plus | [Mybatis-Plus文档](https://baomidou.com/guide/) | 快速 CRUD 增加开发效率 |
 | 
			
		||||
| 数据库框架 | p6spy | [p6spy官网](https://p6spy.readthedocs.io/) | 更强劲的 SQL 分析 |
 | 
			
		||||
| 多数据源框架 | dynamic-datasource | [dynamic-ds文档](https://www.kancloud.cn/tracy5546/dynamic-datasource/content) | 支持主从与多种类数据库异构 |
 | 
			
		||||
| 序列化框架 | Jackson | [Jackson官网](https://github.com/FasterXML/jackson) | 统一使用 jackson 高效可靠 |
 | 
			
		||||
| 网络框架 | Feign、OkHttp3 | [Feign官网](https://github.com/OpenFeign/feign) | 接口化管理 HTTP 请求 |
 | 
			
		||||
| Redis客户端 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 支持单机、集群配置 |
 | 
			
		||||
| 分布式限流 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 全局、请求IP、集群ID 多种限流 |
 | 
			
		||||
| 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 |
 | 
			
		||||
| 分布式幂等 | Lock4j | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 基于分布式锁实现 |
 | 
			
		||||
| 分布式日志 | TLog | [TLog文档](https://yomahub.com/tlog/docs) | 支持跟踪链路日志记录、性能分析、链路排查 |
 | 
			
		||||
| 分布式任务调度 | Xxl-Job | [Xxl-Job官网](https://www.xuxueli.com/xxl-job/) | 高性能 高可靠 易扩展 |
 | 
			
		||||
| 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 |
 | 
			
		||||
| 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 |
 | 
			
		||||
| 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 |
 | 
			
		||||
| 校验框架 | Validation | [Validation文档](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/) | 增强接口安全性、严谨性 |
 | 
			
		||||
| Excel框架 | Alibaba EasyExcel | [EasyExcel文档](https://www.yuque.com/easyexcel/doc/easyexcel) | 性能优异 扩展性强 |
 | 
			
		||||
| 文档框架 | Knife4j | [Knife4j文档](https://doc.xiaominfo.com/knife4j/documentation/) | 美化接口文档 |
 | 
			
		||||
| 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 |
 | 
			
		||||
| 代码生成器 | 适配MP、Knife4j规范化代码 | [Hutool文档](https://www.hutool.cn/docs/) | 一键生成前后端代码 |
 | 
			
		||||
| 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 |
 | 
			
		||||
| 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 |
 | 
			
		||||
> 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
 | 
			
		||||
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
 | 
			
		||||
 | 
			
		||||
> 系统演示: [传送门](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4836388&doc_id=1469725)
 | 
			
		||||
 | 
			
		||||
# 本框架与RuoYi的功能差异
 | 
			
		||||
 | 
			
		||||
| 功能          | 本框架                                                                                                               | RuoYi                                                                              |
 | 
			
		||||
|-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
 | 
			
		||||
| 前端项目        | 基于vue3-element-admin开源项目重写<br/>Vue3 + TS + ElementPlus                                                            | 基于Vue2/Vue3 + JS                                                                   | 
 | 
			
		||||
| 后端项目结构      | 采用插件化 + 扩展包形式 结构解耦 易于扩展                                                                                           | 模块相互注入耦合严重难以扩展                                                                     | 
 | 
			
		||||
| 后端代码风格      | 严格遵守Alibaba规范与项目统一配置的代码格式化                                                                                        | 代码书写与常规结构不同阅读障碍大                                                                   |
 | 
			
		||||
| Web容器       | 采用 Undertow 基于 XNIO 的高性能容器                                                                                        | 采用 Tomcat                                                                          |
 | 
			
		||||
| 权限认证        | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展                                                                                  | Spring Security 配置繁琐扩展性极差                                                          |
 | 
			
		||||
| 权限注解        | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR` 或 `权限 OR 角色` 等复杂表达式        | 只支持是否存在匹配                                                                          |
 | 
			
		||||
| 关系数据库支持     | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换                                                              | 支持 Mysql、Oracle 不支持同时使用、不支持异构切换                                                    |
 | 
			
		||||
| 缓存数据库       | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列                                                                             | Redis 简单 get set 支持                                                                |
 | 
			
		||||
| Redis客户端    | 采用 Redisson Redis官方推荐 基于Netty的客户端工具<br/>支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan<br/>支持单机、哨兵、单主集群、多主集群等模式 | Lettuce + RedisTemplate 支持模式少 工具使用繁琐<br/>连接池采用 common-pool Bug多经常性出问题              |
 | 
			
		||||
| 缓存注解        | 采用 Spring-Cache 注解 对其扩展了实现支持了更多功能<br/>例如 过期时间 最大空闲时间 组最大长度等 只需一个注解即可完成数据自动缓存                                      | 需手动编写Redis代码逻辑                                                                     |
 | 
			
		||||
| ORM框架       | 采用 Mybatis-Plus 基于对象几乎不用写SQL全java操作 功能强大插件众多<br/>例如多租户插件 分页插件 乐观锁插件等等                                             | 采用 Mybatis 基于XML需要手写SQL                                                            |
 | 
			
		||||
| SQL监控       | 采用 p6spy 可输出完整SQL与执行时间监控                                                                                          | log输出 需手动拼接sql与参数无法快速查看调试问题                                                        |
 | 
			
		||||
| 数据分页        | 采用 Mybatis-Plus 分页插件<br/>框架对其进行了扩展 对象化分页对象 支持多种方式传参 支持前端多排序 复杂排序                                                  | 采用 PageHelper 仅支持单查询分页 参数只能从param传 只能单排序 功能扩展性差 体验不好                               |
 | 
			
		||||
| 数据权限        | 采用 Mybatis-Plus 插件 自行分析拼接SQL 无感式过滤<br/>只需为Mapper设置好注解条件 支持多种自定义 不限于部门角色                                           | 采用 注解+aop 实现 基于部门角色 生成的sql兼容性差 不支持其他业务扩展<br/>生成sql后需手动拼接到具体业务sql上 对于多个Mapper查询不起作用 |
 | 
			
		||||
| 数据脱敏        | 采用 注解 + jackson 序列化期间脱敏 支持不同模块不同的脱敏条件<br/>支持多种策略 如身份证、手机号、地址、邮箱、银行卡等 可自行扩展                                        | 无                                                                                  |
 | 
			
		||||
| 数据加解密       | 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密<br/>支持多种策略 如BASE64、AES、RSA、SM2、SM4等                                              | 无                                                                                  |
 | 
			
		||||
| 数据翻译        | 采用 注解 + jackson 序列化期间动态修改数据 数据进行翻译<br/>支持多种模式: `映射翻译` `直接翻译` `其他扩展条件翻译` 接口化两步即可完成自定义扩展 内置多种翻译实现                   | 无                                                                                  |
 | 
			
		||||
| 多数据源框架      | 采用 dynamic-datasource 支持世面大部分数据库<br/>通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源<br/>支持spel表达式从请求头参数等条件切换数据源            | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差                                                     |
 | 
			
		||||
| 多数据源事务      | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚                                                                          | 不支持                                                                                |
 | 
			
		||||
| 数据库连接池      | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下                                                                        | 采用 druid bug众多 社区维护差 活跃度低 配置众多繁琐性能一般                                               |
 | 
			
		||||
| 数据库主键       | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁                                                                  | 采用 数据库自增ID 支持数据量有限 不支持多数据源主键唯一                                                     |
 | 
			
		||||
| WebSocket协议 | 基于 Spring 封装的 WebSocket 协议 扩展了Token鉴权与分布式会话同步 不再只是基于单机的废物                                                         | 无                                                                                  |
 | 
			
		||||
| 序列化         | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                                    | 采用 fastjson bugjson 远近闻名                                                           | 
 | 
			
		||||
| 分布式幂等       | 参考美团GTIS防重系统简化实现(细节可看文档)                                                                                          | 手动编写注解基于aop实现                                                                      |
 | 
			
		||||
| 分布式任务调度     | 采用 Xxl-Job 天生支持分布式 统一的管理中心                                                                                        | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造                                                   | 
 | 
			
		||||
| 文件存储        | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储                                                     | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应                                                    |
 | 
			
		||||
| 云存储         | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家                                                                          | 不支持                                                                                |
 | 
			
		||||
| 短信          | 采用 sms4j 短信融合包 支持数十种短信厂家 只需在yml配置好厂家密钥即可使用 可多厂家共用                                                                 | 不支持                                                                                |
 | 
			
		||||
| 邮件          | 采用 mail-api 通用协议支持大部分邮件厂商                                                                                         | 不支持                                                                                |
 | 
			
		||||
| 接口文档        | 采用 SpringDoc、javadoc 无注解零入侵基于java注释<br/>只需把注释写好 无需再写一大堆的文档注解了                                                     | 采用 Springfox 已停止维护 需要编写大量的注解来支持文档生成                                                | 
 | 
			
		||||
| 校验框架        | 采用 Validation 支持注解与工具类校验 注解支持国际化                                                                                  | 仅支持注解 且注解不支持国际化                                                                    |
 | 
			
		||||
| Excel框架     | 采用 Alibaba EasyExcel 基于插件化<br/>框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等                                               | 基于 POI 手写实现 功能有限 复杂 扩展性差                                                           |
 | 
			
		||||
| 工具类框架       | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码                                                       | 手写工具稳定性差易出问题 工具数量有限 代码臃肿需自己手写 get set 等                                            | 
 | 
			
		||||
| 监控框架        | 采用 SpringBoot-Admin 基于SpringBoot官方 actuator 探针机制<br/>实时监控服务状态 框架还为其扩展了在线日志查看监控                                    | 无                                                                                  | 
 | 
			
		||||
| 链路追踪        | 采用 Apache SkyWalking 还在为请求不知道去哪了 到哪出了问题而烦恼吗<br/>用了它即可实时查看请求经过的每一处每一个节点                                            | 无                                                                                  |
 | 
			
		||||
| 代码生成器       | 只需设计好表结构 一键生成所有crud代码与页面<br/>降低80%的开发量 把精力都投入到业务设计上<br/>框架为其适配MP、SpringDoc规范化代码 同时支持动态多数据源代码生成                    | 代码生成原生结构 只支持单数据源生成                                                                 |
 | 
			
		||||
| 部署方式        | 支持 Docker 编排 一键搭建所有环境 让开发人员从此不再为搭建环境而烦恼                                                                           | 原生jar部署 其他环境需手动下载安装 自行搭建                                                           | 
 | 
			
		||||
| 项目路径修改      | 提供详细的修改方案文档 并为其做了一些改动 非常简单即可修改成自己想要的                                                                              | 需要做很多改造 文档说明有限                                                                     |
 | 
			
		||||
| 国际化         | 基于请求头动态返回不同语种的文本内容 开发难度低 有对应的工具类 支持大部分注解内容国际化                                                                     | 只提供基础功能 其他需自行编写扩展                                                                  |
 | 
			
		||||
| 代码单例测试      | 提供单例测试 使用方式编写方法与maven多环境单测插件                                                                                      | 只提供基础功能 其他需自行编写扩展                                                                  |
 | 
			
		||||
| Demo案例      | 提供框架功能的实际使用案例 单独一个模块提供了很多很全                                                                                       | 无                                                                                  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 本框架与RuoYi的业务差异
 | 
			
		||||
 | 
			
		||||
| 业务     | 功能说明                                    | 本框架 | RuoYi            |
 | 
			
		||||
|--------|-----------------------------------------|-----|------------------|
 | 
			
		||||
| 用户管理   | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等          | 支持  | 支持               |
 | 
			
		||||
| 部门管理   | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限          | 支持  | 支持               |
 | 
			
		||||
| 岗位管理   | 配置系统用户所属担任职务                            | 支持  | 支持               |
 | 
			
		||||
| 菜单管理   | 配置系统菜单、操作权限、按钮权限标识等                     | 支持  | 支持               |
 | 
			
		||||
| 角色管理   | 角色菜单权限分配、设置角色按机构进行数据范围权限划分              | 支持  | 支持               |
 | 
			
		||||
| 字典管理   | 对系统中经常使用的一些较为固定的数据进行维护                  | 支持  | 支持               |
 | 
			
		||||
| 参数管理   | 对系统动态配置常用参数                             | 支持  | 支持               |
 | 
			
		||||
| 通知公告   | 系统通知公告信息发布维护                            | 支持  | 支持               |
 | 
			
		||||
| 操作日志   | 系统正常操作日志记录和查询 系统异常信息日志记录和查询             | 支持  | 支持               |
 | 
			
		||||
| 登录日志   | 系统登录日志记录查询包含登录异常                        | 支持  | 支持               |
 | 
			
		||||
| 文件管理   | 系统文件展示、上传、下载、删除等管理                      | 支持  | 无                |
 | 
			
		||||
| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理          | 支持  | 无                |
 | 
			
		||||
| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作                   | 支持  | 支持               |
 | 
			
		||||
| 定时任务   | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等         | 支持  | 仅支持任务与日志管理       |
 | 
			
		||||
| 代码生成   | 多数据源前后端代码的生成(java、html、xml、sql)支持CRUD下载 | 支持  | 仅支持单数据源          |
 | 
			
		||||
| 系统接口   | 根据业务代码自动生成相关的api接口文档                    | 支持  | 支持               |
 | 
			
		||||
| 服务监控   | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等     | 支持  | 仅支持单机CPU、内存、磁盘监控 |
 | 
			
		||||
| 缓存监控   | 对系统的缓存信息查询,命令统计等。                       | 支持  | 支持               |
 | 
			
		||||
| 在线构建器  | 拖动表单元素生成相应的HTML代码。                      | 支持  | 支持               |
 | 
			
		||||
| 使用案例   | 系统的一些功能案例                               | 支持  | 不支持              |
 | 
			
		||||
 | 
			
		||||
## 参考文档
 | 
			
		||||
 | 
			
		||||
使用框架前请仔细阅读文档重点注意事项
 | 
			
		||||
<br>
 | 
			
		||||
>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117)
 | 
			
		||||
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117)
 | 
			
		||||
>[初始化项目 必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
 | 
			
		||||
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725)
 | 
			
		||||
>
 | 
			
		||||
>[专栏与视频 入门必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
 | 
			
		||||
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725)
 | 
			
		||||
>
 | 
			
		||||
>[部署项目 必看](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
 | 
			
		||||
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725)
 | 
			
		||||
> 
 | 
			
		||||
>[部署项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382)
 | 
			
		||||
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382)
 | 
			
		||||
> 
 | 
			
		||||
>[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
 | 
			
		||||
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages)
 | 
			
		||||
>[参考文档 Wiki](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages)
 | 
			
		||||
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages)
 | 
			
		||||
 | 
			
		||||
## 软件架构图
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
## 贡献代码
 | 
			
		||||
 | 
			
		||||
欢迎各路英雄豪杰 `PR` 代码 请提交到 `dev` 开发分支 统一测试发版
 | 
			
		||||
@@ -72,81 +130,42 @@ RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 `分布式集群` 场景升级(不兼
 | 
			
		||||
### 其他
 | 
			
		||||
 | 
			
		||||
* 同步升级 RuoYi-Vue
 | 
			
		||||
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/JavaLionLi/RuoYi-Vue-Plus)
 | 
			
		||||
* 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/)
 | 
			
		||||
* satoken 分支 [RuoYi-Vue-Plus-satoken](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/)
 | 
			
		||||
* 用户扩展项目 [扩展项目列表](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
 | 
			
		||||
* GitHub 地址 [RuoYi-Vue-Plus-github](https://github.com/dromara/RuoYi-Vue-Plus)
 | 
			
		||||
* 单模块 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/dromara/RuoYi-Vue-Plus/tree/fast/)
 | 
			
		||||
* 微服务 分支 [RuoYi-Cloud-Plus](https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus)
 | 
			
		||||
* 用户扩展项目 [扩展项目列表](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/pages?sort_id=4478302&doc_id=1469725)
 | 
			
		||||
 | 
			
		||||
## 加群与捐献
 | 
			
		||||
>[加群与捐献](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
 | 
			
		||||
>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
 | 
			
		||||
>[加群与捐献](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
 | 
			
		||||
>>[https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598](https://gitee.com/dromara/RuoYi-Vue-Plus/wikis/加群与捐献?sort_id=4104598)
 | 
			
		||||
 | 
			
		||||
## 捐献作者
 | 
			
		||||
作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭  
 | 
			
		||||
<img src="https://images.gitee.com/uploads/images/2021/0525/101654_451e4523_1766278.jpeg" width="300px" height="450px" />
 | 
			
		||||
<img src="https://images.gitee.com/uploads/images/2022/0218/213734_b1b8197f_1766278.jpeg" width="300px" height="450px" />
 | 
			
		||||
<img src="https://images.gitee.com/uploads/images/2021/0525/101713_3d18b119_1766278.jpeg" width="300px" height="450px" />
 | 
			
		||||
 | 
			
		||||
## 业务功能
 | 
			
		||||
 | 
			
		||||
| 功能 | 介绍 |
 | 
			
		||||
|---|---|
 | 
			
		||||
| 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置。 |
 | 
			
		||||
| 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 |
 | 
			
		||||
| 岗位管理 | 配置系统用户所属担任职务。 |
 | 
			
		||||
| 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等。 |
 | 
			
		||||
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分。 |
 | 
			
		||||
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护。 |
 | 
			
		||||
| 参数管理 | 对系统动态配置常用参数。 |
 | 
			
		||||
| 通知公告 | 系统通知公告信息发布维护。 |
 | 
			
		||||
| 操作日志 | 系统正常操作日志记录和查询;系统异常信息日志记录和查询。 |
 | 
			
		||||
| 登录日志 | 系统登录日志记录查询包含登录异常。 |
 | 
			
		||||
| 文件管理 | 系统文件上传、下载等管理。 |
 | 
			
		||||
| 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志。 |
 | 
			
		||||
| 代码生成 | 前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 |
 | 
			
		||||
| 系统接口 | 根据业务代码自动生成相关的api接口文档。 |
 | 
			
		||||
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等。 |
 | 
			
		||||
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 |
 | 
			
		||||
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 |
 | 
			
		||||
| 连接池监视 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 |
 | 
			
		||||
| 使用案例 | 系统的一些功能案例 |
 | 
			
		||||
 | 
			
		||||
## 演示图例
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
 | 
			
		||||
	<tbody>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-972235bcbe3518dedd351ff0e2ee7d1031c.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-5e0097702fa91e2e36391de8127676a7fa1.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td>
 | 
			
		||||
			<p><img src="https://oscimg.oschina.net/oscnet/up-e56e3828f48cd9886d88731766f06d5f3c1.png" width="1920" /></p>
 | 
			
		||||
			</td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-0715990ea1a9f254ec2138fcd063c1f556a.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-eaf5417ccf921bb64abb959e3d8e290467f.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-fc285cf33095ebf8318de6999af0f473861.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-60c83fd8bd61c29df6dbf47c88355e9c272.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-7f731948c8b73c7d90f67f9e1c7a534d5c3.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-e4de89b5e2d20c52d3c3a47f9eb88eb8526.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-8791d823a508eb90e67c604f36f57491a67.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-4589afd99982ead331785299b894174feb6.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-8ea177cdacaea20995daf2f596b15232561.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-32d1d04c55c11f74c9129fbbc58399728c4.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-04fa118f7631b7ae6fd72299ca0a1430a63.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
		<tr>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-fe7e85b65827802bfaadf3acd42568b58c7.png" width="1920" /></td>
 | 
			
		||||
			<td><img src="https://oscimg.oschina.net/oscnet/up-eff2b02a54f8188022d8498cfe6af6fcc06.png" width="1920" /></td>
 | 
			
		||||
		</tr>
 | 
			
		||||
	</tbody>
 | 
			
		||||
</table>
 | 
			
		||||
|                                                                                            |                                                                                            |
 | 
			
		||||
|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
|  |  |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										361
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										361
									
								
								pom.xml
									
									
									
									
									
								
							@@ -2,60 +2,80 @@
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
			
		||||
         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">
 | 
			
		||||
	<modelVersion>4.0.0</modelVersion>
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
 | 
			
		||||
    <groupId>com.ruoyi</groupId>
 | 
			
		||||
    <artifactId>ruoyi-vue-plus</artifactId>
 | 
			
		||||
    <version>3.3.0</version>
 | 
			
		||||
    <version>4.8.2</version>
 | 
			
		||||
 | 
			
		||||
    <name>RuoYi-Vue-Plus</name>
 | 
			
		||||
    <url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
 | 
			
		||||
    <url>https://gitee.com/dromara/RuoYi-Vue-Plus</url>
 | 
			
		||||
    <description>RuoYi-Vue-Plus后台管理系统</description>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
        <ruoyi-vue-plus.version>3.3.0</ruoyi-vue-plus.version>
 | 
			
		||||
        <spring-boot.version>2.5.6</spring-boot.version>
 | 
			
		||||
        <ruoyi-vue-plus.version>4.8.2</ruoyi-vue-plus.version>
 | 
			
		||||
        <spring-boot.version>2.7.18</spring-boot.version>
 | 
			
		||||
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
			
		||||
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 | 
			
		||||
        <java.version>1.8</java.version>
 | 
			
		||||
        <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
 | 
			
		||||
        <druid.version>1.2.8</druid.version>
 | 
			
		||||
        <knife4j.version>3.0.3</knife4j.version>
 | 
			
		||||
        <swagger-annotations.version>1.5.22</swagger-annotations.version>
 | 
			
		||||
        <poi.version>4.1.2</poi.version>
 | 
			
		||||
        <easyexcel.version>2.2.11</easyexcel.version>
 | 
			
		||||
        <velocity.version>1.7</velocity.version>
 | 
			
		||||
        <jwt.version>0.9.1</jwt.version>
 | 
			
		||||
        <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
 | 
			
		||||
        <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
 | 
			
		||||
        <spring-boot.mybatis>2.2.2</spring-boot.mybatis>
 | 
			
		||||
        <springdoc.version>1.6.15</springdoc.version>
 | 
			
		||||
        <poi.version>5.2.3</poi.version>
 | 
			
		||||
        <easyexcel.version>3.3.2</easyexcel.version>
 | 
			
		||||
        <velocity.version>2.3</velocity.version>
 | 
			
		||||
        <satoken.version>1.37.0</satoken.version>
 | 
			
		||||
        <mybatis-plus.version>3.5.4</mybatis-plus.version>
 | 
			
		||||
        <p6spy.version>3.9.1</p6spy.version>
 | 
			
		||||
        <hutool.version>5.7.15</hutool.version>
 | 
			
		||||
        <feign.version>3.0.3</feign.version>
 | 
			
		||||
        <feign-okhttp.version>11.6</feign-okhttp.version>
 | 
			
		||||
        <okhttp.version>4.9.1</okhttp.version>
 | 
			
		||||
        <spring-boot-admin.version>2.5.2</spring-boot-admin.version>
 | 
			
		||||
        <redisson.version>3.16.3</redisson.version>
 | 
			
		||||
        <lock4j.version>2.2.1</lock4j.version>
 | 
			
		||||
        <dynamic-ds.version>3.4.1</dynamic-ds.version>
 | 
			
		||||
        <tlog.version>1.3.3</tlog.version>
 | 
			
		||||
        <xxl-job.version>2.3.0</xxl-job.version>
 | 
			
		||||
 | 
			
		||||
        <!-- jdk11 缺失依赖 jaxb-->
 | 
			
		||||
        <jaxb.version>3.0.1</jaxb.version>
 | 
			
		||||
        <hutool.version>5.8.22</hutool.version>
 | 
			
		||||
        <okhttp.version>4.10.0</okhttp.version>
 | 
			
		||||
        <spring-boot-admin.version>2.7.11</spring-boot-admin.version>
 | 
			
		||||
        <redisson.version>3.20.1</redisson.version>
 | 
			
		||||
        <lock4j.version>2.2.3</lock4j.version>
 | 
			
		||||
        <dynamic-ds.version>3.5.2</dynamic-ds.version>
 | 
			
		||||
        <alibaba-ttl.version>2.14.2</alibaba-ttl.version>
 | 
			
		||||
        <xxl-job.version>2.4.0</xxl-job.version>
 | 
			
		||||
        <lombok.version>1.18.30</lombok.version>
 | 
			
		||||
        <bouncycastle.version>1.72</bouncycastle.version>
 | 
			
		||||
        <!-- 离线IP地址定位库 -->
 | 
			
		||||
        <ip2region.version>2.7.0</ip2region.version>
 | 
			
		||||
 | 
			
		||||
        <!-- OSS 配置 -->
 | 
			
		||||
        <qiniu.version>7.8.0</qiniu.version>
 | 
			
		||||
        <aliyun.oss.version>3.13.1</aliyun.oss.version>
 | 
			
		||||
        <qcloud.cos.version>5.6.58</qcloud.cos.version>
 | 
			
		||||
        <minio.version>8.3.3</minio.version>
 | 
			
		||||
 | 
			
		||||
        <!-- docker 配置 -->
 | 
			
		||||
        <docker.registry.url>localhost</docker.registry.url>
 | 
			
		||||
        <docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
 | 
			
		||||
        <docker.namespace>ruoyi</docker.namespace>
 | 
			
		||||
        <docker.plugin.version>1.2.2</docker.plugin.version>
 | 
			
		||||
 | 
			
		||||
        <aws-java-sdk-s3.version>1.12.540</aws-java-sdk-s3.version>
 | 
			
		||||
        <!-- SMS 配置 -->
 | 
			
		||||
        <sms4j.version>2.2.0</sms4j.version>
 | 
			
		||||
    </properties>
 | 
			
		||||
 | 
			
		||||
    <profiles>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>local</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <!-- 环境标识,需要与配置文件的名称相对应 -->
 | 
			
		||||
                <profiles.active>local</profiles.active>
 | 
			
		||||
                <logging.level>info</logging.level>
 | 
			
		||||
            </properties>
 | 
			
		||||
        </profile>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>dev</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <!-- 环境标识,需要与配置文件的名称相对应 -->
 | 
			
		||||
                <profiles.active>dev</profiles.active>
 | 
			
		||||
                <logging.level>info</logging.level>
 | 
			
		||||
            </properties>
 | 
			
		||||
            <activation>
 | 
			
		||||
                <!-- 默认环境 -->
 | 
			
		||||
                <activeByDefault>true</activeByDefault>
 | 
			
		||||
            </activation>
 | 
			
		||||
        </profile>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>prod</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <profiles.active>prod</profiles.active>
 | 
			
		||||
                <logging.level>warn</logging.level>
 | 
			
		||||
            </properties>
 | 
			
		||||
        </profile>
 | 
			
		||||
    </profiles>
 | 
			
		||||
 | 
			
		||||
    <!-- 依赖声明 -->
 | 
			
		||||
    <dependencyManagement>
 | 
			
		||||
        <dependencies>
 | 
			
		||||
@@ -69,47 +89,48 @@
 | 
			
		||||
                <scope>import</scope>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- 阿里数据库连接池 -->
 | 
			
		||||
            <!-- hutool 的依赖配置-->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.alibaba</groupId>
 | 
			
		||||
                <artifactId>druid-spring-boot-starter</artifactId>
 | 
			
		||||
                <version>${druid.version}</version>
 | 
			
		||||
                <groupId>cn.hutool</groupId>
 | 
			
		||||
                <artifactId>hutool-bom</artifactId>
 | 
			
		||||
                <version>${hutool.version}</version>
 | 
			
		||||
                <type>pom</type>
 | 
			
		||||
                <scope>import</scope>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.github.xiaoymin</groupId>
 | 
			
		||||
                <artifactId>knife4j-spring-boot-starter</artifactId>
 | 
			
		||||
                <version>${knife4j.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <artifactId>swagger-annotations</artifactId>
 | 
			
		||||
                        <groupId>io.swagger</groupId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
                <groupId>org.springdoc</groupId>
 | 
			
		||||
                <artifactId>springdoc-openapi-webmvc-core</artifactId>
 | 
			
		||||
                <version>${springdoc.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>io.swagger</groupId>
 | 
			
		||||
                <artifactId>swagger-annotations</artifactId>
 | 
			
		||||
                <version>${swagger-annotations.version}</version>
 | 
			
		||||
                <groupId>org.springdoc</groupId>
 | 
			
		||||
                <artifactId>springdoc-openapi-javadoc</artifactId>
 | 
			
		||||
                <version>${springdoc.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- excel工具 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.projectlombok</groupId>
 | 
			
		||||
                <artifactId>lombok</artifactId>
 | 
			
		||||
                <version>${lombok.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.apache.poi</groupId>
 | 
			
		||||
                <artifactId>poi</artifactId>
 | 
			
		||||
                <version>${poi.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.apache.poi</groupId>
 | 
			
		||||
                <artifactId>poi-ooxml</artifactId>
 | 
			
		||||
                <version>${poi.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.alibaba</groupId>
 | 
			
		||||
                <artifactId>easyexcel</artifactId>
 | 
			
		||||
                <version>${easyexcel.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <groupId>org.apache.poi</groupId>
 | 
			
		||||
                        <artifactId>poi</artifactId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <groupId>org.apache.poi</groupId>
 | 
			
		||||
                        <artifactId>poi-ooxml-schemas</artifactId>
 | 
			
		||||
@@ -120,22 +141,27 @@
 | 
			
		||||
            <!-- velocity代码生成使用模板 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.apache.velocity</groupId>
 | 
			
		||||
                <artifactId>velocity</artifactId>
 | 
			
		||||
                <artifactId>velocity-engine-core</artifactId>
 | 
			
		||||
                <version>${velocity.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- Token生成与解析-->
 | 
			
		||||
            <!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>io.jsonwebtoken</groupId>
 | 
			
		||||
                <artifactId>jjwt</artifactId>
 | 
			
		||||
                <version>${jwt.version}</version>
 | 
			
		||||
                <groupId>cn.dev33</groupId>
 | 
			
		||||
                <artifactId>sa-token-spring-boot-starter</artifactId>
 | 
			
		||||
                <version>${satoken.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- jdk11 缺失依赖 jaxb-->
 | 
			
		||||
            <!-- Sa-Token 整合 jwt -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.sun.xml.bind</groupId>
 | 
			
		||||
                <artifactId>jaxb-impl</artifactId>
 | 
			
		||||
                <version>${jaxb.version}</version>
 | 
			
		||||
                <groupId>cn.dev33</groupId>
 | 
			
		||||
                <artifactId>sa-token-jwt</artifactId>
 | 
			
		||||
                <version>${satoken.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <groupId>cn.hutool</groupId>
 | 
			
		||||
                        <artifactId>hutool-all</artifactId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- dynamic-datasource 多数据源-->
 | 
			
		||||
@@ -150,11 +176,7 @@
 | 
			
		||||
                <artifactId>mybatis-plus-boot-starter</artifactId>
 | 
			
		||||
                <version>${mybatis-plus.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.baomidou</groupId>
 | 
			
		||||
                <artifactId>mybatis-plus-extension</artifactId>
 | 
			
		||||
                <version>${mybatis-plus.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- sql性能分析插件 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>p6spy</groupId>
 | 
			
		||||
@@ -162,37 +184,25 @@
 | 
			
		||||
                <version>${p6spy.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>cn.hutool</groupId>
 | 
			
		||||
                <artifactId>hutool-all</artifactId>
 | 
			
		||||
                <version>${hutool.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.cloud</groupId>
 | 
			
		||||
                <artifactId>spring-cloud-starter-openfeign</artifactId>
 | 
			
		||||
                <version>${feign.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <artifactId>feign-core</artifactId>
 | 
			
		||||
                        <groupId>io.github.openfeign</groupId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>io.github.openfeign</groupId>
 | 
			
		||||
                <artifactId>feign-okhttp</artifactId>
 | 
			
		||||
                <version>${feign-okhttp.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.squareup.okhttp3</groupId>
 | 
			
		||||
                <artifactId>okhttp</artifactId>
 | 
			
		||||
                <version>${okhttp.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.amazonaws</groupId>
 | 
			
		||||
                <artifactId>aws-java-sdk-s3</artifactId>
 | 
			
		||||
                <version>${aws-java-sdk-s3.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!--短信sms4j-->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.dromara.sms4j</groupId>
 | 
			
		||||
                <artifactId>sms4j-spring-boot-starter</artifactId>
 | 
			
		||||
                <version>${sms4j.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>de.codecentric</groupId>
 | 
			
		||||
                <artifactId>spring-boot-admin-starter-server</artifactId>
 | 
			
		||||
@@ -209,7 +219,19 @@
 | 
			
		||||
                <groupId>org.redisson</groupId>
 | 
			
		||||
                <artifactId>redisson-spring-boot-starter</artifactId>
 | 
			
		||||
                <version>${redisson.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <groupId>org.redisson</groupId>
 | 
			
		||||
                        <artifactId>redisson-spring-data-30</artifactId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.redisson</groupId>
 | 
			
		||||
                <artifactId>redisson-spring-data-27</artifactId>
 | 
			
		||||
                <version>${redisson.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.baomidou</groupId>
 | 
			
		||||
                <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
 | 
			
		||||
@@ -224,44 +246,23 @@
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.yomahub</groupId>
 | 
			
		||||
                <artifactId>tlog-spring-boot-configuration</artifactId>
 | 
			
		||||
                <version>${tlog.version}</version>
 | 
			
		||||
                <groupId>com.alibaba</groupId>
 | 
			
		||||
                <artifactId>transmittable-thread-local</artifactId>
 | 
			
		||||
                <version>${alibaba-ttl.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- 离线IP地址定位库 ip2region -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.yomahub</groupId>
 | 
			
		||||
                <artifactId>tlog-webroot</artifactId>
 | 
			
		||||
                <version>${tlog.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <artifactId>javassist</artifactId>
 | 
			
		||||
                        <groupId>org.javassist</groupId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <artifactId>guava</artifactId>
 | 
			
		||||
                        <groupId>com.google.guava</groupId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
                <groupId>org.lionsoul</groupId>
 | 
			
		||||
                <artifactId>ip2region</artifactId>
 | 
			
		||||
                <version>${ip2region.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- 加密包引入 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.yomahub</groupId>
 | 
			
		||||
                <artifactId>tlog-feign</artifactId>
 | 
			
		||||
                <version>${tlog.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.yomahub</groupId>
 | 
			
		||||
                <artifactId>tlog-xxl-job</artifactId>
 | 
			
		||||
                <version>${tlog.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- 定时任务 @deprecated 3.4.0删除 迁移至xxl-job -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.ruoyi</groupId>
 | 
			
		||||
                <artifactId>ruoyi-quartz</artifactId>
 | 
			
		||||
                <version>${ruoyi-vue-plus.version}</version>
 | 
			
		||||
                <groupId>org.bouncycastle</groupId>
 | 
			
		||||
                <artifactId>bcprov-jdk15to18</artifactId>
 | 
			
		||||
                <version>${bouncycastle.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- 定时任务 -->
 | 
			
		||||
@@ -306,6 +307,13 @@
 | 
			
		||||
                <version>${ruoyi-vue-plus.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- SMS短信模块 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.ruoyi</groupId>
 | 
			
		||||
                <artifactId>ruoyi-sms</artifactId>
 | 
			
		||||
                <version>${ruoyi-vue-plus.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
 | 
			
		||||
            <!-- demo模块 -->
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>com.ruoyi</groupId>
 | 
			
		||||
@@ -320,13 +328,13 @@
 | 
			
		||||
        <module>ruoyi-admin</module>
 | 
			
		||||
        <module>ruoyi-framework</module>
 | 
			
		||||
        <module>ruoyi-system</module>
 | 
			
		||||
        <module>ruoyi-quartz</module>
 | 
			
		||||
        <module>ruoyi-job</module>
 | 
			
		||||
        <module>ruoyi-generator</module>
 | 
			
		||||
        <module>ruoyi-common</module>
 | 
			
		||||
        <module>ruoyi-demo</module>
 | 
			
		||||
        <module>ruoyi-extend</module>
 | 
			
		||||
        <module>ruoyi-oss</module>
 | 
			
		||||
        <module>ruoyi-sms</module>
 | 
			
		||||
    </modules>
 | 
			
		||||
    <packaging>pom</packaging>
 | 
			
		||||
 | 
			
		||||
@@ -335,18 +343,58 @@
 | 
			
		||||
            <plugin>
 | 
			
		||||
                <groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
                <artifactId>maven-compiler-plugin</artifactId>
 | 
			
		||||
                <version>3.1</version>
 | 
			
		||||
                <version>3.9.0</version>
 | 
			
		||||
                <configuration>
 | 
			
		||||
                    <source>${java.version}</source>
 | 
			
		||||
                    <target>${java.version}</target>
 | 
			
		||||
                    <encoding>${project.build.sourceEncoding}</encoding>
 | 
			
		||||
                    <annotationProcessorPaths>
 | 
			
		||||
                        <path>
 | 
			
		||||
                            <groupId>com.github.therapi</groupId>
 | 
			
		||||
                            <artifactId>therapi-runtime-javadoc-scribe</artifactId>
 | 
			
		||||
                            <version>0.15.0</version>
 | 
			
		||||
                        </path>
 | 
			
		||||
                        <path>
 | 
			
		||||
                            <groupId>org.projectlombok</groupId>
 | 
			
		||||
                            <artifactId>lombok</artifactId>
 | 
			
		||||
                            <version>${lombok.version}</version>
 | 
			
		||||
                        </path>
 | 
			
		||||
                        <path>
 | 
			
		||||
                            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
                            <artifactId>spring-boot-configuration-processor</artifactId>
 | 
			
		||||
                            <version>${spring-boot.version}</version>
 | 
			
		||||
                        </path>
 | 
			
		||||
                    </annotationProcessorPaths>
 | 
			
		||||
                </configuration>
 | 
			
		||||
            </plugin>
 | 
			
		||||
            <!-- 单元测试使用 -->
 | 
			
		||||
            <plugin>
 | 
			
		||||
                <groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
                <artifactId>maven-surefire-plugin</artifactId>
 | 
			
		||||
                <version>2.22.2</version>
 | 
			
		||||
                <configuration>
 | 
			
		||||
                    <argLine>-Dfile.encoding=UTF-8</argLine>
 | 
			
		||||
                    <!-- 根据打包环境执行对应的@Tag测试方法 -->
 | 
			
		||||
                    <groups>${profiles.active}</groups>
 | 
			
		||||
                    <!-- 排除标签 -->
 | 
			
		||||
                    <excludedGroups>exclude</excludedGroups>
 | 
			
		||||
                </configuration>
 | 
			
		||||
            </plugin>
 | 
			
		||||
        </plugins>
 | 
			
		||||
        <resources>
 | 
			
		||||
            <resource>
 | 
			
		||||
                <!--打包该目录下的 application.yml -->
 | 
			
		||||
                <directory>src/main/resources</directory>
 | 
			
		||||
                <!-- 关闭过滤 -->
 | 
			
		||||
                <filtering>false</filtering>
 | 
			
		||||
            </resource>
 | 
			
		||||
            <resource>
 | 
			
		||||
                <directory>src/main/resources</directory>
 | 
			
		||||
                <!-- 引入所有 匹配文件进行过滤 -->
 | 
			
		||||
                <includes>
 | 
			
		||||
                    <include>application*</include>
 | 
			
		||||
                    <include>bootstrap*</include>
 | 
			
		||||
                    <include>banner*</include>
 | 
			
		||||
                </includes>
 | 
			
		||||
                <!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
 | 
			
		||||
                <filtering>true</filtering>
 | 
			
		||||
            </resource>
 | 
			
		||||
@@ -356,8 +404,8 @@
 | 
			
		||||
    <repositories>
 | 
			
		||||
        <repository>
 | 
			
		||||
            <id>public</id>
 | 
			
		||||
            <name>aliyun nexus</name>
 | 
			
		||||
            <url>https://maven.aliyun.com/repository/public/</url>
 | 
			
		||||
            <name>huawei nexus</name>
 | 
			
		||||
            <url>https://mirrors.huaweicloud.com/repository/maven/</url>
 | 
			
		||||
            <releases>
 | 
			
		||||
                <enabled>true</enabled>
 | 
			
		||||
            </releases>
 | 
			
		||||
@@ -367,8 +415,8 @@
 | 
			
		||||
    <pluginRepositories>
 | 
			
		||||
        <pluginRepository>
 | 
			
		||||
            <id>public</id>
 | 
			
		||||
            <name>aliyun nexus</name>
 | 
			
		||||
            <url>https://maven.aliyun.com/repository/public/</url>
 | 
			
		||||
            <name>huawei nexus</name>
 | 
			
		||||
            <url>https://mirrors.huaweicloud.com/repository/maven/</url>
 | 
			
		||||
            <releases>
 | 
			
		||||
                <enabled>true</enabled>
 | 
			
		||||
            </releases>
 | 
			
		||||
@@ -378,37 +426,6 @@
 | 
			
		||||
        </pluginRepository>
 | 
			
		||||
    </pluginRepositories>
 | 
			
		||||
 | 
			
		||||
    <profiles>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>local</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <!-- 环境标识,需要与配置文件的名称相对应 -->
 | 
			
		||||
                <profiles.active>local</profiles.active>
 | 
			
		||||
                <logging.level>debug</logging.level>
 | 
			
		||||
                <endpoints.include>'*'</endpoints.include>
 | 
			
		||||
            </properties>
 | 
			
		||||
        </profile>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>dev</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <!-- 环境标识,需要与配置文件的名称相对应 -->
 | 
			
		||||
                <profiles.active>dev</profiles.active>
 | 
			
		||||
                <logging.level>debug</logging.level>
 | 
			
		||||
                <endpoints.include>'*'</endpoints.include>
 | 
			
		||||
            </properties>
 | 
			
		||||
            <activation>
 | 
			
		||||
                <!-- 默认环境 -->
 | 
			
		||||
                <activeByDefault>true</activeByDefault>
 | 
			
		||||
            </activation>
 | 
			
		||||
        </profile>
 | 
			
		||||
        <profile>
 | 
			
		||||
            <id>prod</id>
 | 
			
		||||
            <properties>
 | 
			
		||||
                <profiles.active>prod</profiles.active>
 | 
			
		||||
                <logging.level>warn</logging.level>
 | 
			
		||||
                <endpoints.include>health, info, logfile</endpoints.include>
 | 
			
		||||
            </properties>
 | 
			
		||||
        </profile>
 | 
			
		||||
    </profiles>
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,22 @@ FROM anapsix/alpine-java:8_server-jre_unlimited
 | 
			
		||||
 | 
			
		||||
MAINTAINER Lion Li
 | 
			
		||||
 | 
			
		||||
RUN mkdir -p /ruoyi/server
 | 
			
		||||
RUN mkdir -p /ruoyi/server/logs
 | 
			
		||||
RUN mkdir -p /ruoyi/server/logs \
 | 
			
		||||
    /ruoyi/server/temp \
 | 
			
		||||
    /ruoyi/skywalking/agent
 | 
			
		||||
 | 
			
		||||
WORKDIR /ruoyi/server
 | 
			
		||||
 | 
			
		||||
EXPOSE 8080
 | 
			
		||||
ENV SERVER_PORT=8080
 | 
			
		||||
 | 
			
		||||
EXPOSE ${SERVER_PORT}
 | 
			
		||||
 | 
			
		||||
ADD ./target/ruoyi-admin.jar ./app.jar
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
 | 
			
		||||
ENTRYPOINT ["java", \
 | 
			
		||||
            "-Djava.security.egd=file:/dev/./urandom", \
 | 
			
		||||
            "-Dserver.port=${SERVER_PORT}", \
 | 
			
		||||
            # 应用名称 如果想区分集群节点监控 改成不同的名称即可
 | 
			
		||||
#            "-Dskywalking.agent.service_name=ruoyi-server", \
 | 
			
		||||
#            "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \
 | 
			
		||||
            "-jar", "app.jar"]
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <artifactId>ruoyi-vue-plus</artifactId>
 | 
			
		||||
        <groupId>com.ruoyi</groupId>
 | 
			
		||||
        <version>3.3.0</version>
 | 
			
		||||
        <version>4.8.2</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
    <packaging>jar</packaging>
 | 
			
		||||
@@ -26,8 +26,23 @@
 | 
			
		||||
 | 
			
		||||
        <!-- Mysql驱动包 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>mysql</groupId>
 | 
			
		||||
            <artifactId>mysql-connector-java</artifactId>
 | 
			
		||||
            <groupId>com.mysql</groupId>
 | 
			
		||||
            <artifactId>mysql-connector-j</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- Oracle -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.oracle.database.jdbc</groupId>
 | 
			
		||||
            <artifactId>ojdbc8</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- PostgreSql -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.postgresql</groupId>
 | 
			
		||||
            <artifactId>postgresql</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- SqlServer -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.microsoft.sqlserver</groupId>
 | 
			
		||||
            <artifactId>mssql-jdbc</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 核心模块-->
 | 
			
		||||
@@ -41,12 +56,6 @@
 | 
			
		||||
            <artifactId>ruoyi-system</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 定时任务 @deprecated 3.4.0删除 迁移至xxl-job -->
 | 
			
		||||
<!--        <dependency>-->
 | 
			
		||||
<!--            <groupId>com.ruoyi</groupId>-->
 | 
			
		||||
<!--            <artifactId>ruoyi-quartz</artifactId>-->
 | 
			
		||||
<!--        </dependency>-->
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.ruoyi</groupId>
 | 
			
		||||
            <artifactId>ruoyi-job</artifactId>
 | 
			
		||||
@@ -69,6 +78,24 @@
 | 
			
		||||
            <artifactId>ruoyi-demo</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-test</artifactId>
 | 
			
		||||
            <scope>test</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- skywalking 整合 logback -->
 | 
			
		||||
<!--        <dependency>-->
 | 
			
		||||
<!--            <groupId>org.apache.skywalking</groupId>-->
 | 
			
		||||
<!--            <artifactId>apm-toolkit-logback-1.x</artifactId>-->
 | 
			
		||||
<!--            <version>${与你的agent探针版本保持一致}</version>-->
 | 
			
		||||
<!--        </dependency>-->
 | 
			
		||||
<!--        <dependency>-->
 | 
			
		||||
<!--            <groupId>org.apache.skywalking</groupId>-->
 | 
			
		||||
<!--            <artifactId>apm-toolkit-trace</artifactId>-->
 | 
			
		||||
<!--            <version>${与你的agent探针版本保持一致}</version>-->
 | 
			
		||||
<!--        </dependency>-->
 | 
			
		||||
 | 
			
		||||
    </dependencies>
 | 
			
		||||
 | 
			
		||||
    <build>
 | 
			
		||||
@@ -92,31 +119,12 @@
 | 
			
		||||
            <plugin>
 | 
			
		||||
                <groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
                <artifactId>maven-war-plugin</artifactId>
 | 
			
		||||
                <version>3.2.0</version>
 | 
			
		||||
                <version>3.2.2</version>
 | 
			
		||||
                <configuration>
 | 
			
		||||
                    <failOnMissingWebXml>false</failOnMissingWebXml>
 | 
			
		||||
                    <warName>${project.artifactId}</warName>
 | 
			
		||||
                </configuration>
 | 
			
		||||
            </plugin>
 | 
			
		||||
            <plugin>
 | 
			
		||||
                <groupId>com.spotify</groupId>
 | 
			
		||||
                <artifactId>docker-maven-plugin</artifactId>
 | 
			
		||||
                <version>${docker.plugin.version}</version>
 | 
			
		||||
                <configuration>
 | 
			
		||||
                    <imageName>${docker.namespace}/ruoyi-server:${project.version}</imageName>
 | 
			
		||||
                    <dockerDirectory>${project.basedir}</dockerDirectory>
 | 
			
		||||
                    <dockerHost>${docker.registry.host}</dockerHost>
 | 
			
		||||
                    <registryUrl>${docker.registry.url}</registryUrl>
 | 
			
		||||
                    <serverId>${docker.registry.url}</serverId>
 | 
			
		||||
                    <resources>
 | 
			
		||||
                        <resource>
 | 
			
		||||
                            <targetPath>/</targetPath>
 | 
			
		||||
                            <directory>${project.build.directory}</directory>
 | 
			
		||||
                            <include>${project.build.finalName}.jar</include>
 | 
			
		||||
                        </resource>
 | 
			
		||||
                    </resources>
 | 
			
		||||
                </configuration>
 | 
			
		||||
            </plugin>
 | 
			
		||||
        </plugins>
 | 
			
		||||
    </build>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package com.ruoyi;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
 | 
			
		||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 启动程序
 | 
			
		||||
@@ -14,7 +15,9 @@ public class RuoYiApplication {
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args) {
 | 
			
		||||
        System.setProperty("spring.devtools.restart.enabled", "false");
 | 
			
		||||
        SpringApplication.run(RuoYiApplication.class, args);
 | 
			
		||||
        SpringApplication application = new SpringApplication(RuoYiApplication.class);
 | 
			
		||||
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
 | 
			
		||||
        application.run(args);
 | 
			
		||||
        System.out.println("(♥◠‿◠)ノ゙  RuoYi-Vue-Plus启动成功   ლ(´ڡ`ლ)゙");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,57 +1,116 @@
 | 
			
		||||
package com.ruoyi.web.controller.common;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaIgnore;
 | 
			
		||||
import cn.hutool.captcha.AbstractCaptcha;
 | 
			
		||||
import cn.hutool.captcha.generator.CodeGenerator;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.hutool.core.util.IdUtil;
 | 
			
		||||
import cn.hutool.core.util.RandomUtil;
 | 
			
		||||
import com.ruoyi.common.constant.CacheConstants;
 | 
			
		||||
import com.ruoyi.common.constant.Constants;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.enums.CaptchaType;
 | 
			
		||||
import com.ruoyi.common.utils.RedisUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.email.MailUtils;
 | 
			
		||||
import com.ruoyi.common.utils.redis.RedisUtils;
 | 
			
		||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
 | 
			
		||||
import com.ruoyi.common.utils.spring.SpringUtils;
 | 
			
		||||
import com.ruoyi.framework.config.properties.CaptchaProperties;
 | 
			
		||||
import com.ruoyi.framework.config.properties.MailProperties;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.dromara.sms4j.api.SmsBlend;
 | 
			
		||||
import org.dromara.sms4j.api.entity.SmsResponse;
 | 
			
		||||
import org.dromara.sms4j.core.factory.SmsFactory;
 | 
			
		||||
import org.dromara.sms4j.provider.enumerate.SupplierType;
 | 
			
		||||
import org.springframework.expression.Expression;
 | 
			
		||||
import org.springframework.expression.ExpressionParser;
 | 
			
		||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import java.time.Duration;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 验证码操作处理
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Api(value = "验证码操作处理", tags = {"验证码管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@SaIgnore
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Validated
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
public class CaptchaController {
 | 
			
		||||
 | 
			
		||||
    private final CaptchaProperties captchaProperties;
 | 
			
		||||
    private final ISysConfigService configService;
 | 
			
		||||
    private final MailProperties mailProperties;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信验证码
 | 
			
		||||
     *
 | 
			
		||||
     * @param phonenumber 用户手机号
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/captchaSms")
 | 
			
		||||
    public R<Void> smsCaptcha(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
 | 
			
		||||
        String key = CacheConstants.CAPTCHA_CODE_KEY + phonenumber;
 | 
			
		||||
        String code = RandomUtil.randomNumbers(4);
 | 
			
		||||
        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
 | 
			
		||||
        // 验证码模板id 自行处理 (查数据库或写死均可)
 | 
			
		||||
        String templateId = "";
 | 
			
		||||
        LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
 | 
			
		||||
        map.put("code", code);
 | 
			
		||||
        SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
 | 
			
		||||
        SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
 | 
			
		||||
        if (!"OK".equals(smsResponse.getCode())) {
 | 
			
		||||
            log.error("验证码短信发送异常 => {}", smsResponse);
 | 
			
		||||
            return R.fail(smsResponse.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱验证码
 | 
			
		||||
     *
 | 
			
		||||
     * @param email 邮箱
 | 
			
		||||
     */
 | 
			
		||||
    @GetMapping("/captchaEmail")
 | 
			
		||||
    public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) {
 | 
			
		||||
        if (!mailProperties.getEnabled()) {
 | 
			
		||||
            return R.fail("当前系统没有开启邮箱功能!");
 | 
			
		||||
        }
 | 
			
		||||
        String key = CacheConstants.CAPTCHA_CODE_KEY + email;
 | 
			
		||||
        String code = RandomUtil.randomNumbers(4);
 | 
			
		||||
        RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
 | 
			
		||||
        try {
 | 
			
		||||
            MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            log.error("验证码短信发送异常 => {}", e.getMessage());
 | 
			
		||||
            return R.fail(e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 生成验证码
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("生成验证码")
 | 
			
		||||
    @GetMapping("/captchaImage")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> getCode() {
 | 
			
		||||
    public R<Map<String, Object>> getCode() {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        boolean captchaOnOff = configService.selectCaptchaOnOff();
 | 
			
		||||
        ajax.put("captchaOnOff", captchaOnOff);
 | 
			
		||||
        if (!captchaOnOff) {
 | 
			
		||||
            return AjaxResult.success(ajax);
 | 
			
		||||
        boolean captchaEnabled = configService.selectCaptchaEnabled();
 | 
			
		||||
        ajax.put("captchaEnabled", captchaEnabled);
 | 
			
		||||
        if (!captchaEnabled) {
 | 
			
		||||
            return R.ok(ajax);
 | 
			
		||||
        }
 | 
			
		||||
        // 保存验证码信息
 | 
			
		||||
        String uuid = IdUtil.simpleUUID();
 | 
			
		||||
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
 | 
			
		||||
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
 | 
			
		||||
        // 生成验证码
 | 
			
		||||
        CaptchaType captchaType = captchaProperties.getType();
 | 
			
		||||
        boolean isMath = CaptchaType.MATH == captchaType;
 | 
			
		||||
@@ -60,28 +119,16 @@ public class CaptchaController {
 | 
			
		||||
        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
 | 
			
		||||
        captcha.setGenerator(codeGenerator);
 | 
			
		||||
        captcha.createCode();
 | 
			
		||||
        String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode();
 | 
			
		||||
        RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
 | 
			
		||||
        String code = captcha.getCode();
 | 
			
		||||
        if (isMath) {
 | 
			
		||||
            ExpressionParser parser = new SpelExpressionParser();
 | 
			
		||||
            Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
 | 
			
		||||
            code = exp.getValue(String.class);
 | 
			
		||||
        }
 | 
			
		||||
        RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
 | 
			
		||||
        ajax.put("uuid", uuid);
 | 
			
		||||
        ajax.put("img", captcha.getImageBase64());
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getCodeResult(String capStr) {
 | 
			
		||||
        int numberLength = captchaProperties.getNumberLength();
 | 
			
		||||
        int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim());
 | 
			
		||||
        char operator = capStr.charAt(numberLength);
 | 
			
		||||
        int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
 | 
			
		||||
        switch (operator) {
 | 
			
		||||
            case '*':
 | 
			
		||||
                return Convert.toStr(a * b);
 | 
			
		||||
            case '+':
 | 
			
		||||
                return Convert.toStr(a + b);
 | 
			
		||||
            case '-':
 | 
			
		||||
                return Convert.toStr(a - b);
 | 
			
		||||
            default:
 | 
			
		||||
                return StringUtils.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,58 @@
 | 
			
		||||
package com.ruoyi.web.controller.monitor;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import com.ruoyi.common.constant.CacheConstants;
 | 
			
		||||
import com.ruoyi.common.constant.CacheNames;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.utils.JsonUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import com.ruoyi.common.utils.redis.CacheUtils;
 | 
			
		||||
import com.ruoyi.common.utils.redis.RedisUtils;
 | 
			
		||||
import com.ruoyi.system.domain.SysCache;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.data.redis.connection.RedisServerCommands;
 | 
			
		||||
import org.springframework.data.redis.core.RedisCallback;
 | 
			
		||||
import org.springframework.data.redis.core.RedisTemplate;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.redisson.spring.data.connection.RedissonConnectionFactory;
 | 
			
		||||
import org.springframework.data.redis.connection.RedisConnection;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 缓存监控
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Api(value = "缓存监控", tags = {"缓存监控管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/monitor/cache")
 | 
			
		||||
public class CacheController {
 | 
			
		||||
 | 
			
		||||
    private final RedisTemplate<String, String> redisTemplate;
 | 
			
		||||
    private final RedissonConnectionFactory connectionFactory;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("获取缓存监控详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
 | 
			
		||||
    private final static List<SysCache> CACHES = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        CACHES.add(new SysCache(CacheConstants.ONLINE_TOKEN_KEY, "在线用户"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheNames.SYS_CONFIG, "配置信息"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheNames.SYS_DICT, "数据字典"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheNames.SYS_OSS_CONFIG, "OSS配置"));
 | 
			
		||||
        CACHES.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取缓存监控列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @GetMapping()
 | 
			
		||||
    public AjaxResult<Map<String, Object>> getInfo() throws Exception {
 | 
			
		||||
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::info);
 | 
			
		||||
        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
 | 
			
		||||
        Object dbSize = redisTemplate.execute((RedisCallback<Object>) RedisServerCommands::dbSize);
 | 
			
		||||
    public R<Map<String, Object>> getInfo() throws Exception {
 | 
			
		||||
        RedisConnection connection = connectionFactory.getConnection();
 | 
			
		||||
        Properties info = connection.info();
 | 
			
		||||
        Properties commandStats = connection.info("commandstats");
 | 
			
		||||
        Long dbSize = connection.dbSize();
 | 
			
		||||
 | 
			
		||||
        Map<String, Object> result = new HashMap<>(3);
 | 
			
		||||
        result.put("info", info);
 | 
			
		||||
@@ -52,6 +69,100 @@ public class CacheController {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        result.put("commandStats", pieList);
 | 
			
		||||
        return AjaxResult.success(result);
 | 
			
		||||
        return R.ok(result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取缓存监控缓存名列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @GetMapping("/getNames")
 | 
			
		||||
    public R<List<SysCache>> cache() {
 | 
			
		||||
        return R.ok(CACHES);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取缓存监控Key列表
 | 
			
		||||
     *
 | 
			
		||||
     * @param cacheName 缓存名
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @GetMapping("/getKeys/{cacheName}")
 | 
			
		||||
    public R<Collection<String>> getCacheKeys(@PathVariable String cacheName) {
 | 
			
		||||
        Collection<String> cacheKeys = new HashSet<>(0);
 | 
			
		||||
        if (isCacheNames(cacheName)) {
 | 
			
		||||
            Set<Object> keys = CacheUtils.keys(cacheName);
 | 
			
		||||
            if (CollUtil.isNotEmpty(keys)) {
 | 
			
		||||
                cacheKeys = keys.stream().map(Object::toString).collect(Collectors.toList());
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            cacheKeys = RedisUtils.keys(cacheName + "*");
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok(cacheKeys);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取缓存监控缓存值详情
 | 
			
		||||
     *
 | 
			
		||||
     * @param cacheName 缓存名
 | 
			
		||||
     * @param cacheKey  缓存key
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @GetMapping("/getValue/{cacheName}/{cacheKey}")
 | 
			
		||||
    public R<SysCache> getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) {
 | 
			
		||||
        Object cacheValue;
 | 
			
		||||
        if (isCacheNames(cacheName)) {
 | 
			
		||||
            cacheValue = CacheUtils.get(cacheName, cacheKey);
 | 
			
		||||
        } else {
 | 
			
		||||
            cacheValue = RedisUtils.getCacheObject(cacheKey);
 | 
			
		||||
        }
 | 
			
		||||
        SysCache sysCache = new SysCache(cacheName, cacheKey, JsonUtils.toJsonString(cacheValue));
 | 
			
		||||
        return R.ok(sysCache);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 清理缓存监控缓存名
 | 
			
		||||
     *
 | 
			
		||||
     * @param cacheName 缓存名
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @DeleteMapping("/clearCacheName/{cacheName}")
 | 
			
		||||
    public R<Void> clearCacheName(@PathVariable String cacheName) {
 | 
			
		||||
        if (isCacheNames(cacheName)) {
 | 
			
		||||
            CacheUtils.clear(cacheName);
 | 
			
		||||
        } else {
 | 
			
		||||
            RedisUtils.deleteKeys(cacheName + "*");
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 清理缓存监控Key
 | 
			
		||||
     *
 | 
			
		||||
     * @param cacheKey key名
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @DeleteMapping("/clearCacheKey/{cacheName}/{cacheKey}")
 | 
			
		||||
    public R<Void> clearCacheKey(@PathVariable String cacheName, @PathVariable String cacheKey) {
 | 
			
		||||
        if (isCacheNames(cacheName)) {
 | 
			
		||||
            CacheUtils.evict(cacheName, cacheKey);
 | 
			
		||||
        } else {
 | 
			
		||||
            RedisUtils.deleteObject(cacheKey);
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 清理全部缓存监控
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:cache:list")
 | 
			
		||||
    @DeleteMapping("/clearCacheAll")
 | 
			
		||||
    public R<Void> clearCacheAll() {
 | 
			
		||||
        RedisUtils.deleteKeys("*");
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isCacheNames(String cacheName) {
 | 
			
		||||
        return !StringUtils.contains(cacheName, ":");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,18 @@
 | 
			
		||||
package com.ruoyi.web.controller.monitor;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.CacheConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.common.utils.redis.RedisUtils;
 | 
			
		||||
import com.ruoyi.system.domain.SysLogininfor;
 | 
			
		||||
import com.ruoyi.system.service.ISysLogininforService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -25,44 +25,64 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "系统访问记录", tags = {"系统访问记录管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/monitor/logininfor")
 | 
			
		||||
public class SysLogininforController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysLogininforService logininforService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("查询系统访问记录列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取系统访问记录列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:logininfor:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor) {
 | 
			
		||||
        return logininforService.selectPageLogininforList(logininfor);
 | 
			
		||||
    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor, PageQuery pageQuery) {
 | 
			
		||||
        return logininforService.selectPageLogininforList(logininfor, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出系统访问记录列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出系统访问记录列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "登录日志", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("monitor:logininfor:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysLogininfor logininfor, HttpServletResponse response) {
 | 
			
		||||
        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "登录日志", SysLogininfor.class, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("删除系统访问记录")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 批量删除登录日志
 | 
			
		||||
     * @param infoIds 日志ids
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:logininfor:remove")
 | 
			
		||||
    @Log(title = "登录日志", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{infoIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] infoIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] infoIds) {
 | 
			
		||||
        return toAjax(logininforService.deleteLogininforByIds(infoIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("清空系统访问记录")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 清理系统访问记录
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:logininfor:remove")
 | 
			
		||||
    @Log(title = "登录日志", businessType = BusinessType.CLEAN)
 | 
			
		||||
    @DeleteMapping("/clean")
 | 
			
		||||
    public AjaxResult<Void> clean() {
 | 
			
		||||
    public R<Void> clean() {
 | 
			
		||||
        logininforService.cleanLogininfor();
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SaCheckPermission("monitor:logininfor:unlock")
 | 
			
		||||
    @Log(title = "账户解锁", businessType = BusinessType.OTHER)
 | 
			
		||||
    @GetMapping("/unlock/{userName}")
 | 
			
		||||
    public R<Void> unlock(@PathVariable("userName") String userName) {
 | 
			
		||||
        String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName;
 | 
			
		||||
        if (RedisUtils.hasKey(loginName)) {
 | 
			
		||||
            RedisUtils.deleteObject(loginName);
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,16 @@
 | 
			
		||||
package com.ruoyi.web.controller.monitor;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.domain.SysOperLog;
 | 
			
		||||
import com.ruoyi.system.service.ISysOperLogService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -25,44 +23,52 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "操作日志记录", tags = {"操作日志记录管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/monitor/operlog")
 | 
			
		||||
public class SysOperlogController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysOperLogService operLogService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("查询操作日志记录列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取操作日志记录列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:operlog:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysOperLog> list(SysOperLog operLog) {
 | 
			
		||||
        return operLogService.selectPageOperLogList(operLog);
 | 
			
		||||
    public TableDataInfo<SysOperLog> list(SysOperLog operLog, PageQuery pageQuery) {
 | 
			
		||||
        return operLogService.selectPageOperLogList(operLog, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出操作日志记录列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出操作日志记录列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("monitor:operlog:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysOperLog operLog, HttpServletResponse response) {
 | 
			
		||||
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "操作日志", SysOperLog.class, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("删除操作日志记录")
 | 
			
		||||
    /**
 | 
			
		||||
     * 批量删除操作日志记录
 | 
			
		||||
     * @param operIds 日志ids
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "操作日志", businessType = BusinessType.DELETE)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
 | 
			
		||||
    @SaCheckPermission("monitor:operlog:remove")
 | 
			
		||||
    @DeleteMapping("/{operIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] operIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] operIds) {
 | 
			
		||||
        return toAjax(operLogService.deleteOperLogByIds(operIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("清空操作日志记录")
 | 
			
		||||
    /**
 | 
			
		||||
     * 清理操作日志记录
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
 | 
			
		||||
    @SaCheckPermission("monitor:operlog:remove")
 | 
			
		||||
    @DeleteMapping("/clean")
 | 
			
		||||
    public AjaxResult<Void> clean() {
 | 
			
		||||
    public R<Void> clean() {
 | 
			
		||||
        operLogService.cleanOperLog();
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,24 @@
 | 
			
		||||
package com.ruoyi.web.controller.monitor;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.dev33.satoken.exception.NotLoginException;
 | 
			
		||||
import cn.dev33.satoken.stp.StpUtil;
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.Constants;
 | 
			
		||||
import com.ruoyi.common.constant.CacheConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.LoginUser;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.PageUtils;
 | 
			
		||||
import com.ruoyi.common.utils.RedisUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StreamUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.redis.RedisUtils;
 | 
			
		||||
import com.ruoyi.system.domain.SysUserOnline;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserOnlineService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@@ -29,52 +27,64 @@ import java.util.List;
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Api(value = "在线用户监控", tags = {"在线用户监控管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/monitor/online")
 | 
			
		||||
public class SysUserOnlineController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysUserOnlineService userOnlineService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("在线用户列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取在线用户监控列表
 | 
			
		||||
     *
 | 
			
		||||
     * @param ipaddr   IP地址
 | 
			
		||||
     * @param userName 用户名
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("monitor:online:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysUserOnline> list(String ipaddr, String userName) {
 | 
			
		||||
        Collection<String> keys = RedisUtils.keys(Constants.LOGIN_TOKEN_KEY + "*");
 | 
			
		||||
        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
 | 
			
		||||
        // 获取所有未过期的 token
 | 
			
		||||
        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
 | 
			
		||||
        List<UserOnlineDTO> userOnlineDTOList = new ArrayList<>();
 | 
			
		||||
        for (String key : keys) {
 | 
			
		||||
            LoginUser user = RedisUtils.getCacheObject(key);
 | 
			
		||||
            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
 | 
			
		||||
                if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) {
 | 
			
		||||
                    userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
 | 
			
		||||
                }
 | 
			
		||||
            } else if (StringUtils.isNotEmpty(ipaddr)) {
 | 
			
		||||
                if (StringUtils.equals(ipaddr, user.getIpaddr())) {
 | 
			
		||||
                    userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
 | 
			
		||||
                }
 | 
			
		||||
            } else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) {
 | 
			
		||||
                if (StringUtils.equals(userName, user.getUsername())) {
 | 
			
		||||
                    userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
 | 
			
		||||
            String token = StringUtils.substringAfterLast(key, ":");
 | 
			
		||||
            // 如果已经过期则跳过
 | 
			
		||||
            if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token));
 | 
			
		||||
        }
 | 
			
		||||
        Collections.reverse(userOnlineList);
 | 
			
		||||
        userOnlineList.removeAll(Collections.singleton(null));
 | 
			
		||||
        return PageUtils.buildDataInfo(userOnlineList);
 | 
			
		||||
        if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
 | 
			
		||||
            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
 | 
			
		||||
                StringUtils.equals(ipaddr, userOnline.getIpaddr()) &&
 | 
			
		||||
                    StringUtils.equals(userName, userOnline.getUserName())
 | 
			
		||||
            );
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(ipaddr)) {
 | 
			
		||||
            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
 | 
			
		||||
                StringUtils.equals(ipaddr, userOnline.getIpaddr())
 | 
			
		||||
            );
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(userName)) {
 | 
			
		||||
            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
 | 
			
		||||
                StringUtils.equals(userName, userOnline.getUserName())
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        Collections.reverse(userOnlineDTOList);
 | 
			
		||||
        userOnlineDTOList.removeAll(Collections.singleton(null));
 | 
			
		||||
        List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
 | 
			
		||||
        return TableDataInfo.build(userOnlineList);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 强退用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param tokenId token值
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("强退用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
 | 
			
		||||
    @SaCheckPermission("monitor:online:forceLogout")
 | 
			
		||||
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
 | 
			
		||||
    @DeleteMapping("/{tokenId}")
 | 
			
		||||
    public AjaxResult<Void> forceLogout(@PathVariable String tokenId) {
 | 
			
		||||
        RedisUtils.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
    public R<Void> forceLogout(@PathVariable String tokenId) {
 | 
			
		||||
        try {
 | 
			
		||||
            StpUtil.kickoutByTokenValue(tokenId);
 | 
			
		||||
        } catch (NotLoginException ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,17 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.annotation.RepeatSubmit;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.domain.SysConfig;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -27,8 +24,7 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "参数配置控制器", tags = {"参数配置管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/config")
 | 
			
		||||
public class SysConfigController extends BaseController {
 | 
			
		||||
@@ -38,17 +34,18 @@ public class SysConfigController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取参数配置列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取参数配置列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:list')")
 | 
			
		||||
    @SaCheckPermission("system:config:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysConfig> list(SysConfig config) {
 | 
			
		||||
        return configService.selectPageConfigList(config);
 | 
			
		||||
    public TableDataInfo<SysConfig> list(SysConfig config, PageQuery pageQuery) {
 | 
			
		||||
        return configService.selectPageConfigList(config, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出参数配置列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出参数配置列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:config:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysConfig config, HttpServletResponse response) {
 | 
			
		||||
        List<SysConfig> list = configService.selectConfigList(config);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "参数数据", SysConfig.class, response);
 | 
			
		||||
@@ -56,73 +53,85 @@ public class SysConfigController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据参数编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param configId 参数ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据参数编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:query')")
 | 
			
		||||
    @SaCheckPermission("system:config:query")
 | 
			
		||||
    @GetMapping(value = "/{configId}")
 | 
			
		||||
    public AjaxResult<SysConfig> getInfo(@PathVariable Long configId) {
 | 
			
		||||
        return AjaxResult.success(configService.selectConfigById(configId));
 | 
			
		||||
    public R<SysConfig> getInfo(@PathVariable Long configId) {
 | 
			
		||||
        return R.ok(configService.selectConfigById(configId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据参数键名查询参数值
 | 
			
		||||
     *
 | 
			
		||||
     * @param configKey 参数Key
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据参数键名查询参数值")
 | 
			
		||||
    @GetMapping(value = "/configKey/{configKey}")
 | 
			
		||||
    public AjaxResult<Void> getConfigKey(@PathVariable String configKey) {
 | 
			
		||||
        return AjaxResult.success(configService.selectConfigByKey(configKey));
 | 
			
		||||
    public R<Void> getConfigKey(@PathVariable String configKey) {
 | 
			
		||||
        return R.ok(configService.selectConfigByKey(configKey));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增参数配置
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增参数配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:add')")
 | 
			
		||||
    @SaCheckPermission("system:config:add")
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    @RepeatSubmit
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysConfig config) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
 | 
			
		||||
            return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysConfig config) {
 | 
			
		||||
        if (!configService.checkConfigKeyUnique(config)) {
 | 
			
		||||
            return R.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(configService.insertConfig(config));
 | 
			
		||||
        configService.insertConfig(config);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改参数配置
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改参数配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:edit')")
 | 
			
		||||
    @SaCheckPermission("system:config:edit")
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysConfig config) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
 | 
			
		||||
            return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysConfig config) {
 | 
			
		||||
        if (!configService.checkConfigKeyUnique(config)) {
 | 
			
		||||
            return R.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(configService.updateConfig(config));
 | 
			
		||||
        configService.updateConfig(config);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据参数键名修改参数配置
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:config:edit")
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/updateByKey")
 | 
			
		||||
    public R<Void> updateByKey(@RequestBody SysConfig config) {
 | 
			
		||||
        configService.updateConfig(config);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除参数配置
 | 
			
		||||
     *
 | 
			
		||||
     * @param configIds 参数ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除参数配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
 | 
			
		||||
    @SaCheckPermission("system:config:remove")
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{configIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] configIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] configIds) {
 | 
			
		||||
        configService.deleteConfigByIds(configIds);
 | 
			
		||||
        return success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 刷新参数缓存
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("刷新参数缓存")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
 | 
			
		||||
    @SaCheckPermission("system:config:remove")
 | 
			
		||||
    @Log(title = "参数管理", businessType = BusinessType.CLEAN)
 | 
			
		||||
    @DeleteMapping("/refreshCache")
 | 
			
		||||
    public AjaxResult<Void> refreshCache() {
 | 
			
		||||
    public R<Void> refreshCache() {
 | 
			
		||||
        configService.resetConfigCache();
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,20 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.TreeSelect;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysDept;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.system.service.ISysDeptService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 部门信息
 | 
			
		||||
@@ -28,8 +22,7 @@ import java.util.Map;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "部门控制器", tags = {"部门管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/dept")
 | 
			
		||||
public class SysDeptController extends BaseController {
 | 
			
		||||
@@ -39,71 +32,48 @@ public class SysDeptController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取部门列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取部门列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
 | 
			
		||||
    @SaCheckPermission("system:dept:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public AjaxResult<List<SysDept>> list(SysDept dept) {
 | 
			
		||||
    public R<List<SysDept>> list(SysDept dept) {
 | 
			
		||||
        List<SysDept> depts = deptService.selectDeptList(dept);
 | 
			
		||||
        return AjaxResult.success(depts);
 | 
			
		||||
        return R.ok(depts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询部门列表(排除节点)
 | 
			
		||||
     *
 | 
			
		||||
     * @param deptId 部门ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询部门列表(排除节点)")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
 | 
			
		||||
    @SaCheckPermission("system:dept:list")
 | 
			
		||||
    @GetMapping("/list/exclude/{deptId}")
 | 
			
		||||
    public AjaxResult<List<SysDept>> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
 | 
			
		||||
    public R<List<SysDept>> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
 | 
			
		||||
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
 | 
			
		||||
        depts.removeIf(d -> d.getDeptId().equals(deptId)
 | 
			
		||||
                || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
 | 
			
		||||
        return AjaxResult.success(depts);
 | 
			
		||||
            || StringUtils.splitList(d.getAncestors()).contains(Convert.toStr(deptId)));
 | 
			
		||||
        return R.ok(depts);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据部门编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param deptId 部门ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据部门编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:query')")
 | 
			
		||||
    @SaCheckPermission("system:dept:query")
 | 
			
		||||
    @GetMapping(value = "/{deptId}")
 | 
			
		||||
    public AjaxResult<SysDept> getInfo(@PathVariable Long deptId) {
 | 
			
		||||
    public R<SysDept> getInfo(@PathVariable Long deptId) {
 | 
			
		||||
        deptService.checkDeptDataScope(deptId);
 | 
			
		||||
        return AjaxResult.success(deptService.selectDeptById(deptId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取部门下拉树列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取部门下拉树列表")
 | 
			
		||||
    @GetMapping("/treeselect")
 | 
			
		||||
    public AjaxResult<List<TreeSelect>> treeselect(SysDept dept) {
 | 
			
		||||
        List<SysDept> depts = deptService.selectDeptList(dept);
 | 
			
		||||
        return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 加载对应角色部门列表树
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("加载对应角色部门列表树")
 | 
			
		||||
    @GetMapping(value = "/roleDeptTreeselect/{roleId}")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
 | 
			
		||||
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
 | 
			
		||||
        ajax.put("depts", deptService.buildDeptTreeSelect(depts));
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        return R.ok(deptService.selectDeptById(deptId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增部门
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增部门")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:add')")
 | 
			
		||||
    @SaCheckPermission("system:dept:add")
 | 
			
		||||
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysDept dept) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
 | 
			
		||||
            return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysDept dept) {
 | 
			
		||||
        if (!deptService.checkDeptNameUnique(dept)) {
 | 
			
		||||
            return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(deptService.insertDept(dept));
 | 
			
		||||
    }
 | 
			
		||||
@@ -111,36 +81,42 @@ public class SysDeptController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改部门
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改部门")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
 | 
			
		||||
    @SaCheckPermission("system:dept:edit")
 | 
			
		||||
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysDept dept) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
 | 
			
		||||
            return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
 | 
			
		||||
        } else if (dept.getParentId().equals(dept.getDeptId())) {
 | 
			
		||||
            return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
 | 
			
		||||
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
 | 
			
		||||
                && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) {
 | 
			
		||||
            return AjaxResult.error("该部门包含未停用的子部门!");
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysDept dept) {
 | 
			
		||||
        Long deptId = dept.getDeptId();
 | 
			
		||||
        deptService.checkDeptDataScope(deptId);
 | 
			
		||||
        if (!deptService.checkDeptNameUnique(dept)) {
 | 
			
		||||
            return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
 | 
			
		||||
        } else if (dept.getParentId().equals(deptId)) {
 | 
			
		||||
            return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
 | 
			
		||||
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())) {
 | 
			
		||||
            if (deptService.selectNormalChildrenDeptById(deptId) > 0) {
 | 
			
		||||
                return R.fail("该部门包含未停用的子部门!");
 | 
			
		||||
            } else if (deptService.checkDeptExistUser(deptId)) {
 | 
			
		||||
                return R.fail("该部门下存在已分配用户,不能禁用!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(deptService.updateDept(dept));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除部门
 | 
			
		||||
     *
 | 
			
		||||
     * @param deptId 部门ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除部门")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
 | 
			
		||||
    @SaCheckPermission("system:dept:remove")
 | 
			
		||||
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{deptId}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long deptId) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long deptId) {
 | 
			
		||||
        if (deptService.hasChildByDeptId(deptId)) {
 | 
			
		||||
            return AjaxResult.error("存在下级部门,不允许删除");
 | 
			
		||||
            return R.warn("存在下级部门,不允许删除");
 | 
			
		||||
        }
 | 
			
		||||
        if (deptService.checkDeptExistUser(deptId)) {
 | 
			
		||||
            return AjaxResult.error("部门存在用户,不允许删除");
 | 
			
		||||
            return R.warn("部门存在用户,不允许删除");
 | 
			
		||||
        }
 | 
			
		||||
        deptService.checkDeptDataScope(deptId);
 | 
			
		||||
        return toAjax(deptService.deleteDeptById(deptId));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,18 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysDictData;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.service.ISysDictDataService;
 | 
			
		||||
import com.ruoyi.system.service.ISysDictTypeService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -28,8 +26,7 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/dict/data")
 | 
			
		||||
public class SysDictDataController extends BaseController {
 | 
			
		||||
@@ -37,17 +34,21 @@ public class SysDictDataController extends BaseController {
 | 
			
		||||
    private final ISysDictDataService dictDataService;
 | 
			
		||||
    private final ISysDictTypeService dictTypeService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("查询字典数据列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询字典数据列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:dict:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysDictData> list(SysDictData dictData) {
 | 
			
		||||
        return dictDataService.selectPageDictDataList(dictData);
 | 
			
		||||
    public TableDataInfo<SysDictData> list(SysDictData dictData, PageQuery pageQuery) {
 | 
			
		||||
        return dictDataService.selectPageDictDataList(dictData, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出字典数据列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出字典数据列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "字典数据", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:dict:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysDictData dictData, HttpServletResponse response) {
 | 
			
		||||
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "字典数据", SysDictData.class, response);
 | 
			
		||||
@@ -55,58 +56,61 @@ public class SysDictDataController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询字典数据详细
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictCode 字典code
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询字典数据详细")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
 | 
			
		||||
    @SaCheckPermission("system:dict:query")
 | 
			
		||||
    @GetMapping(value = "/{dictCode}")
 | 
			
		||||
    public AjaxResult<SysDictData> getInfo(@PathVariable Long dictCode) {
 | 
			
		||||
        return AjaxResult.success(dictDataService.selectDictDataById(dictCode));
 | 
			
		||||
    public R<SysDictData> getInfo(@PathVariable Long dictCode) {
 | 
			
		||||
        return R.ok(dictDataService.selectDictDataById(dictCode));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据字典类型查询字典数据信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictType 字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据字典类型查询字典数据信息")
 | 
			
		||||
    @GetMapping(value = "/type/{dictType}")
 | 
			
		||||
    public AjaxResult<List<SysDictData>> dictType(@PathVariable String dictType) {
 | 
			
		||||
    public R<List<SysDictData>> dictType(@PathVariable String dictType) {
 | 
			
		||||
        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
 | 
			
		||||
        if (StringUtils.isNull(data)) {
 | 
			
		||||
        if (ObjectUtil.isNull(data)) {
 | 
			
		||||
            data = new ArrayList<>();
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.success(data);
 | 
			
		||||
        return R.ok(data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
 | 
			
		||||
    @SaCheckPermission("system:dict:add")
 | 
			
		||||
    @Log(title = "字典数据", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysDictData dict) {
 | 
			
		||||
        return toAjax(dictDataService.insertDictData(dict));
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysDictData dict) {
 | 
			
		||||
        dictDataService.insertDictData(dict);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改保存字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改保存字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
 | 
			
		||||
    @SaCheckPermission("system:dict:edit")
 | 
			
		||||
    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysDictData dict) {
 | 
			
		||||
        return toAjax(dictDataService.updateDictData(dict));
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysDictData dict) {
 | 
			
		||||
        dictDataService.updateDictData(dict);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除字典类型
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictCodes 字典code串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
 | 
			
		||||
    @SaCheckPermission("system:dict:remove")
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{dictCodes}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] dictCodes) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] dictCodes) {
 | 
			
		||||
        dictDataService.deleteDictDataByIds(dictCodes);
 | 
			
		||||
        return success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,17 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysDictType;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.service.ISysDictTypeService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -26,25 +24,28 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/dict/type")
 | 
			
		||||
public class SysDictTypeController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysDictTypeService dictTypeService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("查询字典类型列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询字典类型列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:dict:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysDictType> list(SysDictType dictType) {
 | 
			
		||||
        return dictTypeService.selectPageDictTypeList(dictType);
 | 
			
		||||
    public TableDataInfo<SysDictType> list(SysDictType dictType, PageQuery pageQuery) {
 | 
			
		||||
        return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出字典类型列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出字典类型列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:dict:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysDictType dictType, HttpServletResponse response) {
 | 
			
		||||
        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "字典类型", SysDictType.class, response);
 | 
			
		||||
@@ -52,73 +53,73 @@ public class SysDictTypeController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询字典类型详细
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictId 字典ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询字典类型详细")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
 | 
			
		||||
    @SaCheckPermission("system:dict:query")
 | 
			
		||||
    @GetMapping(value = "/{dictId}")
 | 
			
		||||
    public AjaxResult<SysDictType> getInfo(@PathVariable Long dictId) {
 | 
			
		||||
        return AjaxResult.success(dictTypeService.selectDictTypeById(dictId));
 | 
			
		||||
    public R<SysDictType> getInfo(@PathVariable Long dictId) {
 | 
			
		||||
        return R.ok(dictTypeService.selectDictTypeById(dictId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
 | 
			
		||||
    @SaCheckPermission("system:dict:add")
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysDictType dict) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
 | 
			
		||||
            return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysDictType dict) {
 | 
			
		||||
        if (!dictTypeService.checkDictTypeUnique(dict)) {
 | 
			
		||||
            return R.fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(dictTypeService.insertDictType(dict));
 | 
			
		||||
        dictTypeService.insertDictType(dict);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
 | 
			
		||||
    @SaCheckPermission("system:dict:edit")
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysDictType dict) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
 | 
			
		||||
            return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysDictType dict) {
 | 
			
		||||
        if (!dictTypeService.checkDictTypeUnique(dict)) {
 | 
			
		||||
            return R.fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(dictTypeService.updateDictType(dict));
 | 
			
		||||
        dictTypeService.updateDictType(dict);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除字典类型
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictIds 字典ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除字典类型")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
 | 
			
		||||
    @SaCheckPermission("system:dict:remove")
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{dictIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] dictIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] dictIds) {
 | 
			
		||||
        dictTypeService.deleteDictTypeByIds(dictIds);
 | 
			
		||||
        return success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 刷新字典缓存
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("刷新字典缓存")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
 | 
			
		||||
    @SaCheckPermission("system:dict:remove")
 | 
			
		||||
    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
 | 
			
		||||
    @DeleteMapping("/refreshCache")
 | 
			
		||||
    public AjaxResult<Void> refreshCache() {
 | 
			
		||||
    public R<Void> refreshCache() {
 | 
			
		||||
        dictTypeService.resetDictCache();
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取字典选择框列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取字典选择框列表")
 | 
			
		||||
    @GetMapping("/optionselect")
 | 
			
		||||
    public AjaxResult<List<SysDictType>> optionselect() {
 | 
			
		||||
    public R<List<SysDictType>> optionselect() {
 | 
			
		||||
        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
 | 
			
		||||
        return AjaxResult.success(dictTypes);
 | 
			
		||||
        return R.ok(dictTypes);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaIgnore;
 | 
			
		||||
import com.ruoyi.common.config.RuoYiConfig;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
@@ -14,8 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Api(value = "首页控制器", tags = {"首页管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
public class SysIndexController {
 | 
			
		||||
 | 
			
		||||
@@ -27,7 +24,7 @@ public class SysIndexController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 访问首页,提示语
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("访问首页,提示语")
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @GetMapping("/")
 | 
			
		||||
    public String index() {
 | 
			
		||||
        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,30 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaIgnore;
 | 
			
		||||
import com.ruoyi.common.constant.Constants;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysMenu;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysUser;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.EmailLoginBody;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.LoginBody;
 | 
			
		||||
import com.ruoyi.common.utils.SecurityUtils;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.LoginUser;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.SmsLoginBody;
 | 
			
		||||
import com.ruoyi.common.helper.LoginHelper;
 | 
			
		||||
import com.ruoyi.system.domain.vo.RouterVo;
 | 
			
		||||
import com.ruoyi.system.service.ISysMenuService;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserService;
 | 
			
		||||
import com.ruoyi.system.service.SysLoginService;
 | 
			
		||||
import com.ruoyi.system.service.SysPermissionService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 登录验证
 | 
			
		||||
@@ -31,14 +32,13 @@ import java.util.Set;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
public class SysLoginController {
 | 
			
		||||
 | 
			
		||||
    private final SysLoginService loginService;
 | 
			
		||||
    private final ISysMenuService menuService;
 | 
			
		||||
    private final SysPermissionService permissionService;
 | 
			
		||||
    private final ISysUserService userService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录方法
 | 
			
		||||
@@ -46,15 +46,72 @@ public class SysLoginController {
 | 
			
		||||
     * @param loginBody 登录信息
 | 
			
		||||
     * @return 结果
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("登录方法")
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @PostMapping("/login")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> login(@RequestBody LoginBody loginBody) {
 | 
			
		||||
    public R<Map<String, Object>> login(@Validated @RequestBody LoginBody loginBody) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        // 生成令牌
 | 
			
		||||
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
 | 
			
		||||
                loginBody.getUuid());
 | 
			
		||||
            loginBody.getUuid());
 | 
			
		||||
        ajax.put(Constants.TOKEN, token);
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信登录
 | 
			
		||||
     *
 | 
			
		||||
     * @param smsLoginBody 登录信息
 | 
			
		||||
     * @return 结果
 | 
			
		||||
     */
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @PostMapping("/smsLogin")
 | 
			
		||||
    public R<Map<String, Object>> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        // 生成令牌
 | 
			
		||||
        String token = loginService.smsLogin(smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode());
 | 
			
		||||
        ajax.put(Constants.TOKEN, token);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮件登录
 | 
			
		||||
     *
 | 
			
		||||
     * @param body 登录信息
 | 
			
		||||
     * @return 结果
 | 
			
		||||
     */
 | 
			
		||||
    @PostMapping("/emailLogin")
 | 
			
		||||
    public R<Map<String, Object>> emailLogin(@Validated @RequestBody EmailLoginBody body) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        // 生成令牌
 | 
			
		||||
        String token = loginService.emailLogin(body.getEmail(), body.getEmailCode());
 | 
			
		||||
        ajax.put(Constants.TOKEN, token);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 小程序登录(示例)
 | 
			
		||||
     *
 | 
			
		||||
     * @param xcxCode 小程序code
 | 
			
		||||
     * @return 结果
 | 
			
		||||
     */
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @PostMapping("/xcxLogin")
 | 
			
		||||
    public R<Map<String, Object>> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        // 生成令牌
 | 
			
		||||
        String token = loginService.xcxLogin(xcxCode);
 | 
			
		||||
        ajax.put(Constants.TOKEN, token);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 退出登录
 | 
			
		||||
     */
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @PostMapping("/logout")
 | 
			
		||||
    public R<Void> logout() {
 | 
			
		||||
        loginService.logout();
 | 
			
		||||
        return R.ok("退出成功");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -62,19 +119,15 @@ public class SysLoginController {
 | 
			
		||||
     *
 | 
			
		||||
     * @return 用户信息
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取用户信息")
 | 
			
		||||
    @GetMapping("getInfo")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> getInfo() {
 | 
			
		||||
        SysUser user = SecurityUtils.getLoginUser().getUser();
 | 
			
		||||
        // 角色集合
 | 
			
		||||
        Set<String> roles = permissionService.getRolePermission(user);
 | 
			
		||||
        // 权限集合
 | 
			
		||||
        Set<String> permissions = permissionService.getMenuPermission(user);
 | 
			
		||||
    public R<Map<String, Object>> getInfo() {
 | 
			
		||||
        LoginUser loginUser = LoginHelper.getLoginUser();
 | 
			
		||||
        SysUser user = userService.selectUserById(loginUser.getUserId());
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("user", user);
 | 
			
		||||
        ajax.put("roles", roles);
 | 
			
		||||
        ajax.put("permissions", permissions);
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        ajax.put("roles", loginUser.getRolePermission());
 | 
			
		||||
        ajax.put("permissions", loginUser.getMenuPermission());
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -82,11 +135,10 @@ public class SysLoginController {
 | 
			
		||||
     *
 | 
			
		||||
     * @return 路由信息
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取路由信息")
 | 
			
		||||
    @GetMapping("getRouters")
 | 
			
		||||
    public AjaxResult<List<RouterVo>> getRouters() {
 | 
			
		||||
        Long userId = SecurityUtils.getUserId();
 | 
			
		||||
    public R<List<RouterVo>> getRouters() {
 | 
			
		||||
        Long userId = LoginHelper.getUserId();
 | 
			
		||||
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
 | 
			
		||||
        return AjaxResult.success(menuService.buildMenus(menus));
 | 
			
		||||
        return R.ok(menuService.buildMenus(menus));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,16 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.hutool.core.lang.tree.Tree;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.TreeSelect;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysMenu;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.system.service.ISysMenuService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -27,8 +24,7 @@ import java.util.Map;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "菜单信息控制器", tags = {"菜单信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/menu")
 | 
			
		||||
public class SysMenuController extends BaseController {
 | 
			
		||||
@@ -38,59 +34,58 @@ public class SysMenuController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取菜单列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取菜单列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
 | 
			
		||||
    @SaCheckPermission("system:menu:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public AjaxResult<List<SysMenu>> list(SysMenu menu) {
 | 
			
		||||
    public R<List<SysMenu>> list(SysMenu menu) {
 | 
			
		||||
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
 | 
			
		||||
        return AjaxResult.success(menus);
 | 
			
		||||
        return R.ok(menus);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据菜单编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param menuId 菜单ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据菜单编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:menu:query')")
 | 
			
		||||
    @SaCheckPermission("system:menu:query")
 | 
			
		||||
    @GetMapping(value = "/{menuId}")
 | 
			
		||||
    public AjaxResult<SysMenu> getInfo(@PathVariable Long menuId) {
 | 
			
		||||
        return AjaxResult.success(menuService.selectMenuById(menuId));
 | 
			
		||||
    public R<SysMenu> getInfo(@PathVariable Long menuId) {
 | 
			
		||||
        return R.ok(menuService.selectMenuById(menuId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取菜单下拉树列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取菜单下拉树列表")
 | 
			
		||||
    @GetMapping("/treeselect")
 | 
			
		||||
    public AjaxResult<List<TreeSelect>> treeselect(SysMenu menu) {
 | 
			
		||||
    public R<List<Tree<Long>>> treeselect(SysMenu menu) {
 | 
			
		||||
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
 | 
			
		||||
        return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
 | 
			
		||||
        return R.ok(menuService.buildMenuTreeSelect(menus));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 加载对应角色菜单列表树
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleId 角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("加载对应角色菜单列表树")
 | 
			
		||||
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
 | 
			
		||||
    public R<Map<String, Object>> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
 | 
			
		||||
        List<SysMenu> menus = menuService.selectMenuList(getUserId());
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
 | 
			
		||||
        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增菜单
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增菜单")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:menu:add')")
 | 
			
		||||
    @SaCheckPermission("system:menu:add")
 | 
			
		||||
    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysMenu menu) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
 | 
			
		||||
            return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysMenu menu) {
 | 
			
		||||
        if (!menuService.checkMenuNameUnique(menu)) {
 | 
			
		||||
            return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
 | 
			
		||||
        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
 | 
			
		||||
            return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
 | 
			
		||||
            return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(menuService.insertMenu(menu));
 | 
			
		||||
    }
 | 
			
		||||
@@ -98,34 +93,34 @@ public class SysMenuController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改菜单
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改菜单")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
 | 
			
		||||
    @SaCheckPermission("system:menu:edit")
 | 
			
		||||
    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysMenu menu) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
 | 
			
		||||
            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysMenu menu) {
 | 
			
		||||
        if (!menuService.checkMenuNameUnique(menu)) {
 | 
			
		||||
            return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
 | 
			
		||||
        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
 | 
			
		||||
            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
 | 
			
		||||
            return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
 | 
			
		||||
        } else if (menu.getMenuId().equals(menu.getParentId())) {
 | 
			
		||||
            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
 | 
			
		||||
            return R.fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(menuService.updateMenu(menu));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除菜单
 | 
			
		||||
     *
 | 
			
		||||
     * @param menuId 菜单ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除菜单")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
 | 
			
		||||
    @SaCheckPermission("system:menu:remove")
 | 
			
		||||
    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{menuId}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable("menuId") Long menuId) {
 | 
			
		||||
    public R<Void> remove(@PathVariable("menuId") Long menuId) {
 | 
			
		||||
        if (menuService.hasChildByMenuId(menuId)) {
 | 
			
		||||
            return AjaxResult.error("存在子菜单,不允许删除");
 | 
			
		||||
            return R.warn("存在子菜单,不允许删除");
 | 
			
		||||
        }
 | 
			
		||||
        if (menuService.checkMenuExistRole(menuId)) {
 | 
			
		||||
            return AjaxResult.error("菜单已分配,不允许删除");
 | 
			
		||||
            return R.warn("菜单已分配,不允许删除");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(menuService.deleteMenuById(menuId));
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,15 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.system.domain.SysNotice;
 | 
			
		||||
import com.ruoyi.system.service.ISysNoticeService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -21,8 +19,7 @@ import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "公告信息控制器", tags = {"公告信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/notice")
 | 
			
		||||
public class SysNoticeController extends BaseController {
 | 
			
		||||
@@ -32,53 +29,52 @@ public class SysNoticeController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取通知公告列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取通知公告列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
 | 
			
		||||
    @SaCheckPermission("system:notice:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysNotice> list(SysNotice notice) {
 | 
			
		||||
        return noticeService.selectPageNoticeList(notice);
 | 
			
		||||
    public TableDataInfo<SysNotice> list(SysNotice notice, PageQuery pageQuery) {
 | 
			
		||||
        return noticeService.selectPageNoticeList(notice, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据通知公告编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param noticeId 公告ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据通知公告编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:notice:query')")
 | 
			
		||||
    @SaCheckPermission("system:notice:query")
 | 
			
		||||
    @GetMapping(value = "/{noticeId}")
 | 
			
		||||
    public AjaxResult<SysNotice> getInfo(@PathVariable Long noticeId) {
 | 
			
		||||
        return AjaxResult.success(noticeService.selectNoticeById(noticeId));
 | 
			
		||||
    public R<SysNotice> getInfo(@PathVariable Long noticeId) {
 | 
			
		||||
        return R.ok(noticeService.selectNoticeById(noticeId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增通知公告
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增通知公告")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:notice:add')")
 | 
			
		||||
    @SaCheckPermission("system:notice:add")
 | 
			
		||||
    @Log(title = "通知公告", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysNotice notice) {
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysNotice notice) {
 | 
			
		||||
        return toAjax(noticeService.insertNotice(notice));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改通知公告
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改通知公告")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:notice:edit')")
 | 
			
		||||
    @SaCheckPermission("system:notice:edit")
 | 
			
		||||
    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysNotice notice) {
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysNotice notice) {
 | 
			
		||||
        return toAjax(noticeService.updateNotice(notice));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除通知公告
 | 
			
		||||
     *
 | 
			
		||||
     * @param noticeIds 公告ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除通知公告")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
 | 
			
		||||
    @SaCheckPermission("system:notice:remove")
 | 
			
		||||
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{noticeIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] noticeIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] noticeIds) {
 | 
			
		||||
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.annotation.RepeatSubmit;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.core.validate.AddGroup;
 | 
			
		||||
import com.ruoyi.common.core.validate.EditGroup;
 | 
			
		||||
@@ -12,11 +14,7 @@ import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.system.domain.bo.SysOssConfigBo;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysOssConfigVo;
 | 
			
		||||
import com.ruoyi.system.service.ISysOssConfigService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -25,15 +23,14 @@ import javax.validation.constraints.NotNull;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 对象存储配置Controller
 | 
			
		||||
 * 对象存储配置
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 * @author 孤舟烟雨
 | 
			
		||||
 * @date 2021-08-13
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "对象存储配置控制器", tags = {"对象存储配置管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/oss/config")
 | 
			
		||||
public class SysOssConfigController extends BaseController {
 | 
			
		||||
@@ -43,68 +40,66 @@ public class SysOssConfigController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询对象存储配置列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询对象存储配置列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:list')")
 | 
			
		||||
    @SaCheckPermission("system:oss:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
 | 
			
		||||
        return iSysOssConfigService.queryPageList(bo);
 | 
			
		||||
    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
 | 
			
		||||
        return iSysOssConfigService.queryPageList(bo, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取对象存储配置详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param ossConfigId OSS配置ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取对象存储配置详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:query')")
 | 
			
		||||
    @SaCheckPermission("system:oss:query")
 | 
			
		||||
    @GetMapping("/{ossConfigId}")
 | 
			
		||||
    public AjaxResult<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
 | 
			
		||||
                                              @PathVariable("ossConfigId") Integer ossConfigId) {
 | 
			
		||||
        return AjaxResult.success(iSysOssConfigService.queryById(ossConfigId));
 | 
			
		||||
    public R<SysOssConfigVo> getInfo(@NotNull(message = "主键不能为空")
 | 
			
		||||
                                     @PathVariable Long ossConfigId) {
 | 
			
		||||
        return R.ok(iSysOssConfigService.queryById(ossConfigId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增对象存储配置
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增对象存储配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:add')")
 | 
			
		||||
    @SaCheckPermission("system:oss:add")
 | 
			
		||||
    @Log(title = "对象存储配置", businessType = BusinessType.INSERT)
 | 
			
		||||
    @RepeatSubmit()
 | 
			
		||||
    @PostMapping()
 | 
			
		||||
    public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0);
 | 
			
		||||
    public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.insertByBo(bo));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改对象存储配置
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改对象存储配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:edit')")
 | 
			
		||||
    @SaCheckPermission("system:oss:edit")
 | 
			
		||||
    @Log(title = "对象存储配置", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @RepeatSubmit()
 | 
			
		||||
    @PutMapping()
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0);
 | 
			
		||||
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.updateByBo(bo));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除对象存储配置
 | 
			
		||||
     *
 | 
			
		||||
     * @param ossConfigIds OSS配置ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除对象存储配置")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:remove')")
 | 
			
		||||
    @SaCheckPermission("system:oss:remove")
 | 
			
		||||
    @Log(title = "对象存储配置", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{ossConfigIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
 | 
			
		||||
                                   @PathVariable Long[] ossConfigIds) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0);
 | 
			
		||||
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
 | 
			
		||||
                          @PathVariable Long[] ossConfigIds) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态修改
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("状态修改")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:edit')")
 | 
			
		||||
    @SaCheckPermission("system:oss:edit")
 | 
			
		||||
    @Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/changeStatus")
 | 
			
		||||
    public AjaxResult<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
 | 
			
		||||
    public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
 | 
			
		||||
        return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,20 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.http.HttpException;
 | 
			
		||||
import cn.hutool.http.HttpUtil;
 | 
			
		||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.annotation.RepeatSubmit;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.core.validate.QueryGroup;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.exception.ServiceException;
 | 
			
		||||
import com.ruoyi.common.utils.JsonUtils;
 | 
			
		||||
import com.ruoyi.common.utils.file.FileUtils;
 | 
			
		||||
import com.ruoyi.oss.constant.CloudConstant;
 | 
			
		||||
import com.ruoyi.system.domain.SysConfig;
 | 
			
		||||
import com.ruoyi.system.domain.SysOss;
 | 
			
		||||
import com.ruoyi.system.domain.bo.SysOssBo;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysOssVo;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import com.ruoyi.system.service.ISysOssService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParam;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParams;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
@@ -40,6 +24,7 @@ import javax.validation.constraints.NotEmpty;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -48,96 +33,77 @@ import java.util.Map;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "OSS对象存储控制器", tags = {"OSS对象存储管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/oss")
 | 
			
		||||
public class SysOssController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysOssService iSysOssService;
 | 
			
		||||
    private final ISysConfigService iSysConfigService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询OSS对象存储列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询OSS对象存储列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:list')")
 | 
			
		||||
    @SaCheckPermission("system:oss:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
 | 
			
		||||
        return iSysOssService.queryPageList(bo);
 | 
			
		||||
    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
 | 
			
		||||
        return iSysOssService.queryPageList(bo, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询OSS对象基于id串
 | 
			
		||||
     *
 | 
			
		||||
     * @param ossIds OSS对象ID串
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:oss:list")
 | 
			
		||||
    @GetMapping("/listByIds/{ossIds}")
 | 
			
		||||
    public R<List<SysOssVo>> listByIds(@NotEmpty(message = "主键不能为空")
 | 
			
		||||
                                       @PathVariable Long[] ossIds) {
 | 
			
		||||
        List<SysOssVo> list = iSysOssService.listByIds(Arrays.asList(ossIds));
 | 
			
		||||
        return R.ok(list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上传OSS对象存储
 | 
			
		||||
     *
 | 
			
		||||
     * @param file 文件
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("上传OSS对象存储")
 | 
			
		||||
    @ApiImplicitParams({
 | 
			
		||||
            @ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
 | 
			
		||||
    })
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:upload')")
 | 
			
		||||
    @SaCheckPermission("system:oss:upload")
 | 
			
		||||
    @Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
 | 
			
		||||
    @RepeatSubmit
 | 
			
		||||
    @PostMapping("/upload")
 | 
			
		||||
    public AjaxResult<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
 | 
			
		||||
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 | 
			
		||||
    public R<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
 | 
			
		||||
        if (ObjectUtil.isNull(file)) {
 | 
			
		||||
            throw new ServiceException("上传文件不能为空");
 | 
			
		||||
            return R.fail("上传文件不能为空");
 | 
			
		||||
        }
 | 
			
		||||
        SysOss oss = iSysOssService.upload(file);
 | 
			
		||||
        SysOssVo oss = iSysOssService.upload(file);
 | 
			
		||||
        Map<String, String> map = new HashMap<>(2);
 | 
			
		||||
        map.put("url", oss.getUrl());
 | 
			
		||||
        map.put("fileName", oss.getFileName());
 | 
			
		||||
        return AjaxResult.success(map);
 | 
			
		||||
        map.put("fileName", oss.getOriginalName());
 | 
			
		||||
        map.put("ossId", oss.getOssId().toString());
 | 
			
		||||
        return R.ok(map);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("下载OSS对象存储")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:download')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 下载OSS对象
 | 
			
		||||
     *
 | 
			
		||||
     * @param ossId OSS对象ID
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:oss:download")
 | 
			
		||||
    @GetMapping("/download/{ossId}")
 | 
			
		||||
    public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
 | 
			
		||||
        SysOss sysOss = iSysOssService.getById(ossId);
 | 
			
		||||
        if (ObjectUtil.isNull(sysOss)) {
 | 
			
		||||
            throw new ServiceException("文件数据不存在!");
 | 
			
		||||
        }
 | 
			
		||||
        response.reset();
 | 
			
		||||
        FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
 | 
			
		||||
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
 | 
			
		||||
        long data;
 | 
			
		||||
        try {
 | 
			
		||||
            data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
 | 
			
		||||
        } catch (HttpException e) {
 | 
			
		||||
            if (e.getMessage().contains("403")) {
 | 
			
		||||
                throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new ServiceException(e.getMessage());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        response.setContentLength(Convert.toInt(data));
 | 
			
		||||
        iSysOssService.download(ossId,response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除OSS对象存储
 | 
			
		||||
     *
 | 
			
		||||
     * @param ossIds OSS对象ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除OSS对象存储")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:remove')")
 | 
			
		||||
    @SaCheckPermission("system:oss:remove")
 | 
			
		||||
    @Log(title = "OSS对象存储", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{ossIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
 | 
			
		||||
                                   @PathVariable Long[] ossIds) {
 | 
			
		||||
        return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 变更图片列表预览状态
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("变更图片列表预览状态")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:oss:edit')")
 | 
			
		||||
    @Log(title = "OSS对象存储", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/changePreviewListResource")
 | 
			
		||||
    public AjaxResult<Void> changePreviewListResource(@RequestBody String body) {
 | 
			
		||||
        Map<String, Boolean> map = JsonUtils.parseMap(body);
 | 
			
		||||
        SysConfig config = iSysConfigService.getOne(new LambdaQueryWrapper<SysConfig>()
 | 
			
		||||
                .eq(SysConfig::getConfigKey, CloudConstant.PEREVIEW_LIST_RESOURCE_KEY));
 | 
			
		||||
        config.setConfigValue(map.get("previewListResource").toString());
 | 
			
		||||
        return toAjax(iSysConfigService.updateConfig(config));
 | 
			
		||||
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
 | 
			
		||||
                          @PathVariable Long[] ossIds) {
 | 
			
		||||
        return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,17 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.domain.SysPost;
 | 
			
		||||
import com.ruoyi.system.service.ISysPostService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
@@ -26,8 +24,7 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "岗位信息控制器", tags = {"岗位信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/post")
 | 
			
		||||
public class SysPostController extends BaseController {
 | 
			
		||||
@@ -37,17 +34,18 @@ public class SysPostController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取岗位列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取岗位列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:list')")
 | 
			
		||||
    @SaCheckPermission("system:post:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysPost> list(SysPost post) {
 | 
			
		||||
        return postService.selectPagePostList(post);
 | 
			
		||||
    public TableDataInfo<SysPost> list(SysPost post, PageQuery pageQuery) {
 | 
			
		||||
        return postService.selectPagePostList(post, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出岗位列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出岗位列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:post:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysPost post, HttpServletResponse response) {
 | 
			
		||||
        List<SysPost> list = postService.selectPostList(post);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "岗位数据", SysPost.class, response);
 | 
			
		||||
@@ -55,26 +53,26 @@ public class SysPostController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据岗位编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param postId 岗位ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据岗位编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:query')")
 | 
			
		||||
    @SaCheckPermission("system:post:query")
 | 
			
		||||
    @GetMapping(value = "/{postId}")
 | 
			
		||||
    public AjaxResult<SysPost> getInfo(@PathVariable Long postId) {
 | 
			
		||||
        return AjaxResult.success(postService.selectPostById(postId));
 | 
			
		||||
    public R<SysPost> getInfo(@PathVariable Long postId) {
 | 
			
		||||
        return R.ok(postService.selectPostById(postId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增岗位
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增岗位")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:add')")
 | 
			
		||||
    @SaCheckPermission("system:post:add")
 | 
			
		||||
    @Log(title = "岗位管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysPost post) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
 | 
			
		||||
            return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
 | 
			
		||||
        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
 | 
			
		||||
            return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysPost post) {
 | 
			
		||||
        if (!postService.checkPostNameUnique(post)) {
 | 
			
		||||
            return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
 | 
			
		||||
        } else if (!postService.checkPostCodeUnique(post)) {
 | 
			
		||||
            return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(postService.insertPost(post));
 | 
			
		||||
    }
 | 
			
		||||
@@ -82,37 +80,41 @@ public class SysPostController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改岗位
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改岗位")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:edit')")
 | 
			
		||||
    @SaCheckPermission("system:post:edit")
 | 
			
		||||
    @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysPost post) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
 | 
			
		||||
            return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
 | 
			
		||||
        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
 | 
			
		||||
            return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysPost post) {
 | 
			
		||||
        if (!postService.checkPostNameUnique(post)) {
 | 
			
		||||
            return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
 | 
			
		||||
        } else if (!postService.checkPostCodeUnique(post)) {
 | 
			
		||||
            return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
 | 
			
		||||
        } else if (UserConstants.POST_DISABLE.equals(post.getStatus())
 | 
			
		||||
            && postService.countUserPostById(post.getPostId()) > 0) {
 | 
			
		||||
            return R.fail("该岗位下存在已分配用户,不能禁用!");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(postService.updatePost(post));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除岗位
 | 
			
		||||
     *
 | 
			
		||||
     * @param postIds 岗位ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除岗位")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:post:remove')")
 | 
			
		||||
    @SaCheckPermission("system:post:remove")
 | 
			
		||||
    @Log(title = "岗位管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{postIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] postIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] postIds) {
 | 
			
		||||
        return toAjax(postService.deletePostByIds(postIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取岗位选择框列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取岗位选择框列表")
 | 
			
		||||
    @GetMapping("/optionselect")
 | 
			
		||||
    public AjaxResult<List<SysPost>> optionselect() {
 | 
			
		||||
        List<SysPost> posts = postService.selectPostAll();
 | 
			
		||||
        return AjaxResult.success(posts);
 | 
			
		||||
    public R<List<SysPost>> optionselect() {
 | 
			
		||||
        SysPost post = new SysPost();
 | 
			
		||||
        post.setStatus(UserConstants.POST_NORMAL);
 | 
			
		||||
        List<SysPost> posts = postService.selectPostList(post);
 | 
			
		||||
        return R.ok(posts);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +1,27 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.secure.BCrypt;
 | 
			
		||||
import cn.hutool.core.io.FileUtil;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
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.core.domain.entity.SysUser;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.LoginUser;
 | 
			
		||||
import com.ruoyi.common.core.service.TokenService;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.SecurityUtils;
 | 
			
		||||
import com.ruoyi.common.helper.LoginHelper;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.file.MimeTypeUtils;
 | 
			
		||||
import com.ruoyi.system.domain.SysOss;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysOssVo;
 | 
			
		||||
import com.ruoyi.system.service.ISysOssService;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserService;
 | 
			
		||||
import io.swagger.annotations.*;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@@ -29,110 +31,96 @@ import java.util.Map;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "个人信息控制器", tags = {"个人信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/user/profile")
 | 
			
		||||
public class SysProfileController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysUserService userService;
 | 
			
		||||
    private final TokenService tokenService;
 | 
			
		||||
    private final ISysOssService iSysOssService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 个人信息
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("个人信息")
 | 
			
		||||
    @GetMapping
 | 
			
		||||
    public AjaxResult<Map<String, Object>> profile() {
 | 
			
		||||
        LoginUser loginUser = getLoginUser();
 | 
			
		||||
        SysUser user = loginUser.getUser();
 | 
			
		||||
    public R<Map<String, Object>> profile() {
 | 
			
		||||
        SysUser user = userService.selectUserById(getUserId());
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("user", user);
 | 
			
		||||
        ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
 | 
			
		||||
        ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        ajax.put("roleGroup", userService.selectUserRoleGroup(user.getUserName()));
 | 
			
		||||
        ajax.put("postGroup", userService.selectUserPostGroup(user.getUserName()));
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改用户
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改用户")
 | 
			
		||||
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> updateProfile(@RequestBody SysUser user) {
 | 
			
		||||
        if (StringUtils.isNotEmpty(user.getPhonenumber())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
    public R<Void> updateProfile(@RequestBody SysUser user) {
 | 
			
		||||
        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
 | 
			
		||||
            return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
        }
 | 
			
		||||
        if (StringUtils.isNotEmpty(user.getEmail())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
 | 
			
		||||
            return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
        }
 | 
			
		||||
        LoginUser loginUser = getLoginUser();
 | 
			
		||||
        SysUser sysUser = loginUser.getUser();
 | 
			
		||||
        user.setUserId(sysUser.getUserId());
 | 
			
		||||
        user.setUserId(getUserId());
 | 
			
		||||
        user.setUserName(null);
 | 
			
		||||
        user.setPassword(null);
 | 
			
		||||
        user.setAvatar(null);
 | 
			
		||||
        user.setDeptId(null);
 | 
			
		||||
        if (userService.updateUserProfile(user) > 0) {
 | 
			
		||||
            // 更新缓存用户信息
 | 
			
		||||
            sysUser.setNickName(user.getNickName());
 | 
			
		||||
            sysUser.setPhonenumber(user.getPhonenumber());
 | 
			
		||||
            sysUser.setEmail(user.getEmail());
 | 
			
		||||
            sysUser.setSex(user.getSex());
 | 
			
		||||
            tokenService.setLoginUser(loginUser);
 | 
			
		||||
            return AjaxResult.success();
 | 
			
		||||
            return R.ok();
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.error("修改个人信息异常,请联系管理员");
 | 
			
		||||
        return R.fail("修改个人信息异常,请联系管理员");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 重置密码
 | 
			
		||||
     *
 | 
			
		||||
     * @param newPassword 新密码
 | 
			
		||||
     * @param oldPassword 旧密码
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("重置密码")
 | 
			
		||||
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/updatePwd")
 | 
			
		||||
    public AjaxResult<Void> updatePwd(String oldPassword, String newPassword) {
 | 
			
		||||
        LoginUser loginUser = getLoginUser();
 | 
			
		||||
        String userName = loginUser.getUsername();
 | 
			
		||||
        String password = loginUser.getPassword();
 | 
			
		||||
        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
 | 
			
		||||
            return AjaxResult.error("修改密码失败,旧密码错误");
 | 
			
		||||
    public R<Void> updatePwd(String oldPassword, String newPassword) {
 | 
			
		||||
        SysUser user = userService.selectUserById(LoginHelper.getUserId());
 | 
			
		||||
        String userName = user.getUserName();
 | 
			
		||||
        String password = user.getPassword();
 | 
			
		||||
        if (!BCrypt.checkpw(oldPassword, password)) {
 | 
			
		||||
            return R.fail("修改密码失败,旧密码错误");
 | 
			
		||||
        }
 | 
			
		||||
        if (SecurityUtils.matchesPassword(newPassword, password)) {
 | 
			
		||||
            return AjaxResult.error("新密码不能与旧密码相同");
 | 
			
		||||
        if (BCrypt.checkpw(newPassword, password)) {
 | 
			
		||||
            return R.fail("新密码不能与旧密码相同");
 | 
			
		||||
        }
 | 
			
		||||
        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
 | 
			
		||||
            // 更新缓存用户密码
 | 
			
		||||
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
 | 
			
		||||
            tokenService.setLoginUser(loginUser);
 | 
			
		||||
            return AjaxResult.success();
 | 
			
		||||
 | 
			
		||||
        if (userService.resetUserPwd(userName, BCrypt.hashpw(newPassword)) > 0) {
 | 
			
		||||
            return R.ok();
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.error("修改密码异常,请联系管理员");
 | 
			
		||||
        return R.fail("修改密码异常,请联系管理员");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 头像上传
 | 
			
		||||
     *
 | 
			
		||||
     * @param avatarfile 用户头像
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("头像上传")
 | 
			
		||||
    @ApiImplicitParams({
 | 
			
		||||
            @ApiImplicitParam(name = "file", value = "用户头像", dataType = "java.io.File", required = true),
 | 
			
		||||
    })
 | 
			
		||||
    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PostMapping("/avatar")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> avatar(@RequestPart("avatarfile") MultipartFile file) {
 | 
			
		||||
    @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 | 
			
		||||
    public R<Map<String, Object>> avatar(@RequestPart("avatarfile") MultipartFile avatarfile) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        if (!file.isEmpty()) {
 | 
			
		||||
            LoginUser loginUser = getLoginUser();
 | 
			
		||||
            SysOss oss = iSysOssService.upload(file);
 | 
			
		||||
        if (!avatarfile.isEmpty()) {
 | 
			
		||||
            String extension = FileUtil.extName(avatarfile.getOriginalFilename());
 | 
			
		||||
            if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
 | 
			
		||||
                return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
 | 
			
		||||
            }
 | 
			
		||||
            SysOssVo oss = iSysOssService.upload(avatarfile);
 | 
			
		||||
            String avatar = oss.getUrl();
 | 
			
		||||
            if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
 | 
			
		||||
            if (userService.updateUserAvatar(getUsername(), avatar)) {
 | 
			
		||||
                ajax.put("imgUrl", avatar);
 | 
			
		||||
                // 更新缓存用户头像
 | 
			
		||||
                loginUser.getUser().setAvatar(avatar);
 | 
			
		||||
                tokenService.setLoginUser(loginUser);
 | 
			
		||||
                return AjaxResult.success(ajax);
 | 
			
		||||
                return R.ok(ajax);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.error("上传图片异常,请联系管理员", ajax);
 | 
			
		||||
        return R.fail("上传图片异常,请联系管理员");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,12 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaIgnore;
 | 
			
		||||
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.core.domain.model.RegisterBody;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import com.ruoyi.system.service.SysRegisterService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
@@ -21,21 +18,23 @@ import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "注册验证控制器", tags = {"注册验证管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
public class SysRegisterController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final SysRegisterService registerService;
 | 
			
		||||
    private final ISysConfigService configService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("用户注册")
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户注册
 | 
			
		||||
     */
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @PostMapping("/register")
 | 
			
		||||
    public AjaxResult<Void> register(@RequestBody RegisterBody user) {
 | 
			
		||||
    public R<Void> register(@Validated @RequestBody RegisterBody user) {
 | 
			
		||||
        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
 | 
			
		||||
            return error("当前系统没有开启注册功能!");
 | 
			
		||||
            return R.fail("当前系统没有开启注册功能!");
 | 
			
		||||
        }
 | 
			
		||||
        String msg = registerService.register(user);
 | 
			
		||||
        return StringUtils.isEmpty(msg) ? success() : error(msg);
 | 
			
		||||
        registerService.register(user);
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,29 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
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.domain.model.LoginUser;
 | 
			
		||||
import com.ruoyi.common.core.page.TableDataInfo;
 | 
			
		||||
import com.ruoyi.common.core.service.TokenService;
 | 
			
		||||
import com.ruoyi.common.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.domain.SysUserRole;
 | 
			
		||||
import com.ruoyi.system.service.ISysDeptService;
 | 
			
		||||
import com.ruoyi.system.service.ISysRoleService;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserService;
 | 
			
		||||
import com.ruoyi.system.service.SysPermissionService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 角色信息
 | 
			
		||||
@@ -33,28 +31,31 @@ import java.util.List;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "角色信息控制器", tags = {"角色信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/role")
 | 
			
		||||
public class SysRoleController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final ISysRoleService roleService;
 | 
			
		||||
    private final TokenService tokenService;
 | 
			
		||||
    private final ISysUserService userService;
 | 
			
		||||
    private final ISysDeptService deptService;
 | 
			
		||||
    private final SysPermissionService permissionService;
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("查询角色信息列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:list')")
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取角色信息列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:role:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysRole> list(SysRole role) {
 | 
			
		||||
        return roleService.selectPageRoleList(role);
 | 
			
		||||
    public TableDataInfo<SysRole> list(SysRole role, PageQuery pageQuery) {
 | 
			
		||||
        return roleService.selectPageRoleList(role, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出角色信息列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出角色信息列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:role:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysRole role, HttpServletResponse response) {
 | 
			
		||||
        List<SysRole> list = roleService.selectRoleList(role);
 | 
			
		||||
        ExcelUtil.exportExcel(list, "角色数据", SysRole.class, response);
 | 
			
		||||
@@ -62,27 +63,28 @@ public class SysRoleController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据角色编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleId 角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据角色编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:query')")
 | 
			
		||||
    @SaCheckPermission("system:role:query")
 | 
			
		||||
    @GetMapping(value = "/{roleId}")
 | 
			
		||||
    public AjaxResult<SysRole> getInfo(@PathVariable Long roleId) {
 | 
			
		||||
    public R<SysRole> getInfo(@PathVariable Long roleId) {
 | 
			
		||||
        roleService.checkRoleDataScope(roleId);
 | 
			
		||||
        return AjaxResult.success(roleService.selectRoleById(roleId));
 | 
			
		||||
        return R.ok(roleService.selectRoleById(roleId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增角色
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增角色")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:add')")
 | 
			
		||||
    @SaCheckPermission("system:role:add")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysRole role) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
 | 
			
		||||
            return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
 | 
			
		||||
        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
 | 
			
		||||
            return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysRole role) {
 | 
			
		||||
        roleService.checkRoleAllowed(role);
 | 
			
		||||
        if (!roleService.checkRoleNameUnique(role)) {
 | 
			
		||||
            return R.fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
 | 
			
		||||
        } else if (!roleService.checkRoleKeyUnique(role)) {
 | 
			
		||||
            return R.fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(roleService.insertRole(role));
 | 
			
		||||
 | 
			
		||||
@@ -91,126 +93,136 @@ public class SysRoleController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改保存角色
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改保存角色")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysRole role) {
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysRole role) {
 | 
			
		||||
        roleService.checkRoleAllowed(role);
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
 | 
			
		||||
            return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
 | 
			
		||||
        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
 | 
			
		||||
            return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
 | 
			
		||||
        roleService.checkRoleDataScope(role.getRoleId());
 | 
			
		||||
        if (!roleService.checkRoleNameUnique(role)) {
 | 
			
		||||
            return R.fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
 | 
			
		||||
        } else if (!roleService.checkRoleKeyUnique(role)) {
 | 
			
		||||
            return R.fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (roleService.updateRole(role) > 0) {
 | 
			
		||||
            // 更新缓存用户权限
 | 
			
		||||
            LoginUser loginUser = getLoginUser();
 | 
			
		||||
            if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) {
 | 
			
		||||
                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
 | 
			
		||||
                loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
 | 
			
		||||
                tokenService.setLoginUser(loginUser);
 | 
			
		||||
            }
 | 
			
		||||
            return AjaxResult.success();
 | 
			
		||||
            roleService.cleanOnlineUserByRole(role.getRoleId());
 | 
			
		||||
            return R.ok();
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
 | 
			
		||||
        return R.fail("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改保存数据权限
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改保存数据权限")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/dataScope")
 | 
			
		||||
    public AjaxResult<Void> dataScope(@RequestBody SysRole role) {
 | 
			
		||||
    public R<Void> dataScope(@RequestBody SysRole role) {
 | 
			
		||||
        roleService.checkRoleAllowed(role);
 | 
			
		||||
        roleService.checkRoleDataScope(role.getRoleId());
 | 
			
		||||
        return toAjax(roleService.authDataScope(role));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态修改
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("状态修改")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/changeStatus")
 | 
			
		||||
    public AjaxResult<Void> changeStatus(@RequestBody SysRole role) {
 | 
			
		||||
    public R<Void> changeStatus(@RequestBody SysRole role) {
 | 
			
		||||
        roleService.checkRoleAllowed(role);
 | 
			
		||||
        roleService.checkRoleDataScope(role.getRoleId());
 | 
			
		||||
        return toAjax(roleService.updateRoleStatus(role));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除角色
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleIds 角色ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除角色")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:remove')")
 | 
			
		||||
    @SaCheckPermission("system:role:remove")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{roleIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] roleIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] roleIds) {
 | 
			
		||||
        return toAjax(roleService.deleteRoleByIds(roleIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取角色选择框列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取角色选择框列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:query')")
 | 
			
		||||
    @SaCheckPermission("system:role:query")
 | 
			
		||||
    @GetMapping("/optionselect")
 | 
			
		||||
    public AjaxResult<List<SysRole>> optionselect() {
 | 
			
		||||
        return AjaxResult.success(roleService.selectRoleAll());
 | 
			
		||||
    public R<List<SysRole>> optionselect() {
 | 
			
		||||
        return R.ok(roleService.selectRoleAll());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询已分配用户角色列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询已分配用户角色列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:list')")
 | 
			
		||||
    @SaCheckPermission("system:role:list")
 | 
			
		||||
    @GetMapping("/authUser/allocatedList")
 | 
			
		||||
    public TableDataInfo<SysUser> allocatedList(SysUser user) {
 | 
			
		||||
        return userService.selectAllocatedList(user);
 | 
			
		||||
    public TableDataInfo<SysUser> allocatedList(SysUser user, PageQuery pageQuery) {
 | 
			
		||||
        return userService.selectAllocatedList(user, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 查询未分配用户角色列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("查询未分配用户角色列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:list')")
 | 
			
		||||
    @SaCheckPermission("system:role:list")
 | 
			
		||||
    @GetMapping("/authUser/unallocatedList")
 | 
			
		||||
    public TableDataInfo<SysUser> unallocatedList(SysUser user) {
 | 
			
		||||
        return userService.selectUnallocatedList(user);
 | 
			
		||||
    public TableDataInfo<SysUser> unallocatedList(SysUser user, PageQuery pageQuery) {
 | 
			
		||||
        return userService.selectUnallocatedList(user, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 取消授权用户
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("取消授权用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
 | 
			
		||||
    @PutMapping("/authUser/cancel")
 | 
			
		||||
    public AjaxResult<Void> cancelAuthUser(@RequestBody SysUserRole userRole) {
 | 
			
		||||
    public R<Void> cancelAuthUser(@RequestBody SysUserRole userRole) {
 | 
			
		||||
        return toAjax(roleService.deleteAuthUser(userRole));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 批量取消授权用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleId  角色ID
 | 
			
		||||
     * @param userIds 用户ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("批量取消授权用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
 | 
			
		||||
    @PutMapping("/authUser/cancelAll")
 | 
			
		||||
    public AjaxResult<Void> cancelAuthUserAll(Long roleId, Long[] userIds) {
 | 
			
		||||
    public R<Void> cancelAuthUserAll(Long roleId, Long[] userIds) {
 | 
			
		||||
        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 批量选择用户授权
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleId  角色ID
 | 
			
		||||
     * @param userIds 用户ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("批量选择用户授权")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
 | 
			
		||||
    @SaCheckPermission("system:role:edit")
 | 
			
		||||
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
 | 
			
		||||
    @PutMapping("/authUser/selectAll")
 | 
			
		||||
    public AjaxResult<Void> selectAuthUserAll(Long roleId, Long[] userIds) {
 | 
			
		||||
    public R<Void> selectAuthUserAll(Long roleId, Long[] userIds) {
 | 
			
		||||
        roleService.checkRoleDataScope(roleId);
 | 
			
		||||
        return toAjax(roleService.insertAuthUsers(roleId, userIds));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取对应角色部门树列表
 | 
			
		||||
     *
 | 
			
		||||
     * @param roleId 角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:role:list")
 | 
			
		||||
    @GetMapping(value = "/deptTree/{roleId}")
 | 
			
		||||
    public R<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
 | 
			
		||||
        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +1,36 @@
 | 
			
		||||
package com.ruoyi.web.controller.system;
 | 
			
		||||
 | 
			
		||||
import cn.dev33.satoken.annotation.SaCheckPermission;
 | 
			
		||||
import cn.dev33.satoken.secure.BCrypt;
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import cn.hutool.core.lang.tree.Tree;
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.ruoyi.common.annotation.Log;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.controller.BaseController;
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.PageQuery;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
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.enums.BusinessType;
 | 
			
		||||
import com.ruoyi.common.utils.SecurityUtils;
 | 
			
		||||
import com.ruoyi.common.excel.ExcelResult;
 | 
			
		||||
import com.ruoyi.common.helper.LoginHelper;
 | 
			
		||||
import com.ruoyi.common.utils.StreamUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.system.domain.SysPost;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysUserExportVo;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysUserImportVo;
 | 
			
		||||
import com.ruoyi.system.listener.SysUserImportListener;
 | 
			
		||||
import com.ruoyi.system.service.ISysDeptService;
 | 
			
		||||
import com.ruoyi.system.service.ISysPostService;
 | 
			
		||||
import com.ruoyi.system.service.ISysRoleService;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserService;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParam;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParams;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
@@ -36,7 +40,6 @@ import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户信息
 | 
			
		||||
@@ -44,8 +47,7 @@ import java.util.stream.Collectors;
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Validated
 | 
			
		||||
@Api(value = "用户信息控制器", tags = {"用户信息管理"})
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/user")
 | 
			
		||||
public class SysUserController extends BaseController {
 | 
			
		||||
@@ -53,21 +55,23 @@ public class SysUserController extends BaseController {
 | 
			
		||||
    private final ISysUserService userService;
 | 
			
		||||
    private final ISysRoleService roleService;
 | 
			
		||||
    private final ISysPostService postService;
 | 
			
		||||
    private final ISysDeptService deptService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户列表
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("获取用户列表")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:list')")
 | 
			
		||||
    @SaCheckPermission("system:user:list")
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    public TableDataInfo<SysUser> list(SysUser user) {
 | 
			
		||||
        return userService.selectPageUserList(user);
 | 
			
		||||
    public TableDataInfo<SysUser> list(SysUser user, PageQuery pageQuery) {
 | 
			
		||||
        return userService.selectPageUserList(user, pageQuery);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导出用户列表")
 | 
			
		||||
    /**
 | 
			
		||||
     * 导出用户列表
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:export')")
 | 
			
		||||
    @GetMapping("/export")
 | 
			
		||||
    @SaCheckPermission("system:user:export")
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    public void export(SysUser user, HttpServletResponse response) {
 | 
			
		||||
        List<SysUser> list = userService.selectUserList(user);
 | 
			
		||||
        List<SysUserExportVo> listVo = BeanUtil.copyToList(list, SysUserExportVo.class);
 | 
			
		||||
@@ -82,97 +86,104 @@ public class SysUserController extends BaseController {
 | 
			
		||||
        ExcelUtil.exportExcel(listVo, "用户数据", SysUserExportVo.class, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("导入用户列表")
 | 
			
		||||
    @ApiImplicitParams({
 | 
			
		||||
            @ApiImplicitParam(name = "file", value = "导入文件", dataType = "java.io.File", required = true),
 | 
			
		||||
    })
 | 
			
		||||
    /**
 | 
			
		||||
     * 导入数据
 | 
			
		||||
     *
 | 
			
		||||
     * @param file          导入文件
 | 
			
		||||
     * @param updateSupport 是否更新已存在数据
 | 
			
		||||
     */
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:import')")
 | 
			
		||||
    @PostMapping("/importData")
 | 
			
		||||
    public AjaxResult<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
 | 
			
		||||
        List<SysUserImportVo> userListVo = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class);
 | 
			
		||||
        List<SysUser> userList = BeanUtil.copyToList(userListVo, SysUser.class);
 | 
			
		||||
        String operName = getUsername();
 | 
			
		||||
        String message = userService.importUser(userList, updateSupport, operName);
 | 
			
		||||
        return AjaxResult.success(message);
 | 
			
		||||
    @SaCheckPermission("system:user:import")
 | 
			
		||||
    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 | 
			
		||||
    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
 | 
			
		||||
        ExcelResult<SysUserImportVo> result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport));
 | 
			
		||||
        return R.ok(result.getAnalysis());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation("下载导入模板")
 | 
			
		||||
    @GetMapping("/importTemplate")
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取导入模板
 | 
			
		||||
     */
 | 
			
		||||
    @PostMapping("/importTemplate")
 | 
			
		||||
    public void importTemplate(HttpServletResponse response) {
 | 
			
		||||
        ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", SysUserImportVo.class, response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据用户编号获取详细信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据用户编号获取详细信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:query')")
 | 
			
		||||
    @SaCheckPermission("system:user:query")
 | 
			
		||||
    @GetMapping(value = {"/", "/{userId}"})
 | 
			
		||||
    public AjaxResult<Map<String, Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
 | 
			
		||||
    public R<Map<String, Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
 | 
			
		||||
        userService.checkUserDataScope(userId);
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        List<SysRole> roles = roleService.selectRoleAll();
 | 
			
		||||
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
 | 
			
		||||
        ajax.put("posts", postService.selectPostAll());
 | 
			
		||||
        if (StringUtils.isNotNull(userId)) {
 | 
			
		||||
            ajax.put("user", userService.selectUserById(userId));
 | 
			
		||||
        SysRole role = new SysRole();
 | 
			
		||||
        role.setStatus(UserConstants.ROLE_NORMAL);
 | 
			
		||||
        SysPost post = new SysPost();
 | 
			
		||||
        post.setStatus(UserConstants.POST_NORMAL);
 | 
			
		||||
        List<SysRole> roles = roleService.selectRoleList(role);
 | 
			
		||||
        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
 | 
			
		||||
        ajax.put("posts", postService.selectPostList(post));
 | 
			
		||||
        if (ObjectUtil.isNotNull(userId)) {
 | 
			
		||||
            SysUser sysUser = userService.selectUserById(userId);
 | 
			
		||||
            ajax.put("user", sysUser);
 | 
			
		||||
            ajax.put("postIds", postService.selectPostListByUserId(userId));
 | 
			
		||||
            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
 | 
			
		||||
            ajax.put("roleIds", StreamUtils.toList(sysUser.getRoles(), SysRole::getRoleId));
 | 
			
		||||
        }
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增用户
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("新增用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:add')")
 | 
			
		||||
    @SaCheckPermission("system:user:add")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
 | 
			
		||||
    @PostMapping
 | 
			
		||||
    public AjaxResult<Void> add(@Validated @RequestBody SysUser user) {
 | 
			
		||||
        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) {
 | 
			
		||||
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getEmail())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
    public R<Void> add(@Validated @RequestBody SysUser user) {
 | 
			
		||||
        deptService.checkDeptDataScope(user.getDeptId());
 | 
			
		||||
        if (!userService.checkUserNameUnique(user)) {
 | 
			
		||||
            return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
 | 
			
		||||
            return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
 | 
			
		||||
            return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
        }
 | 
			
		||||
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
 | 
			
		||||
        user.setPassword(BCrypt.hashpw(user.getPassword()));
 | 
			
		||||
        return toAjax(userService.insertUser(user));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改用户
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("修改用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
 | 
			
		||||
    @SaCheckPermission("system:user:edit")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping
 | 
			
		||||
    public AjaxResult<Void> edit(@Validated @RequestBody SysUser user) {
 | 
			
		||||
    public R<Void> edit(@Validated @RequestBody SysUser user) {
 | 
			
		||||
        userService.checkUserAllowed(user);
 | 
			
		||||
        if (StringUtils.isNotEmpty(user.getPhonenumber())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getEmail())
 | 
			
		||||
                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
 | 
			
		||||
            return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
        userService.checkUserDataScope(user.getUserId());
 | 
			
		||||
        deptService.checkDeptDataScope(user.getDeptId());
 | 
			
		||||
        if (!userService.checkUserNameUnique(user)) {
 | 
			
		||||
            return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
 | 
			
		||||
            return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
 | 
			
		||||
        } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
 | 
			
		||||
            return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(userService.updateUser(user));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param userIds 角色ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("删除用户")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
 | 
			
		||||
    @SaCheckPermission("system:user:remove")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
 | 
			
		||||
    @DeleteMapping("/{userIds}")
 | 
			
		||||
    public AjaxResult<Void> remove(@PathVariable Long[] userIds) {
 | 
			
		||||
    public R<Void> remove(@PathVariable Long[] userIds) {
 | 
			
		||||
        if (ArrayUtil.contains(userIds, getUserId())) {
 | 
			
		||||
            return error("当前用户不能删除");
 | 
			
		||||
            return R.fail("当前用户不能删除");
 | 
			
		||||
        }
 | 
			
		||||
        return toAjax(userService.deleteUserByIds(userIds));
 | 
			
		||||
    }
 | 
			
		||||
@@ -180,52 +191,66 @@ public class SysUserController extends BaseController {
 | 
			
		||||
    /**
 | 
			
		||||
     * 重置密码
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("重置密码")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
 | 
			
		||||
    @SaCheckPermission("system:user:resetPwd")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/resetPwd")
 | 
			
		||||
    public AjaxResult<Void> resetPwd(@RequestBody SysUser user) {
 | 
			
		||||
    public R<Void> resetPwd(@RequestBody SysUser user) {
 | 
			
		||||
        userService.checkUserAllowed(user);
 | 
			
		||||
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
 | 
			
		||||
        userService.checkUserDataScope(user.getUserId());
 | 
			
		||||
        user.setPassword(BCrypt.hashpw(user.getPassword()));
 | 
			
		||||
        return toAjax(userService.resetPwd(user));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态修改
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("状态修改")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
 | 
			
		||||
    @SaCheckPermission("system:user:edit")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
 | 
			
		||||
    @PutMapping("/changeStatus")
 | 
			
		||||
    public AjaxResult<Void> changeStatus(@RequestBody SysUser user) {
 | 
			
		||||
    public R<Void> changeStatus(@RequestBody SysUser user) {
 | 
			
		||||
        userService.checkUserAllowed(user);
 | 
			
		||||
        userService.checkUserDataScope(user.getUserId());
 | 
			
		||||
        return toAjax(userService.updateUserStatus(user));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据用户编号获取授权角色
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("根据用户编号获取授权角色")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:query')")
 | 
			
		||||
    @SaCheckPermission("system:user:query")
 | 
			
		||||
    @GetMapping("/authRole/{userId}")
 | 
			
		||||
    public AjaxResult<Map<String, Object>> authRole(@PathVariable("userId") Long userId) {
 | 
			
		||||
    public R<Map<String, Object>> authRole(@PathVariable Long userId) {
 | 
			
		||||
        SysUser user = userService.selectUserById(userId);
 | 
			
		||||
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
 | 
			
		||||
        Map<String, Object> ajax = new HashMap<>();
 | 
			
		||||
        ajax.put("user", user);
 | 
			
		||||
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
 | 
			
		||||
        return AjaxResult.success(ajax);
 | 
			
		||||
        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
 | 
			
		||||
        return R.ok(ajax);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户授权角色
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId  用户Id
 | 
			
		||||
     * @param roleIds 角色ID串
 | 
			
		||||
     */
 | 
			
		||||
    @ApiOperation("用户授权角色")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
 | 
			
		||||
    @SaCheckPermission("system:user:edit")
 | 
			
		||||
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
 | 
			
		||||
    @PutMapping("/authRole")
 | 
			
		||||
    public AjaxResult<Void> insertAuthRole(Long userId, Long[] roleIds) {
 | 
			
		||||
    public R<Void> insertAuthRole(Long userId, Long[] roleIds) {
 | 
			
		||||
        userService.checkUserDataScope(userId);
 | 
			
		||||
        userService.insertUserAuth(userId, roleIds);
 | 
			
		||||
        return success();
 | 
			
		||||
        return R.ok();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取部门树列表
 | 
			
		||||
     */
 | 
			
		||||
    @SaCheckPermission("system:user:list")
 | 
			
		||||
    @GetMapping("/deptTree")
 | 
			
		||||
    public R<List<Tree<Long>>> deptTree(SysDept dept) {
 | 
			
		||||
        return R.ok(deptService.selectDeptTreeList(dept));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,113 +1,102 @@
 | 
			
		||||
--- # 监控配置
 | 
			
		||||
spring:
 | 
			
		||||
  boot:
 | 
			
		||||
    admin:
 | 
			
		||||
      # Spring Boot Admin Client 客户端的相关配置
 | 
			
		||||
      client:
 | 
			
		||||
        # 增加客户端开关
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置 Spring Boot Admin Server 地址
 | 
			
		||||
        url: http://localhost:9090/admin
 | 
			
		||||
        instance:
 | 
			
		||||
          prefer-ip: true # 注册实例时,优先使用 IP
 | 
			
		||||
        username: ruoyi
 | 
			
		||||
        password: 123456
 | 
			
		||||
--- # 监控中心配置
 | 
			
		||||
spring.boot.admin.client:
 | 
			
		||||
  # 增加客户端开关
 | 
			
		||||
  enabled: true
 | 
			
		||||
  url: http://localhost:9090/admin
 | 
			
		||||
  instance:
 | 
			
		||||
    service-host-type: IP
 | 
			
		||||
  username: ruoyi
 | 
			
		||||
  password: 123456
 | 
			
		||||
 | 
			
		||||
--- # xxl-job 配置
 | 
			
		||||
xxl:
 | 
			
		||||
  job:
 | 
			
		||||
    # 执行器开关
 | 
			
		||||
    enabled: true
 | 
			
		||||
    # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
 | 
			
		||||
    admin-addresses: http://localhost:9100/xxl-job-admin
 | 
			
		||||
    # 执行器通讯TOKEN:非空时启用
 | 
			
		||||
    access-token: xxl-job
 | 
			
		||||
    # 执行器配置
 | 
			
		||||
    executor:
 | 
			
		||||
      # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
 | 
			
		||||
      appname: xxl-job-executor
 | 
			
		||||
      # 执行器端口号 执行器从9101开始往后写
 | 
			
		||||
      port: 9101
 | 
			
		||||
      # 执行器注册:默认IP:PORT
 | 
			
		||||
      address:
 | 
			
		||||
      # 执行器IP:默认自动获取IP
 | 
			
		||||
      ip:
 | 
			
		||||
      # 执行器运行日志文件存储磁盘路径
 | 
			
		||||
      logpath: ./logs/xxl-job
 | 
			
		||||
      # 执行器日志文件保存天数:大于3生效
 | 
			
		||||
      logretentiondays: 30
 | 
			
		||||
xxl.job:
 | 
			
		||||
  # 执行器开关
 | 
			
		||||
  enabled: true
 | 
			
		||||
  # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
 | 
			
		||||
  admin-addresses: http://localhost:9100/xxl-job-admin
 | 
			
		||||
  # 执行器通讯TOKEN:非空时启用
 | 
			
		||||
  access-token: xxl-job
 | 
			
		||||
  executor:
 | 
			
		||||
    # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
 | 
			
		||||
    appname: xxl-job-executor
 | 
			
		||||
    # 28080 端口 随着主应用端口飘逸 避免集群冲突
 | 
			
		||||
    port: 2${server.port}
 | 
			
		||||
    # 执行器注册:默认IP:PORT
 | 
			
		||||
    address:
 | 
			
		||||
    # 执行器IP:默认自动获取IP
 | 
			
		||||
    ip:
 | 
			
		||||
    # 执行器运行日志文件存储磁盘路径
 | 
			
		||||
    logpath: ./logs/xxl-job
 | 
			
		||||
    # 执行器日志文件保存天数:大于3生效
 | 
			
		||||
    logretentiondays: 30
 | 
			
		||||
 | 
			
		||||
--- # 数据源配置
 | 
			
		||||
spring:
 | 
			
		||||
  datasource:
 | 
			
		||||
    type: com.alibaba.druid.pool.DruidDataSource
 | 
			
		||||
    type: com.zaxxer.hikari.HikariDataSource
 | 
			
		||||
    # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
 | 
			
		||||
    dynamic:
 | 
			
		||||
      # 性能分析插件(有性能损耗 不建议生产环境使用)
 | 
			
		||||
      p6spy: true
 | 
			
		||||
      # 设置默认的数据源或者数据源组,默认值即为 master
 | 
			
		||||
      primary: master
 | 
			
		||||
      # 严格模式 匹配不到数据源则报错
 | 
			
		||||
      strict: true
 | 
			
		||||
      datasource:
 | 
			
		||||
        # 主库数据源
 | 
			
		||||
        master:
 | 
			
		||||
          type: ${spring.datasource.type}
 | 
			
		||||
          driverClassName: com.mysql.cj.jdbc.Driver
 | 
			
		||||
          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
 | 
			
		||||
          # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
 | 
			
		||||
          # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
 | 
			
		||||
          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
 | 
			
		||||
          username: root
 | 
			
		||||
          password: root
 | 
			
		||||
        # 从库数据源
 | 
			
		||||
        slave:
 | 
			
		||||
          lazy: true
 | 
			
		||||
          type: ${spring.datasource.type}
 | 
			
		||||
          driverClassName: com.mysql.cj.jdbc.Driver
 | 
			
		||||
          url:
 | 
			
		||||
          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
 | 
			
		||||
          username:
 | 
			
		||||
          password:
 | 
			
		||||
      druid:
 | 
			
		||||
        # 初始连接数
 | 
			
		||||
        initialSize: 5
 | 
			
		||||
        # 最小连接池数量
 | 
			
		||||
        minIdle: 10
 | 
			
		||||
#        oracle:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: oracle.jdbc.OracleDriver
 | 
			
		||||
#          url: jdbc:oracle:thin:@//localhost:1521/XE
 | 
			
		||||
#          username: ROOT
 | 
			
		||||
#          password: root
 | 
			
		||||
#          hikari:
 | 
			
		||||
#            connectionTestQuery: SELECT 1 FROM DUAL
 | 
			
		||||
#        postgres:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: org.postgresql.Driver
 | 
			
		||||
#          url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
 | 
			
		||||
#          username: root
 | 
			
		||||
#          password: root
 | 
			
		||||
#        sqlserver:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
 | 
			
		||||
#          url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
 | 
			
		||||
#          username: SA
 | 
			
		||||
#          password: root
 | 
			
		||||
      hikari:
 | 
			
		||||
        # 最大连接池数量
 | 
			
		||||
        maxActive: 20
 | 
			
		||||
        maxPoolSize: 20
 | 
			
		||||
        # 最小空闲线程数量
 | 
			
		||||
        minIdle: 10
 | 
			
		||||
        # 配置获取连接等待超时的时间
 | 
			
		||||
        maxWait: 60000
 | 
			
		||||
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
 | 
			
		||||
        timeBetweenEvictionRunsMillis: 60000
 | 
			
		||||
        # 配置一个连接在池中最小生存的时间,单位是毫秒
 | 
			
		||||
        minEvictableIdleTimeMillis: 300000
 | 
			
		||||
        # 配置一个连接在池中最大生存的时间,单位是毫秒
 | 
			
		||||
        maxEvictableIdleTimeMillis: 900000
 | 
			
		||||
        # 配置检测连接是否有效
 | 
			
		||||
        validationQuery: SELECT 1 FROM DUAL
 | 
			
		||||
        testWhileIdle: true
 | 
			
		||||
        testOnBorrow: false
 | 
			
		||||
        testOnReturn: false
 | 
			
		||||
        # 注意这个值和druid原生不一致,默认启动了stat
 | 
			
		||||
        filters: stat
 | 
			
		||||
 | 
			
		||||
--- # druid 配置
 | 
			
		||||
spring:
 | 
			
		||||
  datasource:
 | 
			
		||||
    druid:
 | 
			
		||||
      webStatFilter:
 | 
			
		||||
        enabled: true
 | 
			
		||||
      statViewServlet:
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置白名单,不填则允许所有访问
 | 
			
		||||
        allow:
 | 
			
		||||
        url-pattern: /druid/*
 | 
			
		||||
        # 控制台管理用户名和密码
 | 
			
		||||
        login-username: ruoyi
 | 
			
		||||
        login-password: 123456
 | 
			
		||||
      filter:
 | 
			
		||||
        stat:
 | 
			
		||||
          enabled: true
 | 
			
		||||
          # 慢SQL记录
 | 
			
		||||
          log-slow-sql: true
 | 
			
		||||
          slow-sql-millis: 1000
 | 
			
		||||
          merge-sql: true
 | 
			
		||||
        wall:
 | 
			
		||||
          config:
 | 
			
		||||
            multi-statement-allow: true
 | 
			
		||||
        connectionTimeout: 30000
 | 
			
		||||
        # 校验超时时间
 | 
			
		||||
        validationTimeout: 5000
 | 
			
		||||
        # 空闲连接存活最大时间,默认10分钟
 | 
			
		||||
        idleTimeout: 600000
 | 
			
		||||
        # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
 | 
			
		||||
        maxLifetime: 1800000
 | 
			
		||||
        # 连接测试query(配置检测连接是否有效)
 | 
			
		||||
        connectionTestQuery: SELECT 1
 | 
			
		||||
        # 多久检查一次连接的活性
 | 
			
		||||
        keepaliveTime: 30000
 | 
			
		||||
 | 
			
		||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
 | 
			
		||||
spring:
 | 
			
		||||
@@ -118,41 +107,80 @@ spring:
 | 
			
		||||
    port: 6379
 | 
			
		||||
    # 数据库索引
 | 
			
		||||
    database: 0
 | 
			
		||||
    # 密码
 | 
			
		||||
    password:
 | 
			
		||||
    # 密码(如没有密码请注释掉)
 | 
			
		||||
    # password:
 | 
			
		||||
    # 连接超时时间
 | 
			
		||||
    timeout: 10s
 | 
			
		||||
    # 是否开启ssl
 | 
			
		||||
    ssl: false
 | 
			
		||||
 | 
			
		||||
redisson:
 | 
			
		||||
  # redis key前缀
 | 
			
		||||
  keyPrefix:
 | 
			
		||||
  # 线程池数量
 | 
			
		||||
  threads: 16
 | 
			
		||||
  threads: 4
 | 
			
		||||
  # Netty线程池数量
 | 
			
		||||
  nettyThreads: 32
 | 
			
		||||
  # 传输模式
 | 
			
		||||
  transportMode: "NIO"
 | 
			
		||||
  nettyThreads: 8
 | 
			
		||||
  # 单节点配置
 | 
			
		||||
  singleServerConfig:
 | 
			
		||||
    # 客户端名称
 | 
			
		||||
    clientName: ${ruoyi.name}
 | 
			
		||||
    # 最小空闲连接数
 | 
			
		||||
    connectionMinimumIdleSize: 32
 | 
			
		||||
    connectionMinimumIdleSize: 8
 | 
			
		||||
    # 连接池大小
 | 
			
		||||
    connectionPoolSize: 64
 | 
			
		||||
    connectionPoolSize: 32
 | 
			
		||||
    # 连接空闲超时,单位:毫秒
 | 
			
		||||
    idleConnectionTimeout: 10000
 | 
			
		||||
    # 命令等待超时,单位:毫秒
 | 
			
		||||
    timeout: 3000
 | 
			
		||||
    # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
 | 
			
		||||
    retryAttempts: 3
 | 
			
		||||
    # 命令重试发送时间间隔,单位:毫秒
 | 
			
		||||
    retryInterval: 1500
 | 
			
		||||
    # 发布和订阅连接的最小空闲连接数
 | 
			
		||||
    subscriptionConnectionMinimumIdleSize: 1
 | 
			
		||||
    # 发布和订阅连接池大小
 | 
			
		||||
    subscriptionConnectionPoolSize: 50
 | 
			
		||||
    # 单个连接最大订阅数量
 | 
			
		||||
    subscriptionsPerConnection: 5
 | 
			
		||||
    # DNS监测时间间隔,单位:毫秒
 | 
			
		||||
    dnsMonitoringInterval: 5000
 | 
			
		||||
 | 
			
		||||
--- # mail 邮件发送
 | 
			
		||||
mail:
 | 
			
		||||
  enabled: false
 | 
			
		||||
  host: smtp.163.com
 | 
			
		||||
  port: 465
 | 
			
		||||
  # 是否需要用户名密码验证
 | 
			
		||||
  auth: true
 | 
			
		||||
  # 发送方,遵循RFC-822标准
 | 
			
		||||
  from: xxx@163.com
 | 
			
		||||
  # 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
 | 
			
		||||
  user: xxx@163.com
 | 
			
		||||
  # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
 | 
			
		||||
  pass: xxxxxxxxxx
 | 
			
		||||
  # 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
 | 
			
		||||
  starttlsEnable: true
 | 
			
		||||
  # 使用SSL安全连接
 | 
			
		||||
  sslEnable: true
 | 
			
		||||
  # SMTP超时时长,单位毫秒,缺省值不超时
 | 
			
		||||
  timeout: 0
 | 
			
		||||
  # Socket连接超时值,单位毫秒,缺省值不超时
 | 
			
		||||
  connectionTimeout: 0
 | 
			
		||||
 | 
			
		||||
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
 | 
			
		||||
# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
 | 
			
		||||
sms:
 | 
			
		||||
  # 阿里云 dysmsapi.aliyuncs.com
 | 
			
		||||
  alibaba:
 | 
			
		||||
    #请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
 | 
			
		||||
    requestUrl: dysmsapi.aliyuncs.com
 | 
			
		||||
    #阿里云的accessKey
 | 
			
		||||
    accessKeyId: xxxxxxx
 | 
			
		||||
    #阿里云的accessKeySecret
 | 
			
		||||
    accessKeySecret: xxxxxxx
 | 
			
		||||
    #短信签名
 | 
			
		||||
    signature: 测试
 | 
			
		||||
  tencent:
 | 
			
		||||
    #请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
 | 
			
		||||
    requestUrl: sms.tencentcloudapi.com
 | 
			
		||||
    #腾讯云的accessKey
 | 
			
		||||
    accessKeyId: xxxxxxx
 | 
			
		||||
    #腾讯云的accessKeySecret
 | 
			
		||||
    accessKeySecret: xxxxxxx
 | 
			
		||||
    #短信签名
 | 
			
		||||
    signature: 测试
 | 
			
		||||
    #短信sdkAppId
 | 
			
		||||
    sdkAppId: appid
 | 
			
		||||
    #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
 | 
			
		||||
    territory: ap-guangzhou
 | 
			
		||||
 
 | 
			
		||||
@@ -1,137 +1,129 @@
 | 
			
		||||
--- # 监控配置
 | 
			
		||||
spring:
 | 
			
		||||
  boot:
 | 
			
		||||
    admin:
 | 
			
		||||
      # Spring Boot Admin Client 客户端的相关配置
 | 
			
		||||
      client:
 | 
			
		||||
        # 增加客户端开关
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置 Spring Boot Admin Server 地址
 | 
			
		||||
        url: http://172.30.0.90:9090/admin
 | 
			
		||||
        instance:
 | 
			
		||||
          prefer-ip: true # 注册实例时,优先使用 IP
 | 
			
		||||
        username: ruoyi
 | 
			
		||||
        password: 123456
 | 
			
		||||
--- # 临时文件存储位置 避免临时文件被系统清理报错
 | 
			
		||||
spring.servlet.multipart.location: /ruoyi/server/temp
 | 
			
		||||
 | 
			
		||||
--- # 监控中心配置
 | 
			
		||||
spring.boot.admin.client:
 | 
			
		||||
  # 增加客户端开关
 | 
			
		||||
  enabled: true
 | 
			
		||||
  url: http://localhost:9090/admin
 | 
			
		||||
  instance:
 | 
			
		||||
    service-host-type: IP
 | 
			
		||||
  username: ruoyi
 | 
			
		||||
  password: 123456
 | 
			
		||||
 | 
			
		||||
--- # xxl-job 配置
 | 
			
		||||
xxl:
 | 
			
		||||
  job:
 | 
			
		||||
    # 执行器开关
 | 
			
		||||
    enabled: true
 | 
			
		||||
    # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
 | 
			
		||||
    admin-addresses: http://172.30.0.92:9100/xxl-job-admin
 | 
			
		||||
    # 执行器通讯TOKEN:非空时启用
 | 
			
		||||
    access-token: xxl-job
 | 
			
		||||
    # 执行器配置
 | 
			
		||||
    executor:
 | 
			
		||||
      # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
 | 
			
		||||
      appname: xxl-job-executor
 | 
			
		||||
      # 执行器端口号 执行器从9101开始往后写
 | 
			
		||||
      port: 9101
 | 
			
		||||
      # 执行器注册:默认IP:PORT
 | 
			
		||||
      address:
 | 
			
		||||
      # 执行器IP:默认自动获取IP
 | 
			
		||||
      ip:
 | 
			
		||||
      # 执行器运行日志文件存储磁盘路径
 | 
			
		||||
      logpath: ./logs/xxl-job
 | 
			
		||||
      # 执行器日志文件保存天数:大于3生效
 | 
			
		||||
      logretentiondays: 30
 | 
			
		||||
xxl.job:
 | 
			
		||||
  # 执行器开关
 | 
			
		||||
  enabled: true
 | 
			
		||||
  # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
 | 
			
		||||
  admin-addresses: http://localhost:9100/xxl-job-admin
 | 
			
		||||
  # 执行器通讯TOKEN:非空时启用
 | 
			
		||||
  access-token: xxl-job
 | 
			
		||||
  executor:
 | 
			
		||||
    # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
 | 
			
		||||
    appname: xxl-job-executor
 | 
			
		||||
    # 28080 端口 随着主应用端口飘逸 避免集群冲突
 | 
			
		||||
    port: 2${server.port}
 | 
			
		||||
    # 执行器注册:默认IP:PORT
 | 
			
		||||
    address:
 | 
			
		||||
    # 执行器IP:默认自动获取IP
 | 
			
		||||
    ip:
 | 
			
		||||
    # 执行器运行日志文件存储磁盘路径
 | 
			
		||||
    logpath: ./logs/xxl-job
 | 
			
		||||
    # 执行器日志文件保存天数:大于3生效
 | 
			
		||||
    logretentiondays: 30
 | 
			
		||||
 | 
			
		||||
--- # 数据源配置
 | 
			
		||||
spring:
 | 
			
		||||
  datasource:
 | 
			
		||||
    type: com.alibaba.druid.pool.DruidDataSource
 | 
			
		||||
    type: com.zaxxer.hikari.HikariDataSource
 | 
			
		||||
    # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
 | 
			
		||||
    dynamic:
 | 
			
		||||
      # 性能分析插件(有性能损耗 不建议生产环境使用)
 | 
			
		||||
      p6spy: false
 | 
			
		||||
      # 设置默认的数据源或者数据源组,默认值即为 master
 | 
			
		||||
      primary: master
 | 
			
		||||
      # 严格模式 匹配不到数据源则报错
 | 
			
		||||
      strict: true
 | 
			
		||||
      datasource:
 | 
			
		||||
        # 主库数据源
 | 
			
		||||
        master:
 | 
			
		||||
          type: ${spring.datasource.type}
 | 
			
		||||
          driverClassName: com.mysql.cj.jdbc.Driver
 | 
			
		||||
          url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
 | 
			
		||||
          # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
 | 
			
		||||
          # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
 | 
			
		||||
          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
 | 
			
		||||
          username: root
 | 
			
		||||
          password: root
 | 
			
		||||
        # 从库数据源
 | 
			
		||||
        slave:
 | 
			
		||||
          lazy: true
 | 
			
		||||
          type: ${spring.datasource.type}
 | 
			
		||||
          driverClassName: com.mysql.cj.jdbc.Driver
 | 
			
		||||
          url:
 | 
			
		||||
          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
 | 
			
		||||
          username:
 | 
			
		||||
          password:
 | 
			
		||||
      druid:
 | 
			
		||||
        # 初始连接数
 | 
			
		||||
        initialSize: 5
 | 
			
		||||
        # 最小连接池数量
 | 
			
		||||
        minIdle: 10
 | 
			
		||||
#        oracle:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: oracle.jdbc.OracleDriver
 | 
			
		||||
#          url: jdbc:oracle:thin:@//localhost:1521/XE
 | 
			
		||||
#          username: ROOT
 | 
			
		||||
#          password: root
 | 
			
		||||
#          hikari:
 | 
			
		||||
#            connectionTestQuery: SELECT 1 FROM DUAL
 | 
			
		||||
#        postgres:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: org.postgresql.Driver
 | 
			
		||||
#          url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
 | 
			
		||||
#          username: root
 | 
			
		||||
#          password: root
 | 
			
		||||
#        sqlserver:
 | 
			
		||||
#          type: ${spring.datasource.type}
 | 
			
		||||
#          driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
 | 
			
		||||
#          url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
 | 
			
		||||
#          username: SA
 | 
			
		||||
#          password: root
 | 
			
		||||
      hikari:
 | 
			
		||||
        # 最大连接池数量
 | 
			
		||||
        maxActive: 20
 | 
			
		||||
        maxPoolSize: 20
 | 
			
		||||
        # 最小空闲线程数量
 | 
			
		||||
        minIdle: 10
 | 
			
		||||
        # 配置获取连接等待超时的时间
 | 
			
		||||
        maxWait: 60000
 | 
			
		||||
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
 | 
			
		||||
        timeBetweenEvictionRunsMillis: 60000
 | 
			
		||||
        # 配置一个连接在池中最小生存的时间,单位是毫秒
 | 
			
		||||
        minEvictableIdleTimeMillis: 300000
 | 
			
		||||
        # 配置一个连接在池中最大生存的时间,单位是毫秒
 | 
			
		||||
        maxEvictableIdleTimeMillis: 900000
 | 
			
		||||
        # 配置检测连接是否有效
 | 
			
		||||
        validationQuery: SELECT 1 FROM DUAL
 | 
			
		||||
        testWhileIdle: true
 | 
			
		||||
        testOnBorrow: false
 | 
			
		||||
        testOnReturn: false
 | 
			
		||||
        # 注意这个值和druid原生不一致,默认启动了stat
 | 
			
		||||
        filters: stat
 | 
			
		||||
 | 
			
		||||
--- # druid 配置
 | 
			
		||||
spring:
 | 
			
		||||
  datasource:
 | 
			
		||||
    druid:
 | 
			
		||||
      webStatFilter:
 | 
			
		||||
        enabled: true
 | 
			
		||||
      statViewServlet:
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置白名单,不填则允许所有访问
 | 
			
		||||
        allow:
 | 
			
		||||
        url-pattern: /druid/*
 | 
			
		||||
        # 控制台管理用户名和密码
 | 
			
		||||
        login-username: ruoyi
 | 
			
		||||
        login-password: 123456
 | 
			
		||||
      filter:
 | 
			
		||||
        stat:
 | 
			
		||||
          enabled: true
 | 
			
		||||
          # 慢SQL记录
 | 
			
		||||
          log-slow-sql: true
 | 
			
		||||
          slow-sql-millis: 1000
 | 
			
		||||
          merge-sql: true
 | 
			
		||||
        wall:
 | 
			
		||||
          config:
 | 
			
		||||
            multi-statement-allow: true
 | 
			
		||||
        connectionTimeout: 30000
 | 
			
		||||
        # 校验超时时间
 | 
			
		||||
        validationTimeout: 5000
 | 
			
		||||
        # 空闲连接存活最大时间,默认10分钟
 | 
			
		||||
        idleTimeout: 600000
 | 
			
		||||
        # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
 | 
			
		||||
        maxLifetime: 1800000
 | 
			
		||||
        # 连接测试query(配置检测连接是否有效)
 | 
			
		||||
        connectionTestQuery: SELECT 1
 | 
			
		||||
        # 多久检查一次连接的活性
 | 
			
		||||
        keepaliveTime: 30000
 | 
			
		||||
 | 
			
		||||
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
 | 
			
		||||
spring:
 | 
			
		||||
  redis:
 | 
			
		||||
    # 地址
 | 
			
		||||
    host: 172.30.0.48
 | 
			
		||||
    host: localhost
 | 
			
		||||
    # 端口,默认为6379
 | 
			
		||||
    port: 6379
 | 
			
		||||
    # 数据库索引
 | 
			
		||||
    database: 0
 | 
			
		||||
    # 密码
 | 
			
		||||
    password:
 | 
			
		||||
    # 密码(如没有密码请注释掉)
 | 
			
		||||
    # password:
 | 
			
		||||
    # 连接超时时间
 | 
			
		||||
    timeout: 10s
 | 
			
		||||
    # 是否开启ssl
 | 
			
		||||
    ssl: false
 | 
			
		||||
 | 
			
		||||
redisson:
 | 
			
		||||
  # redis key前缀
 | 
			
		||||
  keyPrefix:
 | 
			
		||||
  # 线程池数量
 | 
			
		||||
  threads: 16
 | 
			
		||||
  # Netty线程池数量
 | 
			
		||||
  nettyThreads: 32
 | 
			
		||||
  # 传输模式
 | 
			
		||||
  transportMode: "NIO"
 | 
			
		||||
  # 单节点配置
 | 
			
		||||
  singleServerConfig:
 | 
			
		||||
    # 客户端名称
 | 
			
		||||
@@ -144,15 +136,54 @@ redisson:
 | 
			
		||||
    idleConnectionTimeout: 10000
 | 
			
		||||
    # 命令等待超时,单位:毫秒
 | 
			
		||||
    timeout: 3000
 | 
			
		||||
    # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
 | 
			
		||||
    retryAttempts: 3
 | 
			
		||||
    # 命令重试发送时间间隔,单位:毫秒
 | 
			
		||||
    retryInterval: 1500
 | 
			
		||||
    # 发布和订阅连接的最小空闲连接数
 | 
			
		||||
    subscriptionConnectionMinimumIdleSize: 1
 | 
			
		||||
    # 发布和订阅连接池大小
 | 
			
		||||
    subscriptionConnectionPoolSize: 50
 | 
			
		||||
    # 单个连接最大订阅数量
 | 
			
		||||
    subscriptionsPerConnection: 5
 | 
			
		||||
    # DNS监测时间间隔,单位:毫秒
 | 
			
		||||
    dnsMonitoringInterval: 5000
 | 
			
		||||
 | 
			
		||||
--- # mail 邮件发送
 | 
			
		||||
mail:
 | 
			
		||||
  enabled: false
 | 
			
		||||
  host: smtp.163.com
 | 
			
		||||
  port: 465
 | 
			
		||||
  # 是否需要用户名密码验证
 | 
			
		||||
  auth: true
 | 
			
		||||
  # 发送方,遵循RFC-822标准
 | 
			
		||||
  from: xxx@163.com
 | 
			
		||||
  # 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
 | 
			
		||||
  user: xxx@163.com
 | 
			
		||||
  # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
 | 
			
		||||
  pass: xxxxxxxxxx
 | 
			
		||||
  # 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
 | 
			
		||||
  starttlsEnable: true
 | 
			
		||||
  # 使用SSL安全连接
 | 
			
		||||
  sslEnable: true
 | 
			
		||||
  # SMTP超时时长,单位毫秒,缺省值不超时
 | 
			
		||||
  timeout: 0
 | 
			
		||||
  # Socket连接超时值,单位毫秒,缺省值不超时
 | 
			
		||||
  connectionTimeout: 0
 | 
			
		||||
 | 
			
		||||
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
 | 
			
		||||
# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
 | 
			
		||||
sms:
 | 
			
		||||
  # 阿里云 dysmsapi.aliyuncs.com
 | 
			
		||||
  alibaba:
 | 
			
		||||
    #请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
 | 
			
		||||
    requestUrl: dysmsapi.aliyuncs.com
 | 
			
		||||
    #阿里云的accessKey
 | 
			
		||||
    accessKeyId: xxxxxxx
 | 
			
		||||
    #阿里云的accessKeySecret
 | 
			
		||||
    accessKeySecret: xxxxxxx
 | 
			
		||||
    #短信签名
 | 
			
		||||
    signature: 测试
 | 
			
		||||
  tencent:
 | 
			
		||||
    #请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
 | 
			
		||||
    requestUrl: sms.tencentcloudapi.com
 | 
			
		||||
    #腾讯云的accessKey
 | 
			
		||||
    accessKeyId: xxxxxxx
 | 
			
		||||
    #腾讯云的accessKeySecret
 | 
			
		||||
    accessKeySecret: xxxxxxx
 | 
			
		||||
    #短信签名
 | 
			
		||||
    signature: 测试
 | 
			
		||||
    #短信sdkAppId
 | 
			
		||||
    sdkAppId: appid
 | 
			
		||||
    #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
 | 
			
		||||
    territory: ap-guangzhou
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,9 @@ ruoyi:
 | 
			
		||||
  # 版本
 | 
			
		||||
  version: ${ruoyi-vue-plus.version}
 | 
			
		||||
  # 版权年份
 | 
			
		||||
  copyrightYear: 2021
 | 
			
		||||
  # 实例演示开关
 | 
			
		||||
  demoEnabled: true
 | 
			
		||||
  # 获取ip地址开关
 | 
			
		||||
  addressEnabled: true
 | 
			
		||||
  copyrightYear: 2023
 | 
			
		||||
  # 缓存懒加载
 | 
			
		||||
  cacheLazy: false
 | 
			
		||||
 | 
			
		||||
captcha:
 | 
			
		||||
  # 页面 <参数设置> 可开启关闭 验证码校验
 | 
			
		||||
@@ -49,11 +47,15 @@ logging:
 | 
			
		||||
  level:
 | 
			
		||||
    com.ruoyi: @logging.level@
 | 
			
		||||
    org.springframework: warn
 | 
			
		||||
  config: classpath:logback.xml
 | 
			
		||||
  config: classpath:logback-plus.xml
 | 
			
		||||
 | 
			
		||||
# tlog 全局访问性能拦截
 | 
			
		||||
tlog:
 | 
			
		||||
  enable-invoke-time-print: true
 | 
			
		||||
# 用户配置
 | 
			
		||||
user:
 | 
			
		||||
  password:
 | 
			
		||||
    # 密码最大错误次数
 | 
			
		||||
    maxRetryCount: 5
 | 
			
		||||
    # 密码锁定时间(默认10分钟)
 | 
			
		||||
    lockTime: 10
 | 
			
		||||
 | 
			
		||||
# Spring配置
 | 
			
		||||
spring:
 | 
			
		||||
@@ -77,10 +79,9 @@ spring:
 | 
			
		||||
    restart:
 | 
			
		||||
      # 热部署开关
 | 
			
		||||
      enabled: true
 | 
			
		||||
  # 与vue整合部署使用
 | 
			
		||||
  thymeleaf:
 | 
			
		||||
    # 将系统模板放置到最前面 否则会与 springboot-admin 页面冲突
 | 
			
		||||
    template-resolver-order: 1
 | 
			
		||||
  mvc:
 | 
			
		||||
    format:
 | 
			
		||||
      date-time: yyyy-MM-dd HH:mm:ss
 | 
			
		||||
  jackson:
 | 
			
		||||
    # 日期格式化
 | 
			
		||||
    date-format: yyyy-MM-dd HH:mm:ss
 | 
			
		||||
@@ -93,41 +94,48 @@ spring:
 | 
			
		||||
      # 允许对象忽略json中不存在的属性
 | 
			
		||||
      fail_on_unknown_properties: false
 | 
			
		||||
 | 
			
		||||
# token配置
 | 
			
		||||
token:
 | 
			
		||||
  # 令牌自定义标识
 | 
			
		||||
  header: Authorization
 | 
			
		||||
  # 令牌密钥
 | 
			
		||||
  secret: abcdefghijklmnopqrstuvwxyz
 | 
			
		||||
  # 令牌有效期(默认30分钟)
 | 
			
		||||
  expireTime: 30
 | 
			
		||||
# Sa-Token配置
 | 
			
		||||
sa-token:
 | 
			
		||||
  # token名称 (同时也是cookie名称)
 | 
			
		||||
  token-name: Authorization
 | 
			
		||||
  # token有效期 设为一天 (必定过期) 单位: 秒
 | 
			
		||||
  timeout: 86400
 | 
			
		||||
  # 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
 | 
			
		||||
  # token最低活跃时间 (指定时间无操作就过期) 单位: 秒
 | 
			
		||||
  active-timeout: 1800
 | 
			
		||||
  # 允许动态设置 token 有效期
 | 
			
		||||
  dynamic-active-timeout: true
 | 
			
		||||
  # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
 | 
			
		||||
  is-concurrent: true
 | 
			
		||||
  # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
 | 
			
		||||
  is-share: false
 | 
			
		||||
  # 是否尝试从header里读取token
 | 
			
		||||
  is-read-header: true
 | 
			
		||||
  # 是否尝试从cookie里读取token
 | 
			
		||||
  is-read-cookie: false
 | 
			
		||||
  # token前缀
 | 
			
		||||
  token-prefix: "Bearer"
 | 
			
		||||
  # jwt秘钥
 | 
			
		||||
  jwt-secret-key: abcdefghijklmnopqrstuvwxyz
 | 
			
		||||
 | 
			
		||||
# security配置
 | 
			
		||||
security:
 | 
			
		||||
  # 登出路径
 | 
			
		||||
  logout-url: /logout
 | 
			
		||||
  # 匿名路径
 | 
			
		||||
  anonymous:
 | 
			
		||||
    - /login
 | 
			
		||||
    - /register
 | 
			
		||||
    - /captchaImage
 | 
			
		||||
  # 排除路径
 | 
			
		||||
  excludes:
 | 
			
		||||
    # 静态资源
 | 
			
		||||
    - /*.html
 | 
			
		||||
    - /**/*.html
 | 
			
		||||
    - /**/*.css
 | 
			
		||||
    - /**/*.js
 | 
			
		||||
    # 公共路径
 | 
			
		||||
    - /favicon.ico
 | 
			
		||||
    - /error
 | 
			
		||||
    # swagger 文档配置
 | 
			
		||||
    - /doc.html
 | 
			
		||||
    - /swagger-resources/**
 | 
			
		||||
    - /webjars/**
 | 
			
		||||
    - /*/api-docs
 | 
			
		||||
    # druid 监控配置
 | 
			
		||||
    - /druid/**
 | 
			
		||||
    - /*/api-docs/**
 | 
			
		||||
    # actuator 监控配置
 | 
			
		||||
    - /actuator
 | 
			
		||||
    - /actuator/**
 | 
			
		||||
  # 用户放行
 | 
			
		||||
  permit-all:
 | 
			
		||||
 | 
			
		||||
# 重复提交
 | 
			
		||||
repeat-submit:
 | 
			
		||||
  # 全局间隔时间(毫秒)
 | 
			
		||||
  interval: 5000
 | 
			
		||||
 | 
			
		||||
# MyBatisPlus配置
 | 
			
		||||
# https://baomidou.com/config/
 | 
			
		||||
@@ -141,25 +149,15 @@ mybatis-plus:
 | 
			
		||||
  typeAliasesPackage: com.ruoyi.**.domain
 | 
			
		||||
  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查
 | 
			
		||||
  checkConfigLocation: false
 | 
			
		||||
  # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种:
 | 
			
		||||
  # SIMPLE:每个语句创建新的预处理器 REUSE:会复用预处理器 BATCH:批量执行所有的更新
 | 
			
		||||
  executorType: SIMPLE
 | 
			
		||||
  configuration:
 | 
			
		||||
    # 自动驼峰命名规则(camel case)映射
 | 
			
		||||
    mapUnderscoreToCamelCase: true
 | 
			
		||||
    # 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。
 | 
			
		||||
    aggressiveLazyLoading: true
 | 
			
		||||
    # MyBatis 自动映射策略
 | 
			
		||||
    # NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
 | 
			
		||||
    autoMappingBehavior: PARTIAL
 | 
			
		||||
    # MyBatis 自动映射时未知列或未知属性处理策
 | 
			
		||||
    # NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
 | 
			
		||||
    autoMappingUnknownColumnBehavior: NONE
 | 
			
		||||
    # Mybatis一级缓存,默认为 SESSION
 | 
			
		||||
    # SESSION session级别缓存 STATEMENT 关闭一级缓存
 | 
			
		||||
    localCacheScope: SESSION
 | 
			
		||||
    # 开启Mybatis二级缓存,默认为 true
 | 
			
		||||
    cacheEnabled: false
 | 
			
		||||
    # 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
 | 
			
		||||
    # 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
 | 
			
		||||
    # 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
 | 
			
		||||
@@ -167,16 +165,10 @@ mybatis-plus:
 | 
			
		||||
  global-config:
 | 
			
		||||
    # 是否打印 Logo banner
 | 
			
		||||
    banner: true
 | 
			
		||||
    # 是否初始化 SqlRunner
 | 
			
		||||
    enableSqlRunner: false
 | 
			
		||||
    dbConfig:
 | 
			
		||||
      # 主键类型
 | 
			
		||||
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
 | 
			
		||||
      idType: AUTO
 | 
			
		||||
      # 表名是否使用驼峰转下划线命名,只对表名生效
 | 
			
		||||
      tableUnderline: true
 | 
			
		||||
      # 大写命名,对表名和字段名均生效
 | 
			
		||||
      capitalMode: false
 | 
			
		||||
      idType: ASSIGN_ID
 | 
			
		||||
      # 逻辑已删除值
 | 
			
		||||
      logicDeleteValue: 2
 | 
			
		||||
      # 逻辑未删除值
 | 
			
		||||
@@ -189,30 +181,54 @@ mybatis-plus:
 | 
			
		||||
      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
 | 
			
		||||
      where-strategy: NOT_NULL
 | 
			
		||||
 | 
			
		||||
# Swagger配置
 | 
			
		||||
swagger:
 | 
			
		||||
  # 是否开启swagger
 | 
			
		||||
  enabled: true
 | 
			
		||||
  # 请求前缀
 | 
			
		||||
  pathMapping: /dev-api
 | 
			
		||||
  # 标题
 | 
			
		||||
  title: '标题:${ruoyi.name}后台管理系统_接口文档'
 | 
			
		||||
  # 描述
 | 
			
		||||
  description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
 | 
			
		||||
  # 版本
 | 
			
		||||
  version: '版本号: ${ruoyi-vue-plus.version}'
 | 
			
		||||
  # 作者信息
 | 
			
		||||
  contact:
 | 
			
		||||
    name: Lion Li
 | 
			
		||||
    email: crazylionli@163.com
 | 
			
		||||
    url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus
 | 
			
		||||
  groups:
 | 
			
		||||
    - name: 1.演示案例
 | 
			
		||||
      basePackage: com.ruoyi.demo
 | 
			
		||||
    - name: 2.系统模块
 | 
			
		||||
      basePackage: com.ruoyi.web
 | 
			
		||||
    - name: 3.代码生成模块
 | 
			
		||||
      basePackage: com.ruoyi.generator
 | 
			
		||||
# 数据加密
 | 
			
		||||
mybatis-encryptor:
 | 
			
		||||
  # 是否开启加密
 | 
			
		||||
  enable: false
 | 
			
		||||
  # 默认加密算法
 | 
			
		||||
  algorithm: BASE64
 | 
			
		||||
  # 编码方式 BASE64/HEX。默认BASE64
 | 
			
		||||
  encode: BASE64
 | 
			
		||||
  # 安全秘钥 对称算法的秘钥 如:AES,SM4
 | 
			
		||||
  password:
 | 
			
		||||
  # 公私钥 非对称算法的公私钥 如:SM2,RSA
 | 
			
		||||
  publicKey:
 | 
			
		||||
  privateKey:
 | 
			
		||||
 | 
			
		||||
springdoc:
 | 
			
		||||
  api-docs:
 | 
			
		||||
    # 是否开启接口文档
 | 
			
		||||
    enabled: true
 | 
			
		||||
#  swagger-ui:
 | 
			
		||||
#    # 持久化认证数据
 | 
			
		||||
#    persistAuthorization: true
 | 
			
		||||
  info:
 | 
			
		||||
    # 标题
 | 
			
		||||
    title: '标题:${ruoyi.name}后台管理系统_接口文档'
 | 
			
		||||
    # 描述
 | 
			
		||||
    description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
 | 
			
		||||
    # 版本
 | 
			
		||||
    version: '版本号: ${ruoyi-vue-plus.version}'
 | 
			
		||||
    # 作者信息
 | 
			
		||||
    contact:
 | 
			
		||||
      name: Lion Li
 | 
			
		||||
      email: crazylionli@163.com
 | 
			
		||||
      url: https://gitee.com/dromara/RuoYi-Vue-Plus
 | 
			
		||||
  components:
 | 
			
		||||
    # 鉴权方式配置
 | 
			
		||||
    security-schemes:
 | 
			
		||||
      apiKey:
 | 
			
		||||
        type: APIKEY
 | 
			
		||||
        in: HEADER
 | 
			
		||||
        name: ${sa-token.token-name}
 | 
			
		||||
  #这里定义了两个分组,可定义多个,也可以不定义
 | 
			
		||||
  group-configs:
 | 
			
		||||
    - group: 1.演示模块
 | 
			
		||||
      packages-to-scan: com.ruoyi.demo
 | 
			
		||||
    - group: 2.系统模块
 | 
			
		||||
      packages-to-scan: com.ruoyi.web
 | 
			
		||||
    - group: 3.代码生成模块
 | 
			
		||||
      packages-to-scan: com.ruoyi.generator
 | 
			
		||||
 | 
			
		||||
# 防止XSS攻击
 | 
			
		||||
xss:
 | 
			
		||||
@@ -227,100 +243,26 @@ xss:
 | 
			
		||||
thread-pool:
 | 
			
		||||
  # 是否开启线程池
 | 
			
		||||
  enabled: false
 | 
			
		||||
  # 核心线程池大小
 | 
			
		||||
  corePoolSize: 8
 | 
			
		||||
  # 最大可创建的线程数
 | 
			
		||||
  maxPoolSize: 16
 | 
			
		||||
  # 队列最大长度
 | 
			
		||||
  queueCapacity: 128
 | 
			
		||||
  # 线程池维护线程所允许的空闲时间
 | 
			
		||||
  keepAliveSeconds: 300
 | 
			
		||||
  # 线程池对拒绝任务(无线程可用)的处理策略
 | 
			
		||||
  # CALLER_RUNS_POLICY 调用方执行
 | 
			
		||||
  # DISCARD_OLDEST_POLICY 放弃最旧的
 | 
			
		||||
  # DISCARD_POLICY 丢弃
 | 
			
		||||
  # ABORT_POLICY 中止
 | 
			
		||||
  rejectedExecutionHandler: CALLER_RUNS_POLICY
 | 
			
		||||
 | 
			
		||||
# feign 相关配置
 | 
			
		||||
feign:
 | 
			
		||||
  # 不支持多包, 如有需要可在注解配置 或 提升扫包等级
 | 
			
		||||
  # 例如 com.**.**.feign
 | 
			
		||||
  package: com.ruoyi.**.feign
 | 
			
		||||
  # 开启压缩
 | 
			
		||||
  compression:
 | 
			
		||||
    request:
 | 
			
		||||
      enabled: true
 | 
			
		||||
    response:
 | 
			
		||||
      enabled: true
 | 
			
		||||
  okhttp:
 | 
			
		||||
    enabled: true
 | 
			
		||||
  circuitbreaker:
 | 
			
		||||
    enabled: true
 | 
			
		||||
 | 
			
		||||
--- # redisson 缓存配置
 | 
			
		||||
redisson:
 | 
			
		||||
  cacheGroup:
 | 
			
		||||
    # 用例: @Cacheable(cacheNames="groupId", key="#XXX") 方可使用缓存组配置
 | 
			
		||||
    - groupId: redissonCacheMap
 | 
			
		||||
      # 组过期时间(脚本监控)
 | 
			
		||||
      ttl: 60000
 | 
			
		||||
      # 组最大空闲时间(脚本监控)
 | 
			
		||||
      maxIdleTime: 60000
 | 
			
		||||
      # 组最大长度
 | 
			
		||||
      maxSize: 0
 | 
			
		||||
    - groupId: testCache
 | 
			
		||||
      ttl: 1000
 | 
			
		||||
      maxIdleTime: 500
 | 
			
		||||
 | 
			
		||||
--- # 分布式锁 lock4j 全局配置
 | 
			
		||||
lock4j:
 | 
			
		||||
  # 获取分布式锁超时时间,默认为 3000 毫秒
 | 
			
		||||
  acquire-timeout: 3000
 | 
			
		||||
  # 分布式锁的超时时间,默认为 30 毫秒
 | 
			
		||||
  # 分布式锁的超时时间,默认为 30 秒
 | 
			
		||||
  expire: 30000
 | 
			
		||||
 | 
			
		||||
--- # Actuator 监控端点的配置项
 | 
			
		||||
management:
 | 
			
		||||
  endpoints:
 | 
			
		||||
    web:
 | 
			
		||||
      # Actuator 提供的 API 接口的根目录。默认为 /actuator
 | 
			
		||||
      base-path: /actuator
 | 
			
		||||
      exposure:
 | 
			
		||||
        # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
 | 
			
		||||
        # 生产环境不建议放开所有 根据项目需求放开即可
 | 
			
		||||
        include: @endpoints.include@
 | 
			
		||||
        include: '*'
 | 
			
		||||
  endpoint:
 | 
			
		||||
    health:
 | 
			
		||||
      show-details: ALWAYS
 | 
			
		||||
    logfile:
 | 
			
		||||
      external-file: ./logs/sys-console.log
 | 
			
		||||
 | 
			
		||||
--- # 定时任务配置
 | 
			
		||||
spring:
 | 
			
		||||
  quartz:
 | 
			
		||||
    scheduler-name: RuoyiScheduler
 | 
			
		||||
    startup-delay: 1s
 | 
			
		||||
    overwrite-existing-jobs: true
 | 
			
		||||
    auto-startup: true
 | 
			
		||||
    job-store-type: jdbc
 | 
			
		||||
    properties:
 | 
			
		||||
      org:
 | 
			
		||||
        quartz:
 | 
			
		||||
          # Scheduler 相关配置
 | 
			
		||||
          scheduler:
 | 
			
		||||
            instanceName: RuoyiScheduler
 | 
			
		||||
            instanceId: AUTO
 | 
			
		||||
          # 线程池相关配置
 | 
			
		||||
          threadPool:
 | 
			
		||||
            class: org.quartz.simpl.SimpleThreadPool
 | 
			
		||||
            threadCount: 20
 | 
			
		||||
            threadPriority: 5
 | 
			
		||||
          # JobStore 集群配置
 | 
			
		||||
          jobStore:
 | 
			
		||||
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
 | 
			
		||||
            isClustered: true
 | 
			
		||||
            clusterCheckinInterval: 15000
 | 
			
		||||
            txIsolationLevelSerializable: true
 | 
			
		||||
            misfireThreshold: 60000
 | 
			
		||||
            tablePrefix: QRTZ_
 | 
			
		||||
            # sqlserver 启用
 | 
			
		||||
            # selectWithLockSQL: SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,29 @@
 | 
			
		||||
not.null=* 必须填写
 | 
			
		||||
user.jcaptcha.error=验证码错误
 | 
			
		||||
user.jcaptcha.expire=验证码已失效
 | 
			
		||||
user.not.exists=用户不存在/密码错误
 | 
			
		||||
user.not.exists=对不起, 您的账号:{0} 不存在.
 | 
			
		||||
user.password.not.match=用户不存在/密码错误
 | 
			
		||||
user.password.retry.limit.count=密码输入错误{0}次
 | 
			
		||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
 | 
			
		||||
user.password.delete=对不起,您的账号已被删除
 | 
			
		||||
user.blocked=用户已封禁,请联系管理员
 | 
			
		||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
user.password.delete=对不起,您的账号:{0} 已被删除
 | 
			
		||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
 | 
			
		||||
role.blocked=角色已封禁,请联系管理员
 | 
			
		||||
user.logout.success=退出成功
 | 
			
		||||
length.not.valid=长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.username.not.blank=用户名不能为空
 | 
			
		||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
 | 
			
		||||
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.password.not.blank=用户密码不能为空
 | 
			
		||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.password.not.valid=* 5-50个字符
 | 
			
		||||
user.email.not.valid=邮箱格式错误
 | 
			
		||||
user.email.not.blank=邮箱不能为空
 | 
			
		||||
user.phonenumber.not.blank=用户手机号不能为空
 | 
			
		||||
user.mobile.phone.number.not.valid=手机号格式错误
 | 
			
		||||
user.login.success=登录成功
 | 
			
		||||
user.register.success=注册成功
 | 
			
		||||
user.register.save.error=保存用户 {0} 失败,注册账号已存在
 | 
			
		||||
user.register.error=注册失败,请联系系统管理人员
 | 
			
		||||
user.notfound=请重新登录
 | 
			
		||||
user.forcelogout=管理员强制退出,请重新登录
 | 
			
		||||
user.unknown.error=未知错误,请重新登录
 | 
			
		||||
@@ -30,3 +38,12 @@ no.update.permission=您没有修改数据的权限,请联系管理员添加
 | 
			
		||||
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
repeat.submit.message=不允许重复提交,请稍候再试
 | 
			
		||||
rate.limiter.message=访问过于频繁,请稍候再试
 | 
			
		||||
sms.code.not.blank=短信验证码不能为空
 | 
			
		||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
 | 
			
		||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
email.code.not.blank=邮箱验证码不能为空
 | 
			
		||||
email.code.retry.limit.count=邮箱验证码输入错误{0}次
 | 
			
		||||
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
xcx.code.not.blank=小程序code不能为空
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,29 @@
 | 
			
		||||
not.null=* Required fill in
 | 
			
		||||
user.jcaptcha.error=Captcha error
 | 
			
		||||
user.jcaptcha.expire=Captcha invalid
 | 
			
		||||
user.not.exists=User does not exist/Password error
 | 
			
		||||
user.not.exists=Sorry, your account: {0} does not exist
 | 
			
		||||
user.password.not.match=User does not exist/Password error
 | 
			
		||||
user.password.retry.limit.count=Password input error {0} times
 | 
			
		||||
user.password.retry.limit.exceed=Password input error {0} times, account locked for 10 minutes
 | 
			
		||||
user.password.delete=Sorry, your account has been deleted
 | 
			
		||||
user.blocked=User disabled,please contact administrators
 | 
			
		||||
user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
 | 
			
		||||
user.password.delete=Sorry, your account:{0} has been deleted
 | 
			
		||||
user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
 | 
			
		||||
role.blocked=Role disabled,please contact administrators
 | 
			
		||||
user.logout.success=Exit successful
 | 
			
		||||
length.not.valid=The length must be between {min} and {max} characters
 | 
			
		||||
user.username.not.blank=Username cannot be blank
 | 
			
		||||
user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number
 | 
			
		||||
user.username.length.valid=Account length must be between {min} and {max} characters
 | 
			
		||||
user.password.not.blank=Password cannot be empty
 | 
			
		||||
user.password.length.valid=Password length must be between {min} and {max} characters
 | 
			
		||||
user.password.not.valid=* 5-50 characters
 | 
			
		||||
user.email.not.valid=Mailbox format error
 | 
			
		||||
user.email.not.blank=Mailbox cannot be blank
 | 
			
		||||
user.phonenumber.not.blank=Phone number cannot be blank
 | 
			
		||||
user.mobile.phone.number.not.valid=Phone number format error
 | 
			
		||||
user.login.success=Login successful
 | 
			
		||||
user.register.success=Register successful
 | 
			
		||||
user.register.save.error=Failed to save user {0}, The registered account already exists
 | 
			
		||||
user.register.error=Register failed, please contact system administrator
 | 
			
		||||
user.notfound=Please login again
 | 
			
		||||
user.forcelogout=The administrator is forced to exit,please login again
 | 
			
		||||
user.unknown.error=Unknown error, please login again
 | 
			
		||||
@@ -30,3 +38,12 @@ no.update.permission=You do not have permission to modify data,please contact
 | 
			
		||||
no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}]
 | 
			
		||||
no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}]
 | 
			
		||||
no.view.permission=You do not have permission to view data,please contact your administrator to add permissions [{0}]
 | 
			
		||||
repeat.submit.message=Repeat submit is not allowed, please try again later
 | 
			
		||||
rate.limiter.message=Visit too frequently, please try again later
 | 
			
		||||
sms.code.not.blank=Sms code cannot be blank
 | 
			
		||||
sms.code.retry.limit.count=Sms code input error {0} times
 | 
			
		||||
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
 | 
			
		||||
email.code.not.blank=Email code cannot be blank
 | 
			
		||||
email.code.retry.limit.count=Email code input error {0} times
 | 
			
		||||
email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
 | 
			
		||||
xcx.code.not.blank=Mini program code cannot be blank
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,29 @@
 | 
			
		||||
not.null=* 必须填写
 | 
			
		||||
user.jcaptcha.error=验证码错误
 | 
			
		||||
user.jcaptcha.expire=验证码已失效
 | 
			
		||||
user.not.exists=用户不存在/密码错误
 | 
			
		||||
user.not.exists=对不起, 您的账号:{0} 不存在.
 | 
			
		||||
user.password.not.match=用户不存在/密码错误
 | 
			
		||||
user.password.retry.limit.count=密码输入错误{0}次
 | 
			
		||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
 | 
			
		||||
user.password.delete=对不起,您的账号已被删除
 | 
			
		||||
user.blocked=用户已封禁,请联系管理员
 | 
			
		||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
user.password.delete=对不起,您的账号:{0} 已被删除
 | 
			
		||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
 | 
			
		||||
role.blocked=角色已封禁,请联系管理员
 | 
			
		||||
user.logout.success=退出成功
 | 
			
		||||
length.not.valid=长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.username.not.blank=用户名不能为空
 | 
			
		||||
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
 | 
			
		||||
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.password.not.blank=用户密码不能为空
 | 
			
		||||
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
 | 
			
		||||
user.password.not.valid=* 5-50个字符
 | 
			
		||||
user.email.not.valid=邮箱格式错误
 | 
			
		||||
user.email.not.blank=邮箱不能为空
 | 
			
		||||
user.phonenumber.not.blank=用户手机号不能为空
 | 
			
		||||
user.mobile.phone.number.not.valid=手机号格式错误
 | 
			
		||||
user.login.success=登录成功
 | 
			
		||||
user.register.success=注册成功
 | 
			
		||||
user.register.save.error=保存用户 {0} 失败,注册账号已存在
 | 
			
		||||
user.register.error=注册失败,请联系系统管理人员
 | 
			
		||||
user.notfound=请重新登录
 | 
			
		||||
user.forcelogout=管理员强制退出,请重新登录
 | 
			
		||||
user.unknown.error=未知错误,请重新登录
 | 
			
		||||
@@ -30,3 +38,12 @@ no.update.permission=您没有修改数据的权限,请联系管理员添加
 | 
			
		||||
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
 | 
			
		||||
repeat.submit.message=不允许重复提交,请稍候再试
 | 
			
		||||
rate.limiter.message=访问过于频繁,请稍候再试
 | 
			
		||||
sms.code.not.blank=短信验证码不能为空
 | 
			
		||||
sms.code.retry.limit.count=短信验证码输入错误{0}次
 | 
			
		||||
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
email.code.not.blank=邮箱验证码不能为空
 | 
			
		||||
email.code.retry.limit.count=邮箱验证码输入错误{0}次
 | 
			
		||||
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
 | 
			
		||||
xcx.code.not.blank=小程序code不能为空
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/ip2region.xdb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/ip2region.xdb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										129
									
								
								ruoyi-admin/src/main/resources/logback-plus.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								ruoyi-admin/src/main/resources/logback-plus.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<configuration>
 | 
			
		||||
    <property name="log.path" value="./logs"/>
 | 
			
		||||
    <property name="console.log.pattern"
 | 
			
		||||
              value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
 | 
			
		||||
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 控制台输出 -->
 | 
			
		||||
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
 | 
			
		||||
        <encoder>
 | 
			
		||||
            <pattern>${console.log.pattern}</pattern>
 | 
			
		||||
            <charset>utf-8</charset>
 | 
			
		||||
        </encoder>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <!-- 控制台输出 -->
 | 
			
		||||
    <appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
        <file>${log.path}/sys-console.log</file>
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
            <!-- 日志最大 1天 -->
 | 
			
		||||
            <maxHistory>1</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder>
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
            <charset>utf-8</charset>
 | 
			
		||||
        </encoder>
 | 
			
		||||
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>INFO</level>
 | 
			
		||||
        </filter>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <!-- 系统日志输出 -->
 | 
			
		||||
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
        <file>${log.path}/sys-info.log</file>
 | 
			
		||||
        <!-- 循环政策:基于时间创建日志文件 -->
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
            <!-- 日志最大的历史 60天 -->
 | 
			
		||||
            <maxHistory>60</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder>
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
        </encoder>
 | 
			
		||||
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>INFO</level>
 | 
			
		||||
            <!-- 匹配时的操作:接收(记录) -->
 | 
			
		||||
            <onMatch>ACCEPT</onMatch>
 | 
			
		||||
            <!-- 不匹配时的操作:拒绝(不记录) -->
 | 
			
		||||
            <onMismatch>DENY</onMismatch>
 | 
			
		||||
        </filter>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
        <file>${log.path}/sys-error.log</file>
 | 
			
		||||
        <!-- 循环政策:基于时间创建日志文件 -->
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
            <!-- 日志最大的历史 60天 -->
 | 
			
		||||
            <maxHistory>60</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder>
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
        </encoder>
 | 
			
		||||
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>ERROR</level>
 | 
			
		||||
            <!-- 匹配时的操作:接收(记录) -->
 | 
			
		||||
            <onMatch>ACCEPT</onMatch>
 | 
			
		||||
            <!-- 不匹配时的操作:拒绝(不记录) -->
 | 
			
		||||
            <onMismatch>DENY</onMismatch>
 | 
			
		||||
        </filter>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <!-- info异步输出 -->
 | 
			
		||||
    <appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
 | 
			
		||||
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
 | 
			
		||||
        <discardingThreshold>0</discardingThreshold>
 | 
			
		||||
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
 | 
			
		||||
        <queueSize>512</queueSize>
 | 
			
		||||
        <!-- 添加附加的appender,最多只能添加一个 -->
 | 
			
		||||
        <appender-ref ref="file_info"/>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <!-- error异步输出 -->
 | 
			
		||||
    <appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
 | 
			
		||||
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
 | 
			
		||||
        <discardingThreshold>0</discardingThreshold>
 | 
			
		||||
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
 | 
			
		||||
        <queueSize>512</queueSize>
 | 
			
		||||
        <!-- 添加附加的appender,最多只能添加一个 -->
 | 
			
		||||
        <appender-ref ref="file_error"/>
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <!-- 整合 skywalking 控制台输出 tid -->
 | 
			
		||||
<!--    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
 | 
			
		||||
<!--        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
 | 
			
		||||
<!--            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
 | 
			
		||||
<!--                <pattern>[%tid] ${console.log.pattern}</pattern>-->
 | 
			
		||||
<!--            </layout>-->
 | 
			
		||||
<!--            <charset>utf-8</charset>-->
 | 
			
		||||
<!--        </encoder>-->
 | 
			
		||||
<!--    </appender>-->
 | 
			
		||||
 | 
			
		||||
    <!-- 整合 skywalking 推送采集日志 -->
 | 
			
		||||
<!--    <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
 | 
			
		||||
<!--        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
 | 
			
		||||
<!--            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
 | 
			
		||||
<!--                <pattern>[%tid] ${console.log.pattern}</pattern>-->
 | 
			
		||||
<!--            </layout>-->
 | 
			
		||||
<!--            <charset>utf-8</charset>-->
 | 
			
		||||
<!--        </encoder>-->
 | 
			
		||||
<!--    </appender>-->
 | 
			
		||||
 | 
			
		||||
    <!--系统操作日志-->
 | 
			
		||||
    <root level="info">
 | 
			
		||||
        <appender-ref ref="console" />
 | 
			
		||||
        <appender-ref ref="async_info" />
 | 
			
		||||
        <appender-ref ref="async_error" />
 | 
			
		||||
        <appender-ref ref="file_console" />
 | 
			
		||||
<!--        <appender-ref ref="sky_log"/>-->
 | 
			
		||||
    </root>
 | 
			
		||||
 | 
			
		||||
</configuration>
 | 
			
		||||
@@ -1,114 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<configuration>
 | 
			
		||||
    <property name="log.path" value="./logs"/>
 | 
			
		||||
    <property name="console.log.pattern"
 | 
			
		||||
              value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
 | 
			
		||||
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
 | 
			
		||||
 | 
			
		||||
	<!-- 控制台输出 -->
 | 
			
		||||
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
 | 
			
		||||
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
 | 
			
		||||
			<pattern>${console.log.pattern}</pattern>
 | 
			
		||||
            <charset>utf-8</charset>
 | 
			
		||||
		</encoder>
 | 
			
		||||
	</appender>
 | 
			
		||||
 | 
			
		||||
    <!-- 控制台输出 -->
 | 
			
		||||
    <appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
        <file>${log.path}/sys-console.log</file>
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
            <!-- 日志最大 1天 -->
 | 
			
		||||
            <maxHistory>1</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
            <charset>utf-8</charset>
 | 
			
		||||
        </encoder>
 | 
			
		||||
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>INFO</level>
 | 
			
		||||
        </filter>
 | 
			
		||||
    </appender>
 | 
			
		||||
	
 | 
			
		||||
	<!-- 系统日志输出 -->
 | 
			
		||||
	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
	    <file>${log.path}/sys-info.log</file>
 | 
			
		||||
        <!-- 循环政策:基于时间创建日志文件 -->
 | 
			
		||||
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
			<!-- 日志最大的历史 60天 -->
 | 
			
		||||
			<maxHistory>60</maxHistory>
 | 
			
		||||
		</rollingPolicy>
 | 
			
		||||
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
 | 
			
		||||
			<pattern>${log.pattern}</pattern>
 | 
			
		||||
		</encoder>
 | 
			
		||||
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>INFO</level>
 | 
			
		||||
            <!-- 匹配时的操作:接收(记录) -->
 | 
			
		||||
            <onMatch>ACCEPT</onMatch>
 | 
			
		||||
            <!-- 不匹配时的操作:拒绝(不记录) -->
 | 
			
		||||
            <onMismatch>DENY</onMismatch>
 | 
			
		||||
        </filter>
 | 
			
		||||
	</appender>
 | 
			
		||||
	
 | 
			
		||||
	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
	    <file>${log.path}/sys-error.log</file>
 | 
			
		||||
        <!-- 循环政策:基于时间创建日志文件 -->
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 日志文件名格式 -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
			<!-- 日志最大的历史 60天 -->
 | 
			
		||||
			<maxHistory>60</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
        </encoder>
 | 
			
		||||
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
 | 
			
		||||
            <!-- 过滤的级别 -->
 | 
			
		||||
            <level>ERROR</level>
 | 
			
		||||
			<!-- 匹配时的操作:接收(记录) -->
 | 
			
		||||
            <onMatch>ACCEPT</onMatch>
 | 
			
		||||
			<!-- 不匹配时的操作:拒绝(不记录) -->
 | 
			
		||||
            <onMismatch>DENY</onMismatch>
 | 
			
		||||
        </filter>
 | 
			
		||||
    </appender>
 | 
			
		||||
	
 | 
			
		||||
	<!-- 用户访问日志输出  -->
 | 
			
		||||
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
 | 
			
		||||
		<file>${log.path}/sys-user.log</file>
 | 
			
		||||
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 | 
			
		||||
            <!-- 按天回滚 daily -->
 | 
			
		||||
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
 | 
			
		||||
            <!-- 日志最大的历史 60天 -->
 | 
			
		||||
            <maxHistory>60</maxHistory>
 | 
			
		||||
        </rollingPolicy>
 | 
			
		||||
        <encoder class="com.yomahub.tlog.core.enhance.logback.AspectLogbackEncoder">
 | 
			
		||||
            <pattern>${log.pattern}</pattern>
 | 
			
		||||
        </encoder>
 | 
			
		||||
    </appender>
 | 
			
		||||
	
 | 
			
		||||
	<!-- 系统模块日志级别控制  -->
 | 
			
		||||
	<logger name="com.ruoyi" level="info" />
 | 
			
		||||
	<!-- Spring日志级别控制  -->
 | 
			
		||||
	<logger name="org.springframework" level="warn" />
 | 
			
		||||
 | 
			
		||||
	<root level="info">
 | 
			
		||||
		<appender-ref ref="console" />
 | 
			
		||||
	</root>
 | 
			
		||||
	
 | 
			
		||||
	<!--系统操作日志-->
 | 
			
		||||
    <root level="info">
 | 
			
		||||
        <appender-ref ref="file_info" />
 | 
			
		||||
        <appender-ref ref="file_error" />
 | 
			
		||||
        <appender-ref ref="file_console" />
 | 
			
		||||
    </root>
 | 
			
		||||
	
 | 
			
		||||
	<!--系统用户操作日志-->
 | 
			
		||||
    <logger name="sys-user" level="info">
 | 
			
		||||
        <appender-ref ref="sys-user"/>
 | 
			
		||||
    </logger>
 | 
			
		||||
</configuration> 
 | 
			
		||||
@@ -14,6 +14,8 @@ useprefix=true
 | 
			
		||||
excludecategories=info,debug,result,commit,resultset
 | 
			
		||||
# 日期格式
 | 
			
		||||
dateformat=yyyy-MM-dd HH:mm:ss
 | 
			
		||||
# SQL语句打印时间格式
 | 
			
		||||
databaseDialectTimestampFormat=yyyy-MM-dd HH:mm:ss
 | 
			
		||||
# 实际驱动可多个
 | 
			
		||||
#driverlist=org.h2.Driver
 | 
			
		||||
# 是否开启慢SQL记录
 | 
			
		||||
@@ -22,5 +24,5 @@ outagedetection=true
 | 
			
		||||
outagedetectioninterval=2
 | 
			
		||||
# 是否过滤 Log
 | 
			
		||||
filter=true
 | 
			
		||||
# 过滤 Log 时所排除的表名列表,以逗号分隔
 | 
			
		||||
exclude=QRTZ_
 | 
			
		||||
# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
 | 
			
		||||
exclude=SELECT 1
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
package com.ruoyi.test;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Assertions;
 | 
			
		||||
import org.junit.jupiter.api.DisplayName;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 断言单元测试案例
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@DisplayName("断言单元测试案例")
 | 
			
		||||
public class AssertUnitTest {
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 assertEquals 方法")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAssertEquals() {
 | 
			
		||||
        Assertions.assertEquals("666", new String("666"));
 | 
			
		||||
        Assertions.assertNotEquals("666", new String("666"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 assertSame 方法")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAssertSame() {
 | 
			
		||||
        Object obj = new Object();
 | 
			
		||||
        Object obj1 = obj;
 | 
			
		||||
        Assertions.assertSame(obj, obj1);
 | 
			
		||||
        Assertions.assertNotSame(obj, obj1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 assertTrue 方法")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAssertTrue() {
 | 
			
		||||
        Assertions.assertTrue(true);
 | 
			
		||||
        Assertions.assertFalse(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 assertNull 方法")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAssertNull() {
 | 
			
		||||
        Assertions.assertNull(null);
 | 
			
		||||
        Assertions.assertNotNull(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
package com.ruoyi.test;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.config.RuoYiConfig;
 | 
			
		||||
import org.junit.jupiter.api.*;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 单元测试案例
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
 | 
			
		||||
@DisplayName("单元测试案例")
 | 
			
		||||
public class DemoUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private RuoYiConfig ruoYiConfig;
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTest() {
 | 
			
		||||
        System.out.println(ruoYiConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Disabled
 | 
			
		||||
    @DisplayName("测试 @Disabled 注解")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDisabled() {
 | 
			
		||||
        System.out.println(ruoYiConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Timeout(value = 2L, unit = TimeUnit.SECONDS)
 | 
			
		||||
    @DisplayName("测试 @Timeout 注解")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTimeout() throws InterruptedException {
 | 
			
		||||
        Thread.sleep(3000);
 | 
			
		||||
        System.out.println(ruoYiConfig);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @RepeatedTest 注解")
 | 
			
		||||
    @RepeatedTest(3)
 | 
			
		||||
    public void testRepeatedTest() {
 | 
			
		||||
        System.out.println(666);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @BeforeAll
 | 
			
		||||
    public static void testBeforeAll() {
 | 
			
		||||
        System.out.println("@BeforeAll ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @BeforeEach
 | 
			
		||||
    public void testBeforeEach() {
 | 
			
		||||
        System.out.println("@BeforeEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterEach
 | 
			
		||||
    public void testAfterEach() {
 | 
			
		||||
        System.out.println("@AfterEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterAll
 | 
			
		||||
    public static void testAfterAll() {
 | 
			
		||||
        System.out.println("@AfterAll ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
package com.ruoyi.test;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.enums.UserType;
 | 
			
		||||
import org.junit.jupiter.api.AfterEach;
 | 
			
		||||
import org.junit.jupiter.api.BeforeEach;
 | 
			
		||||
import org.junit.jupiter.api.DisplayName;
 | 
			
		||||
import org.junit.jupiter.params.ParameterizedTest;
 | 
			
		||||
import org.junit.jupiter.params.provider.EnumSource;
 | 
			
		||||
import org.junit.jupiter.params.provider.MethodSource;
 | 
			
		||||
import org.junit.jupiter.params.provider.NullSource;
 | 
			
		||||
import org.junit.jupiter.params.provider.ValueSource;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 带参数单元测试案例
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@DisplayName("带参数单元测试案例")
 | 
			
		||||
public class ParamUnitTest {
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @ValueSource 注解")
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @ValueSource(strings = {"t1", "t2", "t3"})
 | 
			
		||||
    public void testValueSource(String str) {
 | 
			
		||||
        System.out.println(str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @NullSource 注解")
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @NullSource
 | 
			
		||||
    public void testNullSource(String str) {
 | 
			
		||||
        System.out.println(str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @EnumSource 注解")
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @EnumSource(UserType.class)
 | 
			
		||||
    public void testEnumSource(UserType type) {
 | 
			
		||||
        System.out.println(type.getUserType());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DisplayName("测试 @MethodSource 注解")
 | 
			
		||||
    @ParameterizedTest
 | 
			
		||||
    @MethodSource("getParam")
 | 
			
		||||
    public void testMethodSource(String str) {
 | 
			
		||||
        System.out.println(str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Stream<String> getParam() {
 | 
			
		||||
        List<String> list = new ArrayList<>();
 | 
			
		||||
        list.add("t1");
 | 
			
		||||
        list.add("t2");
 | 
			
		||||
        list.add("t3");
 | 
			
		||||
        return list.stream();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @BeforeEach
 | 
			
		||||
    public void testBeforeEach() {
 | 
			
		||||
        System.out.println("@BeforeEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterEach
 | 
			
		||||
    public void testAfterEach() {
 | 
			
		||||
        System.out.println("@AfterEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
package com.ruoyi.test;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.*;
 | 
			
		||||
import org.springframework.boot.test.context.SpringBootTest;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 标签单元测试案例
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@SpringBootTest
 | 
			
		||||
@DisplayName("标签单元测试案例")
 | 
			
		||||
public class TagUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Tag("dev")
 | 
			
		||||
    @DisplayName("测试 @Tag dev")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTagDev() {
 | 
			
		||||
        System.out.println("dev");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Tag("prod")
 | 
			
		||||
    @DisplayName("测试 @Tag prod")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTagProd() {
 | 
			
		||||
        System.out.println("prod");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Tag("local")
 | 
			
		||||
    @DisplayName("测试 @Tag local")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTagLocal() {
 | 
			
		||||
        System.out.println("local");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Tag("exclude")
 | 
			
		||||
    @DisplayName("测试 @Tag exclude")
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testTagExclude() {
 | 
			
		||||
        System.out.println("exclude");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @BeforeEach
 | 
			
		||||
    public void testBeforeEach() {
 | 
			
		||||
        System.out.println("@BeforeEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @AfterEach
 | 
			
		||||
    public void testAfterEach() {
 | 
			
		||||
        System.out.println("@AfterEach ==================");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <artifactId>ruoyi-vue-plus</artifactId>
 | 
			
		||||
        <groupId>com.ruoyi</groupId>
 | 
			
		||||
        <version>3.3.0</version>
 | 
			
		||||
        <version>4.8.2</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
 | 
			
		||||
@@ -29,10 +29,15 @@
 | 
			
		||||
            <artifactId>spring-web</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- spring security 安全认证 -->
 | 
			
		||||
        <!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-security</artifactId>
 | 
			
		||||
            <groupId>cn.dev33</groupId>
 | 
			
		||||
            <artifactId>sa-token-spring-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!-- Sa-Token 整合 jwt -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.dev33</groupId>
 | 
			
		||||
            <artifactId>sa-token-jwt</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 自定义验证注解 -->
 | 
			
		||||
@@ -53,12 +58,6 @@
 | 
			
		||||
            <artifactId>jackson-databind</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- excel工具 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.apache.poi</groupId>
 | 
			
		||||
            <artifactId>poi-ooxml</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.alibaba</groupId>
 | 
			
		||||
            <artifactId>easyexcel</artifactId>
 | 
			
		||||
@@ -70,30 +69,6 @@
 | 
			
		||||
            <artifactId>snakeyaml</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- Token生成与解析-->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>io.jsonwebtoken</groupId>
 | 
			
		||||
            <artifactId>jjwt</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- jdk11 缺失依赖 jaxb-->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.sun.xml.bind</groupId>
 | 
			
		||||
            <artifactId>jaxb-impl</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- redis 缓存操作 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-data-redis</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- pool 对象池 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.apache.commons</groupId>
 | 
			
		||||
            <artifactId>commons-pool2</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- servlet包 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>javax.servlet</groupId>
 | 
			
		||||
@@ -104,50 +79,58 @@
 | 
			
		||||
            <groupId>com.baomidou</groupId>
 | 
			
		||||
            <artifactId>mybatis-plus-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- dynamic-datasource 多数据源-->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.baomidou</groupId>
 | 
			
		||||
            <artifactId>mybatis-plus-extension</artifactId>
 | 
			
		||||
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.hutool</groupId>
 | 
			
		||||
            <artifactId>hutool-all</artifactId>
 | 
			
		||||
            <artifactId>hutool-core</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.hutool</groupId>
 | 
			
		||||
            <artifactId>hutool-http</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.hutool</groupId>
 | 
			
		||||
            <artifactId>hutool-captcha</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.hutool</groupId>
 | 
			
		||||
            <artifactId>hutool-jwt</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.hutool</groupId>
 | 
			
		||||
            <artifactId>hutool-extra</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.sun.mail</groupId>
 | 
			
		||||
            <artifactId>jakarta.mail</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.projectlombok</groupId>
 | 
			
		||||
            <artifactId>lombok</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.cloud</groupId>
 | 
			
		||||
            <artifactId>spring-cloud-starter-openfeign</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>io.github.openfeign</groupId>
 | 
			
		||||
            <artifactId>feign-okhttp</artifactId>
 | 
			
		||||
            <groupId>org.springdoc</groupId>
 | 
			
		||||
            <artifactId>springdoc-openapi-webmvc-core</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>de.codecentric</groupId>
 | 
			
		||||
            <artifactId>spring-boot-admin-starter-client</artifactId>
 | 
			
		||||
            <groupId>org.springdoc</groupId>
 | 
			
		||||
            <artifactId>springdoc-openapi-javadoc</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.github.xiaoymin</groupId>
 | 
			
		||||
            <artifactId>knife4j-spring-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>io.swagger</groupId>
 | 
			
		||||
            <artifactId>swagger-annotations</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-actuator</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <!--  自动生成YML配置关联JSON文件  -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
@@ -160,25 +143,28 @@
 | 
			
		||||
            <artifactId>redisson-spring-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.redisson</groupId>
 | 
			
		||||
            <artifactId>redisson-spring-data-27</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.baomidou</groupId>
 | 
			
		||||
            <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 加密包引入 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.yomahub</groupId>
 | 
			
		||||
            <artifactId>tlog-spring-boot-configuration</artifactId>
 | 
			
		||||
            <groupId>org.bouncycastle</groupId>
 | 
			
		||||
            <artifactId>bcprov-jdk15to18</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 离线IP地址定位库 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.yomahub</groupId>
 | 
			
		||||
            <artifactId>tlog-webroot</artifactId>
 | 
			
		||||
            <groupId>org.lionsoul</groupId>
 | 
			
		||||
            <artifactId>ip2region</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.yomahub</groupId>
 | 
			
		||||
            <artifactId>tlog-feign</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.excel.CellMergeStrategy;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * excel 列单元格合并(合并列相同项)
 | 
			
		||||
 *
 | 
			
		||||
 * 需搭配 {@link CellMergeStrategy} 策略使用
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Inherited
 | 
			
		||||
public @interface CellMerge {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * col index
 | 
			
		||||
	 */
 | 
			
		||||
	int index() default -1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 数据权限
 | 
			
		||||
 *
 | 
			
		||||
 * 一个注解只能对应一个模板
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 * @version 3.5.0
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface DataColumn {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 占位符关键字
 | 
			
		||||
     */
 | 
			
		||||
    String[] key() default "deptName";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 占位符替换值
 | 
			
		||||
     */
 | 
			
		||||
    String[] value() default "dept_id";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 数据权限组
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 * @version 3.5.0
 | 
			
		||||
 */
 | 
			
		||||
@Target({ElementType.METHOD, ElementType.TYPE})
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface DataPermission {
 | 
			
		||||
 | 
			
		||||
    DataColumn[] value();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 数据权限过滤注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface DataScope {
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门表的别名
 | 
			
		||||
     */
 | 
			
		||||
    String deptAlias() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户表的别名
 | 
			
		||||
     */
 | 
			
		||||
    String userAlias() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否过滤用户权限
 | 
			
		||||
     */
 | 
			
		||||
    boolean isUser() default false;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.enums.DataSourceType;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 自定义多数据源切换注解
 | 
			
		||||
 * <p>
 | 
			
		||||
 * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
@Target({ElementType.METHOD, ElementType.TYPE})
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
@Inherited
 | 
			
		||||
public @interface DataSource {
 | 
			
		||||
    /**
 | 
			
		||||
     * 切换数据源名称
 | 
			
		||||
     */
 | 
			
		||||
    DataSourceType value() default DataSourceType.MASTER;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
 | 
			
		||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 | 
			
		||||
import com.ruoyi.common.jackson.DictDataJsonSerializer;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 字典数据映射注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author itino
 | 
			
		||||
 * @deprecated 建议使用通用翻译注解
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target({ElementType.FIELD, ElementType.METHOD})
 | 
			
		||||
@JacksonAnnotationsInside
 | 
			
		||||
@JsonSerialize(using = DictDataJsonSerializer.class)
 | 
			
		||||
public @interface DictDataMapper {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置字典的type值 (如: sys_user_sex)
 | 
			
		||||
     */
 | 
			
		||||
    String dictType() default "";
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.enums.AlgorithmType;
 | 
			
		||||
import com.ruoyi.common.enums.EncodeType;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 字段加密注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author 老马
 | 
			
		||||
 */
 | 
			
		||||
@Documented
 | 
			
		||||
@Inherited
 | 
			
		||||
@Target({ElementType.FIELD})
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
public @interface EncryptField {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 加密算法
 | 
			
		||||
     */
 | 
			
		||||
    AlgorithmType algorithm() default AlgorithmType.DEFAULT;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 秘钥。AES、SM4需要
 | 
			
		||||
     */
 | 
			
		||||
    String password() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 公钥。RSA、SM2需要
 | 
			
		||||
     */
 | 
			
		||||
    String publicKey() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 私钥。RSA、SM2需要
 | 
			
		||||
     */
 | 
			
		||||
    String privateKey() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 编码方式。对加密算法为BASE64的不起作用
 | 
			
		||||
     */
 | 
			
		||||
    EncodeType encode() default EncodeType.DEFAULT;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -25,6 +27,6 @@ public @interface ExcelDictFormat {
 | 
			
		||||
    /**
 | 
			
		||||
     * 分隔符,读取字符串组内容
 | 
			
		||||
     */
 | 
			
		||||
    String separator() default ",";
 | 
			
		||||
    String separator() default StringUtils.SEPARATOR;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 枚举格式化
 | 
			
		||||
 *
 | 
			
		||||
 * @author Liang
 | 
			
		||||
 */
 | 
			
		||||
@Target({ElementType.FIELD})
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Inherited
 | 
			
		||||
public @interface ExcelEnumFormat {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典枚举类型
 | 
			
		||||
     */
 | 
			
		||||
    Class<? extends Enum<?>> enumClass();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典枚举类中对应的code属性名称,默认为code
 | 
			
		||||
     */
 | 
			
		||||
    String codeField() default "code";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典枚举类中对应的text属性名称,默认为text
 | 
			
		||||
     */
 | 
			
		||||
    String textField() default "text";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -38,4 +38,10 @@ public @interface Log {
 | 
			
		||||
     * 是否保存响应的参数
 | 
			
		||||
     */
 | 
			
		||||
    boolean isSaveResponseData() default true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 排除指定的请求参数
 | 
			
		||||
     */
 | 
			
		||||
    String[] excludeParamNames() default {};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,41 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.constant.Constants;
 | 
			
		||||
import com.ruoyi.common.enums.LimitType;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 限流注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface RateLimiter {
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流key
 | 
			
		||||
     */
 | 
			
		||||
    String key() default Constants.RATE_LIMIT_KEY;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流时间,单位秒
 | 
			
		||||
     */
 | 
			
		||||
    int time() default 60;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流次数
 | 
			
		||||
     */
 | 
			
		||||
    int count() default 100;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流类型
 | 
			
		||||
     */
 | 
			
		||||
    LimitType limitType() default LimitType.DEFAULT;
 | 
			
		||||
}
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.enums.LimitType;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 限流注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Target(ElementType.METHOD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface RateLimiter {
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流key,支持使用Spring el表达式来动态获取方法上的参数值
 | 
			
		||||
     * 格式类似于  #code.id #{#code}
 | 
			
		||||
     */
 | 
			
		||||
    String key() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流时间,单位秒
 | 
			
		||||
     */
 | 
			
		||||
    int time() default 60;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流次数
 | 
			
		||||
     */
 | 
			
		||||
    int count() default 100;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流类型
 | 
			
		||||
     */
 | 
			
		||||
    LimitType limitType() default LimitType.DEFAULT;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 提示消息 支持国际化 格式为 {code}
 | 
			
		||||
     */
 | 
			
		||||
    String message() default "{rate.limiter.message}";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,8 @@ public @interface RepeatSubmit {
 | 
			
		||||
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 提示消息
 | 
			
		||||
     * 提示消息 支持国际化 格式为 {code}
 | 
			
		||||
     */
 | 
			
		||||
    String message() default "不允许重复提交,请稍候再试";
 | 
			
		||||
    String message() default "{repeat.submit.message}";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
 | 
			
		||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 | 
			
		||||
import com.ruoyi.common.enums.SensitiveStrategy;
 | 
			
		||||
import com.ruoyi.common.jackson.SensitiveJsonSerializer;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 数据脱敏注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author zhujie
 | 
			
		||||
 */
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@JacksonAnnotationsInside
 | 
			
		||||
@JsonSerialize(using = SensitiveJsonSerializer.class)
 | 
			
		||||
public @interface Sensitive {
 | 
			
		||||
    SensitiveStrategy strategy();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,39 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
 | 
			
		||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 | 
			
		||||
import com.ruoyi.common.translation.handler.TranslationHandler;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用翻译注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Inherited
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target({ElementType.FIELD, ElementType.METHOD})
 | 
			
		||||
@Documented
 | 
			
		||||
@JacksonAnnotationsInside
 | 
			
		||||
@JsonSerialize(using = TranslationHandler.class)
 | 
			
		||||
public @interface Translation {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型 (需与实现类上的 {@link com.ruoyi.common.annotation.TranslationType} 注解type对应)
 | 
			
		||||
     * <p>
 | 
			
		||||
     * 默认取当前字段的值 如果设置了 @{@link Translation#mapper()} 则取映射字段的值
 | 
			
		||||
     */
 | 
			
		||||
    String type();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 映射字段 (如果不为空则取此字段的值)
 | 
			
		||||
     */
 | 
			
		||||
    String mapper() default "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 其他条件 例如: 字典type(sys_user_sex)
 | 
			
		||||
     */
 | 
			
		||||
    String other() default "";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,21 @@
 | 
			
		||||
package com.ruoyi.common.annotation;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 翻译类型注解 (标注到{@link com.ruoyi.common.translation.TranslationInterface} 的实现类)
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Inherited
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target({ElementType.TYPE})
 | 
			
		||||
@Documented
 | 
			
		||||
public @interface TranslationType {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     */
 | 
			
		||||
    String type();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -13,73 +13,73 @@ import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
 */
 | 
			
		||||
public class UnsignedMathGenerator implements CodeGenerator {
 | 
			
		||||
 | 
			
		||||
	private static final long serialVersionUID = -5514819971774091076L;
 | 
			
		||||
    private static final long serialVersionUID = -5514819971774091076L;
 | 
			
		||||
 | 
			
		||||
	private static final String operators = "+-*";
 | 
			
		||||
    private static final String OPERATORS = "+-*";
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 参与计算数字最大长度
 | 
			
		||||
	 */
 | 
			
		||||
	private final int numberLength;
 | 
			
		||||
    /**
 | 
			
		||||
     * 参与计算数字最大长度
 | 
			
		||||
     */
 | 
			
		||||
    private final int numberLength;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 构造
 | 
			
		||||
	 */
 | 
			
		||||
	public UnsignedMathGenerator() {
 | 
			
		||||
		this(2);
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 构造
 | 
			
		||||
     */
 | 
			
		||||
    public UnsignedMathGenerator() {
 | 
			
		||||
        this(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 构造
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param numberLength 参与计算最大数字位数
 | 
			
		||||
	 */
 | 
			
		||||
	public UnsignedMathGenerator(int numberLength) {
 | 
			
		||||
		this.numberLength = numberLength;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 构造
 | 
			
		||||
     *
 | 
			
		||||
     * @param numberLength 参与计算最大数字位数
 | 
			
		||||
     */
 | 
			
		||||
    public UnsignedMathGenerator(int numberLength) {
 | 
			
		||||
        this.numberLength = numberLength;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String generate() {
 | 
			
		||||
		final int limit = getLimit();
 | 
			
		||||
		int min = RandomUtil.randomInt(limit);
 | 
			
		||||
		int max = RandomUtil.randomInt(min, limit);
 | 
			
		||||
		String number1 = Integer.toString(max);
 | 
			
		||||
		String number2 = Integer.toString(min);
 | 
			
		||||
		number1 = StringUtils.rightPad(number1, this.numberLength, CharUtil.SPACE);
 | 
			
		||||
		number2 = StringUtils.rightPad(number2, this.numberLength, CharUtil.SPACE);
 | 
			
		||||
    @Override
 | 
			
		||||
    public String generate() {
 | 
			
		||||
        final int limit = getLimit();
 | 
			
		||||
        int a = RandomUtil.randomInt(limit);
 | 
			
		||||
        int b = RandomUtil.randomInt(limit);
 | 
			
		||||
        String max = Integer.toString(Math.max(a,b));
 | 
			
		||||
        String min = Integer.toString(Math.min(a,b));
 | 
			
		||||
        max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE);
 | 
			
		||||
        min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE);
 | 
			
		||||
 | 
			
		||||
		return number1 + RandomUtil.randomChar(operators) + number2 + '=';
 | 
			
		||||
	}
 | 
			
		||||
        return max + RandomUtil.randomChar(OPERATORS) + min + '=';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean verify(String code, String userInputCode) {
 | 
			
		||||
		int result;
 | 
			
		||||
		try {
 | 
			
		||||
			result = Integer.parseInt(userInputCode);
 | 
			
		||||
		} catch (NumberFormatException e) {
 | 
			
		||||
			// 用户输入非数字
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean verify(String code, String userInputCode) {
 | 
			
		||||
        int result;
 | 
			
		||||
        try {
 | 
			
		||||
            result = Integer.parseInt(userInputCode);
 | 
			
		||||
        } catch (NumberFormatException e) {
 | 
			
		||||
            // 用户输入非数字
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		final int calculateResult = (int) Calculator.conversion(code);
 | 
			
		||||
		return result == calculateResult;
 | 
			
		||||
	}
 | 
			
		||||
        final int calculateResult = (int) Calculator.conversion(code);
 | 
			
		||||
        return result == calculateResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 获取验证码长度
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return 验证码长度
 | 
			
		||||
	 */
 | 
			
		||||
	public int getLength() {
 | 
			
		||||
		return this.numberLength * 2 + 2;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取验证码长度
 | 
			
		||||
     *
 | 
			
		||||
     * @return 验证码长度
 | 
			
		||||
     */
 | 
			
		||||
    public int getLength() {
 | 
			
		||||
        return this.numberLength * 2 + 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 根据长度获取参与计算数字最大值
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return 最大值
 | 
			
		||||
	 */
 | 
			
		||||
	private int getLimit() {
 | 
			
		||||
		return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据长度获取参与计算数字最大值
 | 
			
		||||
     *
 | 
			
		||||
     * @return 最大值
 | 
			
		||||
     */
 | 
			
		||||
    private int getLimit() {
 | 
			
		||||
        return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
package com.ruoyi.common.config;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +11,6 @@ import org.springframework.stereotype.Component;
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@Component
 | 
			
		||||
@ConfigurationProperties(prefix = "ruoyi")
 | 
			
		||||
public class RuoYiConfig {
 | 
			
		||||
@@ -34,18 +31,8 @@ public class RuoYiConfig {
 | 
			
		||||
    private String copyrightYear;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 实例演示开关
 | 
			
		||||
     * 缓存懒加载
 | 
			
		||||
     */
 | 
			
		||||
    private boolean demoEnabled;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取地址开关
 | 
			
		||||
     */
 | 
			
		||||
    @Getter
 | 
			
		||||
    private static boolean addressEnabled;
 | 
			
		||||
 | 
			
		||||
    public void setAddressEnabled(boolean addressEnabled) {
 | 
			
		||||
        RuoYiConfig.addressEnabled = addressEnabled;
 | 
			
		||||
    }
 | 
			
		||||
    private boolean cacheLazy;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 缓存的key 常量
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
public interface CacheConstants {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 在线用户 redis key
 | 
			
		||||
     */
 | 
			
		||||
    String ONLINE_TOKEN_KEY = "online_tokens:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 验证码 redis key
 | 
			
		||||
     */
 | 
			
		||||
    String CAPTCHA_CODE_KEY = "captcha_codes:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 参数管理 cache key
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_CONFIG_KEY = "sys_config:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典管理 cache key
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_DICT_KEY = "sys_dict:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 防重提交 redis key
 | 
			
		||||
     */
 | 
			
		||||
    String REPEAT_SUBMIT_KEY = "repeat_submit:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流 redis key
 | 
			
		||||
     */
 | 
			
		||||
    String RATE_LIMIT_KEY = "rate_limit:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录账户密码错误次数 redis key
 | 
			
		||||
     */
 | 
			
		||||
    String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 缓存组名称常量
 | 
			
		||||
 * <p>
 | 
			
		||||
 * key 格式为 cacheNames#ttl#maxIdleTime#maxSize
 | 
			
		||||
 * <p>
 | 
			
		||||
 * ttl 过期时间 如果设置为0则不过期 默认为0
 | 
			
		||||
 * maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0
 | 
			
		||||
 * maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0
 | 
			
		||||
 * <p>
 | 
			
		||||
 * 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface CacheNames {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 演示案例
 | 
			
		||||
     */
 | 
			
		||||
    String DEMO_CACHE = "demo:cache#60s#10m#20";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 系统配置
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_CONFIG = "sys_config";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据字典
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_DICT = "sys_dict";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户账户
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_USER_NAME = "sys_user_name#30d";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_DEPT = "sys_dept#30d";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * OSS内容
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_OSS = "sys_oss#30d";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * OSS配置
 | 
			
		||||
     */
 | 
			
		||||
    String SYS_OSS_CONFIG = "sys_oss_config";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 在线用户
 | 
			
		||||
     */
 | 
			
		||||
    String ONLINE_TOKEN = "online_tokens";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,145 +1,76 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
import io.jsonwebtoken.Claims;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用常量信息
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
public class Constants {
 | 
			
		||||
public interface Constants {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * UTF-8 字符集
 | 
			
		||||
     */
 | 
			
		||||
    public static final String UTF8 = "UTF-8";
 | 
			
		||||
    String UTF8 = "UTF-8";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * GBK 字符集
 | 
			
		||||
     */
 | 
			
		||||
    public static final String GBK = "GBK";
 | 
			
		||||
    String GBK = "GBK";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * www主域
 | 
			
		||||
     */
 | 
			
		||||
    String WWW = "www.";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * http请求
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTTP = "http://";
 | 
			
		||||
    String HTTP = "http://";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * https请求
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTTPS = "https://";
 | 
			
		||||
    String HTTPS = "https://";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通用成功标识
 | 
			
		||||
     */
 | 
			
		||||
    public static final String SUCCESS = "0";
 | 
			
		||||
    String SUCCESS = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通用失败标识
 | 
			
		||||
     */
 | 
			
		||||
    public static final String FAIL = "1";
 | 
			
		||||
    String FAIL = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录成功
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOGIN_SUCCESS = "Success";
 | 
			
		||||
    String LOGIN_SUCCESS = "Success";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 注销
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOGOUT = "Logout";
 | 
			
		||||
    String LOGOUT = "Logout";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 注册
 | 
			
		||||
     */
 | 
			
		||||
    public static final String REGISTER = "Register";
 | 
			
		||||
    String REGISTER = "Register";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录失败
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOGIN_FAIL = "Error";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 验证码 redis key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录用户 redis key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 防重提交 redis key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 限流 redis key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String RATE_LIMIT_KEY = "rate_limit:";
 | 
			
		||||
    String LOGIN_FAIL = "Error";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 验证码有效期(分钟)
 | 
			
		||||
     */
 | 
			
		||||
    public static final Integer CAPTCHA_EXPIRATION = 2;
 | 
			
		||||
    Integer CAPTCHA_EXPIRATION = 2;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 令牌
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TOKEN = "token";
 | 
			
		||||
    String TOKEN = "token";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 令牌前缀
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TOKEN_PREFIX = "Bearer ";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 令牌前缀
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOGIN_USER_KEY = "login_user_key";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    public static final String JWT_USERID = "userid";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名称
 | 
			
		||||
     */
 | 
			
		||||
    public static final String JWT_USERNAME = Claims.SUBJECT;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户头像
 | 
			
		||||
     */
 | 
			
		||||
    public static final String JWT_AVATAR = "avatar";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建时间
 | 
			
		||||
     */
 | 
			
		||||
    public static final String JWT_CREATED = "created";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户权限
 | 
			
		||||
     */
 | 
			
		||||
    public static final String JWT_AUTHORITIES = "authorities";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 参数管理 cache key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String SYS_CONFIG_KEY = "sys_config:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典管理 cache key
 | 
			
		||||
     */
 | 
			
		||||
    public static final String SYS_DICT_KEY = "sys_dict:";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * RMI 远程方法调用
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOOKUP_RMI = "rmi://";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * LDAP 远程方法调用
 | 
			
		||||
     */
 | 
			
		||||
    public static final String LOOKUP_LDAP = "ldap://";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,184 +5,189 @@ package com.ruoyi.common.constant;
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
public class GenConstants {
 | 
			
		||||
public interface GenConstants {
 | 
			
		||||
    /**
 | 
			
		||||
     * 单表(增删改查)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TPL_CRUD = "crud";
 | 
			
		||||
    String TPL_CRUD = "crud";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 树表(增删改查)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TPL_TREE = "tree";
 | 
			
		||||
    String TPL_TREE = "tree";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 主子表(增删改查)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TPL_SUB = "sub";
 | 
			
		||||
    String TPL_SUB = "sub";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 树编码字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TREE_CODE = "treeCode";
 | 
			
		||||
    String TREE_CODE = "treeCode";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 树父编码字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TREE_PARENT_CODE = "treeParentCode";
 | 
			
		||||
    String TREE_PARENT_CODE = "treeParentCode";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 树名称字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TREE_NAME = "treeName";
 | 
			
		||||
    String TREE_NAME = "treeName";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上级菜单ID字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String PARENT_MENU_ID = "parentMenuId";
 | 
			
		||||
    String PARENT_MENU_ID = "parentMenuId";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 上级菜单名称字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String PARENT_MENU_NAME = "parentMenuName";
 | 
			
		||||
    String PARENT_MENU_NAME = "parentMenuName";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据库字符串类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
 | 
			
		||||
    String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据库文本类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
 | 
			
		||||
    String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据库时间类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
 | 
			
		||||
    String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据库数字类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
 | 
			
		||||
            "bit", "bigint", "float", "double", "decimal"};
 | 
			
		||||
    String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
 | 
			
		||||
        "bit", "bigint", "float", "double", "decimal"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * BO对象 不需要添加字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
            "update_time", "version"};
 | 
			
		||||
    String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
        "update_time", "version"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * BO对象 不需要编辑字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
            "update_time", "version"};
 | 
			
		||||
    String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
        "update_time", "version"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * VO对象 不需要返回字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
            "update_time", "version"};
 | 
			
		||||
    String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
        "update_time", "version"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * BO对象 不需要查询字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
            "update_time", "remark", "version"};
 | 
			
		||||
    String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
 | 
			
		||||
        "update_time", "remark", "version"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Entity基类字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
 | 
			
		||||
    String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tree基类字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final String[] TREE_ENTITY = {"parentName", "parentId", "children"};
 | 
			
		||||
    String[] TREE_ENTITY = {"parentName", "parentId", "children"};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 文本框
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_INPUT = "input";
 | 
			
		||||
    String HTML_INPUT = "input";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 文本域
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_TEXTAREA = "textarea";
 | 
			
		||||
    String HTML_TEXTAREA = "textarea";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 下拉框
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_SELECT = "select";
 | 
			
		||||
    String HTML_SELECT = "select";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 单选框
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_RADIO = "radio";
 | 
			
		||||
    String HTML_RADIO = "radio";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 复选框
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_CHECKBOX = "checkbox";
 | 
			
		||||
    String HTML_CHECKBOX = "checkbox";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 日期控件
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_DATETIME = "datetime";
 | 
			
		||||
    String HTML_DATETIME = "datetime";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 图片上传控件
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
 | 
			
		||||
    String HTML_IMAGE_UPLOAD = "imageUpload";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 文件上传控件
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_FILE_UPLOAD = "fileUpload";
 | 
			
		||||
    String HTML_FILE_UPLOAD = "fileUpload";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 富文本控件
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTML_EDITOR = "editor";
 | 
			
		||||
    String HTML_EDITOR = "editor";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字符串类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_STRING = "String";
 | 
			
		||||
    String TYPE_STRING = "String";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 整型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_INTEGER = "Integer";
 | 
			
		||||
    String TYPE_INTEGER = "Integer";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 长整型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_LONG = "Long";
 | 
			
		||||
    String TYPE_LONG = "Long";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 浮点型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_DOUBLE = "Double";
 | 
			
		||||
    String TYPE_DOUBLE = "Double";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 高精度计算类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_BIGDECIMAL = "BigDecimal";
 | 
			
		||||
    String TYPE_BIGDECIMAL = "BigDecimal";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 时间类型
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_DATE = "Date";
 | 
			
		||||
    String TYPE_DATE = "Date";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 模糊查询
 | 
			
		||||
     */
 | 
			
		||||
    public static final String QUERY_LIKE = "LIKE";
 | 
			
		||||
    String QUERY_LIKE = "LIKE";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 相等查询
 | 
			
		||||
     */
 | 
			
		||||
    String QUERY_EQ = "EQ";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 需要
 | 
			
		||||
     */
 | 
			
		||||
    public static final String REQUIRE = "1";
 | 
			
		||||
    String REQUIRE = "1";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,93 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 返回状态码
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface HttpStatus {
 | 
			
		||||
    /**
 | 
			
		||||
     * 操作成功
 | 
			
		||||
     */
 | 
			
		||||
    int SUCCESS = 200;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 对象创建成功
 | 
			
		||||
     */
 | 
			
		||||
    int CREATED = 201;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求已经被接受
 | 
			
		||||
     */
 | 
			
		||||
    int ACCEPTED = 202;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 操作已经执行成功,但是没有返回数据
 | 
			
		||||
     */
 | 
			
		||||
    int NO_CONTENT = 204;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 资源已被移除
 | 
			
		||||
     */
 | 
			
		||||
    int MOVED_PERM = 301;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 重定向
 | 
			
		||||
     */
 | 
			
		||||
    int SEE_OTHER = 303;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 资源没有被修改
 | 
			
		||||
     */
 | 
			
		||||
    int NOT_MODIFIED = 304;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 参数列表错误(缺少,格式不匹配)
 | 
			
		||||
     */
 | 
			
		||||
    int BAD_REQUEST = 400;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 未授权
 | 
			
		||||
     */
 | 
			
		||||
    int UNAUTHORIZED = 401;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 访问受限,授权过期
 | 
			
		||||
     */
 | 
			
		||||
    int FORBIDDEN = 403;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 资源,服务未找到
 | 
			
		||||
     */
 | 
			
		||||
    int NOT_FOUND = 404;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不允许的http方法
 | 
			
		||||
     */
 | 
			
		||||
    int BAD_METHOD = 405;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 资源冲突,或者资源被锁
 | 
			
		||||
     */
 | 
			
		||||
    int CONFLICT = 409;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 不支持的数据,媒体类型
 | 
			
		||||
     */
 | 
			
		||||
    int UNSUPPORTED_TYPE = 415;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 系统内部错误
 | 
			
		||||
     */
 | 
			
		||||
    int ERROR = 500;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 接口未实现
 | 
			
		||||
     */
 | 
			
		||||
    int NOT_IMPLEMENTED = 501;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 系统警告消息
 | 
			
		||||
     */
 | 
			
		||||
    int WARN = 601;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,51 +0,0 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 任务调度通用常量
 | 
			
		||||
 *
 | 
			
		||||
 * @deprecated 3.4.0删除 迁移至xxl-job
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
public class ScheduleConstants
 | 
			
		||||
{
 | 
			
		||||
    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
 | 
			
		||||
 | 
			
		||||
    /** 执行目标key */
 | 
			
		||||
    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
 | 
			
		||||
 | 
			
		||||
    /** 默认 */
 | 
			
		||||
    public static final String MISFIRE_DEFAULT = "0";
 | 
			
		||||
 | 
			
		||||
    /** 立即触发执行 */
 | 
			
		||||
    public static final String MISFIRE_IGNORE_MISFIRES = "1";
 | 
			
		||||
 | 
			
		||||
    /** 触发一次执行 */
 | 
			
		||||
    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
 | 
			
		||||
 | 
			
		||||
    /** 不触发立即执行 */
 | 
			
		||||
    public static final String MISFIRE_DO_NOTHING = "3";
 | 
			
		||||
 | 
			
		||||
    public enum Status
 | 
			
		||||
    {
 | 
			
		||||
        /**
 | 
			
		||||
         * 正常
 | 
			
		||||
         */
 | 
			
		||||
        NORMAL("0"),
 | 
			
		||||
        /**
 | 
			
		||||
         * 暂停
 | 
			
		||||
         */
 | 
			
		||||
        PAUSE("1");
 | 
			
		||||
 | 
			
		||||
        private String value;
 | 
			
		||||
 | 
			
		||||
        private Status(String value)
 | 
			
		||||
        {
 | 
			
		||||
            this.value = value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String getValue()
 | 
			
		||||
        {
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
package com.ruoyi.common.constant;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 翻译常量
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface TransConstant {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户id转账号
 | 
			
		||||
     */
 | 
			
		||||
    String USER_ID_TO_NAME = "user_id_to_name";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门id转名称
 | 
			
		||||
     */
 | 
			
		||||
    String DEPT_ID_TO_NAME = "dept_id_to_name";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典type转label
 | 
			
		||||
     */
 | 
			
		||||
    String DICT_TYPE_TO_LABEL = "dict_type_to_label";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ossId转url
 | 
			
		||||
     */
 | 
			
		||||
    String OSS_ID_TO_URL = "oss_id_to_url";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -5,108 +5,143 @@ package com.ruoyi.common.constant;
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
public class UserConstants {
 | 
			
		||||
public interface UserConstants {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 平台内系统用户的唯一标志
 | 
			
		||||
     */
 | 
			
		||||
    public static final String SYS_USER = "SYS_USER";
 | 
			
		||||
    String SYS_USER = "SYS_USER";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 正常状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String NORMAL = "0";
 | 
			
		||||
    String NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 异常状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String EXCEPTION = "1";
 | 
			
		||||
    String EXCEPTION = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户正常状态
 | 
			
		||||
     */
 | 
			
		||||
    String USER_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户封禁状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String USER_DISABLE = "1";
 | 
			
		||||
    String USER_DISABLE = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色正常状态
 | 
			
		||||
     */
 | 
			
		||||
    String ROLE_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色封禁状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String ROLE_DISABLE = "1";
 | 
			
		||||
    String ROLE_DISABLE = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门正常状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String DEPT_NORMAL = "0";
 | 
			
		||||
    String DEPT_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门停用状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String DEPT_DISABLE = "1";
 | 
			
		||||
    String DEPT_DISABLE = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 岗位正常状态
 | 
			
		||||
     */
 | 
			
		||||
    String POST_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 岗位停用状态
 | 
			
		||||
     */
 | 
			
		||||
    String POST_DISABLE = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典正常状态
 | 
			
		||||
     */
 | 
			
		||||
    public static final String DICT_NORMAL = "0";
 | 
			
		||||
    String DICT_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否为系统默认(是)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String YES = "Y";
 | 
			
		||||
    String YES = "Y";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否菜单外链(是)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String YES_FRAME = "0";
 | 
			
		||||
    String YES_FRAME = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否菜单外链(否)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String NO_FRAME = "1";
 | 
			
		||||
    String NO_FRAME = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单正常状态
 | 
			
		||||
     */
 | 
			
		||||
    String MENU_NORMAL = "0";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单停用状态
 | 
			
		||||
     */
 | 
			
		||||
    String MENU_DISABLE = "1";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单类型(目录)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_DIR = "M";
 | 
			
		||||
    String TYPE_DIR = "M";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单类型(菜单)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_MENU = "C";
 | 
			
		||||
    String TYPE_MENU = "C";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单类型(按钮)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String TYPE_BUTTON = "F";
 | 
			
		||||
    String TYPE_BUTTON = "F";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Layout组件标识
 | 
			
		||||
     */
 | 
			
		||||
    public final static String LAYOUT = "Layout";
 | 
			
		||||
    String LAYOUT = "Layout";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ParentView组件标识
 | 
			
		||||
     */
 | 
			
		||||
    public final static String PARENT_VIEW = "ParentView";
 | 
			
		||||
    String PARENT_VIEW = "ParentView";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * InnerLink组件标识
 | 
			
		||||
     */
 | 
			
		||||
    public final static String INNER_LINK = "InnerLink";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 校验返回结果码
 | 
			
		||||
     */
 | 
			
		||||
    public final static String UNIQUE = "0";
 | 
			
		||||
    public final static String NOT_UNIQUE = "1";
 | 
			
		||||
    String INNER_LINK = "InnerLink";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名长度限制
 | 
			
		||||
     */
 | 
			
		||||
    public static final int USERNAME_MIN_LENGTH = 2;
 | 
			
		||||
    public static final int USERNAME_MAX_LENGTH = 20;
 | 
			
		||||
    int USERNAME_MIN_LENGTH = 2;
 | 
			
		||||
    int USERNAME_MAX_LENGTH = 20;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码长度限制
 | 
			
		||||
     */
 | 
			
		||||
    public static final int PASSWORD_MIN_LENGTH = 5;
 | 
			
		||||
    public static final int PASSWORD_MAX_LENGTH = 20;
 | 
			
		||||
    int PASSWORD_MIN_LENGTH = 5;
 | 
			
		||||
    int PASSWORD_MAX_LENGTH = 20;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员ID
 | 
			
		||||
     */
 | 
			
		||||
    Long ADMIN_ID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 管理员角色key
 | 
			
		||||
     */
 | 
			
		||||
    String ADMIN_ROLE_KEY = "admin";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,9 @@ import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.alibaba.excel.converters.Converter;
 | 
			
		||||
import com.alibaba.excel.enums.CellDataTypeEnum;
 | 
			
		||||
import com.alibaba.excel.metadata.CellData;
 | 
			
		||||
import com.alibaba.excel.metadata.GlobalConfiguration;
 | 
			
		||||
import com.alibaba.excel.metadata.data.ReadCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.data.WriteCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
@@ -20,32 +21,32 @@ import java.math.BigDecimal;
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ExcelBigNumberConvert implements Converter<Long> {
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Class<Long> supportJavaTypeKey() {
 | 
			
		||||
		return Long.class;
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public Class<Long> supportJavaTypeKey() {
 | 
			
		||||
        return Long.class;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public CellDataTypeEnum supportExcelTypeKey() {
 | 
			
		||||
		return CellDataTypeEnum.STRING;
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public CellDataTypeEnum supportExcelTypeKey() {
 | 
			
		||||
        return CellDataTypeEnum.STRING;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
		return Convert.toLong(cellData.getData());
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        return Convert.toLong(cellData.getData());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public CellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
		if (ObjectUtil.isNotNull(object)) {
 | 
			
		||||
			String str = Convert.toStr(object);
 | 
			
		||||
			if (str.length() > 15) {
 | 
			
		||||
				return new CellData<>(str);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		CellData<Object> cellData = new CellData<>(new BigDecimal(object));
 | 
			
		||||
		cellData.setType(CellDataTypeEnum.NUMBER);
 | 
			
		||||
		return cellData;
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        if (ObjectUtil.isNotNull(object)) {
 | 
			
		||||
            String str = Convert.toStr(object);
 | 
			
		||||
            if (str.length() > 15) {
 | 
			
		||||
                return new WriteCellData<>(str);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object));
 | 
			
		||||
        cellData.setType(CellDataTypeEnum.NUMBER);
 | 
			
		||||
        return cellData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,18 @@ package com.ruoyi.common.convert;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.annotation.AnnotationUtil;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.alibaba.excel.converters.Converter;
 | 
			
		||||
import com.alibaba.excel.enums.CellDataTypeEnum;
 | 
			
		||||
import com.alibaba.excel.metadata.CellData;
 | 
			
		||||
import com.alibaba.excel.metadata.GlobalConfiguration;
 | 
			
		||||
import com.alibaba.excel.metadata.data.ReadCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.data.WriteCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
 | 
			
		||||
import com.ruoyi.common.annotation.ExcelDictFormat;
 | 
			
		||||
import com.ruoyi.common.core.service.DictService;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.poi.ExcelUtil;
 | 
			
		||||
import com.ruoyi.common.utils.spring.SpringUtils;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
@@ -22,48 +26,48 @@ import java.lang.reflect.Field;
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ExcelDictConvert implements Converter<Object> {
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Class<Object> supportJavaTypeKey() {
 | 
			
		||||
		return Object.class;
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public Class<Object> supportJavaTypeKey() {
 | 
			
		||||
        return Object.class;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public CellDataTypeEnum supportExcelTypeKey() {
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public CellDataTypeEnum supportExcelTypeKey() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
		ExcelDictFormat anno = getAnnotation(contentProperty.getField());
 | 
			
		||||
		String type = anno.dictType();
 | 
			
		||||
		String label = cellData.getStringValue();
 | 
			
		||||
		String value;
 | 
			
		||||
		if (StringUtils.isBlank(type)) {
 | 
			
		||||
			value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
 | 
			
		||||
		} else {
 | 
			
		||||
			value = ExcelUtil.reverseDictByExp(label, type, anno.separator());
 | 
			
		||||
		}
 | 
			
		||||
		return Convert.convert(contentProperty.getField().getType(), value);
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
 | 
			
		||||
        String type = anno.dictType();
 | 
			
		||||
        String label = cellData.getStringValue();
 | 
			
		||||
        String value;
 | 
			
		||||
        if (StringUtils.isBlank(type)) {
 | 
			
		||||
            value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
 | 
			
		||||
        } else {
 | 
			
		||||
            value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator());
 | 
			
		||||
        }
 | 
			
		||||
        return Convert.convert(contentProperty.getField().getType(), value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public CellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
		if (StringUtils.isNull(object)) {
 | 
			
		||||
			return new CellData<>("");
 | 
			
		||||
		}
 | 
			
		||||
		ExcelDictFormat anno = getAnnotation(contentProperty.getField());
 | 
			
		||||
		String type = anno.dictType();
 | 
			
		||||
		String value = Convert.toStr(object);
 | 
			
		||||
		String label;
 | 
			
		||||
		if (StringUtils.isBlank(type)) {
 | 
			
		||||
			label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
 | 
			
		||||
		} else {
 | 
			
		||||
			label = ExcelUtil.convertDictByExp(value, type, anno.separator());
 | 
			
		||||
		}
 | 
			
		||||
		return new CellData<>(label);
 | 
			
		||||
	}
 | 
			
		||||
    @Override
 | 
			
		||||
    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        if (ObjectUtil.isNull(object)) {
 | 
			
		||||
            return new WriteCellData<>("");
 | 
			
		||||
        }
 | 
			
		||||
        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
 | 
			
		||||
        String type = anno.dictType();
 | 
			
		||||
        String value = Convert.toStr(object);
 | 
			
		||||
        String label;
 | 
			
		||||
        if (StringUtils.isBlank(type)) {
 | 
			
		||||
            label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
 | 
			
		||||
        } else {
 | 
			
		||||
            label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator());
 | 
			
		||||
        }
 | 
			
		||||
        return new WriteCellData<>(label);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	private ExcelDictFormat getAnnotation(Field field) {
 | 
			
		||||
		return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
 | 
			
		||||
	}
 | 
			
		||||
    private ExcelDictFormat getAnnotation(Field field) {
 | 
			
		||||
        return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,97 @@
 | 
			
		||||
package com.ruoyi.common.convert;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.annotation.AnnotationUtil;
 | 
			
		||||
import cn.hutool.core.convert.Convert;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.alibaba.excel.converters.Converter;
 | 
			
		||||
import com.alibaba.excel.enums.CellDataTypeEnum;
 | 
			
		||||
import com.alibaba.excel.metadata.GlobalConfiguration;
 | 
			
		||||
import com.alibaba.excel.metadata.data.ReadCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.data.WriteCellData;
 | 
			
		||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
 | 
			
		||||
import com.ruoyi.common.annotation.ExcelEnumFormat;
 | 
			
		||||
import com.ruoyi.common.utils.reflect.ReflectUtils;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 枚举格式化转换处理
 | 
			
		||||
 *
 | 
			
		||||
 * @author Liang
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ExcelEnumConvert implements Converter<Object> {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Class<Object> supportJavaTypeKey() {
 | 
			
		||||
        return Object.class;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CellDataTypeEnum supportExcelTypeKey() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        cellData.checkEmpty();
 | 
			
		||||
        // Excel中填入的是枚举中指定的描述
 | 
			
		||||
        Object textValue = null;
 | 
			
		||||
        switch (cellData.getType()) {
 | 
			
		||||
            case STRING:
 | 
			
		||||
            case DIRECT_STRING:
 | 
			
		||||
            case RICH_TEXT_STRING:
 | 
			
		||||
                textValue = cellData.getStringValue();
 | 
			
		||||
                break;
 | 
			
		||||
            case NUMBER:
 | 
			
		||||
                textValue = cellData.getNumberValue();
 | 
			
		||||
                break;
 | 
			
		||||
            case BOOLEAN:
 | 
			
		||||
                textValue = cellData.getBooleanValue();
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw new IllegalArgumentException("单元格类型异常!");
 | 
			
		||||
        }
 | 
			
		||||
        // 如果是空值
 | 
			
		||||
        if (ObjectUtil.isNull(textValue)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        Map<Object, String> enumCodeToTextMap = beforeConvert(contentProperty);
 | 
			
		||||
        // 从Java输出至Excel是code转text
 | 
			
		||||
        // 因此从Excel转Java应该将text与code对调
 | 
			
		||||
        Map<Object, Object> enumTextToCodeMap = new HashMap<>();
 | 
			
		||||
        enumCodeToTextMap.forEach((key, value) -> enumTextToCodeMap.put(value, key));
 | 
			
		||||
        // 应该从text -> code中查找
 | 
			
		||||
        Object codeValue = enumTextToCodeMap.get(textValue);
 | 
			
		||||
        return Convert.convert(contentProperty.getField().getType(), codeValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
 | 
			
		||||
        if (ObjectUtil.isNull(object)) {
 | 
			
		||||
            return new WriteCellData<>("");
 | 
			
		||||
        }
 | 
			
		||||
        Map<Object, String> enumValueMap = beforeConvert(contentProperty);
 | 
			
		||||
        String value = Convert.toStr(enumValueMap.get(object), "");
 | 
			
		||||
        return new WriteCellData<>(value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Map<Object, String> beforeConvert(ExcelContentProperty contentProperty) {
 | 
			
		||||
        ExcelEnumFormat anno = getAnnotation(contentProperty.getField());
 | 
			
		||||
        Map<Object, String> enumValueMap = new HashMap<>();
 | 
			
		||||
        Enum<?>[] enumConstants = anno.enumClass().getEnumConstants();
 | 
			
		||||
        for (Enum<?> enumConstant : enumConstants) {
 | 
			
		||||
            Object codeValue = ReflectUtils.invokeGetter(enumConstant, anno.codeField());
 | 
			
		||||
            String textValue = ReflectUtils.invokeGetter(enumConstant, anno.textField());
 | 
			
		||||
            enumValueMap.put(codeValue, textValue);
 | 
			
		||||
        }
 | 
			
		||||
        return enumValueMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ExcelEnumFormat getAnnotation(Field field) {
 | 
			
		||||
        return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,53 +1,25 @@
 | 
			
		||||
package com.ruoyi.common.core.controller;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.core.domain.AjaxResult;
 | 
			
		||||
import com.ruoyi.common.core.domain.R;
 | 
			
		||||
import com.ruoyi.common.core.domain.model.LoginUser;
 | 
			
		||||
import com.ruoyi.common.utils.SecurityUtils;
 | 
			
		||||
import com.ruoyi.common.helper.LoginHelper;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * web层通用数据处理
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class BaseController {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回成功
 | 
			
		||||
     */
 | 
			
		||||
    public AjaxResult<Void> success() {
 | 
			
		||||
        return AjaxResult.success();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回失败消息
 | 
			
		||||
     */
 | 
			
		||||
    public AjaxResult<Void> error() {
 | 
			
		||||
        return AjaxResult.error();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回成功消息
 | 
			
		||||
     */
 | 
			
		||||
    public AjaxResult<Void> success(String message) {
 | 
			
		||||
        return AjaxResult.success(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回失败消息
 | 
			
		||||
     */
 | 
			
		||||
    public AjaxResult<Void> error(String message) {
 | 
			
		||||
        return AjaxResult.error(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 响应返回结果
 | 
			
		||||
     *
 | 
			
		||||
     * @param rows 影响行数
 | 
			
		||||
     * @return 操作结果
 | 
			
		||||
     */
 | 
			
		||||
    protected AjaxResult<Void> toAjax(int rows) {
 | 
			
		||||
        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
 | 
			
		||||
    protected R<Void> toAjax(int rows) {
 | 
			
		||||
        return rows > 0 ? R.ok() : R.fail();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -56,8 +28,8 @@ public class BaseController {
 | 
			
		||||
     * @param result 结果
 | 
			
		||||
     * @return 操作结果
 | 
			
		||||
     */
 | 
			
		||||
    protected AjaxResult<Void> toAjax(boolean result) {
 | 
			
		||||
        return result ? success() : error();
 | 
			
		||||
    protected R<Void> toAjax(boolean result) {
 | 
			
		||||
        return result ? R.ok() : R.fail();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -71,27 +43,27 @@ public class BaseController {
 | 
			
		||||
     * 获取用户缓存信息
 | 
			
		||||
     */
 | 
			
		||||
    public LoginUser getLoginUser() {
 | 
			
		||||
        return SecurityUtils.getLoginUser();
 | 
			
		||||
        return LoginHelper.getLoginUser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取登录用户id
 | 
			
		||||
     */
 | 
			
		||||
    public Long getUserId() {
 | 
			
		||||
        return getLoginUser().getUserId();
 | 
			
		||||
        return LoginHelper.getUserId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取登录部门id
 | 
			
		||||
     */
 | 
			
		||||
    public Long getDeptId() {
 | 
			
		||||
        return getLoginUser().getDeptId();
 | 
			
		||||
        return LoginHelper.getDeptId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取登录用户名
 | 
			
		||||
     */
 | 
			
		||||
    public String getUsername() {
 | 
			
		||||
        return getLoginUser().getUsername();
 | 
			
		||||
        return LoginHelper.getUsername();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,134 +0,0 @@
 | 
			
		||||
package com.ruoyi.common.core.domain;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.http.HttpStatus;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 操作消息提醒
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@ApiModel("请求响应对象")
 | 
			
		||||
public class AjaxResult<T> {
 | 
			
		||||
 | 
			
		||||
	private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 状态码
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty("消息状态码")
 | 
			
		||||
	private int code;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回内容
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty("消息内容")
 | 
			
		||||
	private String msg;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 数据对象
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty("数据对象")
 | 
			
		||||
	private T data;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 初始化一个新创建的 AjaxResult 对象
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param code 状态码
 | 
			
		||||
	 * @param msg  返回内容
 | 
			
		||||
	 */
 | 
			
		||||
	public AjaxResult(int code, String msg) {
 | 
			
		||||
		this.code = code;
 | 
			
		||||
		this.msg = msg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回成功消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return 成功消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static AjaxResult<Void> success() {
 | 
			
		||||
		return AjaxResult.success("操作成功");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回成功数据
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return 成功消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static <T> AjaxResult<T> success(T data) {
 | 
			
		||||
		return AjaxResult.success("操作成功", data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回成功消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param msg 返回内容
 | 
			
		||||
	 * @return 成功消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static AjaxResult<Void> success(String msg) {
 | 
			
		||||
		return AjaxResult.success(msg, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回成功消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param msg  返回内容
 | 
			
		||||
	 * @param data 数据对象
 | 
			
		||||
	 * @return 成功消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static <T> AjaxResult<T> success(String msg, T data) {
 | 
			
		||||
		return new AjaxResult<>(HttpStatus.HTTP_OK, msg, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回错误消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @return
 | 
			
		||||
	 */
 | 
			
		||||
	public static AjaxResult<Void> error() {
 | 
			
		||||
		return AjaxResult.error("操作失败");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回错误消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param msg 返回内容
 | 
			
		||||
	 * @return 警告消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static AjaxResult<Void> error(String msg) {
 | 
			
		||||
		return AjaxResult.error(msg, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回错误消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param msg  返回内容
 | 
			
		||||
	 * @param data 数据对象
 | 
			
		||||
	 * @return 警告消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static <T> AjaxResult<T> error(String msg, T data) {
 | 
			
		||||
		return new AjaxResult<>(HttpStatus.HTTP_INTERNAL_ERROR, msg, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 返回错误消息
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param code 状态码
 | 
			
		||||
	 * @param msg  返回内容
 | 
			
		||||
	 * @return 警告消息
 | 
			
		||||
	 */
 | 
			
		||||
	public static AjaxResult<Void> error(int code, String msg) {
 | 
			
		||||
		return new AjaxResult<>(code, msg, null);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,9 +3,8 @@ package com.ruoyi.common.core.domain;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.FieldFill;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableField;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
@@ -19,52 +18,46 @@ import java.util.Map;
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
public class BaseEntity implements Serializable {
 | 
			
		||||
 | 
			
		||||
	private static final long serialVersionUID = 1L;
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 搜索值
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "搜索值")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private String searchValue;
 | 
			
		||||
    /**
 | 
			
		||||
     * 搜索值
 | 
			
		||||
     */
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private String searchValue;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 创建者
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "创建者")
 | 
			
		||||
	@TableField(fill = FieldFill.INSERT)
 | 
			
		||||
	private String createBy;
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建者
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(fill = FieldFill.INSERT)
 | 
			
		||||
    private String createBy;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 创建时间
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "创建时间")
 | 
			
		||||
	@TableField(fill = FieldFill.INSERT)
 | 
			
		||||
	private Date createTime;
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建时间
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(fill = FieldFill.INSERT)
 | 
			
		||||
    private Date createTime;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 更新者
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "更新者")
 | 
			
		||||
	@TableField(fill = FieldFill.INSERT_UPDATE)
 | 
			
		||||
	private String updateBy;
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新者
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(fill = FieldFill.INSERT_UPDATE)
 | 
			
		||||
    private String updateBy;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 更新时间
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "更新时间")
 | 
			
		||||
	@TableField(fill = FieldFill.INSERT_UPDATE)
 | 
			
		||||
	private Date updateTime;
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新时间
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(fill = FieldFill.INSERT_UPDATE)
 | 
			
		||||
    private Date updateTime;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 请求参数
 | 
			
		||||
	 */
 | 
			
		||||
	@JsonIgnore
 | 
			
		||||
	@ApiModelProperty(value = "请求参数")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Map<String, Object> params = new HashMap<>();
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求参数
 | 
			
		||||
     */
 | 
			
		||||
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Map<String, Object> params = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,112 @@
 | 
			
		||||
package com.ruoyi.common.core.domain;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
 | 
			
		||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
			
		||||
import com.ruoyi.common.exception.ServiceException;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.sql.SqlUtil;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 分页查询实体类
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class PageQuery implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 分页大小
 | 
			
		||||
     */
 | 
			
		||||
    private Integer pageSize;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 当前页数
 | 
			
		||||
     */
 | 
			
		||||
    private Integer pageNum;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 排序列
 | 
			
		||||
     */
 | 
			
		||||
    private String orderByColumn;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 排序的方向desc或者asc
 | 
			
		||||
     */
 | 
			
		||||
    private String isAsc;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 当前记录起始索引 默认值
 | 
			
		||||
     */
 | 
			
		||||
    public static final int DEFAULT_PAGE_NUM = 1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 每页显示记录数 默认值 默认查全部
 | 
			
		||||
     */
 | 
			
		||||
    public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
 | 
			
		||||
 | 
			
		||||
    public <T> Page<T> build() {
 | 
			
		||||
        Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
 | 
			
		||||
        Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
 | 
			
		||||
        if (pageNum <= 0) {
 | 
			
		||||
            pageNum = DEFAULT_PAGE_NUM;
 | 
			
		||||
        }
 | 
			
		||||
        Page<T> page = new Page<>(pageNum, pageSize);
 | 
			
		||||
        List<OrderItem> orderItems = buildOrderItem();
 | 
			
		||||
        if (CollUtil.isNotEmpty(orderItems)) {
 | 
			
		||||
            page.addOrder(orderItems);
 | 
			
		||||
        }
 | 
			
		||||
        return page;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构建排序
 | 
			
		||||
     *
 | 
			
		||||
     * 支持的用法如下:
 | 
			
		||||
     * {isAsc:"asc",orderByColumn:"id"} order by id asc
 | 
			
		||||
     * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
 | 
			
		||||
     * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
 | 
			
		||||
     * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
 | 
			
		||||
     */
 | 
			
		||||
    private List<OrderItem> buildOrderItem() {
 | 
			
		||||
        if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
 | 
			
		||||
        orderBy = StringUtils.toUnderScoreCase(orderBy);
 | 
			
		||||
 | 
			
		||||
        // 兼容前端排序类型
 | 
			
		||||
        isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"});
 | 
			
		||||
 | 
			
		||||
        String[] orderByArr = orderBy.split(StringUtils.SEPARATOR);
 | 
			
		||||
        String[] isAscArr = isAsc.split(StringUtils.SEPARATOR);
 | 
			
		||||
        if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) {
 | 
			
		||||
            throw new ServiceException("排序参数有误");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<OrderItem> list = new ArrayList<>();
 | 
			
		||||
        // 每个字段各自排序
 | 
			
		||||
        for (int i = 0; i < orderByArr.length; i++) {
 | 
			
		||||
            String orderByStr = orderByArr[i];
 | 
			
		||||
            String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i];
 | 
			
		||||
            if ("asc".equals(isAscStr)) {
 | 
			
		||||
                list.add(OrderItem.asc(orderByStr));
 | 
			
		||||
            } else if ("desc".equals(isAscStr)) {
 | 
			
		||||
                list.add(OrderItem.desc(orderByStr));
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new ServiceException("排序参数有误");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										107
									
								
								ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
package com.ruoyi.common.core.domain;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.constant.HttpStatus;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 响应信息主体
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
public class R<T> implements Serializable {
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 成功
 | 
			
		||||
     */
 | 
			
		||||
    public static final int SUCCESS = 200;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 失败
 | 
			
		||||
     */
 | 
			
		||||
    public static final int FAIL = 500;
 | 
			
		||||
 | 
			
		||||
    private int code;
 | 
			
		||||
 | 
			
		||||
    private String msg;
 | 
			
		||||
 | 
			
		||||
    private T data;
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> ok() {
 | 
			
		||||
        return restResult(null, SUCCESS, "操作成功");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> ok(T data) {
 | 
			
		||||
        return restResult(data, SUCCESS, "操作成功");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> ok(String msg) {
 | 
			
		||||
        return restResult(null, SUCCESS, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> ok(String msg, T data) {
 | 
			
		||||
        return restResult(data, SUCCESS, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> fail() {
 | 
			
		||||
        return restResult(null, FAIL, "操作失败");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> fail(String msg) {
 | 
			
		||||
        return restResult(null, FAIL, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> fail(T data) {
 | 
			
		||||
        return restResult(data, FAIL, "操作失败");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> fail(String msg, T data) {
 | 
			
		||||
        return restResult(data, FAIL, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> R<T> fail(int code, String msg) {
 | 
			
		||||
        return restResult(null, code, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回警告消息
 | 
			
		||||
     *
 | 
			
		||||
     * @param msg 返回内容
 | 
			
		||||
     * @return 警告消息
 | 
			
		||||
     */
 | 
			
		||||
    public static <T> R<T> warn(String msg) {
 | 
			
		||||
        return restResult(null, HttpStatus.WARN, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 返回警告消息
 | 
			
		||||
     *
 | 
			
		||||
     * @param msg 返回内容
 | 
			
		||||
     * @param data 数据对象
 | 
			
		||||
     * @return 警告消息
 | 
			
		||||
     */
 | 
			
		||||
    public static <T> R<T> warn(String msg, T data) {
 | 
			
		||||
        return restResult(data, HttpStatus.WARN, msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static <T> R<T> restResult(T data, int code, String msg) {
 | 
			
		||||
        R<T> r = new R<>();
 | 
			
		||||
        r.setCode(code);
 | 
			
		||||
        r.setData(data);
 | 
			
		||||
        r.setMsg(msg);
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> Boolean isError(R<T> ret) {
 | 
			
		||||
        return !isSuccess(ret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T> Boolean isSuccess(R<T> ret) {
 | 
			
		||||
        return R.SUCCESS == ret.getCode();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
package com.ruoyi.common.core.domain;
 | 
			
		||||
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableField;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -17,29 +15,25 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
public class TreeEntity extends BaseEntity {
 | 
			
		||||
public class TreeEntity<T> extends BaseEntity {
 | 
			
		||||
 | 
			
		||||
	private static final long serialVersionUID = 1L;
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 父菜单名称
 | 
			
		||||
	 */
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	@ApiModelProperty(value = "父菜单名称")
 | 
			
		||||
	private String parentName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 父菜单名称
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private String parentName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 父菜单ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "父菜单ID")
 | 
			
		||||
	private Long parentId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 父菜单ID
 | 
			
		||||
     */
 | 
			
		||||
    private Long parentId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 子部门
 | 
			
		||||
	 */
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	@ApiModelProperty(value = "子部门")
 | 
			
		||||
	private List<?> children = new ArrayList<>();
 | 
			
		||||
    /**
 | 
			
		||||
     * 子部门
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private List<T> children = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
package com.ruoyi.common.core.domain;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysDept;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysMenu;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Treeselect树结构实体类
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@ApiModel("树结构实体类")
 | 
			
		||||
public class TreeSelect implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 节点ID
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "节点ID")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 节点名称
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "节点名称")
 | 
			
		||||
    private String label;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 子节点
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "子节点")
 | 
			
		||||
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
 | 
			
		||||
    private List<TreeSelect> children;
 | 
			
		||||
 | 
			
		||||
    public TreeSelect(SysDept dept) {
 | 
			
		||||
        this.id = dept.getDeptId();
 | 
			
		||||
        this.label = dept.getDeptName();
 | 
			
		||||
        this.children = dept.getChildren()
 | 
			
		||||
                .stream()
 | 
			
		||||
                .map(d -> new TreeSelect((SysDept) d))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TreeSelect(SysMenu menu) {
 | 
			
		||||
        this.id = menu.getMenuId();
 | 
			
		||||
        this.label = menu.getMenuName();
 | 
			
		||||
        this.children = menu.getChildren()
 | 
			
		||||
                .stream()
 | 
			
		||||
                .map(d -> new TreeSelect((SysMenu) d))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.dto;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 角色
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
public class RoleDTO implements Serializable {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色ID
 | 
			
		||||
     */
 | 
			
		||||
    private Long roleId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色名称
 | 
			
		||||
     */
 | 
			
		||||
    private String roleName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色权限
 | 
			
		||||
     */
 | 
			
		||||
    private String roleKey;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
 | 
			
		||||
     */
 | 
			
		||||
    private String dataScope;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,60 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.dto;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 当前在线会话
 | 
			
		||||
 *
 | 
			
		||||
 * @author ruoyi
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
public class UserOnlineDTO implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 会话编号
 | 
			
		||||
     */
 | 
			
		||||
    private String tokenId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门名称
 | 
			
		||||
     */
 | 
			
		||||
    private String deptName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名称
 | 
			
		||||
     */
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录IP地址
 | 
			
		||||
     */
 | 
			
		||||
    private String ipaddr;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录地址
 | 
			
		||||
     */
 | 
			
		||||
    private String loginLocation;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 浏览器类型
 | 
			
		||||
     */
 | 
			
		||||
    private String browser;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 操作系统
 | 
			
		||||
     */
 | 
			
		||||
    private String os;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录时间
 | 
			
		||||
     */
 | 
			
		||||
    private Long loginTime;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -4,14 +4,12 @@ import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableLogic;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.ruoyi.common.core.domain.TreeEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.Email;
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -22,72 +20,61 @@ import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_dept")
 | 
			
		||||
@ApiModel("部门业务对象")
 | 
			
		||||
public class SysDept extends TreeEntity {
 | 
			
		||||
	private static final long serialVersionUID = 1L;
 | 
			
		||||
public class SysDept extends TreeEntity<SysDept> {
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门id")
 | 
			
		||||
	@TableId(value = "dept_id")
 | 
			
		||||
	private Long deptId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门ID
 | 
			
		||||
     */
 | 
			
		||||
    @TableId(value = "dept_id")
 | 
			
		||||
    private Long deptId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门名称
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门名称")
 | 
			
		||||
	@NotBlank(message = "部门名称不能为空")
 | 
			
		||||
	@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
 | 
			
		||||
	private String deptName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门名称
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "部门名称不能为空")
 | 
			
		||||
    @Size(min = 0, max = 30, message = "部门名称长度不能超过{max}个字符")
 | 
			
		||||
    private String deptName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 显示顺序
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "显示顺序")
 | 
			
		||||
	@NotBlank(message = "显示顺序不能为空")
 | 
			
		||||
	private String orderNum;
 | 
			
		||||
    /**
 | 
			
		||||
     * 显示顺序
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "显示顺序不能为空")
 | 
			
		||||
    private Integer orderNum;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 负责人
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "负责人")
 | 
			
		||||
	private String leader;
 | 
			
		||||
    /**
 | 
			
		||||
     * 负责人
 | 
			
		||||
     */
 | 
			
		||||
    private String leader;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 联系电话
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "联系电话")
 | 
			
		||||
	@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
 | 
			
		||||
	private String phone;
 | 
			
		||||
    /**
 | 
			
		||||
     * 联系电话
 | 
			
		||||
     */
 | 
			
		||||
    @Size(min = 0, max = 11, message = "联系电话长度不能超过{max}个字符")
 | 
			
		||||
    private String phone;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 邮箱
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "邮箱")
 | 
			
		||||
	@Email(message = "邮箱格式不正确")
 | 
			
		||||
	@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
 | 
			
		||||
	private String email;
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱
 | 
			
		||||
     */
 | 
			
		||||
    @Email(message = "邮箱格式不正确")
 | 
			
		||||
    @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
 | 
			
		||||
    private String email;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门状态:0正常,1停用
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门状态:0正常,1停用")
 | 
			
		||||
	private String status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门状态:0正常,1停用
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "删除标志(0代表存在 2代表删除)")
 | 
			
		||||
	@TableLogic
 | 
			
		||||
	private String delFlag;
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
     */
 | 
			
		||||
    @TableLogic
 | 
			
		||||
    private String delFlag;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 祖级列表
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "祖级列表")
 | 
			
		||||
	private String ancestors;
 | 
			
		||||
    /**
 | 
			
		||||
     * 祖级列表
 | 
			
		||||
     */
 | 
			
		||||
    private String ancestors;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,8 @@ import com.ruoyi.common.annotation.ExcelDictFormat;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.convert.ExcelDictConvert;
 | 
			
		||||
import com.ruoyi.common.core.domain.BaseEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
@@ -25,91 +22,79 @@ import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_dict_data")
 | 
			
		||||
@ExcelIgnoreUnannotated
 | 
			
		||||
@ApiModel("字典数据业务对象")
 | 
			
		||||
public class SysDictData extends BaseEntity {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典编码
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典编码")
 | 
			
		||||
	@ExcelProperty(value = "字典编码")
 | 
			
		||||
	@TableId(value = "dict_code")
 | 
			
		||||
	private Long dictCode;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典编码
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典编码")
 | 
			
		||||
    @TableId(value = "dict_code")
 | 
			
		||||
    private Long dictCode;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典排序
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典排序")
 | 
			
		||||
	@ExcelProperty(value = "字典排序")
 | 
			
		||||
	private Long dictSort;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典排序
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典排序")
 | 
			
		||||
    private Integer dictSort;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典标签
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典标签")
 | 
			
		||||
	@ExcelProperty(value = "字典标签")
 | 
			
		||||
	@NotBlank(message = "字典标签不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
 | 
			
		||||
	private String dictLabel;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典标签
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典标签")
 | 
			
		||||
    @NotBlank(message = "字典标签不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "字典标签长度不能超过{max}个字符")
 | 
			
		||||
    private String dictLabel;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典键值
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典键值")
 | 
			
		||||
	@ExcelProperty(value = "字典键值")
 | 
			
		||||
	@NotBlank(message = "字典键值不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
 | 
			
		||||
	private String dictValue;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典键值
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典键值")
 | 
			
		||||
    @NotBlank(message = "字典键值不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "字典键值长度不能超过{max}个字符")
 | 
			
		||||
    private String dictValue;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典类型
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典类型")
 | 
			
		||||
	@ExcelProperty(value = "字典类型")
 | 
			
		||||
	@NotBlank(message = "字典类型不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
 | 
			
		||||
	private String dictType;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典类型")
 | 
			
		||||
    @NotBlank(message = "字典类型不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "字典类型长度不能超过{max}个字符")
 | 
			
		||||
    private String dictType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 样式属性(其他样式扩展)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "样式属性(其他样式扩展)")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
 | 
			
		||||
	private String cssClass;
 | 
			
		||||
    /**
 | 
			
		||||
     * 样式属性(其他样式扩展)
 | 
			
		||||
     */
 | 
			
		||||
    @Size(min = 0, max = 100, message = "样式属性长度不能超过{max}个字符")
 | 
			
		||||
    private String cssClass;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 表格字典样式
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "表格字典样式")
 | 
			
		||||
	private String listClass;
 | 
			
		||||
    /**
 | 
			
		||||
     * 表格字典样式
 | 
			
		||||
     */
 | 
			
		||||
    private String listClass;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 是否默认(Y是 N否)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "是否默认(Y是 N否)")
 | 
			
		||||
	@ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class)
 | 
			
		||||
	@ExcelDictFormat(dictType = "sys_yes_no")
 | 
			
		||||
	private String isDefault;
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否默认(Y是 N否)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(dictType = "sys_yes_no")
 | 
			
		||||
    private String isDefault;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 状态(0正常 1停用)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "状态(0正常 1停用)")
 | 
			
		||||
	@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
 | 
			
		||||
	@ExcelDictFormat(dictType = "sys_normal_disable")
 | 
			
		||||
	private String status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态(0正常 1停用)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(dictType = "sys_normal_disable")
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 备注
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "备注")
 | 
			
		||||
	private String remark;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
	public boolean getDefault() {
 | 
			
		||||
		return UserConstants.YES.equals(this.isDefault);
 | 
			
		||||
	}
 | 
			
		||||
    public boolean getDefault() {
 | 
			
		||||
        return UserConstants.YES.equals(this.isDefault);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,13 +7,11 @@ import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.ruoyi.common.annotation.ExcelDictFormat;
 | 
			
		||||
import com.ruoyi.common.convert.ExcelDictConvert;
 | 
			
		||||
import com.ruoyi.common.core.domain.BaseEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.Pattern;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -24,50 +22,44 @@ import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_dict_type")
 | 
			
		||||
@ExcelIgnoreUnannotated
 | 
			
		||||
@ApiModel("字典类型业务对象")
 | 
			
		||||
public class SysDictType extends BaseEntity {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典主键
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典主键")
 | 
			
		||||
	@ExcelProperty(value = "字典主键")
 | 
			
		||||
	@TableId(value = "dict_id")
 | 
			
		||||
	private Long dictId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典主键
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典主键")
 | 
			
		||||
    @TableId(value = "dict_id")
 | 
			
		||||
    private Long dictId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典名称
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典名称")
 | 
			
		||||
	@ExcelProperty(value = "字典名称")
 | 
			
		||||
	@NotBlank(message = "字典名称不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
 | 
			
		||||
	private String dictName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典名称
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典名称")
 | 
			
		||||
    @NotBlank(message = "字典名称不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "字典类型名称长度不能超过{max}个字符")
 | 
			
		||||
    private String dictName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 字典类型
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "字典类型")
 | 
			
		||||
	@ExcelProperty(value = "字典类型")
 | 
			
		||||
	@NotBlank(message = "字典类型不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
 | 
			
		||||
	private String dictType;
 | 
			
		||||
    /**
 | 
			
		||||
     * 字典类型
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "字典类型")
 | 
			
		||||
    @NotBlank(message = "字典类型不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符")
 | 
			
		||||
    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
 | 
			
		||||
    private String dictType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 状态(0正常 1停用)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "状态(0正常 1停用)")
 | 
			
		||||
	@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
 | 
			
		||||
	@ExcelDictFormat(dictType = "sys_normal_disable")
 | 
			
		||||
	private String status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 状态(0正常 1停用)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(dictType = "sys_normal_disable")
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 备注
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "备注")
 | 
			
		||||
	private String remark;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,13 @@ package com.ruoyi.common.core.domain.entity;
 | 
			
		||||
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
			
		||||
import com.ruoyi.common.core.domain.TreeEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -20,101 +19,86 @@ import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_menu")
 | 
			
		||||
@ApiModel("菜单权限业务对象")
 | 
			
		||||
public class SysMenu extends TreeEntity {
 | 
			
		||||
public class SysMenu extends TreeEntity<SysMenu> {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单ID")
 | 
			
		||||
	@TableId(value = "menu_id")
 | 
			
		||||
	private Long menuId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单ID
 | 
			
		||||
     */
 | 
			
		||||
    @TableId(value = "menu_id")
 | 
			
		||||
    private Long menuId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单名称
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单名称")
 | 
			
		||||
	@NotBlank(message = "菜单名称不能为空")
 | 
			
		||||
	@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
 | 
			
		||||
	private String menuName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单名称
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "菜单名称不能为空")
 | 
			
		||||
    @Size(min = 0, max = 50, message = "菜单名称长度不能超过{max}个字符")
 | 
			
		||||
    private String menuName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 显示顺序
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "显示顺序")
 | 
			
		||||
	@NotBlank(message = "显示顺序不能为空")
 | 
			
		||||
	private String orderNum;
 | 
			
		||||
    /**
 | 
			
		||||
     * 显示顺序
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "显示顺序不能为空")
 | 
			
		||||
    private Integer orderNum;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 路由地址
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "路由地址")
 | 
			
		||||
	@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
 | 
			
		||||
	private String path;
 | 
			
		||||
    /**
 | 
			
		||||
     * 路由地址
 | 
			
		||||
     */
 | 
			
		||||
    @Size(min = 0, max = 200, message = "路由地址不能超过{max}个字符")
 | 
			
		||||
    private String path;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 组件路径
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "组件路径")
 | 
			
		||||
	@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
 | 
			
		||||
	private String component;
 | 
			
		||||
    /**
 | 
			
		||||
     * 组件路径
 | 
			
		||||
     */
 | 
			
		||||
    @Size(min = 0, max = 200, message = "组件路径不能超过{max}个字符")
 | 
			
		||||
    private String component;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 路由参数
 | 
			
		||||
     */
 | 
			
		||||
	@ApiModelProperty(value = "路由参数")
 | 
			
		||||
    private String query;
 | 
			
		||||
    private String queryParam;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 是否为外链(0是 1否)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "是否为外链(0是 1否)")
 | 
			
		||||
	private String isFrame;
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否为外链(0是 1否)
 | 
			
		||||
     */
 | 
			
		||||
    private String isFrame;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 是否缓存(0缓存 1不缓存)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "是否缓存(0缓存 1不缓存)")
 | 
			
		||||
	private String isCache;
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否缓存(0缓存 1不缓存)
 | 
			
		||||
     */
 | 
			
		||||
    private String isCache;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 类型(M目录 C菜单 F按钮)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "类型(M目录 C菜单 F按钮)")
 | 
			
		||||
	@NotBlank(message = "菜单类型不能为空")
 | 
			
		||||
	private String menuType;
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型(M目录 C菜单 F按钮)
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "菜单类型不能为空")
 | 
			
		||||
    private String menuType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 显示状态(0显示 1隐藏)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "显示状态(0显示 1隐藏)")
 | 
			
		||||
	private String visible;
 | 
			
		||||
    /**
 | 
			
		||||
     * 显示状态(0显示 1隐藏)
 | 
			
		||||
     */
 | 
			
		||||
    private String visible;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单状态(0显示 1隐藏)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单状态(0显示 1隐藏)")
 | 
			
		||||
	private String status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单状态(0正常 1停用)
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 权限字符串
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "权限字符串")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
 | 
			
		||||
	private String perms;
 | 
			
		||||
    /**
 | 
			
		||||
     * 权限字符串
 | 
			
		||||
     */
 | 
			
		||||
    @JsonInclude(JsonInclude.Include.NON_NULL)
 | 
			
		||||
    @Size(min = 0, max = 100, message = "权限标识长度不能超过{max}个字符")
 | 
			
		||||
    private String perms;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单图标
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单图标")
 | 
			
		||||
	private String icon;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单图标
 | 
			
		||||
     */
 | 
			
		||||
    private String icon;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 备注
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "备注")
 | 
			
		||||
	private String remark;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,15 +7,15 @@ import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableLogic;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import com.ruoyi.common.annotation.ExcelDictFormat;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.convert.ExcelDictConvert;
 | 
			
		||||
import com.ruoyi.common.core.domain.BaseEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -27,118 +27,98 @@ import javax.validation.constraints.Size;
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_role")
 | 
			
		||||
@ExcelIgnoreUnannotated
 | 
			
		||||
public class SysRole extends BaseEntity {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色ID")
 | 
			
		||||
	@ExcelProperty(value = "角色序号")
 | 
			
		||||
	@TableId(value = "role_id")
 | 
			
		||||
	private Long roleId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "角色序号")
 | 
			
		||||
    @TableId(value = "role_id")
 | 
			
		||||
    private Long roleId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色名称
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色名称")
 | 
			
		||||
	@ExcelProperty(value = "角色名称")
 | 
			
		||||
	@NotBlank(message = "角色名称不能为空")
 | 
			
		||||
	@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
 | 
			
		||||
	private String roleName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色名称
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "角色名称")
 | 
			
		||||
    @NotBlank(message = "角色名称不能为空")
 | 
			
		||||
    @Size(min = 0, max = 30, message = "角色名称长度不能超过{max}个字符")
 | 
			
		||||
    private String roleName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色权限
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色权限")
 | 
			
		||||
	@ExcelProperty(value = "角色权限")
 | 
			
		||||
	@NotBlank(message = "权限字符不能为空")
 | 
			
		||||
	@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
 | 
			
		||||
	private String roleKey;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色权限
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "角色权限")
 | 
			
		||||
    @NotBlank(message = "权限字符不能为空")
 | 
			
		||||
    @Size(min = 0, max = 100, message = "权限字符长度不能超过{max}个字符")
 | 
			
		||||
    private String roleKey;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色排序
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色排序")
 | 
			
		||||
	@ExcelProperty(value = "角色排序")
 | 
			
		||||
	@NotBlank(message = "显示顺序不能为空")
 | 
			
		||||
	private String roleSort;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色排序
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "角色排序")
 | 
			
		||||
    @NotNull(message = "显示顺序不能为空")
 | 
			
		||||
    private Integer roleSort;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)")
 | 
			
		||||
	@ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class)
 | 
			
		||||
	@ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
 | 
			
		||||
	private String dataScope;
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
 | 
			
		||||
    private String dataScope;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)")
 | 
			
		||||
	private boolean menuCheckStrictly;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean menuCheckStrictly;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )")
 | 
			
		||||
	private boolean deptCheckStrictly;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean deptCheckStrictly;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色状态(0正常 1停用)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色状态(0正常 1停用)")
 | 
			
		||||
	@ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
 | 
			
		||||
	@ExcelDictFormat(dictType = "sys_common_status")
 | 
			
		||||
	private String status;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色状态(0正常 1停用)
 | 
			
		||||
     */
 | 
			
		||||
    @ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class)
 | 
			
		||||
    @ExcelDictFormat(dictType = "sys_normal_disable")
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "删除标志(0代表存在 2代表删除)")
 | 
			
		||||
	@TableLogic
 | 
			
		||||
	private String delFlag;
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
     */
 | 
			
		||||
    @TableLogic
 | 
			
		||||
    private String delFlag;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 备注
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "备注")
 | 
			
		||||
	private String remark;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户是否存在此角色标识 默认不存在
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户是否存在此角色标识 默认不存在")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private boolean flag = false;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户是否存在此角色标识 默认不存在
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private boolean flag = false;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 菜单组
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "菜单组")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Long[] menuIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 菜单组
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Long[] menuIds;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门组(数据权限)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门组(数据权限)")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Long[] deptIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门组(数据权限)
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Long[] deptIds;
 | 
			
		||||
 | 
			
		||||
	public SysRole(Long roleId) {
 | 
			
		||||
		this.roleId = roleId;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@ApiModelProperty(value = "是否管理员")
 | 
			
		||||
	public boolean isAdmin() {
 | 
			
		||||
		return isAdmin(this.roleId);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static boolean isAdmin(Long roleId) {
 | 
			
		||||
		return roleId != null && 1L == roleId;
 | 
			
		||||
	}
 | 
			
		||||
    public SysRole(Long roleId) {
 | 
			
		||||
        this.roleId = roleId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isAdmin() {
 | 
			
		||||
        return UserConstants.ADMIN_ID.equals(this.roleId);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,14 @@ package com.ruoyi.common.core.domain.entity;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.*;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonProperty;
 | 
			
		||||
import com.ruoyi.common.annotation.Sensitive;
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import com.ruoyi.common.core.domain.BaseEntity;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import com.ruoyi.common.enums.SensitiveStrategy;
 | 
			
		||||
import com.ruoyi.common.xss.Xss;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.Email;
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
@@ -26,159 +27,143 @@ import java.util.List;
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@TableName("sys_user")
 | 
			
		||||
@ApiModel("用户信息业务对象")
 | 
			
		||||
public class SysUser extends BaseEntity {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户ID")
 | 
			
		||||
	@TableId(value = "user_id")
 | 
			
		||||
	private Long userId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    @TableId(value = "user_id")
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门ID")
 | 
			
		||||
	private Long deptId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门ID
 | 
			
		||||
     */
 | 
			
		||||
    private Long deptId;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户账号
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户账号")
 | 
			
		||||
	@NotBlank(message = "用户账号不能为空")
 | 
			
		||||
	@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
 | 
			
		||||
	private String userName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户账号
 | 
			
		||||
     */
 | 
			
		||||
    @Xss(message = "用户账号不能包含脚本字符")
 | 
			
		||||
    @NotBlank(message = "用户账号不能为空")
 | 
			
		||||
    @Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
 | 
			
		||||
    private String userName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户昵称
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户昵称")
 | 
			
		||||
	@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
 | 
			
		||||
	private String nickName;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户昵称
 | 
			
		||||
     */
 | 
			
		||||
    @Xss(message = "用户昵称不能包含脚本字符")
 | 
			
		||||
    @NotBlank(message = "用户昵称不能为空")
 | 
			
		||||
    @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
 | 
			
		||||
    private String nickName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户邮箱
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户邮箱")
 | 
			
		||||
	@Email(message = "邮箱格式不正确")
 | 
			
		||||
	@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
 | 
			
		||||
	private String email;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户类型(sys_user系统用户)
 | 
			
		||||
     */
 | 
			
		||||
    private String userType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 手机号码
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "手机号码")
 | 
			
		||||
	private String phonenumber;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户邮箱
 | 
			
		||||
     */
 | 
			
		||||
    @Sensitive(strategy = SensitiveStrategy.EMAIL)
 | 
			
		||||
    @Email(message = "邮箱格式不正确")
 | 
			
		||||
    @Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
 | 
			
		||||
    private String email;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户性别
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户性别")
 | 
			
		||||
	private String sex;
 | 
			
		||||
    /**
 | 
			
		||||
     * 手机号码
 | 
			
		||||
     */
 | 
			
		||||
    @Sensitive(strategy = SensitiveStrategy.PHONE)
 | 
			
		||||
    private String phonenumber;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 用户头像
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "用户头像")
 | 
			
		||||
	private String avatar;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户性别
 | 
			
		||||
     */
 | 
			
		||||
    private String sex;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 密码
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "密码")
 | 
			
		||||
	@TableField(
 | 
			
		||||
			insertStrategy = FieldStrategy.NOT_EMPTY,
 | 
			
		||||
			updateStrategy = FieldStrategy.NOT_EMPTY,
 | 
			
		||||
			whereStrategy = FieldStrategy.NOT_EMPTY
 | 
			
		||||
	)
 | 
			
		||||
	private String password;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户头像
 | 
			
		||||
     */
 | 
			
		||||
    private String avatar;
 | 
			
		||||
 | 
			
		||||
	@JsonIgnore
 | 
			
		||||
	@JsonProperty
 | 
			
		||||
	public String getPassword() {
 | 
			
		||||
		return password;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(
 | 
			
		||||
        insertStrategy = FieldStrategy.NOT_EMPTY,
 | 
			
		||||
        updateStrategy = FieldStrategy.NOT_EMPTY,
 | 
			
		||||
        whereStrategy = FieldStrategy.NOT_EMPTY
 | 
			
		||||
    )
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 帐号状态(0正常 1停用)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "帐号状态(0正常 1停用)")
 | 
			
		||||
	private String status;
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @JsonProperty
 | 
			
		||||
    public String getPassword() {
 | 
			
		||||
        return password;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "删除标志(0代表存在 2代表删除)")
 | 
			
		||||
	@TableLogic
 | 
			
		||||
	private String delFlag;
 | 
			
		||||
    /**
 | 
			
		||||
     * 帐号状态(0正常 1停用)
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 最后登录IP
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "最后登录IP")
 | 
			
		||||
	private String loginIp;
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除标志(0代表存在 2代表删除)
 | 
			
		||||
     */
 | 
			
		||||
    @TableLogic
 | 
			
		||||
    private String delFlag;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 最后登录时间
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "最后登录时间")
 | 
			
		||||
	private Date loginDate;
 | 
			
		||||
    /**
 | 
			
		||||
     * 最后登录IP
 | 
			
		||||
     */
 | 
			
		||||
    private String loginIp;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 备注
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "备注")
 | 
			
		||||
	private String remark;
 | 
			
		||||
    /**
 | 
			
		||||
     * 最后登录时间
 | 
			
		||||
     */
 | 
			
		||||
    private Date loginDate;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 部门对象
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "部门对象")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private SysDept dept;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色对象
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色对象")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private List<SysRole> roles;
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门对象
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private SysDept dept;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色组
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色组")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Long[] roleIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色对象
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private List<SysRole> roles;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 岗位组
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "岗位组")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Long[] postIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 角色组
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Long[] roleIds;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 角色ID
 | 
			
		||||
	 */
 | 
			
		||||
	@ApiModelProperty(value = "角色ID")
 | 
			
		||||
	@TableField(exist = false)
 | 
			
		||||
	private Long roleId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 岗位组
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Long[] postIds;
 | 
			
		||||
 | 
			
		||||
	public SysUser(Long userId) {
 | 
			
		||||
		this.userId = userId;
 | 
			
		||||
	}
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据权限 当前角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @TableField(exist = false)
 | 
			
		||||
    private Long roleId;
 | 
			
		||||
 | 
			
		||||
	@ApiModelProperty(value = "是否管理员")
 | 
			
		||||
	public boolean isAdmin() {
 | 
			
		||||
		return isAdmin(this.userId);
 | 
			
		||||
	}
 | 
			
		||||
    public SysUser(Long userId) {
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	public static boolean isAdmin(Long userId) {
 | 
			
		||||
		return userId != null && 1L == userId;
 | 
			
		||||
	}
 | 
			
		||||
    public boolean isAdmin() {
 | 
			
		||||
        return UserConstants.ADMIN_ID.equals(this.userId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.event;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 登录事件
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class LogininforEvent implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户账号
 | 
			
		||||
     */
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录状态 0成功 1失败
 | 
			
		||||
     */
 | 
			
		||||
    private String status;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 提示消息
 | 
			
		||||
     */
 | 
			
		||||
    private String message;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 请求体
 | 
			
		||||
     */
 | 
			
		||||
    private HttpServletRequest request;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 其他参数
 | 
			
		||||
     */
 | 
			
		||||
    private Object[] args;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,22 +1,18 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.dto;
 | 
			
		||||
package com.ruoyi.common.core.domain.event;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用操作日志实体
 | 
			
		||||
 * 操作日志事件
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
public class OperLogDTO implements Serializable {
 | 
			
		||||
public class OperLogEvent implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.Email;
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 邮箱登录对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class EmailLoginBody {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{user.email.not.blank}")
 | 
			
		||||
    @Email(message = "{user.email.not.valid}")
 | 
			
		||||
    private String email;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱code
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{email.code.not.blank}")
 | 
			
		||||
    private String emailCode;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +1,42 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户登录对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
@ApiModel("用户登录对象")
 | 
			
		||||
public class LoginBody {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "用户名")
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户密码
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "用户密码")
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 验证码
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "验证码")
 | 
			
		||||
    private String code;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 唯一标识
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty(value = "唯一标识")
 | 
			
		||||
    private String uuid = "";
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.constant.UserConstants;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.hibernate.validator.constraints.Length;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户登录对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class LoginBody {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{user.username.not.blank}")
 | 
			
		||||
    @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户密码
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{user.password.not.blank}")
 | 
			
		||||
    @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 验证码
 | 
			
		||||
     */
 | 
			
		||||
    private String code;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 唯一标识
 | 
			
		||||
     */
 | 
			
		||||
    private String uuid;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,11 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysUser;
 | 
			
		||||
import com.ruoyi.common.core.domain.dto.RoleDTO;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.experimental.Accessors;
 | 
			
		||||
import org.springframework.security.core.GrantedAuthority;
 | 
			
		||||
import org.springframework.security.core.userdetails.UserDetails;
 | 
			
		||||
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -19,8 +16,7 @@ import java.util.Set;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@Accessors(chain = true)
 | 
			
		||||
public class LoginUser implements UserDetails {
 | 
			
		||||
public class LoginUser implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
@@ -34,11 +30,21 @@ public class LoginUser implements UserDetails {
 | 
			
		||||
     */
 | 
			
		||||
    private Long deptId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门名
 | 
			
		||||
     */
 | 
			
		||||
    private String deptName;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户唯一标识
 | 
			
		||||
     */
 | 
			
		||||
    private String token;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户类型
 | 
			
		||||
     */
 | 
			
		||||
    private String userType;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 登录时间
 | 
			
		||||
     */
 | 
			
		||||
@@ -70,76 +76,41 @@ public class LoginUser implements UserDetails {
 | 
			
		||||
    private String os;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 权限列表
 | 
			
		||||
     * 菜单权限
 | 
			
		||||
     */
 | 
			
		||||
    private Set<String> permissions;
 | 
			
		||||
    private Set<String> menuPermission;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户信息
 | 
			
		||||
     * 角色权限
 | 
			
		||||
     */
 | 
			
		||||
    private SysUser user;
 | 
			
		||||
 | 
			
		||||
    public LoginUser(SysUser user, Set<String> permissions) {
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this.permissions = permissions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions) {
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
        this.deptId = deptId;
 | 
			
		||||
        this.user = user;
 | 
			
		||||
        this.permissions = permissions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getPassword() {
 | 
			
		||||
        return user.getPassword();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getUsername() {
 | 
			
		||||
        return user.getUserName();
 | 
			
		||||
    }
 | 
			
		||||
    private Set<String> rolePermission;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 账户是否未过期,过期无法验证
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isAccountNonExpired() {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 指定用户是否解锁,锁定的用户无法进行身份验证
 | 
			
		||||
     * 角色对象
 | 
			
		||||
     */
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isAccountNonLocked() {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    private List<RoleDTO> roles;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
 | 
			
		||||
     * 数据权限 当前角色ID
 | 
			
		||||
     */
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isCredentialsNonExpired() {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    private Long roleId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否可用 ,禁用的用户不能身份验证
 | 
			
		||||
     * 获取登录id
 | 
			
		||||
     */
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isEnabled() {
 | 
			
		||||
        return true;
 | 
			
		||||
    public String getLoginId() {
 | 
			
		||||
        if (userType == null) {
 | 
			
		||||
            throw new IllegalArgumentException("用户类型不能为空");
 | 
			
		||||
        }
 | 
			
		||||
        if (userId == null) {
 | 
			
		||||
            throw new IllegalArgumentException("用户ID不能为空");
 | 
			
		||||
        }
 | 
			
		||||
        return userType + ":" + userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Collection<? extends GrantedAuthority> getAuthorities() {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,17 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户注册对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@ApiModel("用户注册对象")
 | 
			
		||||
public class RegisterBody extends LoginBody {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户注册对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class RegisterBody extends LoginBody {
 | 
			
		||||
 | 
			
		||||
    private String userType;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package com.ruoyi.common.core.domain.model;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 短信登录对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class SmsLoginBody {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 手机号
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{user.phonenumber.not.blank}")
 | 
			
		||||
    private String phonenumber;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 短信code
 | 
			
		||||
     */
 | 
			
		||||
    @NotBlank(message = "{sms.code.not.blank}")
 | 
			
		||||
    private String smsCode;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user