Compare commits
	
		
			446 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8d6ae203a0 | ||
| 
						 | 
					4353479a5c | ||
| 
						 | 
					34d7687f9e | ||
| 
						 | 
					b1dc3cf4af | ||
| 
						 | 
					6a58b95933 | ||
| 
						 | 
					d3badfd02b | ||
| 
						 | 
					0098be057b | ||
| 
						 | 
					6f972aa515 | ||
| 
						 | 
					7407ba6313 | ||
| 
						 | 
					1c79de207b | ||
| 
						 | 
					257c79db92 | ||
| 
						 | 
					9d1934a308 | ||
| 
						 | 
					d70f959902 | ||
| 
						 | 
					e4d810222f | ||
| 
						 | 
					bc1af4ae07 | ||
| 
						 | 
					6e688ef43f | ||
| 
						 | 
					f0fe1b23dc | ||
| 
						 | 
					aaf2006401 | ||
| 
						 | 
					b821e26935 | ||
| 
						 | 
					7ae4287157 | ||
| 
						 | 
					c6fcc38a65 | ||
| 
						 | 
					ab2d5c8853 | ||
| 
						 | 
					5e557ff0bc | ||
| 
						 | 
					918ca449a1 | ||
| 
						 | 
					8e73368008 | ||
| 
						 | 
					f3c1faf672 | ||
| 
						 | 
					d6df04dd6a | ||
| 
						 | 
					b1b9e51ab6 | ||
| 
						 | 
					e49d4770ac | ||
| 
						 | 
					8fa1075511 | ||
| 
						 | 
					9a70169b94 | ||
| 
						 | 
					fefb928237 | ||
| 
						 | 
					ad7e700d0d | ||
| 
						 | 
					1699c69147 | ||
| 
						 | 
					1695f7cece | ||
| 
						 | 
					052c27f907 | ||
| 
						 | 
					dc46c32b30 | ||
| 
						 | 
					fa63349bb2 | ||
| 
						 | 
					ffe26448a6 | ||
| 
						 | 
					4af51e8a84 | ||
| 
						 | 
					1e453cf5a5 | ||
| 
						 | 
					591282b87d | ||
| 
						 | 
					e87528d520 | ||
| 
						 | 
					d79eb0411d | ||
| 
						 | 
					ac1e0a4cf7 | ||
| 
						 | 
					9525eab130 | ||
| 
						 | 
					89b317496c | ||
| 
						 | 
					13be91e78b | ||
| 
						 | 
					f68c1437f3 | ||
| 
						 | 
					4c64c969bb | ||
| 
						 | 
					b4bf3b5138 | ||
| 
						 | 
					083bc4b400 | ||
| 
						 | 
					e8683c5bcc | ||
| 
						 | 
					80e0d1de91 | ||
| 
						 | 
					dbe841037e | ||
| 
						 | 
					bdd537c33c | ||
| 
						 | 
					c0c3846094 | ||
| 
						 | 
					9e8710e7d2 | ||
| 
						 | 
					475553fdf6 | ||
| 
						 | 
					9d570f5b45 | ||
| 
						 | 
					af7fafd34f | ||
| 
						 | 
					d43130f4fc | ||
| 
						 | 
					7500194620 | ||
| 
						 | 
					eb27c29144 | ||
| 
						 | 
					43260b3e24 | ||
| 
						 | 
					f80713f0aa | ||
| 
						 | 
					0c4bdc7ad1 | ||
| 
						 | 
					811cff7bd0 | ||
| 
						 | 
					30269aa75c | ||
| 
						 | 
					e345ef7083 | ||
| 
						 | 
					f559c9b8f7 | ||
| 
						 | 
					f4af0916b2 | ||
| 
						 | 
					f15f14f28d | ||
| 
						 | 
					834f44f58d | ||
| 
						 | 
					b36f45dcf4 | ||
| 
						 | 
					11ba21c9a8 | ||
| 
						 | 
					b045557ce1 | ||
| 
						 | 
					0dd251a3f6 | ||
| 
						 | 
					793acb1725 | ||
| 
						 | 
					921243e8bd | ||
| 
						 | 
					bd9d7a90d9 | ||
| 
						 | 
					cc444a4cea | ||
| 
						 | 
					38ca1fa168 | ||
| 
						 | 
					7a552b87ec | ||
| 
						 | 
					36923d3190 | ||
| 
						 | 
					a9d3017123 | ||
| 
						 | 
					313acd4976 | ||
| 
						 | 
					a4c91bb268 | ||
| 
						 | 
					f9b566984b | ||
| 
						 | 
					8dd261854d | ||
| 
						 | 
					7351e62d87 | ||
| 
						 | 
					0593ae720b | ||
| 
						 | 
					a0a7b08e08 | ||
| 
						 | 
					9a3bc6b8b3 | ||
| 
						 | 
					5acae17f71 | ||
| 
						 | 
					f1e5b76ef2 | ||
| 
						 | 
					53c628fde9 | ||
| 
						 | 
					baca0a70c0 | ||
| 
						 | 
					3e8d0af404 | ||
| 
						 | 
					cf9a91d9d5 | ||
| 
						 | 
					02b9e282c6 | ||
| 
						 | 
					9ce87f235f | ||
| 
						 | 
					e329bea1b2 | ||
| 
						 | 
					8086e7b54d | ||
| 
						 | 
					f7a875606e | ||
| 
						 | 
					196eaf85f4 | ||
| 
						 | 
					876a55668e | ||
| 
						 | 
					05bd21bdd5 | ||
| 
						 | 
					fb51a08cc6 | ||
| 
						 | 
					dd83d7f4d3 | ||
| 
						 | 
					842a56f7ce | ||
| 
						 | 
					9246a6e797 | ||
| 
						 | 
					8ad693f717 | ||
| 
						 | 
					f4c2ee7cc4 | ||
| 
						 | 
					6043441faa | ||
| 
						 | 
					4a065c3710 | ||
| 
						 | 
					0ef800bdd7 | ||
| 
						 | 
					56eaa1910d | ||
| 
						 | 
					201788e286 | ||
| 
						 | 
					506e0f144f | ||
| 
						 | 
					72f68bfdd9 | ||
| 
						 | 
					2f9869b11d | ||
| 
						 | 
					8ffcf6498c | ||
| 
						 | 
					d224ae1923 | ||
| 
						 | 
					fed2063a19 | ||
| 
						 | 
					db2810cdd7 | ||
| 
						 | 
					4f1a6781ef | ||
| 
						 | 
					beffa5d5a4 | ||
| 
						 | 
					7a20f1de07 | ||
| 
						 | 
					cd25cf726b | ||
| 
						 | 
					d6b1bc3842 | ||
| 
						 | 
					a4385fb9bb | ||
| 
						 | 
					7045f2b8ea | ||
| 
						 | 
					07ca1a4de8 | ||
| 
						 | 
					24f289e692 | ||
| 
						 | 
					01bcdaae2d | ||
| 
						 | 
					55890008d1 | ||
| 
						 | 
					5ab9b01879 | ||
| 
						 | 
					e4abb333b3 | ||
| 
						 | 
					09f476c745 | ||
| 
						 | 
					8806e68dce | ||
| 
						 | 
					2ef1e25cd8 | ||
| 
						 | 
					10e7f202aa | ||
| 
						 | 
					ccd7000c09 | ||
| 
						 | 
					8ee7b798cf | ||
| 
						 | 
					7733cf5bf0 | ||
| 
						 | 
					a05ce86dd7 | ||
| 
						 | 
					91f51c32e8 | ||
| 
						 | 
					f910202bba | ||
| 
						 | 
					6d77194a8f | ||
| 
						 | 
					9deb89c15f | ||
| 
						 | 
					4b62a092b4 | ||
| 
						 | 
					81c8f626f9 | ||
| 
						 | 
					3e846c42fb | ||
| 
						 | 
					63ad7fd766 | ||
| 
						 | 
					9ff1e9aa34 | ||
| 
						 | 
					8d162b6f3d | ||
| 
						 | 
					9844d10bef | ||
| 
						 | 
					b908fa8489 | ||
| 
						 | 
					15a10643a7 | ||
| 
						 | 
					299617aca1 | ||
| 
						 | 
					45647d697a | ||
| 
						 | 
					48f5105d38 | ||
| 
						 | 
					fe1c741d68 | ||
| 
						 | 
					fa42cc1f00 | ||
| 
						 | 
					42cf5e7a81 | ||
| 
						 | 
					47905e1aa1 | ||
| 
						 | 
					9a8e907df3 | ||
| 
						 | 
					106fe85582 | ||
| 
						 | 
					4b3571bd57 | ||
| 
						 | 
					96b537401a | ||
| 
						 | 
					721c9eb057 | ||
| 
						 | 
					51701bf6d6 | ||
| 
						 | 
					dbde68bd56 | ||
| 
						 | 
					ad2c9f585a | ||
| 
						 | 
					562093c468 | ||
| 
						 | 
					b0295584a3 | ||
| 
						 | 
					208c54de98 | ||
| 
						 | 
					63e2d941a1 | ||
| 
						 | 
					3956838e9c | ||
| 
						 | 
					abeee58bb0 | ||
| 
						 | 
					d5b1b49722 | ||
| 
						 | 
					564ed03ff8 | ||
| 
						 | 
					70db4c76b4 | ||
| 
						 | 
					d059f7975b | ||
| 
						 | 
					4e74e6dc2d | ||
| 
						 | 
					b6deb96658 | ||
| 
						 | 
					3839e966be | ||
| 
						 | 
					3dd035849c | ||
| 
						 | 
					3d6532b5d6 | ||
| 
						 | 
					bf7c175ee7 | ||
| 
						 | 
					f84af35ed6 | ||
| 
						 | 
					99063b3eb1 | ||
| 
						 | 
					3bec18f28d | ||
| 
						 | 
					15de7a7894 | ||
| 
						 | 
					e20e04e677 | ||
| 
						 | 
					5fc6ae2835 | ||
| 
						 | 
					7d281b8c96 | ||
| 
						 | 
					4880b801a7 | ||
| 
						 | 
					74e354456a | ||
| 
						 | 
					af2e03aa36 | ||
| 
						 | 
					d8fa660ab6 | ||
| 
						 | 
					1a62d48297 | ||
| 
						 | 
					7ba01be13d | ||
| 
						 | 
					1a83d64db7 | ||
| 
						 | 
					5b53014c40 | ||
| 
						 | 
					83685340af | ||
| 
						 | 
					31e0cc4dec | ||
| 
						 | 
					56b87fc1f5 | ||
| 
						 | 
					6b956a2dd7 | ||
| 
						 | 
					1937623d7d | ||
| 
						 | 
					3b60b10945 | ||
| 
						 | 
					7173acd350 | ||
| 
						 | 
					6310d87338 | ||
| 
						 | 
					49a1ed7c18 | ||
| 
						 | 
					d426e280d9 | ||
| 
						 | 
					6154fb29f1 | ||
| 
						 | 
					97d48ef9d6 | ||
| 
						 | 
					88992625c4 | ||
| 
						 | 
					bc6eb44218 | ||
| 
						 | 
					cf9ccd799d | ||
| 
						 | 
					ffa0e4e771 | ||
| 
						 | 
					60fa9c196c | ||
| 
						 | 
					df860d22fb | ||
| 
						 | 
					cb46ff326c | ||
| 
						 | 
					f277a853ef | ||
| 
						 | 
					9ae34f67c3 | ||
| 
						 | 
					c9223218cc | ||
| 
						 | 
					c0dd645aba | ||
| 
						 | 
					2e948eb5b6 | ||
| 
						 | 
					c3276889cf | ||
| 
						 | 
					a76ca8282d | ||
| 
						 | 
					8ce6b8362f | ||
| 
						 | 
					842fb12f05 | ||
| 
						 | 
					d63e1511af | ||
| 
						 | 
					278783b8e0 | ||
| 
						 | 
					d24e3c922d | ||
| 
						 | 
					1d02cd2283 | ||
| 
						 | 
					8edeb82a87 | ||
| 
						 | 
					146e9279de | ||
| 
						 | 
					47105f50a9 | ||
| 
						 | 
					16c9c80f37 | ||
| 
						 | 
					8e7e4bc95a | ||
| 
						 | 
					0aa3d2f930 | ||
| 
						 | 
					ce77755a1e | ||
| 
						 | 
					0f31f20c87 | ||
| 
						 | 
					ee6da2aaa5 | ||
| 
						 | 
					a35f087cd9 | ||
| 
						 | 
					6e029b44dd | ||
| 
						 | 
					973c0cff34 | ||
| 
						 | 
					2027eea6ac | ||
| 
						 | 
					2f43692f33 | ||
| 
						 | 
					6d24992f88 | ||
| 
						 | 
					b4388a58d6 | ||
| 
						 | 
					158aa05fac | ||
| 
						 | 
					f2731bf55e | ||
| 
						 | 
					7304e99fce | ||
| 
						 | 
					02700b83eb | ||
| 
						 | 
					676b25acf9 | ||
| 
						 | 
					556359ea2d | ||
| 
						 | 
					b72923e0f5 | ||
| 
						 | 
					115ac9f75e | ||
| 
						 | 
					32e36f6708 | ||
| 
						 | 
					d949b7a4f9 | ||
| 
						 | 
					eae1171ff5 | ||
| 
						 | 
					76a1b75a51 | ||
| 
						 | 
					8882c0daea | ||
| 
						 | 
					07ebc16d59 | ||
| 
						 | 
					0ceb109964 | ||
| 
						 | 
					118b0d0038 | ||
| 
						 | 
					5e87067792 | ||
| 
						 | 
					c946a252e8 | ||
| 
						 | 
					f9ad2ba1dd | ||
| 
						 | 
					0d0ecd33bd | ||
| 
						 | 
					e4b98fd05b | ||
| 
						 | 
					95a5933303 | ||
| 
						 | 
					da3b55fa64 | ||
| 
						 | 
					fbbabfb90e | ||
| 
						 | 
					f13da6830d | ||
| 
						 | 
					f560a8e2f8 | ||
| 
						 | 
					56f1139c2f | ||
| 
						 | 
					773bdfc1e2 | ||
| 
						 | 
					f449666628 | ||
| 
						 | 
					3f282de0ab | ||
| 
						 | 
					440dd8d22f | ||
| 
						 | 
					dcff9de2f7 | ||
| 
						 | 
					a192866543 | ||
| 
						 | 
					10081416de | ||
| 
						 | 
					e2bed618f9 | ||
| 
						 | 
					03ab1f3823 | ||
| 
						 | 
					ac8aeb63d9 | ||
| 
						 | 
					2e16d822fa | ||
| 
						 | 
					e407d873fa | ||
| 
						 | 
					fd712a1dbe | ||
| 
						 | 
					e9028b40ce | ||
| 
						 | 
					c9da3dee7c | ||
| 
						 | 
					c8c224e202 | ||
| 
						 | 
					f34559daaf | ||
| 
						 | 
					9fefbf4c27 | ||
| 
						 | 
					1af9fd73ea | ||
| 
						 | 
					75ef394eff | ||
| 
						 | 
					ec6cc2c63e | ||
| 
						 | 
					06bc2e192b | ||
| 
						 | 
					78701ec7c1 | ||
| 
						 | 
					c925fab7e4 | ||
| 
						 | 
					42fd72c164 | ||
| 
						 | 
					7fd160e1a2 | ||
| 
						 | 
					97a0d940eb | ||
| 
						 | 
					efaa099d81 | ||
| 
						 | 
					47864a804b | ||
| 
						 | 
					91136c0e43 | ||
| 
						 | 
					28c3b1bd61 | ||
| 
						 | 
					551352bc40 | ||
| 
						 | 
					e73c24c925 | ||
| 
						 | 
					7ec4c286cc | ||
| 
						 | 
					6705e2ec4b | ||
| 
						 | 
					6f0373063b | ||
| 
						 | 
					f64eef60b5 | ||
| 
						 | 
					89546bf86b | ||
| 
						 | 
					793678feca | ||
| 
						 | 
					923cc3019a | ||
| 
						 | 
					10eb98a5f6 | ||
| 
						 | 
					bd9e89d8dd | ||
| 
						 | 
					1926b4ce73 | ||
| 
						 | 
					4ef3062d74 | ||
| 
						 | 
					abb6e0f60f | ||
| 
						 | 
					f204d8d84e | ||
| 
						 | 
					fa301656f1 | ||
| 
						 | 
					7e1221028f | ||
| 
						 | 
					41308cb2dd | ||
| 
						 | 
					130600521c | ||
| 
						 | 
					cd57548a48 | ||
| 
						 | 
					efacc99f76 | ||
| 
						 | 
					f0d236e172 | ||
| 
						 | 
					a8118bd8c6 | ||
| 
						 | 
					0e58f2ef53 | ||
| 
						 | 
					f4b22b3a0c | ||
| 
						 | 
					df5bd281c7 | ||
| 
						 | 
					a3f23837ce | ||
| 
						 | 
					612d989b97 | ||
| 
						 | 
					42c01ee9a2 | ||
| 
						 | 
					14074db591 | ||
| 
						 | 
					43dfdd7942 | ||
| 
						 | 
					f397b97ccf | ||
| 
						 | 
					95f8716144 | ||
| 
						 | 
					17ba472b2e | ||
| 
						 | 
					42d82571ab | ||
| 
						 | 
					9119a28141 | ||
| 
						 | 
					a32263d838 | ||
| 
						 | 
					208ae2bb88 | ||
| 
						 | 
					4d85462a85 | ||
| 
						 | 
					f601aa9ca0 | ||
| 
						 | 
					8aee3ad455 | ||
| 
						 | 
					6a2a1e9561 | ||
| 
						 | 
					5f8786c9dc | ||
| 
						 | 
					73f1d3eead | ||
| 
						 | 
					2bf21bb3c3 | ||
| 
						 | 
					f80f0dbb11 | ||
| 
						 | 
					37518c70c4 | ||
| 
						 | 
					e5951b5bef | ||
| 
						 | 
					ab320bd90b | ||
| 
						 | 
					7bd36b5371 | ||
| 
						 | 
					b882b0f2bc | ||
| 
						 | 
					38d7ae73cc | ||
| 
						 | 
					4527c6ee5d | ||
| 
						 | 
					85829e70c1 | ||
| 
						 | 
					256c08d82a | ||
| 
						 | 
					c2ce03c047 | ||
| 
						 | 
					f2af19e198 | ||
| 
						 | 
					930b7c092d | ||
| 
						 | 
					00757c69c6 | ||
| 
						 | 
					55f267d0fc | ||
| 
						 | 
					6b96aff6e8 | ||
| 
						 | 
					32b773a8fa | ||
| 
						 | 
					03089adad6 | ||
| 
						 | 
					4a1fe746ab | ||
| 
						 | 
					aa52c05d2c | ||
| 
						 | 
					26407a43e7 | ||
| 
						 | 
					a02934bf19 | ||
| 
						 | 
					09c65fba09 | ||
| 
						 | 
					4305c727d0 | ||
| 
						 | 
					188339897f | ||
| 
						 | 
					4ecff9a707 | ||
| 
						 | 
					355aed49c6 | ||
| 
						 | 
					4717b6b0f0 | ||
| 
						 | 
					45ebe9048d | ||
| 
						 | 
					b2170c49a3 | ||
| 
						 | 
					dc2f4d6115 | ||
| 
						 | 
					1eb132440f | ||
| 
						 | 
					a464bbc37a | ||
| 
						 | 
					ed995697c2 | ||
| 
						 | 
					163cd84c7b | ||
| 
						 | 
					293d7cc292 | ||
| 
						 | 
					5de1b4e74c | ||
| 
						 | 
					7b474975da | ||
| 
						 | 
					beab51516b | ||
| 
						 | 
					fe8685a50c | ||
| 
						 | 
					f9af5d0885 | ||
| 
						 | 
					e8136a9720 | ||
| 
						 | 
					531e5d4556 | ||
| 
						 | 
					e66255963a | ||
| 
						 | 
					246aac8ee4 | ||
| 
						 | 
					23cfeff685 | ||
| 
						 | 
					a5e7e0d126 | ||
| 
						 | 
					5bebc30ba0 | ||
| 
						 | 
					0e7057f5b9 | ||
| 
						 | 
					7c6c365ba4 | ||
| 
						 | 
					424c9bb0c5 | ||
| 
						 | 
					9d0f26594c | ||
| 
						 | 
					99c17de079 | ||
| 
						 | 
					b1e3dd0af6 | ||
| 
						 | 
					261cb89530 | ||
| 
						 | 
					ff6773ba37 | ||
| 
						 | 
					bdfbbfcbbd | ||
| 
						 | 
					0c4cd56758 | ||
| 
						 | 
					4a36658321 | ||
| 
						 | 
					7aae938685 | ||
| 
						 | 
					3723401e7a | ||
| 
						 | 
					70631366a9 | ||
| 
						 | 
					0e40bbda3e | ||
| 
						 | 
					e9aa475398 | ||
| 
						 | 
					8d2a811184 | ||
| 
						 | 
					dd7f5b6700 | ||
| 
						 | 
					a4f6277737 | ||
| 
						 | 
					c2bfaacbb7 | ||
| 
						 | 
					a17cbfa2d4 | ||
| 
						 | 
					fb9a101555 | ||
| 
						 | 
					e319cf0200 | ||
| 
						 | 
					0a8395ef6a | ||
| 
						 | 
					38df5e01be | ||
| 
						 | 
					ebd891a868 | ||
| 
						 | 
					4ab2395cbe | ||
| 
						 | 
					5f1f989fc9 | ||
| 
						 | 
					44b709eee3 | ||
| 
						 | 
					d0d7726597 | ||
| 
						 | 
					054c342aeb | ||
| 
						 | 
					c79c33baf7 | ||
| 
						 | 
					23b00e35b2 | ||
| 
						 | 
					fe51079266 | ||
| 
						 | 
					0791b0bbee | ||
| 
						 | 
					dbf04c8eeb | ||
| 
						 | 
					6204256df8 | ||
| 
						 | 
					93cc8c2327 | ||
| 
						 | 
					68a2e5bbbc | ||
| 
						 | 
					72792153f2 | ||
| 
						 | 
					88b6ef1897 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -363,6 +363,4 @@ MigrationBackup/
 | 
			
		||||
FodyWeavers.xsd
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/framework/*pro*
 | 
			
		||||
/framework/*Pro*
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
 **ThingsGateway** 存储库同时提供 [**设备采集驱动**](https://www.nuget.org/packages?q=Tags%3A%22ThingsGateway%22)
 | 
			
		||||
 | 
			
		||||
 **ThingsGateway** 存储库同时提供 **基于Blazor的权限框架** 查看 **ThingsGateway - Admin**
 | 
			
		||||
 **ThingsGateway** 存储库同时提供 **基于Blazor的权限框架** 查看 [**ThingsGateway.Admin**](https://gitee.com/dotnetchina/ThingsGateway/blob/master/framework/ThingsGateway.Admin.sln)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 文档
 | 
			
		||||
@@ -22,9 +22,7 @@
 | 
			
		||||
 | 
			
		||||
[ThingsGateway演示地址](http://120.24.62.140:5000/)
 | 
			
		||||
 | 
			
		||||
账户	:  **superAdmin**	
 | 
			
		||||
 | 
			
		||||
密码 : **111111**
 | 
			
		||||
账户	:  **superAdmin**	密码 : **111111**
 | 
			
		||||
 | 
			
		||||
## 赞助
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								framework/.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								framework/.editorconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
[*.cs]
 | 
			
		||||
 | 
			
		||||
# CA1822: 将成员标记为 static
 | 
			
		||||
dotnet_diagnostic.CA1822.severity = none
 | 
			
		||||
 | 
			
		||||
# CA1816: Dispose 方法应调用 SuppressFinalize
 | 
			
		||||
dotnet_diagnostic.CA1816.severity = none
 | 
			
		||||
 | 
			
		||||
# CA2254: 模板应为静态表达式
 | 
			
		||||
dotnet_diagnostic.CA2254.severity = none
 | 
			
		||||
 | 
			
		||||
[*.cs]
 | 
			
		||||
#### 命名样式 ####
 | 
			
		||||
 | 
			
		||||
# 命名规则
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
 | 
			
		||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
 | 
			
		||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
 | 
			
		||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
 | 
			
		||||
 | 
			
		||||
# 符号规范
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_kinds = interface
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.interface.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
 | 
			
		||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.types.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
 | 
			
		||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
 | 
			
		||||
dotnet_naming_symbols.non_field_members.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
# 命名样式
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.begins_with_i.required_prefix = I
 | 
			
		||||
dotnet_naming_style.begins_with_i.required_suffix = 
 | 
			
		||||
dotnet_naming_style.begins_with_i.word_separator = 
 | 
			
		||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.pascal_case.required_prefix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.required_suffix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.word_separator = 
 | 
			
		||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.pascal_case.required_prefix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.required_suffix = 
 | 
			
		||||
dotnet_naming_style.pascal_case.word_separator = 
 | 
			
		||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
 | 
			
		||||
csharp_using_directive_placement = outside_namespace:silent
 | 
			
		||||
csharp_style_expression_bodied_methods = false:silent
 | 
			
		||||
csharp_style_expression_bodied_constructors = false:silent
 | 
			
		||||
csharp_style_expression_bodied_operators = false:silent
 | 
			
		||||
csharp_style_expression_bodied_properties = true:silent
 | 
			
		||||
csharp_style_expression_bodied_indexers = true:silent
 | 
			
		||||
csharp_style_expression_bodied_accessors = true:silent
 | 
			
		||||
csharp_style_expression_bodied_lambdas = true:silent
 | 
			
		||||
csharp_style_expression_bodied_local_functions = false:silent
 | 
			
		||||
csharp_style_conditional_delegate_call = true:suggestion
 | 
			
		||||
csharp_style_var_for_built_in_types = false:silent
 | 
			
		||||
csharp_style_var_when_type_is_apparent = false:silent
 | 
			
		||||
csharp_style_var_elsewhere = false:silent
 | 
			
		||||
csharp_prefer_simple_using_statement = true:suggestion
 | 
			
		||||
csharp_prefer_braces = true:silent
 | 
			
		||||
csharp_style_namespace_declarations = block_scoped:silent
 | 
			
		||||
csharp_style_prefer_method_group_conversion = true:silent
 | 
			
		||||
csharp_style_prefer_top_level_statements = true:silent
 | 
			
		||||
 | 
			
		||||
# CA2208: 正确实例化参数异常
 | 
			
		||||
dotnet_diagnostic.CA2208.severity = none
 | 
			
		||||
 | 
			
		||||
# IDE0057: 使用范围运算符
 | 
			
		||||
dotnet_diagnostic.IDE0057.severity = none
 | 
			
		||||
 | 
			
		||||
# IDE0056: 使用索引运算符
 | 
			
		||||
dotnet_diagnostic.IDE0056.severity = none
 | 
			
		||||
 | 
			
		||||
# CA1830: 最好使用 StringBuilder 的强类型 Append 和 Insert 方法重载
 | 
			
		||||
dotnet_diagnostic.CA1830.severity = none
 | 
			
		||||
 | 
			
		||||
# CA1847: 将字符型文本用于单个字符查找
 | 
			
		||||
dotnet_diagnostic.CA1847.severity = none
 | 
			
		||||
 | 
			
		||||
[*.vb]
 | 
			
		||||
#### 命名样式 ####
 | 
			
		||||
 | 
			
		||||
# 命名规则
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
 | 
			
		||||
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
 | 
			
		||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
 | 
			
		||||
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
 | 
			
		||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
 | 
			
		||||
 | 
			
		||||
# 符号规范
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_kinds = interface
 | 
			
		||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.interface.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
 | 
			
		||||
dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.类型.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
 | 
			
		||||
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
 | 
			
		||||
dotnet_naming_symbols.非字段成员.required_modifiers = 
 | 
			
		||||
 | 
			
		||||
# 命名样式
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.以_i_开始.required_prefix = I
 | 
			
		||||
dotnet_naming_style.以_i_开始.required_suffix = 
 | 
			
		||||
dotnet_naming_style.以_i_开始.word_separator = 
 | 
			
		||||
dotnet_naming_style.以_i_开始.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_prefix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_suffix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.word_separator = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_prefix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.required_suffix = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.word_separator = 
 | 
			
		||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
 | 
			
		||||
 | 
			
		||||
[*.{cs,vb}]
 | 
			
		||||
dotnet_style_qualification_for_field = false:silent
 | 
			
		||||
dotnet_style_qualification_for_property = false:silent
 | 
			
		||||
dotnet_style_qualification_for_method = false:silent
 | 
			
		||||
dotnet_style_qualification_for_event = false:silent
 | 
			
		||||
end_of_line = crlf
 | 
			
		||||
 | 
			
		||||
# IDE0060: 删除未使用的参数
 | 
			
		||||
dotnet_diagnostic.IDE0060.severity = none
 | 
			
		||||
@@ -1,20 +1,30 @@
 | 
			
		||||
<Project>
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		
 | 
			
		||||
		<ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
		<TargetFrameworks>net6.0;net8.0;</TargetFrameworks>
 | 
			
		||||
		<Version>4.0.0.6</Version>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
		<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
 | 
			
		||||
		<Version>2.0.6.0</Version>
 | 
			
		||||
		<Authors>Diego</Authors>
 | 
			
		||||
		<Product>ThingsGateway</Product>
 | 
			
		||||
		<Copyright>© 2023-present Diego</Copyright>
 | 
			
		||||
		<RepositoryUrl>https://gitee.com/diego2098/ThingsGateway</RepositoryUrl>
 | 
			
		||||
		<PublishRepositoryUrl>true</PublishRepositoryUrl>
 | 
			
		||||
		<EmbedUntrackedSource>true</EmbedUntrackedSource>
 | 
			
		||||
		<EmbedAllSources>true</EmbedAllSources>
 | 
			
		||||
		<RepositoryType>Gitee</RepositoryType>
 | 
			
		||||
		<IncludeSymbols>true</IncludeSymbols>
 | 
			
		||||
		<SymbolPackageFormat>snupkg</SymbolPackageFormat>
 | 
			
		||||
		<SignAssembly>True</SignAssembly>
 | 
			
		||||
		<DelaySign>False</DelaySign>
 | 
			
		||||
		<SatelliteResourceLanguages>zh-Hans</SatelliteResourceLanguages>
 | 
			
		||||
		<GenerateDocumentationFile>False</GenerateDocumentationFile>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<LangVersion>latest</LangVersion>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
@@ -1,101 +0,0 @@
 | 
			
		||||
 | 
			
		||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
			
		||||
# Visual Studio Version 17
 | 
			
		||||
VisualStudioVersion = 17.6.33927.249
 | 
			
		||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
			
		||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin", "admin", "{4E66C22C-0636-4949-BF6A-9E3BBE1550BA}"
 | 
			
		||||
	ProjectSection(SolutionItems) = preProject
 | 
			
		||||
		admin\Directory.Build.props = admin\Directory.Build.props
 | 
			
		||||
	EndProjectSection
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Components", "admin\ThingsGateway.Components\ThingsGateway.Components.csproj", "{0A891D8E-23B3-46AD-8D30-565EE5004F93}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Core", "admin\ThingsGateway.Core\ThingsGateway.Core.csproj", "{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Core", "admin\ThingsGateway.Admin.Core\ThingsGateway.Admin.Core.csproj", "{5DA3D2BD-6768-4479-B52F-49E022EFF310}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Blazor", "admin\ThingsGateway.Admin.Blazor\ThingsGateway.Admin.Blazor.csproj", "{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.Application", "admin\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj", "{D6685A42-2712-417A-92C5-5EFF90B9FA94}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Admin.ApiController", "admin\ThingsGateway.Admin.ApiController\ThingsGateway.Admin.ApiController.csproj", "{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}"
 | 
			
		||||
	ProjectSection(SolutionItems) = preProject
 | 
			
		||||
		web\Directory.Build.props = web\Directory.Build.props
 | 
			
		||||
	EndProjectSection
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Core", "web\ThingsGateway.Web.Core\ThingsGateway.Web.Core.csproj", "{D37EC028-EA46-4510-8261-6E780A906314}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Web.Entry", "web\ThingsGateway.Web.Entry\ThingsGateway.Web.Entry.csproj", "{C5F662EB-991F-438D-BF61-EF87E7371C04}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{97B23D8B-C6C0-4746-A21F-C7B49354B284}"
 | 
			
		||||
	ProjectSection(SolutionItems) = preProject
 | 
			
		||||
		..\.gitignore = ..\.gitignore
 | 
			
		||||
	EndProjectSection
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThingsGateway.Foundation", "foundation\ThingsGateway.Foundation\ThingsGateway.Foundation.csproj", "{6961511A-8787-42AF-827D-B630B2AF4791}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "foundation", "foundation", "{268A1A81-2685-47E1-9986-5934A58A31A4}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
			
		||||
		Debug|Any CPU = Debug|Any CPU
 | 
			
		||||
		Release|Any CPU = Release|Any CPU
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
			
		||||
		{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{0A891D8E-23B3-46AD-8D30-565EE5004F93}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{A712EAEE-94F2-4F01-8C1C-2EC802280DD7}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{5DA3D2BD-6768-4479-B52F-49E022EFF310}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{D6685A42-2712-417A-92C5-5EFF90B9FA94}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{D37EC028-EA46-4510-8261-6E780A906314}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{D37EC028-EA46-4510-8261-6E780A906314}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{C5F662EB-991F-438D-BF61-EF87E7371C04}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{C5F662EB-991F-438D-BF61-EF87E7371C04}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{6961511A-8787-42AF-827D-B630B2AF4791}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{6961511A-8787-42AF-827D-B630B2AF4791}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(SolutionProperties) = preSolution
 | 
			
		||||
		HideSolutionNode = FALSE
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(NestedProjects) = preSolution
 | 
			
		||||
		{0A891D8E-23B3-46AD-8D30-565EE5004F93} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{A712EAEE-94F2-4F01-8C1C-2EC802280DD7} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{5DA3D2BD-6768-4479-B52F-49E022EFF310} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{8DD5DF98-7FDE-4B49-8661-AEB44D923CFE} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{D6685A42-2712-417A-92C5-5EFF90B9FA94} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{0D17D801-6DAA-4FD1-9A99-F9F07FA6BA88} = {4E66C22C-0636-4949-BF6A-9E3BBE1550BA}
 | 
			
		||||
		{D37EC028-EA46-4510-8261-6E780A906314} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
 | 
			
		||||
		{C5F662EB-991F-438D-BF61-EF87E7371C04} = {F0C9A8CB-231B-45E0-B91B-4FEF7EF47197}
 | 
			
		||||
		{6961511A-8787-42AF-827D-B630B2AF4791} = {268A1A81-2685-47E1-9986-5934A58A31A4}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
			
		||||
		SolutionGuid = {C49B2D3E-6818-4E28-91B7-6E4E7E264BBB}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
EndGlobal
 | 
			
		||||
@@ -10,12 +10,14 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion.DynamicApiController;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.ApiController;
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 后台登录控制器
 | 
			
		||||
@@ -10,9 +10,13 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion.DynamicApiController;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.ApiController;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 文件下载
 | 
			
		||||
@@ -22,16 +26,19 @@ namespace ThingsGateway.Admin.ApiController;
 | 
			
		||||
[LoggingMonitor]
 | 
			
		||||
public class FileController : IDynamicApiController
 | 
			
		||||
{
 | 
			
		||||
    private readonly IFileService _fileService;
 | 
			
		||||
    private readonly IOperateLogService _operateLogService;
 | 
			
		||||
    private readonly IVisitLogService _visitLogService;
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// <inheritdoc cref="FileController"/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public FileController(
 | 
			
		||||
        IFileService fileService,
 | 
			
		||||
        IOperateLogService operateLogService,
 | 
			
		||||
        IVisitLogService visitLogService
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        _fileService = fileService;
 | 
			
		||||
        _operateLogService = operateLogService;
 | 
			
		||||
        _visitLogService = visitLogService;
 | 
			
		||||
    }
 | 
			
		||||
@@ -44,9 +51,10 @@ public class FileController : IDynamicApiController
 | 
			
		||||
    public async Task<IActionResult> DownloadOperateLogAsync([FromQuery] OperateLogInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var memoryStream = await _operateLogService.ExportFileAsync(input);
 | 
			
		||||
        memoryStream.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
        var data = new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
 | 
			
		||||
        {
 | 
			
		||||
            FileDownloadName = $"operateLog{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
 | 
			
		||||
            FileDownloadName = $"operateLog{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
 | 
			
		||||
        };
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
@@ -58,9 +66,10 @@ public class FileController : IDynamicApiController
 | 
			
		||||
    public async Task<IActionResult> DownloadVisitLogAsync([FromQuery] VisitLogInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var memoryStream = await _visitLogService.ExportFileAsync(input);
 | 
			
		||||
        memoryStream.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
        var data = new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
 | 
			
		||||
        {
 | 
			
		||||
            FileDownloadName = $"operateLog{DateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
 | 
			
		||||
            FileDownloadName = $"operateLog{SysDateTimeExtensions.CurrentDateTime.ToFileDateTimeFormat()}.xlsx"
 | 
			
		||||
        };
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion.DynamicApiController;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// OpenApi登录控制器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [ApiDescriptionSettings(CateGoryConst.ThingsGatewayOpenApi, Order = 200)]
 | 
			
		||||
    [Route("auth/openapi")]
 | 
			
		||||
    [LoggingMonitor]
 | 
			
		||||
    [Description("OpenApi登录")]
 | 
			
		||||
    [Authorize(AuthenticationSchemes = "Bearer")]
 | 
			
		||||
    public class OpenApiAuthController : IDynamicApiController
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IOpenApiAuthService _authService;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc cref="OpenApiAuthController"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="authService"></param>
 | 
			
		||||
        public OpenApiAuthController(IOpenApiAuthService authService)
 | 
			
		||||
        {
 | 
			
		||||
            _authService = authService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// OpenApi登录
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="input"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        [AllowAnonymous]
 | 
			
		||||
        [HttpPost("login")]
 | 
			
		||||
        [Description(EventSubscriberConst.LoginOpenApi)]
 | 
			
		||||
        public async Task<LoginOpenApiOutput> LoginOpenApiAsync(LoginOpenApiInput input)
 | 
			
		||||
        {
 | 
			
		||||
            return await _authService.LoginOpenApiAsync(input);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 登出
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        [HttpPost("logout")]
 | 
			
		||||
        [Description(EventSubscriberConst.LogoutOpenApi)]
 | 
			
		||||
        public async Task LogoutAsync()
 | 
			
		||||
        {
 | 
			
		||||
            await _authService.LogoutAsync();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
using Furion.DynamicApiController;
 | 
			
		||||
using Furion.SpecificationDocument;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Swagger登录授权服务
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [ApiDescriptionSettings(CateGoryConst.ThingsGatewayAdmin, Order = 200)]
 | 
			
		||||
    [Route("Swagger")]
 | 
			
		||||
    public class SwaggerController : IDynamicApiController, IScoped
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConfigService _configService;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <inheritdoc cref="SwaggerController"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="sysConfigService"></param>
 | 
			
		||||
        public SwaggerController(ConfigService sysConfigService)
 | 
			
		||||
        {
 | 
			
		||||
            _configService = sysConfigService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Swagger登录检查
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        [HttpPost("CheckUrl")]
 | 
			
		||||
        [AllowAnonymous, NonUnify]
 | 
			
		||||
        public async Task<int> SwaggerCheckUrlAsync()
 | 
			
		||||
        {
 | 
			
		||||
            var enable = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGERLOGIN_OPEN)).ConfigValue.ToBoolean();
 | 
			
		||||
            return enable ? 401 : 200;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Swagger登录
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="auth"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        [HttpPost("SubmitUrl")]
 | 
			
		||||
        [AllowAnonymous, NonUnify]
 | 
			
		||||
        public async Task<int> SwaggerSubmitUrlAsync([FromForm] SpecificationAuth auth)
 | 
			
		||||
        {
 | 
			
		||||
            var userName = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGER_NAME)).ConfigValue;
 | 
			
		||||
            var password = (await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SWAGGER_PASSWORD)).ConfigValue;
 | 
			
		||||
            if (auth.UserName == userName && auth.Password == password)
 | 
			
		||||
            {
 | 
			
		||||
                return 200;
 | 
			
		||||
            }
 | 
			
		||||
            return 401;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								framework/ThingsGateway.Admin.ApiController/GlobalUsings.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								framework/ThingsGateway.Admin.ApiController/GlobalUsings.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
global using System;
 | 
			
		||||
global using System.IO;
 | 
			
		||||
global using System.Threading.Tasks;
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
 | 
			
		||||
	<PropertyGroup>
 | 
			
		||||
		<DocumentationFile>$(MSBuildProjectName).xml</DocumentationFile>
 | 
			
		||||
		<GenerateDocumentationFile>True</GenerateDocumentationFile>
 | 
			
		||||
		<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
 | 
			
		||||
	</PropertyGroup>
 | 
			
		||||
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
		<None Include="..\.editorconfig" Link=".editorconfig" />
 | 
			
		||||
	</ItemGroup>
 | 
			
		||||
	
 | 
			
		||||
	<ItemGroup>
 | 
			
		||||
	  <ProjectReference Include="..\ThingsGateway.Admin.Application\ThingsGateway.Admin.Application.csproj" />
 | 
			
		||||
@@ -0,0 +1,102 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<doc>
 | 
			
		||||
    <assembly>
 | 
			
		||||
        <name>ThingsGateway.Admin.ApiController</name>
 | 
			
		||||
    </assembly>
 | 
			
		||||
    <members>
 | 
			
		||||
        <member name="T:ThingsGateway.Admin.Application.AuthController">
 | 
			
		||||
            <summary>
 | 
			
		||||
            后台登录控制器
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.AuthController.#ctor(ThingsGateway.Admin.Application.IAuthService)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc cref="T:ThingsGateway.Admin.Application.AuthController"/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="authService"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.AuthController.LoginAsync(ThingsGateway.Admin.Application.LoginInput)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            后台登录
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="input"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.AuthController.LogoutAsync">
 | 
			
		||||
            <summary>
 | 
			
		||||
            后台登出
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Admin.Application.FileController">
 | 
			
		||||
            <summary>
 | 
			
		||||
            文件下载
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.FileController.#ctor(ThingsGateway.Admin.Application.IFileService,ThingsGateway.Admin.Application.IOperateLogService,ThingsGateway.Admin.Application.IVisitLogService)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc cref="T:ThingsGateway.Admin.Application.FileController"/>
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.FileController.DownloadOperateLogAsync(ThingsGateway.Admin.Application.OperateLogInput)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            下载操作日志
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.FileController.DownloadVisitLogAsync(ThingsGateway.Admin.Application.VisitLogInput)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            下载访问日志
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Admin.Application.OpenApiAuthController">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OpenApi登录控制器
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.OpenApiAuthController.#ctor(ThingsGateway.Admin.Application.IOpenApiAuthService)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc cref="T:ThingsGateway.Admin.Application.OpenApiAuthController"/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="authService"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.OpenApiAuthController.LoginOpenApiAsync(ThingsGateway.Admin.Application.LoginOpenApiInput)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            OpenApi登录
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="input"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.OpenApiAuthController.LogoutAsync">
 | 
			
		||||
            <summary>
 | 
			
		||||
            登出
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="T:ThingsGateway.Admin.Application.SwaggerController">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Swagger登录授权服务
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.SwaggerController.#ctor(ThingsGateway.Admin.Application.ConfigService)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            <inheritdoc cref="T:ThingsGateway.Admin.Application.SwaggerController"/>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="sysConfigService"></param>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.SwaggerController.SwaggerCheckUrlAsync">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Swagger登录检查
 | 
			
		||||
            </summary>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:ThingsGateway.Admin.Application.SwaggerController.SwaggerSubmitUrlAsync(Furion.SpecificationDocument.SpecificationAuth)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            Swagger登录
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="auth"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
@@ -37,7 +37,7 @@ public class OperDescAttribute : Attribute
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public string Description { get; }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 记录参数,默认true
 | 
			
		||||
    /// 记录参数,默认位true
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool IsRecordPar { get; set; } = true;
 | 
			
		||||
}
 | 
			
		||||
@@ -10,13 +10,14 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
using Furion.Reflection;
 | 
			
		||||
using Furion.Reflection.Extensions;
 | 
			
		||||
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using UAParser;
 | 
			
		||||
 | 
			
		||||
@@ -43,6 +44,7 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
    /// <param name="method"></param>
 | 
			
		||||
    /// <param name="args"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    /// <exception cref="NotImplementedException"></exception>
 | 
			
		||||
    public override object Invoke(MethodInfo method, object[] args)
 | 
			
		||||
    {
 | 
			
		||||
        var desc = Target.GetCustomAttribute<OperDescAttribute>(method.ToString(), true);
 | 
			
		||||
@@ -96,7 +98,7 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
    /// <exception cref="NotImplementedException"></exception>
 | 
			
		||||
    public override async Task InvokeAsync(MethodInfo method, object[] args)
 | 
			
		||||
    {
 | 
			
		||||
        var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target, true);
 | 
			
		||||
        var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target);
 | 
			
		||||
        if (desc == null)
 | 
			
		||||
        {
 | 
			
		||||
            var task = method.Invoke(Target, args) as Task;
 | 
			
		||||
@@ -134,7 +136,7 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
    /// <exception cref="NotImplementedException"></exception>
 | 
			
		||||
    public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)
 | 
			
		||||
    {
 | 
			
		||||
        var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target, true);
 | 
			
		||||
        var desc = method.GetActualCustomAttribute<OperDescAttribute>(Target);
 | 
			
		||||
        if (desc == null)
 | 
			
		||||
        {
 | 
			
		||||
            var taskT = method.Invoke(Target, args) as Task<T>;
 | 
			
		||||
@@ -168,15 +170,15 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private void WriteOperLog(MethodInfo method, object[] args, OperDescAttribute desc, object result, Exception exception)
 | 
			
		||||
    private static void WriteOperLog(MethodInfo method, object[] args, OperDescAttribute desc, object result, Exception exception)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        //写入操作日志
 | 
			
		||||
        var str = App.HttpContext?.Request?.Headers?.UserAgent;
 | 
			
		||||
        ClientInfo clientInfo = null;
 | 
			
		||||
        if (str.HasValue)
 | 
			
		||||
        {
 | 
			
		||||
            var uaParser = Parser.GetDefault();
 | 
			
		||||
            clientInfo = uaParser.Parse(str);
 | 
			
		||||
            clientInfo = StaticParser.Parser.Parse(str);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        StringBuilder stringBuilder = new();
 | 
			
		||||
@@ -184,9 +186,9 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
        {
 | 
			
		||||
            var parameters = method.GetParameters();
 | 
			
		||||
            var jsonParameters = parameters.Select((p, i) => $"\"{p.Name}\": {args[i].ToJsonString()}");
 | 
			
		||||
            stringBuilder.Append('{');
 | 
			
		||||
            stringBuilder.Append("{");
 | 
			
		||||
            stringBuilder.Append(string.Join(", ", jsonParameters));
 | 
			
		||||
            stringBuilder.Append('}');
 | 
			
		||||
            stringBuilder.Append("}");
 | 
			
		||||
        }
 | 
			
		||||
        var paramJson = stringBuilder.ToString();
 | 
			
		||||
        var resultJson = desc.IsRecordPar ? result?.ToJsonString() : null;
 | 
			
		||||
@@ -199,7 +201,7 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
            OpIp = App.HttpContext?.Connection?.RemoteIpAddress?.MapToIPv4().ToString(),
 | 
			
		||||
            OpBrowser = clientInfo?.UA?.Family + clientInfo?.UA?.Major,
 | 
			
		||||
            OpOs = clientInfo?.OS?.Family + clientInfo?.OS?.Major,
 | 
			
		||||
            OpTime = DateTimeExtensions.CurrentDateTime,
 | 
			
		||||
            OpTime = SysDateTimeExtensions.CurrentDateTime,
 | 
			
		||||
            OpAccount = UserManager.UserAccount,
 | 
			
		||||
            ReqUrl = "",
 | 
			
		||||
            ReqMethod = LogConst.LOG_REQMETHOD,
 | 
			
		||||
@@ -215,10 +217,8 @@ public class OperDispatchProxy : AspectDispatchProxy, IDispatchProxy
 | 
			
		||||
            log.ExeStatus = LogConst.LOG_FAIL;//操作状态为失败
 | 
			
		||||
            log.ExeMessage = exception.Source + ":" + exception.Message + Environment.NewLine + exception.StackTrace;
 | 
			
		||||
        }
 | 
			
		||||
        DbContext.Db.CopyNew().InsertableWithAttr(log).ExecuteCommand();//入库
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        DbContext.Db.InsertableWithAttr(log).ExecuteCommand();//入库
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -40,10 +40,6 @@ public static class ConfigConst
 | 
			
		||||
    /// 版权跳转url
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string CONFIG_COPYRIGHT_URL = "CONFIG_COPYRIGHT_URL";
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 是否启用PageTab
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string CONFIG_PAGETAB = "CONFIG_PAGETAB";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 登录验证码开关
 | 
			
		||||
@@ -55,6 +55,7 @@ public class LogConst
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string LOG_REQMETHOD = "BLAZORSERVER";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 操作成功
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -16,5 +16,3 @@ global using System.IO;
 | 
			
		||||
global using System.Linq;
 | 
			
		||||
global using System.Threading;
 | 
			
		||||
global using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
global using ThingsGateway.Foundation.Core;
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
 | 
			
		||||
@@ -17,6 +19,8 @@ using System.ComponentModel;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -32,8 +36,8 @@ public class PermissionUtil
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static List<OpenApiPermissionTreeSelector> OpenApiPermissionTreeSelector()
 | 
			
		||||
    {
 | 
			
		||||
        var cacheKey = $"{nameof(OpenApiPermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}-{typeof(PermissionUtil).FullName}-{typeof(PermissionUtil).TypeHandle.Value}";
 | 
			
		||||
        var cacheValue = App.GetService<MemoryCache>().GetOrCreate(cacheKey, entry =>
 | 
			
		||||
        var cacheKey = $"{nameof(OpenApiPermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}";
 | 
			
		||||
        List<OpenApiPermissionTreeSelector> displayName = CacheStatic.Cache.GetOrCreate(cacheKey, entry =>
 | 
			
		||||
        {
 | 
			
		||||
            List<OpenApiPermissionTreeSelector> openApiGroups = new();
 | 
			
		||||
            var controllerTypes = App.EffectiveTypes
 | 
			
		||||
@@ -96,8 +100,7 @@ public class PermissionUtil
 | 
			
		||||
            }
 | 
			
		||||
            return openApiGroups;
 | 
			
		||||
        }, false);
 | 
			
		||||
 | 
			
		||||
        return cacheValue;
 | 
			
		||||
        return displayName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -107,8 +110,8 @@ public class PermissionUtil
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static List<PermissionTreeSelector> PermissionTreeSelector(List<string> routers)
 | 
			
		||||
    {
 | 
			
		||||
        var cacheKey = $"{nameof(PermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}-{typeof(PermissionUtil).FullName}-{typeof(PermissionUtil).TypeHandle.Value}";
 | 
			
		||||
        var cacheValue = App.GetService<MemoryCache>().GetOrCreate(cacheKey, entry =>
 | 
			
		||||
        var cacheKey = $"{nameof(PermissionTreeSelector)}-{CultureInfo.CurrentUICulture.Name}-{routers.ToJsonString()}";
 | 
			
		||||
        List<PermissionTreeSelector> displayName = CacheStatic.Cache.GetOrCreate(cacheKey, entry =>
 | 
			
		||||
        {
 | 
			
		||||
            List<PermissionTreeSelector> permissions = new();//权限列表
 | 
			
		||||
 | 
			
		||||
@@ -130,7 +133,8 @@ public class PermissionUtil
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return permissions;
 | 
			
		||||
        }, false);
 | 
			
		||||
        return cacheValue;
 | 
			
		||||
        }, false
 | 
			
		||||
        );
 | 
			
		||||
        return displayName;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,8 +10,9 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -30,14 +31,13 @@ public class SeedDataUtil
 | 
			
		||||
        var seedData = new List<T>();//种子数据结果
 | 
			
		||||
        var basePath = AppContext.BaseDirectory;//获取项目目录
 | 
			
		||||
        var json = basePath.CombinePath("SeedData", "Json", jsonName);//获取文件路径
 | 
			
		||||
        var dataString = FileUtil.ReadFile(json);//读取文件
 | 
			
		||||
        var dataString = ReadFile(json);//读取文件
 | 
			
		||||
        if (!string.IsNullOrEmpty(dataString))//如果有内容
 | 
			
		||||
        {
 | 
			
		||||
            //字段没有数据的替换成null
 | 
			
		||||
            dataString = dataString.Replace("\"\"", "null");
 | 
			
		||||
            //将json字符串转为实体,这里extjson可以正常转换为字符串
 | 
			
		||||
            var seedDataRecord = Newtonsoft.Json.JsonConvert.DeserializeObject<SeedDataRecords<T>>(dataString);
 | 
			
		||||
 | 
			
		||||
            var seedDataRecord = dataString.ToJsonWithT<SeedDataRecords<T>>();
 | 
			
		||||
 | 
			
		||||
            //遍历seedDataRecord
 | 
			
		||||
            for (int i = 0; i < seedDataRecord.Records.Count; i++)
 | 
			
		||||
@@ -89,6 +89,25 @@ public class SeedDataUtil
 | 
			
		||||
        return seedData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 读取文件
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="Path"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public static string ReadFile(string Path)
 | 
			
		||||
    {
 | 
			
		||||
        if (!File.Exists(Path))
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
 | 
			
		||||
        StreamReader streamReader = new(Path, Encoding.GetEncoding("utf-8"));
 | 
			
		||||
        string result = streamReader.ReadToEnd();
 | 
			
		||||
        streamReader.Close();
 | 
			
		||||
        streamReader.Dispose();
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -10,16 +10,17 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Core;
 | 
			
		||||
using UAParser;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 主键id基类
 | 
			
		||||
/// 单例Parser
 | 
			
		||||
/// </summary>
 | 
			
		||||
public interface IPrimaryIdEntity
 | 
			
		||||
public class StaticParser
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 主键Id
 | 
			
		||||
    /// 单例
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    long Id { get; set; }
 | 
			
		||||
    public static Parser Parser { get; } = Parser.GetDefault();
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
using Furion.Schedule;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
@@ -22,9 +23,30 @@ public class JobPersistence : IJobPersistence
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public JobPersistence(IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
    public JobPersistence(IServiceProvider serviceProvider)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
        _serviceScope = serviceProvider.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 作业调度服务启动时
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public IEnumerable<SchedulerBuilder> Preload()
 | 
			
		||||
    {
 | 
			
		||||
        // 获取所有定义的作业
 | 
			
		||||
        var allJobs = App.EffectiveTypes.ScanToBuilders().ToList();
 | 
			
		||||
        return allJobs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 作业计划初始化通知
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="builder"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public SchedulerBuilder OnLoading(SchedulerBuilder builder)
 | 
			
		||||
    {
 | 
			
		||||
        return builder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -39,30 +61,9 @@ public class JobPersistence : IJobPersistence
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 作业计划初始化通知
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="builder"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public SchedulerBuilder OnLoading(SchedulerBuilder builder)
 | 
			
		||||
    {
 | 
			
		||||
        return builder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public void OnTriggerChanged(PersistenceTriggerContext context)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 作业调度服务启动时
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    public IEnumerable<SchedulerBuilder> Preload()
 | 
			
		||||
    {
 | 
			
		||||
        // 获取所有定义的作业
 | 
			
		||||
        var allJobs = App.EffectiveTypes.ScanToBuilders().ToList();
 | 
			
		||||
        return allJobs;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.Schedule;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -25,8 +27,8 @@ public class LogJob : IJob
 | 
			
		||||
    public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
 | 
			
		||||
    {
 | 
			
		||||
        var db = DbContext.Db.CopyNew();
 | 
			
		||||
        var daysAgo = App.GetConfig<int?>("Logging:LogJob:DaysAgo") ?? 30;
 | 
			
		||||
        await db.DeleteableWithAttr<SysVisitLog>().Where(u => u.CreateTime < DateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除访问日志
 | 
			
		||||
        await db.DeleteableWithAttr<SysOperateLog>().Where(u => u.CreateTime < DateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(stoppingToken); // 删除操作日志
 | 
			
		||||
        var daysAgo = 30; // 删除30天以前
 | 
			
		||||
        await db.Deleteable<SysVisitLog>().Where(u => u.CreateTime < SysDateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(); // 删除访问日志
 | 
			
		||||
        await db.Deleteable<SysOperateLog>().Where(u => u.CreateTime < SysDateTimeExtensions.CurrentDateTime.AddDays(-daysAgo)).ExecuteCommandAsync(); // 删除操作日志
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -20,7 +22,7 @@ public class LoginOpenApiEvent
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 时间
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public DateTime DateTime = DateTimeExtensions.CurrentDateTime;
 | 
			
		||||
    public DateTime DateTime = SysDateTimeExtensions.CurrentDateTime;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 登录设备
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
using Furion.EventBus;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -46,7 +48,7 @@ public class OpenApiAuthEventSubscriber : IEventSubscriber, ISingleton
 | 
			
		||||
        //更新用户信息
 | 
			
		||||
        if (await db.UpdateableWithAttr(openApiUser).ExecuteCommandAsync() > 0)
 | 
			
		||||
        {
 | 
			
		||||
            App.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id, openApiUser, false); //更新Cache信息
 | 
			
		||||
            CacheStatic.Cache.Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id, openApiUser, false); //更新Cache信息
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
using Furion.DataEncryption;
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
using Furion.EventBus;
 | 
			
		||||
@@ -18,7 +19,7 @@ using Furion.FriendlyException;
 | 
			
		||||
using Microsoft.AspNetCore.Authentication;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
@@ -148,7 +149,7 @@ public class OpenApiAuthService : IOpenApiAuthService, ITransient
 | 
			
		||||
        {
 | 
			
		||||
            bool isSingle = false;//默认不开启单用户登录
 | 
			
		||||
            var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
 | 
			
		||||
            if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool(false);//如果配置不为空则设置单用户登录选项为系统配置的值
 | 
			
		||||
            if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBoolean();//如果配置不为空则设置单用户登录选项为系统配置的值
 | 
			
		||||
 | 
			
		||||
            //判断是否单用户登录
 | 
			
		||||
            if (isSingle)
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -44,7 +46,7 @@ public class OpenApiSessionOutput : PrimaryKeyEntity
 | 
			
		||||
    /// 令牌数量
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Description("令牌数量")]
 | 
			
		||||
    [DataTable(Order = 4, IsShow = true, Sortable = false)]
 | 
			
		||||
    [DataTable(Order = 4, IsShow = true, Sortable = true)]
 | 
			
		||||
    public int VerificatCount { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -36,5 +38,5 @@ public interface IOpenApiSessionService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>B端会话列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -14,6 +14,8 @@ using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -58,12 +60,12 @@ public class OpenApiSessionService : DbRepository<OpenApiUser>, IOpenApiSessionS
 | 
			
		||||
    /// 获取verificat剩余时间信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="verificatInfos">verificat列表</param>
 | 
			
		||||
    private static void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
 | 
			
		||||
    private void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
 | 
			
		||||
    {
 | 
			
		||||
        verificatInfos = verificatInfos.ToList();
 | 
			
		||||
        verificatInfos.ForEach(it =>
 | 
			
		||||
        {
 | 
			
		||||
            var now = DateTimeExtensions.CurrentDateTime;
 | 
			
		||||
            var now = SysDateTimeExtensions.CurrentDateTime;
 | 
			
		||||
            it.VerificatRemain = now.GetDiffTime(it.VerificatTimeout);//获取时间差
 | 
			
		||||
            var verificatSecond = it.VerificatTimeout.AddMinutes(-it.Expire).ToLong();//颁发时间转为时间戳
 | 
			
		||||
            var timeoutSecond = it.VerificatTimeout.ToLong();//过期时间转为时间戳
 | 
			
		||||
@@ -71,7 +73,7 @@ public class OpenApiSessionService : DbRepository<OpenApiUser>, IOpenApiSessionS
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<OpenApiSessionOutput>> PageAsync(OpenApiSessionPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<OpenApiUser>()
 | 
			
		||||
            .WhereIF(!string.IsNullOrEmpty(input.Account), it => it.Account.Contains(input.Account))//根据账号查询
 | 
			
		||||
@@ -93,7 +95,7 @@ public class OpenApiSessionService : DbRepository<OpenApiUser>, IOpenApiSessionS
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -15,6 +15,8 @@ using SqlSugar;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -100,5 +102,5 @@ public interface IOpenApiUserService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>用户分页列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -16,11 +16,9 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -31,15 +29,13 @@ namespace ThingsGateway.Admin.Application;
 | 
			
		||||
public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
{
 | 
			
		||||
    private readonly IVerificatService _verificatService;
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="IOpenApiUserService"/>
 | 
			
		||||
    public OpenApiUserService(
 | 
			
		||||
        IVerificatService verificatService, IServiceScopeFactory serviceScopeFactory
 | 
			
		||||
        IVerificatService verificatService
 | 
			
		||||
                      )
 | 
			
		||||
    {
 | 
			
		||||
        _verificatService = verificatService;
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -83,9 +79,9 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
        List<OpenApiUser> openApiUsers = new();
 | 
			
		||||
        foreach (var item in userIds)
 | 
			
		||||
        {
 | 
			
		||||
            var user = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + item, false);//获取用户列表
 | 
			
		||||
            var user = CacheStatic.Cache.Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + item, false);//获取用户列表
 | 
			
		||||
            openApiUsers.Add(user);
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_OPENAPIUSER + item);
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_OPENAPIUSER + item);
 | 
			
		||||
        }
 | 
			
		||||
        openApiUsers = openApiUsers.Where(it => it != null).ToList();//过滤掉不存在的
 | 
			
		||||
        if (openApiUsers.Count > 0)
 | 
			
		||||
@@ -94,7 +90,7 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
            foreach (var item in accounts)
 | 
			
		||||
            {
 | 
			
		||||
                //删除账号
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_OPENAPIUSERACCOUNT + item);
 | 
			
		||||
                CacheStatic.Cache.Remove(CacheConst.CACHE_OPENAPIUSERACCOUNT + item);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -154,7 +150,7 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
    public async Task<long> GetIdByAccountAsync(string account)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿
 | 
			
		||||
        var userId = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<long>(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, false);
 | 
			
		||||
        var userId = CacheStatic.Cache.Get<long>(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, false);
 | 
			
		||||
        if (userId == 0)
 | 
			
		||||
        {
 | 
			
		||||
            //单查获取用户账号对应ID
 | 
			
		||||
@@ -162,7 +158,7 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
            if (userId != 0)
 | 
			
		||||
            {
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, userId, false);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CACHE_OPENAPIUSERACCOUNT + account, userId, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return userId;
 | 
			
		||||
@@ -190,7 +186,7 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
    public async Task<OpenApiUser> GetUsertByIdAsync(long Id)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
        var openApiUser = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + Id.ToString(), true);
 | 
			
		||||
        var openApiUser = CacheStatic.Cache.Get<OpenApiUser>(CacheConst.CACHE_OPENAPIUSER + Id.ToString(), true);
 | 
			
		||||
        if (openApiUser == null)
 | 
			
		||||
        {
 | 
			
		||||
            openApiUser = await Context.Queryable<OpenApiUser>()
 | 
			
		||||
@@ -199,7 +195,7 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
            if (openApiUser != null)
 | 
			
		||||
            {
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id.ToString(), openApiUser, true);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CACHE_OPENAPIUSER + openApiUser.Id.ToString(), openApiUser, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return openApiUser;
 | 
			
		||||
@@ -238,11 +234,11 @@ public class OpenApiUserService : DbRepository<OpenApiUser>, IOpenApiUserService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<OpenApiUser>> PageAsync(OpenApiUserPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<OpenApiUser>()
 | 
			
		||||
         .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.Account.Contains(input.SearchKey));//根据关键字查询
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -0,0 +1,104 @@
 | 
			
		||||
{
 | 
			
		||||
  "RECORDS": [
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222222",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_SWAGGER_NAME",
 | 
			
		||||
      "ConfigValue": "admin",
 | 
			
		||||
      "Remark": "swagger账号",
 | 
			
		||||
      "SortCode": "1",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222223",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_SWAGGER_PASSWORD",
 | 
			
		||||
      "ConfigValue": "123456",
 | 
			
		||||
      "Remark": "swagger密码",
 | 
			
		||||
      "SortCode": "2",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222224",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_SWAGGERLOGIN_OPEN",
 | 
			
		||||
      "ConfigValue": "false",
 | 
			
		||||
      "Remark": "swagger开启登录",
 | 
			
		||||
      "SortCode": "3",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222226",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_TITLE",
 | 
			
		||||
      "ConfigValue": "ThingsGateway",
 | 
			
		||||
      "Remark": "标题",
 | 
			
		||||
      "SortCode": "5",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222228",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_COPYRIGHT",
 | 
			
		||||
      "ConfigValue": "ThingsGateway ©2023 Diego",
 | 
			
		||||
      "Remark": "系统版权",
 | 
			
		||||
      "SortCode": "6",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222229",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_COPYRIGHT_URL",
 | 
			
		||||
      "ConfigValue": "https://gitee.com/diego2098/ThingsGateway",
 | 
			
		||||
      "Remark": "系统版权链接地址",
 | 
			
		||||
      "SortCode": "7",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222231",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_PASSWORD",
 | 
			
		||||
      "ConfigValue": "111111",
 | 
			
		||||
      "Remark": "默认用户密码",
 | 
			
		||||
      "SortCode": "8",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222227",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_VERIFICAT_EXPIRES",
 | 
			
		||||
      "ConfigValue": "14400",
 | 
			
		||||
      "Remark": "Verificat过期时间(分)",
 | 
			
		||||
      "SortCode": "9",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222232",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_SINGLE_OPEN",
 | 
			
		||||
      "ConfigValue": "false",
 | 
			
		||||
      "Remark": "单用户登录开关",
 | 
			
		||||
      "SortCode": "10",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222230",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_CAPTCHA_OPEN",
 | 
			
		||||
      "ConfigValue": "true",
 | 
			
		||||
      "Remark": "登录验证码开关",
 | 
			
		||||
      "SortCode": "11",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "22222222222225",
 | 
			
		||||
      "Category": "SYS_CONFIGBASEDEFAULT",
 | 
			
		||||
      "ConfigKey": "CONFIG_REMARK",
 | 
			
		||||
      "ConfigValue": "边缘采集网关",
 | 
			
		||||
      "Remark": "说明",
 | 
			
		||||
      "SortCode": "12",
 | 
			
		||||
      "IsDelete": "false"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
{
 | 
			
		||||
  "RECORDS": [
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "212725263001001",
 | 
			
		||||
      "Code": "superAdmin",
 | 
			
		||||
      "Name": "超级管理员",
 | 
			
		||||
      "SortCode": "1"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "212725263001002",
 | 
			
		||||
      "Code": "admin",
 | 
			
		||||
      "Name": "业务管理员",
 | 
			
		||||
      "SortCode": "2"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
{
 | 
			
		||||
  "RECORDS": [
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "212725263002001",
 | 
			
		||||
      "Account": "superAdmin",
 | 
			
		||||
      "LastLoginDevice": "PC",
 | 
			
		||||
      "LastLoginIp": "0.0.0.1",
 | 
			
		||||
      "LastLoginTime": "2023-03-03 21:18:43.7092169",
 | 
			
		||||
      "LatestLoginDevice": "PC",
 | 
			
		||||
      "LatestLoginIp": "0.0.0.1",
 | 
			
		||||
      "LatestLoginTime": "2023-03-03 21:19:16.1043309",
 | 
			
		||||
      "Password": "7DA385A25A98388E",
 | 
			
		||||
      "SortCode": "1",
 | 
			
		||||
      "UserEnable": "true",
 | 
			
		||||
      "IsDelete": "false",
 | 
			
		||||
      "UpdateTime": "2023-03-03 21:19:16.1202211"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "Id": "201725263002001",
 | 
			
		||||
      "Account": "admin",
 | 
			
		||||
      "LastLoginDevice": "PC",
 | 
			
		||||
      "LastLoginIp": "0.0.0.1",
 | 
			
		||||
      "LastLoginTime": "2023-03-03 18:20:49.1875384",
 | 
			
		||||
      "LatestLoginDevice": "PC",
 | 
			
		||||
      "LatestLoginIp": "0.0.0.1",
 | 
			
		||||
      "LatestLoginTime": "2023-03-03 18:23:08.6424099",
 | 
			
		||||
      "Password": "7DA385A25A98388E",
 | 
			
		||||
      "SortCode": "2",
 | 
			
		||||
      "UserEnable": "true",
 | 
			
		||||
      "IsDelete": "false",
 | 
			
		||||
      "UpdateTime": "2023-03-03 18:23:08.6727296"
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
@@ -10,22 +10,18 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Adapter.DLT645;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// <inheritdoc/>
 | 
			
		||||
/// 系统配置种子数据
 | 
			
		||||
/// </summary>
 | 
			
		||||
internal class DLT645_2007Message : MessageBase, IMessage
 | 
			
		||||
public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override int HeadBytesLength => -1;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public override bool CheckHeadBytes(byte[] heads)
 | 
			
		||||
    public IEnumerable<SysConfig> SeedData()
 | 
			
		||||
    {
 | 
			
		||||
        BodyLength = -1;
 | 
			
		||||
        return true;
 | 
			
		||||
        return SeedDataUtil.GetSeedData<SysConfig>("sys_config.json");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -10,21 +10,18 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Foundation.Core;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 通道类型
 | 
			
		||||
/// 角色种子数据
 | 
			
		||||
/// </summary>
 | 
			
		||||
public enum ChannelEnum
 | 
			
		||||
public class SysRoleSeedData : ISqlSugarEntitySeedData<SysRole>
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    None = 0,
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    TcpClient = 1,
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    SerialSession = 2,
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    UdpSession = 4,
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    TcpServer = 8,
 | 
			
		||||
    public IEnumerable<SysRole> SeedData()
 | 
			
		||||
    {
 | 
			
		||||
        return SeedDataUtil.GetSeedData<SysRole>("sys_role.json");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
#region copyright
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
//  此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
 | 
			
		||||
//  此代码版权(除特别声明外的代码)归作者本人Diego所有
 | 
			
		||||
//  源代码使用协议遵循本仓库的开源协议及附加协议
 | 
			
		||||
//  Gitee源代码仓库:https://gitee.com/diego2098/ThingsGateway
 | 
			
		||||
//  Github源代码仓库:https://github.com/kimdiego2098/ThingsGateway
 | 
			
		||||
//  使用文档:https://diego2098.gitee.io/thingsgateway-docs/
 | 
			
		||||
//  QQ群:605534569
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// 用户表种子数据
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
 | 
			
		||||
{
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public IEnumerable<SysUser> SeedData()
 | 
			
		||||
    {
 | 
			
		||||
        return SeedDataUtil.GetSeedData<SysUser>("sys_user.json");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,14 +10,15 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
using Furion.InstantMessaging;
 | 
			
		||||
using Furion.Logging.Extensions;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.Http.Connections.Features;
 | 
			
		||||
using Microsoft.AspNetCore.SignalR;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -27,19 +28,17 @@ namespace ThingsGateway.Admin.Application;
 | 
			
		||||
[MapHub(HubConst.SysHubUrl)]
 | 
			
		||||
public class SysHub : Hub<ISysHub>
 | 
			
		||||
{
 | 
			
		||||
    readonly ILogger<ISysHub> _logger;
 | 
			
		||||
    /// <inheritdoc cref="ISysHub"/>
 | 
			
		||||
    public SysHub(ILogger<ISysHub> logger)
 | 
			
		||||
    {
 | 
			
		||||
        _logger = logger;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 分隔符
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public const string Separate = "_s_e_p_a_r_a_t_e_";
 | 
			
		||||
    public const string SYS_TrackingCircuitHandlerid = "SYS_TrackingCircuitHandlerid";
 | 
			
		||||
 | 
			
		||||
    private readonly ILogger<ISysHub> _logger;
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    /// <inheritdoc cref="ISysHub"/>
 | 
			
		||||
    public SysHub(IServiceScopeFactory scopeFactory, ILogger<ISysHub> logger)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = scopeFactory.CreateScope();
 | 
			
		||||
        _logger = logger;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 连接
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -75,10 +74,10 @@ public class SysHub : Hub<ISysHub>
 | 
			
		||||
    /// <param name="isConnect">是否是上线</param>
 | 
			
		||||
    private async Task UpdateVerificatAsync(string userIdentifier, bool isConnect = true, long verificat = 0)
 | 
			
		||||
    {
 | 
			
		||||
        var userId = userIdentifier.Split(Separate)[0].ToLong();//分割取第一个
 | 
			
		||||
        var userId = userIdentifier.Split(SYS_TrackingCircuitHandlerid)[0].ToLong();//分割取第一个
 | 
			
		||||
        if (userId > 0)
 | 
			
		||||
        {
 | 
			
		||||
            var _verificatService = _serviceScope.ServiceProvider.GetService<IVerificatService>();
 | 
			
		||||
            var _verificatService = App.GetService<IVerificatService>();
 | 
			
		||||
            //获取cache当前用户的verificat信息列表
 | 
			
		||||
            List<VerificatInfo> verificatInfos = await _verificatService.GetVerificatIdAsync(userId);
 | 
			
		||||
 | 
			
		||||
@@ -106,6 +105,13 @@ public class SysHub : Hub<ISysHub>
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (isConnect)
 | 
			
		||||
                _logger.LogWarning($"未认证SignalR ID:{userIdentifier} 登录");
 | 
			
		||||
            else
 | 
			
		||||
                _logger.LogWarning($"未认证SignalR ID:{userIdentifier} 注销");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 方法
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
using Microsoft.AspNetCore.Http.Connections.Features;
 | 
			
		||||
using Microsoft.AspNetCore.SignalR;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ public class UserIdProvider : IUserIdProvider
 | 
			
		||||
 | 
			
		||||
        if (UserId > 0)
 | 
			
		||||
        {
 | 
			
		||||
            return $"{UserId}{SysHub.Separate}{YitIdHelper.NextId()}";//返回用户ID
 | 
			
		||||
            return $"{UserId}{SysHub.SYS_TrackingCircuitHandlerid}{YitIdHelper.NextId()}";//返回用户ID
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return connection.ConnectionId;
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -17,7 +19,6 @@ namespace ThingsGateway.Admin.Application;
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// AppStartup启动类
 | 
			
		||||
/// </summary>
 | 
			
		||||
[AppStartup(9997)]
 | 
			
		||||
public class Startup : AppStartup
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -26,6 +27,7 @@ public class Startup : AppStartup
 | 
			
		||||
    public void ConfigureServices(IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // 任务调度
 | 
			
		||||
        services.AddSchedule(options =>
 | 
			
		||||
        {
 | 
			
		||||
@@ -35,5 +37,7 @@ public class Startup : AppStartup
 | 
			
		||||
        //事件总线
 | 
			
		||||
        services.AddEventBus();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
using Furion.EventBus;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -47,7 +49,7 @@ public class AuthEventSubscriber : IEventSubscriber, ISingleton
 | 
			
		||||
        //更新用户信息
 | 
			
		||||
        if (await db.UpdateableWithAttr(sysUser).ExecuteCommandAsync() > 0)
 | 
			
		||||
        {
 | 
			
		||||
            App.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSUSER + sysUser.Id, sysUser, false); //更新Cache信息
 | 
			
		||||
            CacheStatic.Cache.Set(CacheConst.CACHE_SYSUSER + sysUser.Id, sysUser, false); //更新Cache信息
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
using Furion.DataEncryption;
 | 
			
		||||
using Furion.EventBus;
 | 
			
		||||
using Furion.FriendlyException;
 | 
			
		||||
@@ -17,11 +18,10 @@ using Furion.FriendlyException;
 | 
			
		||||
using Microsoft.AspNetCore.Authentication;
 | 
			
		||||
using Microsoft.AspNetCore.Authentication.Cookies;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
@@ -33,16 +33,16 @@ public class AuthService : IAuthService
 | 
			
		||||
    private readonly IConfigService _configService;
 | 
			
		||||
    private readonly IEventPublisher _eventPublisher;
 | 
			
		||||
    private readonly INoticeService _noticeService;
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    private readonly ISysUserService _userService;
 | 
			
		||||
    private readonly IVerificatService _verificatService;
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc cref="IAuthService"/>
 | 
			
		||||
    public AuthService(
 | 
			
		||||
                       IEventPublisher eventPublisher,
 | 
			
		||||
                       ISysUserService userService,
 | 
			
		||||
                       IConfigService configService,
 | 
			
		||||
                       IVerificatService verificatService,
 | 
			
		||||
                        INoticeService noticeService, IServiceScopeFactory serviceScopeFactory
 | 
			
		||||
                        INoticeService noticeService
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        _eventPublisher = eventPublisher;
 | 
			
		||||
@@ -50,7 +50,6 @@ public class AuthService : IAuthService
 | 
			
		||||
        _configService = configService;
 | 
			
		||||
        _verificatService = verificatService;
 | 
			
		||||
        _noticeService = noticeService;
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -61,15 +60,15 @@ public class AuthService : IAuthService
 | 
			
		||||
        //生成请求号,并将验证码放入cache
 | 
			
		||||
        var reqNo = YitIdHelper.NextId();
 | 
			
		||||
        //插入cache
 | 
			
		||||
        _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.LOGIN_CAPTCHA + reqNo, captchInfo, TimeSpan.FromMinutes(1), false);
 | 
			
		||||
        CacheStatic.Cache.Set(CacheConst.LOGIN_CAPTCHA + reqNo, captchInfo, TimeSpan.FromMinutes(1), false);
 | 
			
		||||
        //返回验证码和请求号
 | 
			
		||||
        return new ValidCodeOutput { CodeValue = captchInfo, ValidCodeReqNo = reqNo };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<SysUser> GetLoginUserAsync()
 | 
			
		||||
    public Task<SysUser> GetLoginUserAsync()
 | 
			
		||||
    {
 | 
			
		||||
        return await _userService.GetUserByIdAsync(UserManager.UserId);
 | 
			
		||||
        return _userService.GetUserByIdAsync(UserManager.UserId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -80,7 +79,7 @@ public class AuthService : IAuthService
 | 
			
		||||
 | 
			
		||||
        if (sysBase != null)//如果有这个配置项
 | 
			
		||||
        {
 | 
			
		||||
            if (sysBase.ConfigValue.ToBool(false))//如果需要验证码
 | 
			
		||||
            if (sysBase.ConfigValue.ToBoolean())//如果需要验证码
 | 
			
		||||
            {
 | 
			
		||||
                //如果没填验证码,提示验证码不能为空
 | 
			
		||||
                if (input.ValidCode.IsNullOrEmpty() || input.ValidCodeReqNo == 0) throw Oops.Bah("验证码不能为空").StatusCode(410);
 | 
			
		||||
@@ -89,7 +88,8 @@ public class AuthService : IAuthService
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var password = DESCEncryption.Decrypt(input.Password, DESCKeyConst.DESCKey);  // 解密
 | 
			
		||||
        var userInfo = await _userService.GetUserByAccountAsync(input.Account) ?? throw Oops.Bah("用户不存在");//获取用户信息
 | 
			
		||||
        var userInfo = await _userService.GetUserByAccountAsync(input.Account);//获取用户信息
 | 
			
		||||
        if (userInfo == null) throw Oops.Bah("用户不存在");//用户不存在
 | 
			
		||||
        if (userInfo.Password != password) throw Oops.Bah("账号密码错误");//账号密码错误
 | 
			
		||||
        return await LoginAsync(userInfo, input.Device);
 | 
			
		||||
    }
 | 
			
		||||
@@ -117,10 +117,10 @@ public class AuthService : IAuthService
 | 
			
		||||
    /// <param name="validCode">验证码</param>
 | 
			
		||||
    /// <param name="validCodeReqNo">请求号</param>
 | 
			
		||||
    /// <param name="isDelete">是否从Cache删除</param>
 | 
			
		||||
    private void ValidValidCode(string validCode, long validCodeReqNo, bool isDelete = true)
 | 
			
		||||
    private static void ValidValidCode(string validCode, long validCodeReqNo, bool isDelete = true)
 | 
			
		||||
    {
 | 
			
		||||
        var code = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<string>(CacheConst.LOGIN_CAPTCHA + validCodeReqNo, false);//从cache拿数据
 | 
			
		||||
        if (isDelete) _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.LOGIN_CAPTCHA + validCodeReqNo);//删除验证码
 | 
			
		||||
        var code = CacheStatic.Cache.Get<string>(CacheConst.LOGIN_CAPTCHA + validCodeReqNo, false);//从cache拿数据
 | 
			
		||||
        if (isDelete) CacheStatic.Cache.Remove(CacheConst.LOGIN_CAPTCHA + validCodeReqNo);//删除验证码
 | 
			
		||||
        if (code != null)//如果有
 | 
			
		||||
        {
 | 
			
		||||
            //验证码如果不匹配直接抛错误,这里忽略大小写
 | 
			
		||||
@@ -128,7 +128,7 @@ public class AuthService : IAuthService
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            throw Oops.Bah("验证码已过期");
 | 
			
		||||
            throw Oops.Bah("验证码不能为空");//抛出验证码不能为空
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -152,7 +152,7 @@ public class AuthService : IAuthService
 | 
			
		||||
        identity.AddClaim(new Claim(ClaimConst.IsOpenApi, false.ToString()));
 | 
			
		||||
 | 
			
		||||
        var config = sysBase.ConfigValue.ToInt(2880);
 | 
			
		||||
        var diffTime = DateTimeExtensions.CurrentDateTime.AddMinutes(config);
 | 
			
		||||
        var diffTime = SysDateTimeExtensions.CurrentDateTime.AddMinutes(config);
 | 
			
		||||
        await App.HttpContext.SignInAsync(new ClaimsPrincipal(identity), new AuthenticationProperties()
 | 
			
		||||
        {
 | 
			
		||||
            IsPersistent = true,
 | 
			
		||||
@@ -217,7 +217,7 @@ public class AuthService : IAuthService
 | 
			
		||||
            bool isSingle = false;//默认不开启单用户登录
 | 
			
		||||
 | 
			
		||||
            var singleConfig = await _configService.GetByConfigKeyAsync(ConfigConst.SYS_CONFIGBASEDEFAULT, ConfigConst.CONFIG_SINGLE_OPEN);//获取系统单用户登录选项
 | 
			
		||||
            if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBool(false);//如果配置不为空则设置单用户登录选项为系统配置的值
 | 
			
		||||
            if (singleConfig != null) isSingle = singleConfig.ConfigValue.ToBoolean();//如果配置不为空则设置单用户登录选项为系统配置的值
 | 
			
		||||
            if (isSingle)//判断是否单用户登录
 | 
			
		||||
            {
 | 
			
		||||
                await _noticeService.LogoutAsync(loginEvent.SysUser.Id, verificatInfos.Where(it => it.Device == loginEvent.Device.ToString()).ToList(), "该账号已在别处登录!");//通知其他用户下线
 | 
			
		||||
@@ -10,6 +10,8 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -20,7 +22,7 @@ public class LoginEvent
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 时间
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public DateTime DateTime = DateTimeExtensions.CurrentDateTime;
 | 
			
		||||
    public DateTime DateTime = SysDateTimeExtensions.CurrentDateTime;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 登录设备
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -15,6 +15,8 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -70,7 +72,7 @@ public class ButtonService : DbRepository<SysResource>, IButtonService
 | 
			
		||||
        //遍历关系表
 | 
			
		||||
        relationList.ForEach(it =>
 | 
			
		||||
        {
 | 
			
		||||
            var relationRoleResuorce = it.ExtJson.FromJsonString<RelationRoleResuorce>();//拓展信息转实体
 | 
			
		||||
            var relationRoleResuorce = it.ExtJson.ToJsonWithT<RelationRoleResuorce>();//拓展信息转实体
 | 
			
		||||
            var buttonInfo = relationRoleResuorce.ButtonInfo;//获取按钮信息
 | 
			
		||||
            if (buttonInfo.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
@@ -123,12 +125,12 @@ public class ButtonService : DbRepository<SysResource>, IButtonService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysResource>()
 | 
			
		||||
                         .Where(it => it.ParentId == input.ParentId && it.Category == ResourceCategoryEnum.BUTTON)
 | 
			
		||||
                         .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title.Contains(input.SearchKey) || it.Component.Contains(input.SearchKey));//根据关键字查询
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -47,5 +49,5 @@ public interface IButtonService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询条件</param>
 | 
			
		||||
    /// <returns>按钮分页列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysResource>> PageAsync(ButtonPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -23,11 +23,6 @@ namespace ThingsGateway.Admin.Application;
 | 
			
		||||
[Injection(Proxy = typeof(OperDispatchProxy))]
 | 
			
		||||
public class ConfigService : DbRepository<SysConfig>, IConfigService
 | 
			
		||||
{
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    public ConfigService(IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    [OperDesc("编辑网关系统配置")]
 | 
			
		||||
    public async Task EditBatchAsync(List<SysConfig> sysConfigs)
 | 
			
		||||
@@ -75,27 +70,27 @@ public class ConfigService : DbRepository<SysConfig>, IConfigService
 | 
			
		||||
    public async Task<List<SysConfig>> GetListByCategoryAsync(string category)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
        var configList = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysConfig>>(CacheConst.SYS_CONFIGCATEGORY + category, true);
 | 
			
		||||
        var configList = CacheStatic.Cache.Get<List<SysConfig>>(CacheConst.SYS_CONFIGCATEGORY + category, true);
 | 
			
		||||
        if (configList == null)
 | 
			
		||||
        {
 | 
			
		||||
            //cache没有再去数据可拿
 | 
			
		||||
            configList = await Context.Queryable<SysConfig>().Where(it => it.Category == category).OrderBy(it => it.SortCode).ToListAsync();//获取系统配置列表
 | 
			
		||||
            if (configList.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.SYS_CONFIGCATEGORY + category, configList, true);//如果不为空,插入cache
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.SYS_CONFIGCATEGORY + category, configList, true);//如果不为空,插入cache
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return configList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysConfig>()
 | 
			
		||||
                         .Where(it => it.Category == ConfigConst.SYS_CONFIGOTHER)//自定义配置
 | 
			
		||||
                         .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.ConfigKey.Contains(input.SearchKey) || it.ConfigKey.Contains(input.SearchKey));
 | 
			
		||||
        //根据关键字查询
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -130,7 +125,7 @@ public class ConfigService : DbRepository<SysConfig>, IConfigService
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    private void RefreshCache(string category)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.SYS_CONFIGCATEGORY + category);//cache删除
 | 
			
		||||
        CacheStatic.Cache.Remove(CacheConst.SYS_CONFIGCATEGORY + category);//cache删除
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #endregion 方法
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -66,5 +68,5 @@ public interface IConfigService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>其他配置列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysConfig>> PageAsync(ConfigPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -17,6 +17,8 @@ using Mapster;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -10,8 +10,11 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
#endregion
 | 
			
		||||
 | 
			
		||||
using Furion;
 | 
			
		||||
 | 
			
		||||
using Microsoft.AspNetCore.SignalR;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -20,23 +23,18 @@ namespace ThingsGateway.Admin.Application;
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class NoticeService : INoticeService
 | 
			
		||||
{
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    public NoticeService(IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task LogoutAsync(long userId, List<VerificatInfo> verificatInfos, string message)
 | 
			
		||||
    {
 | 
			
		||||
        //客户端ID列表
 | 
			
		||||
        var clientIds = new List<string>();
 | 
			
		||||
        //遍历cancellationToken列表获取客户端ID列表
 | 
			
		||||
        //遍历token列表获取客户端ID列表
 | 
			
		||||
        verificatInfos.ForEach(it =>
 | 
			
		||||
        {
 | 
			
		||||
            clientIds.AddRange(it.ClientIds);
 | 
			
		||||
        });
 | 
			
		||||
        //获取signalr实例
 | 
			
		||||
        var signalr = _serviceScope.ServiceProvider.GetService<IHubContext<SysHub, ISysHub>>();
 | 
			
		||||
        var signalr = App.GetService<IHubContext<SysHub, ISysHub>>();
 | 
			
		||||
        //发送其他客户端登录消息
 | 
			
		||||
        await signalr.Clients.Users(clientIds).Logout(message);
 | 
			
		||||
    }
 | 
			
		||||
@@ -23,5 +23,4 @@ public class OperateLogPageInput : VisitLogPageInput
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class OperateLogInput : VisitLogInput
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -43,5 +45,5 @@ public interface IOperateLogService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>分页列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -18,6 +18,8 @@ using MiniExcelLibs;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -45,12 +47,12 @@ public class OperateLogService : DbRepository<SysOperateLog>, IOperateLogService
 | 
			
		||||
        {
 | 
			
		||||
            #region sheet
 | 
			
		||||
            //变量页
 | 
			
		||||
            var data = devData.GetType().GetProperties();
 | 
			
		||||
            var data = devData.GetType().GetPropertiesWithCache();
 | 
			
		||||
            Dictionary<string, object> devExport = new();
 | 
			
		||||
            foreach (var item in data)
 | 
			
		||||
            {
 | 
			
		||||
                //描述
 | 
			
		||||
                var desc = item.FindDisplayAttribute();
 | 
			
		||||
                var desc = TypeExtensions.FindDisplayAttribute(item);
 | 
			
		||||
                //数据源增加
 | 
			
		||||
                devExport.Add(desc ?? item.Name, item.GetValue(devData)?.ToString());
 | 
			
		||||
            }
 | 
			
		||||
@@ -64,7 +66,6 @@ public class OperateLogService : DbRepository<SysOperateLog>, IOperateLogService
 | 
			
		||||
 | 
			
		||||
        var memoryStream = new MemoryStream();
 | 
			
		||||
        await memoryStream.SaveAsAsync(sheets);
 | 
			
		||||
        memoryStream.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
        return memoryStream;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -77,7 +78,7 @@ public class OperateLogService : DbRepository<SysOperateLog>, IOperateLogService
 | 
			
		||||
        return await ExportFileAsync(data);
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SysOperateLog>> PageAsync(OperateLogPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = GetPage(input);
 | 
			
		||||
        var pageInfo = await query.ToPagedListAsync(input.Current, input.Size);//分页
 | 
			
		||||
@@ -87,15 +88,13 @@ public class OperateLogService : DbRepository<SysOperateLog>, IOperateLogService
 | 
			
		||||
    private ISugarQueryable<SysOperateLog> GetPage(OperateLogPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysOperateLog>()
 | 
			
		||||
                             .WhereIF(input.StartTime != null, a => a.OpTime >= input.StartTime.Value.ToLocalTime())
 | 
			
		||||
                           .WhereIF(input.EndTime != null, a => a.OpTime <= input.EndTime.Value.ToLocalTime())
 | 
			
		||||
                           .WhereIF(!string.IsNullOrEmpty(input.Account), it => it.OpAccount == input.Account)//根据账号查询
 | 
			
		||||
                           .WhereIF(!string.IsNullOrEmpty(input.Category), it => it.Category == input.Category)//根据分类查询
 | 
			
		||||
                           .WhereIF(!string.IsNullOrEmpty(input.ExeStatus), it => it.ExeStatus == input.ExeStatus)//根据结果查询
 | 
			
		||||
                           .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Name.Contains(input.SearchKey) || it.OpIp.Contains(input.SearchKey));//根据关键字查询
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,23 +12,18 @@
 | 
			
		||||
 | 
			
		||||
using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="IRelationService"/>
 | 
			
		||||
public class RelationService : DbRepository<SysRelation>, IRelationService
 | 
			
		||||
{
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    public RelationService(IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<List<SysRelation>> GetRelationByCategoryAsync(string category)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
        var sysRelations = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysRelation>>(CacheConst.CACHE_SYSRELATION + category, true);
 | 
			
		||||
        var sysRelations = CacheStatic.Cache.Get<List<SysRelation>>(CacheConst.CACHE_SYSRELATION + category, true);
 | 
			
		||||
        if (sysRelations == null)
 | 
			
		||||
        {
 | 
			
		||||
            //cache没有就去数据库拿
 | 
			
		||||
@@ -36,7 +31,7 @@ public class RelationService : DbRepository<SysRelation>, IRelationService
 | 
			
		||||
            if (sysRelations.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSRELATION + category, sysRelations, true);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CACHE_SYSRELATION + category, sysRelations, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return sysRelations;
 | 
			
		||||
@@ -85,7 +80,7 @@ public class RelationService : DbRepository<SysRelation>, IRelationService
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public void RefreshCache(string category)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRELATION + category);//删除cache
 | 
			
		||||
        CacheStatic.Cache.Remove(CacheConst.CACHE_SYSRELATION + category);//删除cache
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -94,5 +96,10 @@ public interface IResourceService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="data"></param>
 | 
			
		||||
    List<SysResource> ResourceTreeToList(List<SysResource> data);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取PageTabItems
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="nav"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    List<PageTabItem> SameLevelMenuPasePageTab(List<SysResource> nav);
 | 
			
		||||
}
 | 
			
		||||
@@ -12,19 +12,21 @@
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Tab表示类
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <param name="Title">标题</param>
 | 
			
		||||
/// <param name="Href">跳转类型</param>
 | 
			
		||||
/// <param name="Icon">图标</param>
 | 
			
		||||
public record PageTabItem(string Title, string Href, string Icon);
 | 
			
		||||
 | 
			
		||||
/// <inheritdoc cref="IResourceService"/>
 | 
			
		||||
public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
{
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    public ResourceService(IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
    {
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<List<SysResource>> GetaMenuAndSpaListAsync()
 | 
			
		||||
    {
 | 
			
		||||
@@ -59,7 +61,7 @@ public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
    public async Task<List<SysResource>> GetListByCategoryAsync(ResourceCategoryEnum category)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
        var sysResources = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysResource>>(CacheConst.CACHE_SYSRESOURCE + category.ToString(), true);
 | 
			
		||||
        var sysResources = CacheStatic.Cache.Get<List<SysResource>>(CacheConst.CACHE_SYSRESOURCE + category.ToString(), true);
 | 
			
		||||
        if (sysResources == null)
 | 
			
		||||
        {
 | 
			
		||||
            //cache没有就去数据库拿
 | 
			
		||||
@@ -67,7 +69,7 @@ public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
            if (sysResources.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSRESOURCE + category.ToString(), sysResources, true);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CACHE_SYSRESOURCE + category.ToString(), sysResources, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return sysResources;
 | 
			
		||||
@@ -198,14 +200,14 @@ public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
        if (category == ResourceCategoryEnum.None)
 | 
			
		||||
        {
 | 
			
		||||
            //删除全部key
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.SPA.ToString());
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.BUTTON.ToString());
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.MENU.ToString());
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.SPA.ToString());
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.BUTTON.ToString());
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSRESOURCE + ResourceCategoryEnum.MENU.ToString());
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            //否则只删除一个Key
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSRESOURCE + category.ToString());
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSRESOURCE + category.ToString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -244,6 +246,23 @@ public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc />
 | 
			
		||||
    public List<PageTabItem> SameLevelMenuPasePageTab(List<SysResource> nav)
 | 
			
		||||
    {
 | 
			
		||||
        List<PageTabItem> pageTabItems = new();
 | 
			
		||||
        if (nav == null) return pageTabItems;
 | 
			
		||||
        foreach (var item in nav)
 | 
			
		||||
        {
 | 
			
		||||
            if ((item.Category == ResourceCategoryEnum.MENU || item.Category == ResourceCategoryEnum.SPA) && item.TargetType == TargetTypeEnum.SELF)
 | 
			
		||||
            {
 | 
			
		||||
                if (item.Icon == null)
 | 
			
		||||
                    pageTabItems.Add(new PageTabItem(item.Title, item.Component, ""));
 | 
			
		||||
                else
 | 
			
		||||
                    pageTabItems.Add(new PageTabItem(item.Title, item.Component, item.Icon));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return pageTabItems;
 | 
			
		||||
    }
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取授权菜单类菜单名称
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -258,7 +277,7 @@ public class ResourceService : DbRepository<SysResource>, IResourceService
 | 
			
		||||
        if (parentList.Count > 0)
 | 
			
		||||
        {
 | 
			
		||||
            var titles = parentList.Select(it => it.Title).ToList();//提取出父级的name
 | 
			
		||||
            var title = $"{string.Join("- ", titles)}-{menu.Title}";//根据-分割,转换成字符串并在最后加上菜单的title
 | 
			
		||||
            var title = string.Join("- ", titles) + $"-{menu.Title}";//根据-分割,转换成字符串并在最后加上菜单的title
 | 
			
		||||
            return title;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -86,7 +88,7 @@ public interface IRoleService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysRole>> PageAsync(RolePageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysRole>> PageAsync(RolePageInput input);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 刷新缓存
 | 
			
		||||
@@ -16,9 +16,7 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
@@ -31,19 +29,16 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
        private readonly IEventPublisher _eventPublisher;
 | 
			
		||||
        private readonly IRelationService _relationService;
 | 
			
		||||
        private readonly IResourceService _resourceService;
 | 
			
		||||
        private readonly IServiceScope _serviceScope;
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc cref="IRoleService"/>
 | 
			
		||||
        public RoleService(
 | 
			
		||||
                           IRelationService relationService,
 | 
			
		||||
                           IResourceService resourceService,
 | 
			
		||||
                           IEventPublisher eventPublisher,
 | 
			
		||||
                           IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
                           IEventPublisher eventPublisher)
 | 
			
		||||
        {
 | 
			
		||||
            _relationService = relationService;
 | 
			
		||||
            _resourceService = resourceService;
 | 
			
		||||
            _eventPublisher = eventPublisher;
 | 
			
		||||
            _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
@@ -143,7 +138,7 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
        public override async Task<List<SysRole>> GetListAsync()
 | 
			
		||||
        {
 | 
			
		||||
            //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
            var sysRoles = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<List<SysRole>>(CacheConst.CACHE_SYSROLE, true);
 | 
			
		||||
            var sysRoles = CacheStatic.Cache.Get<List<SysRole>>(CacheConst.CACHE_SYSROLE, true);
 | 
			
		||||
            if (sysRoles == null)
 | 
			
		||||
            {
 | 
			
		||||
                //cache没有就去数据库拿
 | 
			
		||||
@@ -151,7 +146,7 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
                if (sysRoles.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    //插入Cache
 | 
			
		||||
                    _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSROLE, sysRoles, true);
 | 
			
		||||
                    CacheStatic.Cache.Set(CacheConst.CACHE_SYSROLE, sysRoles, true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return sysRoles;
 | 
			
		||||
@@ -313,7 +308,7 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
            relations.ForEach(it =>
 | 
			
		||||
            {
 | 
			
		||||
                //将扩展信息转为实体
 | 
			
		||||
                var relationRole = it.ExtJson.FromJsonString<RelationRoleResuorce>();
 | 
			
		||||
                var relationRole = it.ExtJson.ToJsonWithT<RelationRoleResuorce>();
 | 
			
		||||
                GrantInfoList.Add(relationRole);//添加到已授权信息
 | 
			
		||||
            });
 | 
			
		||||
            roleOwnResource.GrantInfoList = GrantInfoList;//赋值已授权信息
 | 
			
		||||
@@ -329,11 +324,11 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc/>
 | 
			
		||||
        public async Task<ISqlSugarPagedList<SysRole>> PageAsync(RolePageInput input)
 | 
			
		||||
        public async Task<SqlSugarPagedList<SysRole>> PageAsync(RolePageInput input)
 | 
			
		||||
        {
 | 
			
		||||
            var query = Context.Queryable<SysRole>()
 | 
			
		||||
                             .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Name.Contains(input.SearchKey));//根据关键字查询
 | 
			
		||||
            for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
            for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
            }
 | 
			
		||||
@@ -346,7 +341,7 @@ namespace ThingsGateway.Admin.Application
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public void RefreshCache()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSROLE);//删除KEY
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSROLE);//删除KEY
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -51,7 +53,7 @@ public class SessionOutput : PrimaryKeyEntity
 | 
			
		||||
    /// 令牌数量
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Description("令牌数量")]
 | 
			
		||||
    [DataTable(Order = 5, IsShow = true, Sortable = false)]
 | 
			
		||||
    [DataTable(Order = 5, IsShow = true, Sortable = true)]
 | 
			
		||||
    public int VerificatCount { get; set; }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -36,5 +38,5 @@ public interface ISessionService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>会话列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -14,6 +14,8 @@ using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -61,7 +63,7 @@ public class SessionService : DbRepository<SysUser>, ISessionService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SessionOutput>> PageAsync(SessionPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysUser>()
 | 
			
		||||
              .WhereIF(!string.IsNullOrEmpty(input.Account), it => it.Account.Contains(input.Account))//根据账号查询
 | 
			
		||||
@@ -86,7 +88,7 @@ public class SessionService : DbRepository<SysUser>, ISessionService
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
              });
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -101,11 +103,11 @@ public class SessionService : DbRepository<SysUser>, ISessionService
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取verificat剩余时间信息
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private static void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
 | 
			
		||||
    private void GetVerificatInfos(ref List<VerificatInfo> verificatInfos)
 | 
			
		||||
    {
 | 
			
		||||
        verificatInfos.ForEach(it =>
 | 
			
		||||
        {
 | 
			
		||||
            var now = DateTimeExtensions.CurrentDateTime;
 | 
			
		||||
            var now = SysDateTimeExtensions.CurrentDateTime;
 | 
			
		||||
            it.VerificatRemain = now.GetDiffTime(it.VerificatTimeout);//获取时间差
 | 
			
		||||
            var verificatSecond = it.VerificatTimeout.AddMinutes(-it.Expire).ToLong();//颁发时间转为时间戳
 | 
			
		||||
            var timeoutSecond = it.VerificatTimeout.ToLong();//过期时间转为时间戳
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -45,5 +47,5 @@ public interface ISpaService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input);
 | 
			
		||||
}
 | 
			
		||||
@@ -15,6 +15,8 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
using Yitter.IdGenerator;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
@@ -77,13 +79,13 @@ public class SpaService : DbRepository<SysResource>, ISpaService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SysResource>> PageAsync(SpaPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysResource>()
 | 
			
		||||
                         .Where(it => it.Category == ResourceCategoryEnum.SPA)//单页
 | 
			
		||||
                         .WhereIF(input.TargetType != 0, it => it.TargetType == input.TargetType)//根据菜单类型查询
 | 
			
		||||
                         .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title.Contains(input.SearchKey) || it.Component.Contains(input.SearchKey));//根据关键字查询
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -14,6 +14,8 @@ using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -107,7 +109,7 @@ public interface ISysUserService : ITransient
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="input">查询参数</param>
 | 
			
		||||
    /// <returns>用户分页列表</returns>
 | 
			
		||||
    Task<ISqlSugarPagedList<SysUser>> PageAsync(UserPageInput input);
 | 
			
		||||
    Task<SqlSugarPagedList<SysUser>> PageAsync(UserPageInput input);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 重置密码
 | 
			
		||||
@@ -16,11 +16,9 @@ using Furion.FriendlyException;
 | 
			
		||||
 | 
			
		||||
using Mapster;
 | 
			
		||||
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using SqlSugar;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Foundation.Extension.String;
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
@@ -33,22 +31,19 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
    private readonly IResourceService _resourceService;
 | 
			
		||||
    private readonly IRoleService _roleService;
 | 
			
		||||
    private readonly IVerificatService _verificatService;
 | 
			
		||||
    private readonly IServiceScope _serviceScope;
 | 
			
		||||
    /// <inheritdoc cref="ISysUserService"/>
 | 
			
		||||
    public SysUserService(
 | 
			
		||||
                       IRelationService relationService,
 | 
			
		||||
                       IResourceService resourceService,
 | 
			
		||||
                       IVerificatService verificatService,
 | 
			
		||||
                       IRoleService roleService,
 | 
			
		||||
                       IConfigService configService,
 | 
			
		||||
                           IServiceScopeFactory serviceScopeFactory)
 | 
			
		||||
                       IConfigService configService)
 | 
			
		||||
    {
 | 
			
		||||
        _relationService = relationService;
 | 
			
		||||
        _resourceService = resourceService;
 | 
			
		||||
        _roleService = roleService;
 | 
			
		||||
        _configService = configService;
 | 
			
		||||
        _verificatService = verificatService;
 | 
			
		||||
        _serviceScope = serviceScopeFactory.CreateScope();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
@@ -100,10 +95,10 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
        List<SysUser> sysUsers = new();
 | 
			
		||||
        foreach (var item in ids)
 | 
			
		||||
        {
 | 
			
		||||
            var user = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<SysUser>(CacheConst.CACHE_SYSUSER + item, false);//获取用户列表
 | 
			
		||||
            var user = CacheStatic.Cache.Get<SysUser>(CacheConst.CACHE_SYSUSER + item, false);//获取用户列表
 | 
			
		||||
            sysUsers.Add(user);
 | 
			
		||||
            //删除账号
 | 
			
		||||
            _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CACHE_SYSUSER + item);
 | 
			
		||||
            CacheStatic.Cache.Remove(CacheConst.CACHE_SYSUSER + item);
 | 
			
		||||
        }
 | 
			
		||||
        sysUsers = sysUsers.Where(it => it != null).ToList();//过滤掉不存在的
 | 
			
		||||
        if (sysUsers.Count > 0)
 | 
			
		||||
@@ -112,7 +107,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
            foreach (var item in accounts)
 | 
			
		||||
            {
 | 
			
		||||
                //删除账号
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Remove(CacheConst.CAHCE_SYSUSERACCOUNT + item);
 | 
			
		||||
                CacheStatic.Cache.Remove(CacheConst.CAHCE_SYSUSERACCOUNT + item);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -191,7 +186,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
            var resourceList = await _relationService.GetRelationListByObjectIdListAndCategoryAsync(roleIdList, CateGoryConst.Relation_SYS_ROLE_HAS_RESOURCE);//获取资源集合
 | 
			
		||||
            resourceList.ForEach(it =>
 | 
			
		||||
            {
 | 
			
		||||
                if (!string.IsNullOrEmpty(it.ExtJson)) buttonIdList.AddRange(it.ExtJson.FromJsonString<RelationRoleResuorce>().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList
 | 
			
		||||
                if (!string.IsNullOrEmpty(it.ExtJson)) buttonIdList.AddRange(it.ExtJson.ToJsonWithT<RelationRoleResuorce>().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList
 | 
			
		||||
            });
 | 
			
		||||
            if (buttonIdList.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
@@ -205,7 +200,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
    public async Task<long> GetIdByAccountAsync(string account)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿
 | 
			
		||||
        var userId = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<long>(CacheConst.CAHCE_SYSUSERACCOUNT + account, false);
 | 
			
		||||
        var userId = CacheStatic.Cache.Get<long>(CacheConst.CAHCE_SYSUSERACCOUNT + account, false);
 | 
			
		||||
        if (userId == 0)
 | 
			
		||||
        {
 | 
			
		||||
            //单查获取用户账号对应ID
 | 
			
		||||
@@ -213,7 +208,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
            if (userId != 0)
 | 
			
		||||
            {
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CAHCE_SYSUSERACCOUNT + account, userId, false);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CAHCE_SYSUSERACCOUNT + account, userId, false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return userId;
 | 
			
		||||
@@ -237,7 +232,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
                var relationList = it.ToList();//关系列表
 | 
			
		||||
                relationList.ForEach(it =>
 | 
			
		||||
                {
 | 
			
		||||
                    var rolePermission = it.ExtJson.FromJsonString<RelationRolePermission>();
 | 
			
		||||
                    var rolePermission = it.ExtJson.ToJsonWithT<RelationRolePermission>();
 | 
			
		||||
                    scopeSet.Add(rolePermission.ApiUrl);
 | 
			
		||||
                });
 | 
			
		||||
                permissions.AddRange(scopeSet);//将改URL的权限集合加入权限集合列表
 | 
			
		||||
@@ -268,7 +263,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
    public async Task<SysUser> GetUserByIdAsync(long Id)
 | 
			
		||||
    {
 | 
			
		||||
        //先从Cache拿,需要获取新的对象,避免操作导致缓存中对象改变
 | 
			
		||||
        var sysUser = _serviceScope.ServiceProvider.GetService<MemoryCache>().Get<SysUser>(CacheConst.CACHE_SYSUSER + Id.ToString(), true);
 | 
			
		||||
        var sysUser = CacheStatic.Cache.Get<SysUser>(CacheConst.CACHE_SYSUSER + Id.ToString(), true);
 | 
			
		||||
        if (sysUser == null)
 | 
			
		||||
        {
 | 
			
		||||
            sysUser = await Context.Queryable<SysUser>()
 | 
			
		||||
@@ -289,7 +284,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
                sysUser.RoleIdList = roleCodeList.Select(it => it.Id).ToList();
 | 
			
		||||
                sysUser.PermissionCodeList = permissionCodeList;
 | 
			
		||||
                //插入Cache
 | 
			
		||||
                _serviceScope.ServiceProvider.GetService<MemoryCache>().Set(CacheConst.CACHE_SYSUSER + sysUser.Id.ToString(), sysUser, true);
 | 
			
		||||
                CacheStatic.Cache.Set(CacheConst.CACHE_SYSUSER + sysUser.Id.ToString(), sysUser, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return sysUser;
 | 
			
		||||
@@ -321,7 +316,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <inheritdoc/>
 | 
			
		||||
    public async Task<ISqlSugarPagedList<SysUser>> PageAsync(UserPageInput input)
 | 
			
		||||
    public async Task<SqlSugarPagedList<SysUser>> PageAsync(UserPageInput input)
 | 
			
		||||
    {
 | 
			
		||||
        var query = Context.Queryable<SysUser>()
 | 
			
		||||
         .WhereIF(input.Expression != null, input.Expression?.ToExpression())//动态查询
 | 
			
		||||
@@ -330,7 +325,7 @@ public class SysUserService : DbRepository<SysUser>, ISysUserService
 | 
			
		||||
         {
 | 
			
		||||
             u.Password = null;//密码清空
 | 
			
		||||
         });
 | 
			
		||||
        for (int i = input.SortField.Count - 1; i >= 0; i--)
 | 
			
		||||
        for (int i = 0; i < input.SortField.Count; i++)
 | 
			
		||||
        {
 | 
			
		||||
            query = query.OrderByIF(!string.IsNullOrEmpty(input.SortField[i]), $"{input.SortField[i]} {(input.SortDesc[i] ? "desc" : "asc")}");
 | 
			
		||||
        }
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
 | 
			
		||||
using Furion.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
using ThingsGateway.Admin.Core;
 | 
			
		||||
 | 
			
		||||
namespace ThingsGateway.Admin.Application;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
@@ -48,9 +50,9 @@ public interface IUserCenterService : ITransient
 | 
			
		||||
    /// 设置个人主页
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="userId"></param>
 | 
			
		||||
    /// <param name="defaultRazor"></param>
 | 
			
		||||
    /// <param name="defalutRazor"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    Task UpdateUserDefaultRazorAsync(long userId, long defaultRazor);
 | 
			
		||||
    Task UpdateUserDefaultRazorAsync(long userId, long defalutRazor);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 更新个人信息
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user