mirror of
				https://github.com/snltty/linker.git
				synced 2025-10-31 04:26:45 +08:00 
			
		
		
		
	同步
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -117,4 +117,287 @@ | ||||
|   <resheader name="writer"> | ||||
|     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
|   </resheader> | ||||
|   <data name="label15.Text" xml:space="preserve"> | ||||
|     <value>每项1024长度,0项保留不可用</value> | ||||
|   </data> | ||||
|   <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|     <value> | ||||
|         AAABAAEAAAAAAAEAIABdQAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAEAAAABAAgGAAAAXHKoZgAAQCRJ | ||||
|         REFUeNrtnXd8XMW5sJ/ZIq16lyzZsi1Z7sYFY9xxwwUINU7hkpBCQsKFG0joBGKZllySmwspBEJyk5BQ | ||||
|         EhIwfDHYuGKMK+7dlmXZkmVZVu9b5/tjJFuWzqrualfSPP6dn9Y7Z8+Zc3bnPe+88xbQaDQajUbT/xCB | ||||
|         7oDGx2RffCUu/pXN3hOAvNjatI+8+J5s/P+lVnlxn8uPr+kDaAEQzGQ3/hWEAjYkNiAMsDVuUQgSkEQD | ||||
|         4Y1bWIvXoUBI42YBrI1/QxpfAzgBB+BqfO1q/L8DsAP1QF3j1vx1FYJSJNVAQ2NbA9CAiQbM2JHAk4G+ | ||||
|         kRpvaAEQKLIvvjIhMWPGCsTiIRlIBlIa/yYDiUA8ENtsi0MNcAGYGo8lmm3+QDbbADyNr+uBcqCi2VYG | ||||
|         lADFwHkExUiKMVGMoAInTkJwk4yHSuDhQH0R/RstAHqKZwCw4iYeSAASEAxCMgIYDmRxaVA3bTbAHOiu | ||||
|         dxM3l7SDpq0MyUkEJ4DjSAqAEkyUYqIccPJUoLvdP9ACwNc8i7qrLqxIwoAkYDQwBhgFDAEGAmlAJPo7 | ||||
|         kEANUAicBU4DR4FDwBEkFxA0oKYm2gbhY/r7j883ZAPqSZ2KepKPAsYBVwAZQDQQgZp7a9rHBdQCVcAp | ||||
|         4ACCA0iOATnAOcCthUH30QKgKzwNgBkPscBQYCowBfWkz0LN1/W99S0SKEUJgKPADgTbgdMIKgA3Pwl0 | ||||
|         F3sf+kfaUX4CCEwIBgETUIN+NupJH4myqmt6Dgdq6nAQ2ARsR7APOIvEo7WDjqEFQFtkA4JwYBCSq5HM | ||||
|         RzARyARiAt09zWVUAieBvcB6BDuBAiR1Whh4RwuA5mQDM4HPMeFkIB5mA/OBeUA6l9bNNcGNE8gHNgDr | ||||
|         EHyKpBC1bKkNic3QAqCJxwAbSQgmI7kBuAb1pI8MdNc03aIGyAU+Af4N7AEuaCGg6L8CIPviKwtqae4G | ||||
|         4EZgGnrQ91VqgC0oQbASwRkcuAgHfhzorgWG/icAnkctLoURjeRK4GbgOpQ1PzTQ3dP0CHYgD/gQwfvA | ||||
|         HuqpIhp4ItBd61n6jwDIRtnpncQjmQ/cAcxCudlq+i8XgM3Am8A6lEtzv7ET9A8BsAwwkYhkIXAnavku | ||||
|         ItDd0gQVNShB8BcEa/BQyvJAd8n/9G0BkA2oJ/x1qIE/HT3wNW1TA2wFXkewijWU8G3g24Huln/omwJg | ||||
|         OSAIw8Ni4PvAXPT8XtM5GoCNwKtIViOo74vTgr4lAJTKFgpchYd7EFyHcsvVaLpKKZIPMfEKgl1I7CwL | ||||
|         dJd8R98QAE+hIs9TyEQ98e9ARdtpNL7iLPAGglc4xikyUZGfvZzeLwCyAYhCchOCB4BJ9P4Yek1w4gZ2 | ||||
|         A/+L4N9AdW/XBnqvAHgasGDCyXgk9wNL0Q48mp6hGvgnghexcRAHnt6awKT3CYDsi69igTuQ3I9gGJfS | ||||
|         Ymk0PYEHOAH8CngDFYzU6/wHepeq/DRgwgSMRPn03Y9gAL1RkGl6OwK1xDwP5Up+BChjLmrtoJfQewSA | ||||
|         SrVlxcMtSF4CFqFj8DWBxwqMB2agvApPMhdPbxECvUMALAMkKXh4CKVkDUM/9TXBg0CtOs1DJXI9wlxq | ||||
|         e4MQCO5BlH3x1ShUXt1b0Hn1NMGNC/gnsAzBcTwQzC7FwasBPIOy8nuYBfwWuDao+6vRKEyoDNCTgWPY | ||||
|         KGAuKjVJEBKcA2o5ILHiZinwEmqOFdzaikZzCQEMBmbipgg4wbzgtAsEnwDIBtR6/g9QekB6oLuk0XSR | ||||
|         RGAO4EZwgHk4gk0IBJcAeBoQRCN5AngEVSlHo+nNRKJWCKyY2Mk8HME0HQgeAbAMEMQjWQ7ciypuqdH0 | ||||
|         BUKAKUiigB3MoyFYNIHgEADZgCAJ+CnwXXTorqbvYUUZBuOQbGcudXwS6C4FgwDIBlQF3F+gknbo1Nua | ||||
|         vooZmIggFcGWYPAVCKwAUIk74oHngG+g1/g1fR8zqmZkLIItzKM+kEIgcAIgG4AolBj4LvrJr+k/mFBC | ||||
|         IALYzNzArQ4ERgBkA8o6+gRwH3rOr+l/mFE1Jk2BXB3oeQGQDShV/wfAw2hrv6b/YgUmIanBxM5ABBH1 | ||||
|         rABoSuLh4UsoJx+9zq/p74QCE5CcwspR5iJ7UhPoOQGgIvrAzTUIXgIG9dxlajRBTSQwEcke3JxhAT0W | ||||
|         O9BzWXRMgIkxwH+jwnk1Gs0lhiP5GWZGIXvupD2jAWQDMAD4HwQL0IE9Go0Rg4BUYBNzqekJe4D/BUA2 | ||||
|         oFwhHwG+g87dp9F4Q6ByXzhRy4NufwsB/w7Gp1HV2FUij+/5/XwaTe/HBHwPwc3sxO+1B/w7ID3AJMYC | ||||
|         jwMJ/r0UjabPkIDkcaYwGpd/T+S/KcAlN9+fAQv9exkaTZ8jFUkMJjb6M3rQPwJgOWDGhIe7UZ5+2sdf | ||||
|         o+ksgiygGCs7mYNf0o37Zwqg1vsnouL6bf66PxpNHycc+C+cTPTX0qDvNYBsAGJQnn5z/XRjNJr+QgIQ | ||||
|         hmA987D7WgvwrQaQffHVrY2bRqPpPrchuRUHPk8x7lsBIADBSOB+VKijRqPpPpHA/YQw3NcH9t0UQFn9 | ||||
|         Q5A8gnr6a28/jcZ3pAANmNjkSwch32kAHkAyBbgdPfg1Gl9jAv4DyWTcvj1o93kWsBCO5B5UjTSNRuN7 | ||||
|         BiH5PibCfFWGvPsCIBtVDc3NIuC6wN0bjaZfcAOqMja+EAK+mgIkAt8H4gNzTzSafkMCaqz5xLXeVwLg | ||||
|         BlQJJI1G43/m4iNtu3sCQFn+k4CvoT3+NJqewgZ8HUFCd/0Cui4AslEuv5JrgemBviMaTT9jBpJFuFFh | ||||
|         912ku1OAOFQ1H+30o9H0LJHA1zETh6frB+muAFgAzA70ndBo+inXIFnQnQN0TQBkAxAN3IF++vdOZLNN | ||||
|         01uJAG5HENVVW0DnPfZ+CtQDZuYh+QdqCVATbDQf3AKsZisWswWBwGwyYxZmROPX75ZuJBK3dOP2uHG6 | ||||
|         nXjcHvV50WzTBCMlwJdoyhaQ3bkPdz5Rhx0wYUFyG3rwBwfNn+ICYm2xDIweSIItgYHRA0mKTGJw9GBS | ||||
|         IlKwmCxEhUQRbYvGJJQCWOOoweF2UOuopdpRzdmqs5yqOEVJXQll9WUU1RRRWF2Iw+W47DyaoCARlXNz | ||||
|         M3Q+gVhXM/UMA5YE+sr7PRIswkJkWCRpUWmMTRrLrMGzmDRgEokRicTaYkkISyDEHNLpQ7s8LuqcdVTa | ||||
|         KympK+HIhSNsL9jOoQuHOFJyhPL6cuqd9WpnLQwCzXUIfguc6OwHO/fVZV989RBqMqBTffUkTWq9gFBL | ||||
|         KKOTRnPTiJu4euDVTE6bTFxYHFaT9eKT3de4PC7qnfXklOew+9xutuZvZd2pdZyuOI2UjWqIFgaBwAk8 | ||||
|         BvwS6NQ0oHNf1zIAUhG8DVwT6KvuV0iIDIkkMz6TGekzWDp6KZlxmQyJHeK3Ad8e9a56jpYcZdPpTXx0 | ||||
|         4iP2nd9HcU0xnu6sS2m6yicIbgfONY7TDtFxAfA04AYENwD/RHv+9QxSGfCmpU/ja1d8jRtH3EhKZErA | ||||
|         Br03ah217Di7gzcPvsnKEyspqi5SWoHWCHqKOuCLSFZhBn7SsQ91PCHIHEBgAh5Ae/75Hwnh1nBmDJnB | ||||
|         8nnLeWLWE8weMpuo0CiECL5RFWIOISMugwUZC5g2aBoWs4XiumJq7DWB7lp/wQpUIFiNRHY0YUjH5/Dq | ||||
|         gZOOR6v+fkWCWZgZkTSCe6++l/8Y9x/EhXWvirpbqqU9p8eJx+NRy35SUu+qJ9QcisVkQQiByWTCLMwX | ||||
|         3+sKESERzBs6j6kDp7K9YDt/O/A3/nn4n1Q1VGltwP/MxcRAIL+jH+jYV5J98dU3gJdR6Yo1vkZCSmQK | ||||
|         Xxv/Ne6efDdZ8VldUvWr7dUU1hSSX5nP6crT5JbnUlBVwNmqs1TaK6myV2F32XFLNyZhIiokihBzCJGh | ||||
|         kcSExjAqcRRDY4cyOHowiRGJpMekkxKegtVs7XRf6px1rD65mhc+e4HPCz/H5XZpQeA/alGhwn8DOmQM | ||||
|         7NhXobyMIpC8gor80/gYq7AyL3MeP5r+I+YNndeppTuH20FRTRHHS4/z2ZnP2HZ2G2erzpJflU9FfUWX | ||||
|         +iMQhFpDiQ+LJz0mnbFJY5k6cCpjksYwJmkMcba4Tk1Fjpce55+H/8lru14jrzxPV4n0H3/GxL1I6jpi | ||||
|         DOy4BiAYheRjID3QV9inkBAXFsddV97Fj6b/iNTI1A5/tMZRw/aC7fz7+L9Zn7ee3LJc6l31uN3uS99s | ||||
|         d5+2jUuPQgisFisR1giuTLuSO8ffyaTUSYxOHN3h6YJbutlwagMPr3mYvUV7A3G3+wN5CJYgOeY7DUAd | ||||
|         6JvA71HGBo0PEFIwMmkk2XOzuXnkzdgs7S+suDwu8iryeOPAG6zNXcuJkhOcrznfs+66EsJCwkiPTmfO | ||||
|         0Dl8ecyXmTZoGpEhkR36+P7z+/nltl/y9v63sXvsPdTpfoMTwV14+GtH4gPaXwX4H8CCGScPAhMDfXV9 | ||||
|         BgnXDruWX1//axYNW4TV1LZcdUs3R0uO8qsdv+KJdU+w4sgKTpefptZZq9TpnpxXCyWISmtL2XNuD6tz | ||||
|         V3Oi7AQWk4WB0QPbnb6kRKYwY/AMbFYbB84fUB6F2i7gK8xANSY+YF77qwHtC4CZgIsMVLGPlEBfXV/A | ||||
|         bDLzxTFf5JeLfsn4lPEXg3KMkEgKqwv59fZf89i6x1h5fCUldSVIIQMfpNN4/lpHLfuK9rEmdw05ZTkk | ||||
|         RySTEJ7QptEwwhrBzMEzSYtK4+CFg5TVlWkh4EsEHwEV3RMAfwZKAZiP4NtA553KNZdodOq5a9JdPL/g | ||||
|         eTLiMtrcvdZRy/pT63nw4wd5fd/rlNaW4hEe38zrQR2nRdRgd6hz1LG3aC8f5nzI2aqzjEseR4wtxuv+ | ||||
|         ZmFmbPJYMuMyOVp6lKLqIi0EfEMEsA04ymJgnfcd2xYAE1GRf4JvoZN+dpswaxj3T7ufZ+Y9Q1JEktf9 | ||||
|         pJQcLTnKY+se42ef/YyjF44q91ofDHyzycyoxFEszFrInCFzGJs8lmhbNPXOemodtd07R6NGUOOoYde5 | ||||
|         Xew6t4tIayRZ8VleDYVmYWZY/DBGJY7iaMlRzlad1UKg+4QCpzGzEReetrSAtgXAXEClH34UGBToq+rN | ||||
|         2Cw27p96P09d8xRRoVFe93N5XGw6vYl7P7qXVTmrfDo/TolM4dFZj7JszjLunnw3N4y4gS+M+AJfHP1F | ||||
|         JqdNptJeSV5FHh7ZfV9+ieR0xWnWnlpLjbOGUYmjiA6NNtzXJExkxGUwJnkMe8/v5Vz1OS0Euo9AsgKo | ||||
|         654AUMU+fwiEBfqKeitmYeb2K27nZ9f+jKgQ74O/2lHNr7b/ikfXPMqxkmO+m+NLSItO43df+B3fmfQd | ||||
|         kiOSL67hm4QJm8XG8IThXD3was5Wn+XIhSO+uXABDa4GtuZvJa8ij+HxwxkQOcCr/0BaVBrD4oaxo3AH | ||||
|         pXWlWgh0jwjgfaCouxrALcDN7e6rMUbCDSNu4KcLfsqAyAFedyupK+G5Tc/xiy2/oLy+3Kc/fovZwiMz | ||||
|         H+E7k77TpmdhfFg8wxOG8+mZT7lQe8FnfZBIjlw4wtazWxmTPIYhMUMMhYBJmBgcO5iEsAR2FO6guqFa | ||||
|         C4GuYwb2Abu6JgCyAXX77wGuCvTV9EokLM5azK+v/zXD4od53e1s9VkeW/sYf977Z98viXlgxuAZPDv/ | ||||
|         Wa8qeHMGRA7A5XGx6uQq394LAedrzrOzcCcJEQkMTxhuaBcwCzOjk0YTExrDxryNONwOLQS6hhkoBv4f | ||||
|         c8GbEPAuAOYBgjTgP9Hef51HwqikUby45EXGp4z3utuZyjP8cNUPeevAW7ikf/zkbxtzG18a86UO7y+E | ||||
|         4MMTH1Jt9/ETWMCFugt8fvZzYkJjGJs81qsQGJs8lip7FbvO7cItfVgOt3/RgOBDBDXeBIB3fVAtD2UB | ||||
|         WYG+il6HhPCQcB6e8TDTBk3zutu56nPcs/Ie/nX4X357ytmsNkYljOrUZ5IjkhkYNdBvt+d05Wme2/wc | ||||
|         7xx+x6vB0Wax8eD0B7ku6zqdubjrDEMyrK37ZywAltN000cByYG+it6GEIJ7rrqHr477qtd9SutL+enm | ||||
|         n7ImZ41fVVynx0mFvaJTn/FIj9+fuqcrTvPspmf5+OTHXvdJjUrlidlPkBWfpYVA10gBRiHBm1uwsQBQ | ||||
|         eedC0K6/nUfCNUOu4b6r7yPcahw1Xeus5eef/Zw/7P4DTun0a3fcLjfHSo6puXQHKasvo7C60O+36njJ | ||||
|         cR5d+yifnvnU6z5T0qbw+OzHiQmL0UKga0xEEOLt3rUVlGkDxqPpFEkRSTw661GGxg41bHd5XLy0/SVe | ||||
|         2v7Spay6fuZIyREVMNRBdpzdcSnAyJ8I2F+0nwdXP8iJMuOEtkIIlo5Zym2jbuuRe9UHGU8b6fuMBYBa | ||||
|         f04Chga6972NpWOWMnfoXK/tG/I28Jvtv6HB2dAz1m0T7CzcyR/2/AGXp/208UdLjvKH3X+4lOXX3wj4 | ||||
|         vPBzntv0HBUNFYa7RIdGc9eku8hK0FOBLjAUQaK335rxKsBcQIUBfRWd/LNjNFr9X1j4glcDWm55Lo+s | ||||
|         eYQDRQd6NCGG9EjOVJ4hKSKJ4fHDvQbpnK06y4OrH2Rj3sYeX3o7WXaSOFsc09KnGQZHDYoeRIOrgY2n | ||||
|         N/rEU7EfIYFNwAmjlYC2BMCtwHXo3C0dwmK28MTsJ7hp5E2G7bXOWrI3ZvPu4XdVJF9PIqCioYJNpzfh | ||||
|         8DjIjMvELMxYzVY8eKhsqOST05/w8JqH+fjkx8gAPGYdbgdHy44yJW0Kg2MGt74EIRgUPYjN+ZsprCrU | ||||
|         vgEdxwIcALYYCYDWtzEbUILhNeBbge59r0DC9PTp/P1Lfyc92thl4u1Db/OtFd+iwdUQ0H6GWEIYnjCc | ||||
|         cUnjyIjLUAOv5ChbC7ZSXudbD8TOYhImlmQt4U83/4nkCOPFp7/s+wv3rLynx+wnfYT/A74LeFpmCWrt | ||||
|         haF+AAlIhgS6170CqTLhfmfyd7wO/lPlp/jfrf/bc/N+bwj1pD10/hCHig5d9n7Acwuglh/X5K7hvaPv | ||||
|         8b3J3zPcZ1HmImYMmsG6k+u0btpxBiNIAC60bGh9C5UDUAKQFuhe9xbGpYxTDisGuD1u3jz4JnvO7Qn4 | ||||
|         ALuIQH3zTVuw9Atwupy8tus1jpceN2xPjUrl5pE3E2oNDXRXexNpSBKMZnaXC4BLWUQTAP+5gvUhQiwh | ||||
|         fGPCN7wm8zxRdoK/7P0LTrd/1/vbRXZiCyQC9hfv5/e7fu91unTLqFsYlTQq8H3tPaQhiTe6X5dPAcw0 | ||||
|         lf8aCHQsw2N/xgNjB4xlUeYir7u8eeBNTpadDNxT1qMMlJG2SOJscUSFRpESkUJyRDLJEcnYXXYKqgso | ||||
|         qyujvKGckroSapw11Nnr1FJgANRsp8vJimMruH3c7UxOm9yqfVDMIO644g72Fe0L0E3tdcRgIg038Czw | ||||
|         5KWGywWABEIROBhOUCmGQYqA2UNme430O1h8kH8c/odaturBjL1NfUuOSGZy2mRmDJrBnKFzVASesGA1 | ||||
|         W7Ga1ObBg9PlxCmduDwuqu3V7Cnaw6qcVewq3MXhksPYnfaLx+yp+5pXkcf7x95nUuqkViHMAsGizEW8 | ||||
|         EvcKuWW5+pfaPgJJFiYErsv1gNYCwIEFGB7oHvcGYmwx3DjiRsM2j/Tw7pF3OV5yvGfTdVvCmDJoCl8d | ||||
|         91UmDZjEqMRRxNpi2/xYqPnSfDopPInMuExuGnET+VX57D63m5UnVrLy+Eou1FzoMY3A7Xaz4ugKvjLu | ||||
|         K4xNGtuqPSs+iwkpE8gt1QKggwxH6fiXeYMZJWqzAMM6csR+jYSMuAwmDJhg2FxQVcB7R9/rmQq5jYU7 | ||||
|         pg6aytcmfI2vjP0KCeEJbWYbbg+r2UpmXCaZcZksyVrCraNu5U97/8S63HW+DxM2QiivxPW56w0FQERI | ||||
|         BF8Y8QU+yvkosEurvYcs1Ni+TABcLs/NgIloIDHQvQ12hEnw1XFfJTHc+Faty113Ka2XP5HKS+7Ja57k | ||||
|         raVvce+Ue0kMT+zW4G9JZEgkN428iT/f/Gf+ettfWZy1GFMPqAJOt5N3j76r0oMZMHPwTFIiUrQxsGMk | ||||
|         YmDXu/xb9ACSFHT+v7aRMDRmKAsyFhgOtDpnHevy1vnfWcWj3I9/f9PvWTZ3mdcAJF8RY4vh5pE38+qN | ||||
|         r3LXlXepqYOfB9++on3sOrfLsG1IzBAWDVvUySP2WyIwqOvRWgB4GICu/ts2jer/qETjRBs5ZTlsyd/i | ||||
|         1y6YhZn5w+bz2o2vsWTYEsyi/ZSNHumhyl5FQVUBx0uPs/vcbvad38ep8lOU1JWoKkMdYEjMEF5Y+AL3 | ||||
|         T7tfeez5SwgIKG8oZ23uWsPgJJvFxuS0yZhM2iOoA4QDrZJSXm4DUA+zFLQAaBsTjEse57UW3vaC7Zwq | ||||
|         P+U39d8kTHxl3Ff42bU/8+p92ITT46SsroytBVtZm7uWM5VnKKsvo8peRVlDGVaTlYSwBBLCE4i1xTI5 | ||||
|         bTILMhYwKmEU4dZwrxl8Y22xLJuzjCuSr+CJdU+QX5nvn+v1wNaCrRTWFBoGWU0cMJFB0YM4U3FGGwPb | ||||
|         pgMCQJGKFgBtYrPYmDPEuE6K0+1kw+kNTUlV/MINI25oM+oQ1NN++9nt/P3g31mTu4aCygKqGqpUY4t+ | ||||
|         5ZXnXXyKv3vkXV6KeImJAybyrYnfYvGwxV7rGIRbw7l93O3Y3XYe+vghVYrc19dsUsVE8yryDK83IzZD | ||||
|         CYByLQDaIYw2BcDTqDJgcbr+X3tEWCMYnTjasK3eVe+7vPotkXBFyhVkz8luc/AfLz3Oyztf5v2j75NX | ||||
|         kafebHL/9Ubj4HF5XBRWFVJYVci2gm0szFzINyd+k/kZ8w2LfppNZr405kvklOXw4tYXaXD73iJfba8m | ||||
|         pyyHmekzW7UlhCcwJmkMW874d8rVBzABKVQDzwE/vvSmwgPEEQ4kdf7Y/QgJ4weM91raa9e5Xf5JpyWV | ||||
|         B9wvFv2CK1Ov9LKLZPXJ1dzx7h38etuv1eDvSpBP42fK6sv4+8G/c8e7d/D8p8+rsl0GRIdG8+jMR7ll | ||||
|         9C1+sQdIKdlWsM0woYlZmJk5eCYhFl22sgMkE4Ot+UJgy2eCDYgLdC+DGqmMYN7y/e0r2ueXqjbh1nAe | ||||
|         mv4Q8zPmG7Y3uBp4++Db3P3B3Xxe8LlvioiCEgR1Zfx8y895fP3jnKo4Zbhbk01gevp0vwiBwxcOU+8y | ||||
|         XlVJi0zzWntQcxlxeAhr/v20FAChQExnjtgfSY9O9yoACqoKcLt8nFFXquIeX5/wdcMfusvj4g97/sB9 | ||||
|         K+/jTOUZ33vrCbW0+bd9f+ORNY+ocxgwMnEkd0++myhblM+FQF5FHrnluYZtKZEpWgB0jBjUGL+IkQYQ | ||||
|         G+heBjUmvDr/VNur1eDw8dM/MjSSH0z9AfFh8Ybt/zryL5755BnK6sv8agiTSFYcWcHj6x6nuLa4VbtA | ||||
|         cP3w61mYudDn565x1FBQVWDYFh8WT2pUqnYIap9YWqT4MxIAWgPwhlSqrjeHmxpnDedrfZxN1wNLspZ4 | ||||
|         TTS6p2gPyzYso7i6uEes4C7pYsXRFby882VDF9zkiGS+c+V3iAuL892AFFBlr+Jk+UnD5jBLmF8LmfQh | ||||
|         YmhHAISiNYA2iQqJ8pquqspepdbDfYWE+PB47rnqHsOqwmX1ZTy1/imOlR7r0bDdOkcdv9n5G1afXG3Y | ||||
|         PjN9JouzFvv0nC6PSy0zGhAdGq2csrQG0B6xeJ0CqHXrKHQW4DYJtYR6dQCqddRyoc53VXUBJqZOZMrA | ||||
|         KYZtq3JWsSFvQ8/fBAGltaX8bufvDFN5R4dGc/3w6wkP8aE7iUfVUbS77a2aTMJkuESpaUU4LeIBLgkA | ||||
|         AUji0ZnWvCNV6Kw3AVDvqu9UBZ6OsDBzoeH5zlSe4eWdL1PnqAvMvRCw+cxmr1rANYOvUV6KPnwqOzwO | ||||
|         3J7WBlaLyeL1O9FchoDLMwNdrgFANNqfqk1CzCFEWCMM26oaqnxXUEPCgKgBzBo8yzDgaG/RXnYW7gzo | ||||
|         t1Vrr+WN/W9Q2VDZqi0lMoVp6dO6cFTv1DvrvRY38eayrLkMAUQ1/81c7ggkiOj0IfsZZpPZ65JTlaPK | ||||
|         dzn1JYxIGMGIhBGtmpweJx/lfITD5Vtto9MI5fh0rPRYqyabxcb4ZN9Wlqt11HrVsGxmPXPtAAKIoFld | ||||
|         lUsCwAxIItEaQJsIITCbjCPvfFpOywRXpV1laHAsry9n0+lNgb4VIOBczTl2nN1h2Dw+ZTwJEQm+mQYI | ||||
|         NcXypgGEWXUEewcQQGTzSX7L+X4EWgC0iQmT19BbX6qhFpOFAZEDDNu2FmxV1XGCAOmRrM9bb7gkODR2 | ||||
|         qO/sAFJpFd60rx6rZdi7EbQI9DO1aNQaQDu4pdurGhodEu2zTDxmk9mr48/hC4epdFQGzTeVV5GH09M6 | ||||
|         7Xl0aDTRodE+O0+ENcKrtb/GURPo29AbaDXGjTQATRs43U6vPulmk9lng9JqsjIoapBhW0VDBdIdPE+8 | ||||
|         sroySmpLWr1vs9iwWXw3N08ITyDM0lrVd3vcVNmrAn0beguXjXEjDUDTBm7p9lrkI8Qc4jMNwGKyGEYc | ||||
|         Ot1OQzfcQOJwOyitb523L8wS5lMNINQcamh/sbvtlNSXdOGI/ZLLpvktNQBtSWmLxtp6dU7jtfe4sDgi | ||||
|         QnyjRJmEyXDw2N12ah0dS93VU9jddsPEnVazyjbkE5kolaGvZY0AUPN/t8cdNFOiIOeyMd5SA2g/sVw/ | ||||
|         p9peTXGd8RM40hrJgIgBPjF6SSkNDWsWkyXovN6sJqvXJ73dZffZKoA3/wtvGojGEGvz/7QUpzqmsh2q | ||||
|         HdVeVfDI0EgVleYDnB4n52rOtXo/xByitIzgMQFgs9hIjmy9XNngalCqeXf7KiHSFklWfJZhs8Pt8Bon | ||||
|         oGmFmTamAFoAtIVQP2ojzzeAOFscGbEZPhmcbo+bC7WtqjljEibibfFBpe5aTBbDYKXyhnLK68t90tfE | ||||
|         8EQmDpho2FbjqFGJSoLongQxl43xlgJATwHaweV2cbTkqKFDitVsJSHcN3Nel3R5VWsz4jKwhQSP59uA | ||||
|         yAGG6nmDs8HrikmnkBATGsPgmMGGzbnluXoVoOO0KQC0BtAB8irzDA2BAsHVA68mxhbTbS3A6XZ6TYAx | ||||
|         I32GSkoSJNOAOUPmYLO2FkiV9koq7T7wVxCQlZDl1fZx6MIhnwdh9VkkFmNXYG0E7DAnSk9Q7ag2bBub | ||||
|         NFYlw+guHnUeu6t1+GtmXCaTBkwK9G0AIDwknNlDZht6Rx6+cFglSPWBAJg+aLpXAbD73G5cLlcnD9pv | ||||
|         0VOAbiFUKK63/HQDowZ6NVZ19jy7z+3mQPGBVk1h1jBmpM8I/JzXowqkGKVIb3A1sCpnFfWO7k8BLCaL | ||||
|         YYFQgMqGSs5UnenkEfsxAgsm70bAIFEqg5tqRzVb87catkWGRKrB2V0EFNYUGkbaCQQ3jrxRDYoAfmNW | ||||
|         i5WlY5YyJHZIq7Z6Vz17ivZ0/yQSxiSNYVi8ccHqguoCztf4OA1bP6K5AJCAj9PZ9k3cbjeHLhzCIz2t | ||||
|         2oQQTE6dTExY91MrOl1OVuesNvQHGJs0lqVjlwauLp6EyamTueOKOwybDxYfNFzG7Mp5pqRNUasrBhwv | ||||
|         OU5+lZ/KkvVNXDR7bJgMGjXtIdUP3Ft67KvSrmJCygTwdPK4Bmwp2HKpuk8LvjH+GwHTAkItodw54U7S | ||||
|         otJatTndTt49/K5P6iNEhEawIHOBYRSgw+1g7am11NqDyzMyqJG4vBkBQQuAjiHgVMUpw/k5QGpUKgsy | ||||
|         FmC2dNOkIuBU+Sn+uv+vhsuOQ2KH8PCMh0mJSOlZIeCBxVmL+eKYLxo27z63m/ePve8TB6CB0QOZPXi2 | ||||
|         YXNJXUlw5EXoTQhcbeUD0FOAjiCgvK6cNSfXGC4/CQQLMhcQZ+t+amyPx8NbB97iYPHBVm0mYeKr477K | ||||
|         PVffg8XcQyu4HpiaPpXnFzxvmKzE6Xby6q5XfVMdWcLcIXO9lmHbfGazX6sw91Eue5JcnhJMagHQGTac | ||||
|         2uDVLXh8ynimD5re/ZM0ahuv7nrVMCOu1Wzlvqvv4+sTvo7VZO3CCTqBhMFxg3lqzlNerfKf5X/GRzkf | ||||
|         +eR0kbZIrh9+PaHm0FZtHunhk9OfBF1gVC/AiwCQrRs1bSCUB9onpz8xbI4KieLOCXeqIBkfqMIrj69k | ||||
|         8+nNhs0JYQk8P/957pxwp+Fg8cnlSsGk1En85vrfcMPwGwz3qbRX8tru1yiqLur+U9kD84bOY0HmAsPm | ||||
|         3PJctuTrisCdRuLGbWQENCMRWgB0hjpnHety1xk+mQEWZCxgztA53T+RgPyqfJZ/stxwWRCUO+4vF/+S | ||||
|         Fxa+oEJwfWUTkGqqsTBrIa/f+jpfGP4Fw91cHhev7HyFfx3+l09U8ojQCO6efLfXdN97ivaoe6HV/85y | ||||
|         2Ri/ZKWaiwBuACYGuoe9ieK6YmYPma1y37UgzBqGw+3g49yPDVNmdZbC6kKq7FXMGjzLsDhpqCWUiQMm | ||||
|         kh6dTrm9nAs1F3C6nF0bJBIswsLg2ME8MO0Bls1ZxvCE4V7zHq48vpIn1j+hAqV88PS/YcQNPDDtAUIt | ||||
|         rTWaOmcdz3/6PPuK9mkB0FkEOzHxARvVI6K5AABYCEzpynH7JULlB4gPj2f+0PmGySqSIpI4WHyQE6Un | ||||
|         uv1j9UgPh4oPYTaZmTV4lmF2HIvJwviU8SzOWszg2MGU28s5V3NO+Sy01Aqa+tPifbPZzPCE4Xxtwtd4 | ||||
|         8boXuXnkzW26N2/N38o9H97jm8KoEqLDosmem82EARMMd9mQt4H/2fo/Kh5DC4DOshn4iI3qPy01gLmA | ||||
|         D9zY+hfna85zbea1hlbx6NBoYmwxrM1dqwxW3RUCHg+HLhwiMjSSMUljDOf8QgiiQqK4KvUqlmQtYX7G | ||||
|         fDLiMvA0/rNarJhMJqSUhFhCiA6NJio0itSoVJYMX8IDUx/goZkP8eWxXyYlIsVQsDWxrWAbD615iH3n | ||||
|         fPc0vm30bfxw+g+xmlsbNasd1Tz/6fNsL9iuB3/X2AisaxIAzdeOJFBDU5VATccQcLriNP849A9GJo40 | ||||
|         tMQvyFjA0rFLeXnnyz45X1ldGY98/Agny06ybM4yr9mDhRAMjB7IwOiBLM5aTJW9itzyXM7XnqesrozS | ||||
|         +lIiQyJJjkwm0hpJWlQaQ2OHdijjkNOjvBSfWPcEB84f8Fnar6GxQ/mvqf9lOMUBJXBW5azywcn6Jc3H | ||||
|         ONBcADQAYdQ1lrbRAqATuDwu3jzwJreNvs0waYXNYuN7k7/HtoJt7C7c7ZPoOLvbzu8+/x0Xai/w+KzH | ||||
|         uSLlijY/YhImYm2xXJl6Zbevt8HVwOv7XufpTU9ztvKsz34tYdYwfjTjR0wdONWwvd5Vz1/2/sUnHob9 | ||||
|         FAlcFsd+aQowDzAxEbgefXs7h1DZb0LMISwatshQZU6JTMFmsbHu1DpV0ssHd9gjPRwtOcreor2kR6cz | ||||
|         KHqQ18IZvsAjPZyqOMWL21/kmU3PUFrrw4Eo4Qsjv8CT1zzp9em/MW8jP9/yc1UQVf9Cu4IHWAHsam0D | ||||
|         mA/AGOAmdIXgziNVZNrktMleA1dGJIyguK6YXed2+ayGoEd6KKgqYMOpDZyuPE2MLYbUyFSv5cu6Sl5F | ||||
|         Hq/vf52HP36Yfx/7N/XOep8O/mHxw3hpyUteQ6kr7ZU8/cnT7CjYoQd/15HAO0j20+i+culXMgcQDAOW | ||||
|         ogVA5xHKQFXRUMH8jPmG6cGtZitjk8eyv3g/p8p868JaZa/i88LPWXdqHWerz5IckUxUSBQWk6VLJcsk | ||||
|         kgZnA2cqz/DPI//kx+t/zP/t/j+Ka4tx48MU3FKlU392/rMsyVri1eD48s6Xefnzl3FJ7arSDTwI/obk | ||||
|         WGsBMBcwkQx8DZ0YpMvkVuQSY4th+qDphj/mWFssWfFZ7D63m6IaH3jMNdF4nMr6SnYU7GBlzko2nd5E | ||||
|         QVUB9c56wq3hRIVGtXsYu8vOoQuH+PDEh/xmx294YcsLvH3gbU5XnFbn8PHTN9QSygPTH+Deq+81tPqD | ||||
|         KoX+yNpHKK4p1k//7uFC8AqSM00C4NLtXAbAJASfAO3/UjTGNKqzf7r5T8weMtvLLpKPTnzEQx8/xJEL | ||||
|         R/zzo242w0gITyArPov0mHTSo9OJD4snPiye1KhUquxVVDZUUlxbTH5VPkU1RZwqP8WZyjOX0pH5adBZ | ||||
|         zVbum3Ify+YuIybUOH9CWX0Z3/7g27x/9H3/dKJ/UYl61O8lW71xyWKkvuSGxp20AOgqAk6WneS/P/tv | ||||
|         shKySI1MNdhFsGjYIh6Z+QgPffyQf6zazY5XWl9KaX4p2/O3g0mtCJiFGbPJjEd68EgPbulGeuSlRWA/ | ||||
|         PO2bYxZmbh55M09e86TXwQ/wzuF3+OiEb4KLNFSgxvhFWnoCRgO3AskdPqSmNY0RfG7p5poh1xj6BpiE | ||||
|         idFJo4kKjWLH2R2+Nap56VPT8SUSj/Tg8rhwS/elzEY9MPCbWDhsIb9Y9AsGRQ/yus+GUxt4dO2jqvCo | ||||
|         Vv19wRngDaDCyBMQVN2wG4HBnTuupiUej4fDFw6TEJ7A5NTJhoY4i8nCpAGTiA2LZU/RHq+ZhvsMUl3z | ||||
|         nRPv5OcLf95m8tTc8lzuX3W/9vf3LceAt4Ga1gJgHiCwAtcBIwLd016PUAa1nLIcRiaOJDMu01AImE1m | ||||
|         xqeMJys+i2Mlx/p0gstQSyj3Xn0vz89/vs0SavmV+dy/6n7W5q7ts/ciQOwD/gk0GPsBmBBIrgUmdP7Y | ||||
|         mlYIKK0rZX/xfsanjPda2cZisjA8YTijE0dzsOSgiqfvS/6YEmJsMfxg6g946pqniLXFet21rL6MH6// | ||||
|         MW8feLvvXH/wsA0TKwBXawGwENiOkzRmAT5IZaMBQKhgoSYh4G3OaxImhsQOYWHmQirtleSU5ah0Y719 | ||||
|         EEjIjM/k+fnP859T/tNrfD+oMN8XPnuB3+/6vV7v9w9rcPERJmgtANYB/wGofAALA93TPoWAc1Xn2Hd+ | ||||
|         H9MGTSMlMsV4NyGIC4tjRvoMbFYbR0qOUGOv6Z1CQKpKxreMvoWXlrzE9cOvbzPIqN5Zz693/JoXPnvB | ||||
|         N/UENS2RwApMbGlaAoSWDj9zARgGLKZFHXFNNxFQWFXIrnO7uCLlijat3xEhEcxMn8mk1EnkV+WTX5mP | ||||
|         lLJ3CIJG/4Nh8cN4bPZjPHnNk2TFZ7XpjVjRUMELW17ghc9e8EnItMaQOpQBcH/T0x+MBcAA1EpAeMeO | ||||
|         q+kwjUJgb9FexiWPY2D0QK8DwyRMZMZmsiBzAcPjh1NYU8iF2gvBLQgkRNuiWZK1hJ8v+jlfGvMlQ5fo | ||||
|         5hRWF/Lkhid55fNXdIIP/1KJ4HUEud4FgFoJiAS+BHS/tI2mNQLOVZ/j83OfkxSRxIiEEYaFNUFNCWJC | ||||
|         Y5icNpm5Q+YSbg2nqLaIivoKFdcVLINFqiKhS7KW8JM5P+HhmQ+3+9QHFWB030f38daBt3C6u5i6TNNR | ||||
|         SoHfA8VtCwD1NdwBJAa6x30WAedrz/PpmU8JtYQyKnEUNoutjd0FieGJzB48m3kZ84ixxVDrqqW8rhy3 | ||||
|         x4eBOZ3Fo6z712ZeyzPznuGBaQ8wOW1yhzIT7y3ayw9X/5APT3yoIiP14Pc35zDxG0zUsuHSm5ff9mxA | ||||
|         OQOtRacG8z8SQiwhfGXsV3hwxoOqnFiHPibJr8hnxbEVrDu1ji35WyirL8Pj9vjPk0+qTQiBLcTG0Nih | ||||
|         3DTiJqanT2fe0Hkq/XkHqHXU8u7Rd3lx24u+SY6i6SibUcb9huZGQCMBYAX+CHw90D3uT0wbNI2nrnmK | ||||
|         +Rnz29QGmiORVNmrOFZyjLW5a9l8ZjMnSk9QUF1Ag7NFQdHODLSWSUJNZqJDo8mIy+DK1Cv58pgvMyZ5 | ||||
|         DEnhSR1KH9ZETlkOv9z6S/66/6+9d3Wj9/IX4LuAsz0BIIAngacD3eN+hVRRe9+d/F3unXJvl5J6VNur | ||||
|         yS3P5VjpMfYW7WXf+X3kV+ZzvvY8Da4GHG7HxeAfj/QogyLK4GgxWzAJEyZhItQcSnxYPENjh3JV6lWM | ||||
|         Sx5HUkQSIxNHkh6d3maSUCMcbgfvH3ufn23+GXvO7QluQ2bf5cfY+Cl2ZGPkL9Dya1hOk3Hpq8Cb6K+p | ||||
|         Z5EqRHZc8ji+OfGb3D7udq918drD5XFR76yn3lVPaX0pBZUFnK48Tb2rnjpnHQ2uBmqdqqxWVEgUKREp | ||||
|         hFvDsVlsDIkdwpCYIYRaQomwRnQ5zZjb4+Z42XFe2/Uar+97XaUQ06lmAoEEvoLkHczATy41XD7A/wAU | ||||
|         ADALWImKDtT0NI22gWszr+X+qfd7LQQSrLg9bo6XHuftQ2/zzqF3OFZyDI8vaqVrukoFkhuALSy/vOFy | ||||
|         HfMDmnwBIlDJQfVKQCAQ4JZuTpSeYO2pteSW52ISJhLDEwmzhgW6d15xSzXwf7vztzy54UlWHFmhfBdE | ||||
|         T9Yu1xiQi+DPCEqbLwHC5XUBmlMKnAVGBbrn/RoBRTVF/HH3H3nv6HuMSRrDtyd+m3lD5zEweqBfMwB3 | ||||
|         htK6UnLKc1iVs4q3D75NTmkOLo+rx3ILaNrlLGpMt6ItAXA60L3WKCSS0tpSPq35lO0F2xmdOJprM69l | ||||
|         SdYSZg6eSZglMFpBg6uBNw68wTuH3mHb2W1U2atUViE98ION04RThkEN29Zm5o3AXCTq6a+ChDWBp3FQ | ||||
|         uaWb8zXn2Za/jfV56xmXPI7hCcMD0qWSuhKWb1zO2pNrL1VI1gM/2HABb+NkS3PrfxNt6ZAHgWogNtBX | ||||
|         oGmBACklaVFphpWIQD2ddxTuwGa2kRmXidVkxWwyYxZmTCYTAoFJmC6mB5NSXkwPVu+sp6KhgryKPMob | ||||
|         yhmRMIJJAya1OkdSRBIzBs9g/an1gb4jGu/UAIe8NRoLACXFjyC1AAhaJCzKXMSAyAGGzRvzNvL9f3+f | ||||
|         WmctcbY4om3RJEckExMaQ2RIJCGmECJCInC4HWpZ0N1Alb2KKnsV+ZX51DpqaXA1YHfbuXvy3UxImdBq | ||||
|         /d8szCzJWsKf9/6ZgsoC/fQPTiqBo94ajQWAMtqWAqeAdDTBhYTkyGTmZ8z36pSz7tQ6TperXP4ltSXd | ||||
|         Ot3qnNXcNekuxiWPa9U2Pnk8YxLHUFChBUCQkosXAyC0Pb+vB/YHuvcaY2YNmcW0QdMM23LKclhzcs3l | ||||
|         WX67sR0tOcrqk6sNzxUVGsXSMUsJsXbcJVjTo+zHRIM34WwsAAQgcaKSCGqCjBBLCDeNuMmrT8CGvA0c | ||||
|         LD7osyeylJI1J9dc9BxsyeKsxYxMGImPyh1qfIcE9uLC6e1Rb/z2Mpp+PEeB84G+Ck0zJGTEZjAvY55h | ||||
|         s91t572j76kwYR+y69wutuRvMWwbEDmAuUPnagEQfBQhOY4AnjLewfsUQKl/J4GcQF+FphkClo5dysDo | ||||
|         gYbNuwt3s/fcXp+fs7SulE/yPrlURKQZIeYQlmQtITEyUQuB4OIkgpNtaYLeBYCK/y6iDQuipoeRkBaZ | ||||
|         xuLMxYZZhFweFyuOrfBt0dGmU0vJu0feJbc817B95uCZTB04NdB3SHM5R8jmPG1kZfMuALIBJQZ2Ao5A | ||||
|         X4kGkDB+wHimDJxi2Hym8gwrj6+8GObrUwScKDvBp6c/NWyOCY3hxpE3djqEWeM37MAOsoGHve/UES+/ | ||||
|         HShnAk2AsVgs3DLqFq8JQ7YVbONYyTG/Lce53C5Wn1yt8vcZMG3QNAZGDdTTgOCgBsGO9nbqiADIR9UU | ||||
|         0wQSCVckX8GizEWGzTWOGt45/I4KwvEjWwu2suvcLsO2EfEjuGHEDdofIDg4gqSwvZ3aFgACMFOByiem | ||||
|         CTALMhcwNHaoYduOszvYmr/Vvx0Qqm7fB8c+MBQ0YdYwrsu6joSwBK0FBJ7PgPL2dmpbAFgBNy5gG3oa | ||||
|         EDik8rtfPGyxYaptj/SwLnddjxQWlVKy+uRqLtReMGyfMXgGIxJ0bdkAU41kG5J214LbFgBP0LQcuAc4 | ||||
|         Geir6s/MSJ/h1fPvXPU5Vp1c1TMdEXC89DifF35u2JwQlsCto2/V04DAkouJPZigeQJQIzoa6nsa7RUY | ||||
|         MIRJcNvo27wW1tyQt4FDxYd6bNDV2Gt479h7qnipAdMGTSMlIkVPAwLHXhI4Q0b7O7YvAJYBEg+qfKiz | ||||
|         3f01HUd2YPPAmMQxTB1kvMZe76zng2MfYHfaO3Y8H22b8jZxoPiAYZ+uSruKxVmLO3Ysja9xIljDBSR3 | ||||
|         tr9zZ3JK7QAKgSGBvsJej1QGs+TIZBLDEtssoeXyuLhxxI0Mixtm2F7WUEZ6dDpLxy3tdLru7iCEoKKh | ||||
|         wrAtzBLGzSNvJqcsB7vbjvCimtQ4aiisLqTGXqOThvqOAiQ7O6oNdmy35YAgHA8vA98I9BX2ZoQQjEka | ||||
|         w2MzH2N+xvx28/pJJOGWcKJCowzb3dJNg6vBP84/7WA1WQm1GJcBc7gdVNor2+yX2+PmWOkxXt31Ku8d | ||||
|         ee9SViFNd/g/TNyHpN4oA1BLOqYBKHWtDlUybCkQ0aHPaS5HQlZCFq/c8AozB8/0+mTsDGZhJsIafF9H | ||||
|         iDmEpPD2axqkRqUyacAkYkJjeG33a4axBpoOUwOsxUN9Rz/QMZ0xm6bVgE2oJCGaLmAymbjv6vuYNXiW | ||||
|         TwZ/XyHGFsMPp/9QJRzRdoHukIvgUwTtWv+b6PikUWkBBcAngb7K3kpkSCTXDL4m0N0ISjJjM7ky9cpA | ||||
|         d6O3sxFJYWeEaGetRh5UxaC6QF9pr0PCoOhBXufy/R2r2UpaVJr2H+g6dcCHSDydGdUd3zX74qu9qAhB | ||||
|         TWcQUFxbTHl9u96Z/RK3dHPkwhE9Beg624F9CC6r/dcendMArICdc8D/Q/sEdJqSuhL+fujv2tBlwN6i | ||||
|         vewp2hPobvRWnMAHSIo6q0F1Lnh7PbAQEJSiagcmBPrKexUScityGRo7lFGJo3p03T6YyS3PZfkny9ly | ||||
|         ZoueAnSNHGAZgvKOGv+a6HxxOaWi5QIfAYEpSdNbEVBUXcSDqx9ka8FWZgyawcjEkYbZffoD1Y5qdhbu | ||||
|         5K2Db6lIRj34u8qHdLGUX+dv+XJodNqai+AddAXhziPBJEyEhYQRZgnrt0uCbummxlGDw+XQg7/rXED5 | ||||
|         5mwCOrz810TXbrs6SRTwF+DWQN+BXk1/N3rpgd9d/oXgW0B1Rzz/WtK1SWg2oOoGvgXUdukYGoWPinf0 | ||||
|         2k3THWqAt5BdG/zQ3cq/grXAp906hkaj6SqfoEzzXabrAsAEuCkHXkdrARpNT1MD/JUOpP1qi64LgJ9c | ||||
|         /PRaYEuXj6PRaLrCZ6ix12nDX3O6NwVQJ76A0gIaAn1HNJp+QgOCvwKl3Rn80F0BAE1BQqvQQUIaTU+x | ||||
|         vnHMdZvuCwBlzS0BXgXKAntfNJo+TynwKi5KsXb/YN0XANkXX61GeSRpNBp/IVmJ5GMswI+7fzjfOKNn | ||||
|         ozIGCV6B9quRaDSaLlGA4BUEDd2d+zfhu2gUAUh2Am+CzvCo0fgYCbyNiV2+dKDynQDIBgQOBH8A9vfw | ||||
|         zdFo+jp7gdfw4Oiq158Rvo1HVSsCx4CX0M5BGo2vqAFeBI77+sC+jUPdCMwFVOLQTGC8f++LRtMveAv4 | ||||
|         X8Duq7l/E74PRN8IzMUO5AHz0UlDNJrucAx4CDjt68EPvp4CXM5e1FRAJxDVaLpGHfAitsZcf37AP6lo | ||||
|         NgLzAMEJJEMRTPDTDdJo+jJvAL/A5btlv5b4LxfVRmAuDQiOAtOBVL+dS6Ppe3wO/Ag466/BD/6dAjRx | ||||
|         BHgOFTSk0Wjapxg1Zo75+0T+zUa5kaZVgRwgHJhFzwgdjaa34gJ+AfwR8Pjz6Q/+FgDQJAQ8wGFUafEx | ||||
|         6GRQGo0RHuAdBM8gqPH34IeeEADQZBSsRbAfmAwM7pHzajS9i80IfgTk+9Lbry16Vh33cBx4HDjRo+fV | ||||
|         aIIfNTZcvvf2a4ueq0ixEbU0CAVAETAHCL7C9hpNz3Me5ezzMSa6leKrs/RsSZqNwDwkgmOo+c4MIKRH | ||||
|         +6DRBBfVwHOY+Qs9YPRrSc/XpNpIk1FwPxAKTKErJco0mt5PPfC/mPgV0NBT8/7mBKYo3UZgLg5gBxAN | ||||
|         XBmwvmg0gcEOvAw8i6QmEIMfAjnoNgLzcCDYgaovOBHtI6DpH7iAPyLJBqpYHriOBPapuxGYSz1KE0gB | ||||
|         xga8TxqNf3GiCno8iaA0kIMfgmGwbQTmUItaA40CJqBtApq+iR34PSZ+jKAkUGp/cwIvAEBVFJhPHYIt | ||||
|         KMPgRPBF0mONJmioA36LYDlQHgyDH4JFAIDSBObTgGArEoEyDIYGulsajQ+oBn6JiecRVAXL4IdgEgAA | ||||
|         G4A5OICdqJs2EYgMdLc0mm5wHngW+BWS2mAa/BBsAgCaVgecCHYBuSghoNOKaXojx4GHEPzVl7n8fUnw | ||||
|         CQBQQmABHqwcwc1eYDSQho4i1PQOPMBW4L8IZTUSNz8JdJeMCU4BAGo6MBuAM6hSyKnACLSvgCa4cQHv | ||||
|         Afcj2IMTgk3tb07veKJmAzAAuBf4HpAU6C5pNAZcAF5BefgVBaPK35Lg1QCasxG4lhpMbEaSAwxHCYTe | ||||
|         IcA0fR0J7EXwKBZew0RVsKr8LekdAgBgPSqIyMQxlOdALJCF9hfQBJY64O/AD3GxGQ/uYFb5W9J7BAA0 | ||||
|         LRNKoKTxf+eRDEcQh9YGND2LB0kOgmeBF4ACTMhAu/Z2lt47aJ4GrJhwMAHJA8AX0QlGND1DLfAvBC8S | ||||
|         wj6ceHqLyt+S3isAmsgGVEjxrcADqHqEeqVA4w88wD5Uxav3gKreYOhri941BTBiI021CPdjYj0SCWSg | ||||
|         PQg1vuU88EdMPIZkA34o1BkIer8G0Bw1/7IhuRr4PrAYiA90tzS9mjJgFYJXUWHrAcnc4y/6lgBoYjkg | ||||
|         CMfDYuBuVHkSW6C7pelVNKD0y1cxsRpJfV8a+E30TQEAzTOrJgJLgDtRNQr11EDTFjUoN97XgY8QlPbF | ||||
|         gd9E3xUAzVkGmEhAshD4BqpEmRYEmiYkyrL/KYLXgTV4Ap+tpyfoHwIAmmsEccAC4D9Q0QaJge6aJqCU | ||||
|         AJuANxCsx0oFDno0N38g6T8CoInngSogjGgkk4FbgOtQdQt1jYL+gQM4DXyEWs7bhco/0W8GfhP9TwA0 | ||||
|         8SzwTeCPWJBkADcBXwCuRlUy1vQ96lCW/H8DHwCnUNF7/W7gN9F/BUBL/geoYgCCq1CCYBYwFO1d2Nup | ||||
|         BfKAzcBKJDuJpogHA92t4EALgOZkAzFALWbcpCOZA8xHLSOmobMV9xZcwFnUMt561Bw/H3AD/fZpb4QW | ||||
|         AG2RDQgigHRgKpIFKFfjTCAq0N3TXEY1cArJXgTrgB0I8pHU6gHvHS0AOsovAImJOoYgmQBMRzIbwSjU | ||||
|         NEEbEHsWB0q9PwJ8CmwD9iI5A3j6wxKeL9ACoLNkX3xlQRKHIANV4PQqYCQwDLW0qAOSfIsHlXEnFzgG | ||||
|         fI5gB5JTCCoAFxKt3ncSLQB8QTagAqsGoKYHw4ErUFWOMlGWhUi0DaGjuFAeeZVITiLYj2B/Y/z9SSRF | ||||
|         BKCUdl9ECwBfk43yKzNjxYMNldJ8FDAOldR0MDAIGIgSDP39O5BAJVDQuOWjnvCHgKNIShHUE44LF/BE | ||||
|         oLvbt+jvP76e4zkAzLiIQZKImiYMRE0bRqLSm8UDYc02G70/ZNuNCqypb7aVASeA4wiOIylAeeSVoISB | ||||
|         Wz/dewYtAAJJNqC+AwtmrEhi8ZCMIBlJMqpicjJKWMSj8iA2bXEoISG4ZG8QzTZ/IJttoOblEjWoy4GK | ||||
|         ZlsZakAXA+cRFCMpxkQxUIEbJwIXNBbJ1gQELQCCmWdR35Cb0MbphI1LmoENtRSZgMqIFN64hbV4HYZK | ||||
|         nGpF2SCsLTZQJasdqLm3s/Gvo3GzowZ4XePW/HUVglIk1ainfNOTvgETDZixI4EnA30jNd7QAqCvkX3x | ||||
|         lbj4VzZ7T6Ce2eKyfeTF92Tj/y+1yov7XH58jUaj0Wg0Gk2v5P8D5M/bzdE8cNIAAAAASUVORK5CYII= | ||||
| </value> | ||||
|   </data> | ||||
| </root> | ||||
| @@ -32,6 +32,7 @@ namespace cmonitor.libs | ||||
|             this.length = length; | ||||
|             this.itemSize = itemSize; | ||||
|             bytes = new byte[length * itemSize]; | ||||
|             states = new ShareMemoryState[length]; | ||||
|         } | ||||
|  | ||||
|         public void InitLocal() | ||||
| @@ -100,6 +101,7 @@ namespace cmonitor.libs | ||||
|  | ||||
|         byte[] valuesBytes; | ||||
|         byte[] gloablBytes; | ||||
|         ShareMemoryState[] states = Array.Empty<ShareMemoryState>(); | ||||
|         private void InitStateValues() | ||||
|         { | ||||
|             gloablBytes = new byte[bytes.Length]; | ||||
| @@ -118,18 +120,15 @@ namespace cmonitor.libs | ||||
|             { | ||||
|                 for (int index = 0; index < length; index++) | ||||
|                 { | ||||
|                     for (int i = 0; i < valuesBytes.Length; i++) | ||||
|                     { | ||||
|                         ShareMemoryState state = (ShareMemoryState)valuesBytes[i]; | ||||
|                         bool result = ReadState(accessorLocal, index, state); | ||||
|                         if (result) | ||||
|                     ShareMemoryState state = ReadState(accessorLocal, index); | ||||
|                     if (state != states[index]) | ||||
|                     { | ||||
|                         states[index] = state; | ||||
|                         stateAction(index, state); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         } | ||||
|         private void SyncMemory() | ||||
|         { | ||||
|             if (accessorGlobal != null && accessorLocal != null) | ||||
| @@ -141,7 +140,7 @@ namespace cmonitor.libs | ||||
|                     for (int index = 0; index < length; index++) | ||||
|                     { | ||||
|                         //检查更新状态 | ||||
|                         if (ReadState(accessorGlobal, index, ShareMemoryState.Updated) == false) | ||||
|                         if (ReadStateIf(accessorGlobal, index, ShareMemoryState.Updated) == false) | ||||
|                         { | ||||
|                             continue; | ||||
|                         } | ||||
| @@ -152,7 +151,7 @@ namespace cmonitor.libs | ||||
|                         { | ||||
|                             accessorLocal.WriteArray(_index, gloablBytes, _index, itemSize); | ||||
|                         } | ||||
|                         WriteState(accessorGlobal, index, ShareMemoryState.Updated, false); | ||||
|                         WriteStateIf(accessorGlobal, index, ShareMemoryState.Updated, false); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -172,13 +171,13 @@ namespace cmonitor.libs | ||||
|                     for (int index = 0; index < length; index++) | ||||
|                     { | ||||
|                         //state | ||||
|                         bool _updated = ReadState(accessorLocal, index, ShareMemoryState.Updated); | ||||
|                         bool _updated = ReadStateIf(accessorLocal, index, ShareMemoryState.Updated); | ||||
|                         if (_updated == false) | ||||
|                         { | ||||
|                             continue; | ||||
|                         } | ||||
|  | ||||
|                         WriteState(accessorLocal, index, ShareMemoryState.Updated, false); | ||||
|                         WriteStateIf(accessorLocal, index, ShareMemoryState.Updated, false); | ||||
|                         updated |= _updated; | ||||
|  | ||||
|                         //key length | ||||
| @@ -310,7 +309,14 @@ namespace cmonitor.libs | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         private bool ReadState(IShareMemory accessor, int index, ShareMemoryState state) | ||||
|         private ShareMemoryState ReadState(IShareMemory accessor, int index) | ||||
|         { | ||||
|             if (accessor == null) return ShareMemoryState.None; | ||||
|  | ||||
|             ShareMemoryState stateByte = (ShareMemoryState)accessor.ReadByte(index * itemSize); | ||||
|             return stateByte; | ||||
|         } | ||||
|         private bool ReadStateIf(IShareMemory accessor, int index, ShareMemoryState state) | ||||
|         { | ||||
|             if (accessor == null) return false; | ||||
|  | ||||
| @@ -320,29 +326,35 @@ namespace cmonitor.libs | ||||
|         public bool ReadUpdated(int index) | ||||
|         { | ||||
|             if (accessorLocal != null) | ||||
|                 return ReadState(accessorLocal, index, ShareMemoryState.Updated); | ||||
|                 return ReadStateIf(accessorLocal, index, ShareMemoryState.Updated); | ||||
|             if (accessorGlobal != null) | ||||
|                 return ReadState(accessorGlobal, index, ShareMemoryState.Updated); | ||||
|                 return ReadStateIf(accessorGlobal, index, ShareMemoryState.Updated); | ||||
|             return false; | ||||
|         } | ||||
|         public bool ReadClosed(int index) | ||||
|         { | ||||
|             if (accessorLocal != null) | ||||
|                 return ReadState(accessorLocal, index, ShareMemoryState.Closed); | ||||
|                 return ReadStateIf(accessorLocal, index, ShareMemoryState.Closed); | ||||
|             if (accessorGlobal != null) | ||||
|                 return ReadState(accessorGlobal, index, ShareMemoryState.Closed); | ||||
|                 return ReadStateIf(accessorGlobal, index, ShareMemoryState.Closed); | ||||
|             return false; | ||||
|         } | ||||
|         public bool ReadRunning(int index) | ||||
|         { | ||||
|             if (accessorLocal != null) | ||||
|                 return ReadState(accessorLocal, index, ShareMemoryState.Running); | ||||
|                 return ReadStateIf(accessorLocal, index, ShareMemoryState.Running); | ||||
|             if (accessorGlobal != null) | ||||
|                 return ReadState(accessorGlobal, index, ShareMemoryState.Running); | ||||
|                 return ReadStateIf(accessorGlobal, index, ShareMemoryState.Running); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         private void WriteState(IShareMemory accessor, int index, ShareMemoryState state, bool value) | ||||
|         private void WriteState(IShareMemory accessor, int index, ShareMemoryState state) | ||||
|         { | ||||
|             if (accessor == null) return; | ||||
|             byte stateByte = (byte)state; | ||||
|             accessor.WriteByte(index * itemSize, stateByte); | ||||
|         } | ||||
|         private void WriteStateIf(IShareMemory accessor, int index, ShareMemoryState state, bool value) | ||||
|         { | ||||
|             if (accessor == null) return; | ||||
|             byte stateValue = accessor.ReadByte(index * itemSize); | ||||
| @@ -359,19 +371,19 @@ namespace cmonitor.libs | ||||
|         } | ||||
|         public void WriteUpdated(int index, bool updated = true) | ||||
|         { | ||||
|             WriteState(accessorLocal, index, ShareMemoryState.Updated, updated); | ||||
|             WriteState(accessorGlobal, index, ShareMemoryState.Updated, updated); | ||||
|             WriteStateIf(accessorLocal, index, ShareMemoryState.Updated, updated); | ||||
|             WriteStateIf(accessorGlobal, index, ShareMemoryState.Updated, updated); | ||||
|         } | ||||
|         public void WriteClosed(int index, bool closed = true) | ||||
|         { | ||||
|             WriteState(accessorLocal, index, ShareMemoryState.Closed, closed); | ||||
|             WriteState(accessorGlobal, index, ShareMemoryState.Closed, closed); | ||||
|             WriteStateIf(accessorLocal, index, ShareMemoryState.Closed, closed); | ||||
|             WriteStateIf(accessorGlobal, index, ShareMemoryState.Closed, closed); | ||||
|             WriteUpdated(index, true); | ||||
|         } | ||||
|         public void WriteRunning(int index, bool running = true) | ||||
|         { | ||||
|             WriteState(accessorLocal, index, ShareMemoryState.Running, running); | ||||
|             WriteState(accessorGlobal, index, ShareMemoryState.Running, running); | ||||
|             WriteStateIf(accessorLocal, index, ShareMemoryState.Running, running); | ||||
|             WriteStateIf(accessorGlobal, index, ShareMemoryState.Running, running); | ||||
|             WriteUpdated(index, true); | ||||
|         } | ||||
|     } | ||||
| @@ -387,6 +399,7 @@ namespace cmonitor.libs | ||||
|  | ||||
|     public enum ShareMemoryState : byte | ||||
|     { | ||||
|         None = 0, | ||||
|         Updated = 0b0000_0001, | ||||
|         Closed = 0b0000_0010, | ||||
|         Running = 0b0000_0100, | ||||
|   | ||||
							
								
								
									
										34
									
								
								cmonitor.sln
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								cmonitor.sln
									
									
									
									
									
								
							| @@ -7,19 +7,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor", "cmonitor\cmonit | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "common.libs", "common.libs\common.libs.csproj", "{00EECF97-99EB-4B12-AAEF-ED2363914275}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmonitor.sas.service", "cmonitor.sas.service\cmonitor.sas.service.csproj", "{0ED28F51-04B0-4B2D-B47E-EB1715F0CE57}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.sas.service", "cmonitor.sas.service\cmonitor.sas.service.csproj", "{0ED28F51-04B0-4B2D-B47E-EB1715F0CE57}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmonitor.libs", "cmonitor.libs\cmonitor.libs.csproj", "{9080618D-367F-474E-AACA-A3C2F294448F}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.libs", "cmonitor.libs\cmonitor.libs.csproj", "{9080618D-367F-474E-AACA-A3C2F294448F}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmonitor.install.win", "cmonitor.install.win\cmonitor.install.win.csproj", "{4EB9FFB0-B05C-4C4E-BD44-796715E47585}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cmonitor.install.win", "cmonitor.install.win\cmonitor.install.win.csproj", "{4EB9FFB0-B05C-4C4E-BD44-796715E47585}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "llock.win", "llock.win\llock.win.csproj", "{6F2602B3-221D-475D-B643-D54987605644}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "llock.win", "llock.win\llock.win.csproj", "{6F2602B3-221D-475D-B643-D54987605644}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wallpaper.win", "wallpaper.win\wallpaper.win.csproj", "{41C61263-4F73-4C62-BD78-8C3612C8F98B}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "wallpaper.win", "wallpaper.win\wallpaper.win.csproj", "{41C61263-4F73-4C62-BD78-8C3612C8F98B}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "notify.win", "notify.win\notify.win.csproj", "{886D781B-9A41-4DD1-8B94-490AE6476E67}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "notify.win", "notify.win\notify.win.csproj", "{886D781B-9A41-4DD1-8B94-490AE6476E67}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "message.win", "message.win\message.win.csproj", "{BCA983E7-928F-4353-BF98-4ACCBB1B173E}" | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "message.win", "message.win\message.win.csproj", "{BCA983E7-928F-4353-BF98-4ACCBB1B173E}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cmonitor.snatch.win", "cmonitor.snatch.win\cmonitor.snatch.win.csproj", "{5267B401-6818-407C-8323-E6C8A3CC01D6}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| @@ -196,6 +198,24 @@ Global | ||||
| 		{BCA983E7-928F-4353-BF98-4ACCBB1B173E}.ReleaseLinux|x64.Build.0 = Release|Any CPU | ||||
| 		{BCA983E7-928F-4353-BF98-4ACCBB1B173E}.ReleaseLinux|x86.ActiveCfg = Release|Any CPU | ||||
| 		{BCA983E7-928F-4353-BF98-4ACCBB1B173E}.ReleaseLinux|x86.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|x64.Build.0 = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|x86.ActiveCfg = Release|Any CPU | ||||
| 		{5267B401-6818-407C-8323-E6C8A3CC01D6}.ReleaseLinux|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
							
								
								
									
										303
									
								
								cmonitor.snatch.win/MainForm.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								cmonitor.snatch.win/MainForm.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | ||||
| namespace cmonitor.snatch.win | ||||
| { | ||||
|     partial class MainForm | ||||
|     { | ||||
|         /// <summary> | ||||
|         ///  Required designer variable. | ||||
|         /// </summary> | ||||
|         private System.ComponentModel.IContainer components = null; | ||||
|  | ||||
|         /// <summary> | ||||
|         ///  Clean up any resources being used. | ||||
|         /// </summary> | ||||
|         /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> | ||||
|         protected override void Dispose(bool disposing) | ||||
|         { | ||||
|             if (disposing && (components != null)) | ||||
|             { | ||||
|                 components.Dispose(); | ||||
|             } | ||||
|             base.Dispose(disposing); | ||||
|         } | ||||
|  | ||||
|         #region Windows Form Designer generated code | ||||
|  | ||||
|         /// <summary> | ||||
|         ///  Required method for Designer support - do not modify | ||||
|         ///  the contents of this method with the code editor. | ||||
|         /// </summary> | ||||
|         private void InitializeComponent() | ||||
|         { | ||||
|             System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); | ||||
|             groupTypeQuestion = new GroupBox(); | ||||
|             groupResult = new GroupBox(); | ||||
|             inputWrong = new TextBox(); | ||||
|             label3 = new Label(); | ||||
|             inputRight = new TextBox(); | ||||
|             label2 = new Label(); | ||||
|             inputJoin = new TextBox(); | ||||
|             label1 = new Label(); | ||||
|             groupTypeInput = new GroupBox(); | ||||
|             inputAnswer = new TextBox(); | ||||
|             groupTypeSelect = new GroupBox(); | ||||
|             checkB = new CheckBox(); | ||||
|             checkF = new CheckBox(); | ||||
|             checkA = new CheckBox(); | ||||
|             checkC = new CheckBox(); | ||||
|             checkE = new CheckBox(); | ||||
|             checkD = new CheckBox(); | ||||
|             btnConfirm = new Button(); | ||||
|             panel1 = new Panel(); | ||||
|             inputQuestion = new TextBox(); | ||||
|             groupTypeQuestion.SuspendLayout(); | ||||
|             groupResult.SuspendLayout(); | ||||
|             groupTypeInput.SuspendLayout(); | ||||
|             groupTypeSelect.SuspendLayout(); | ||||
|             panel1.SuspendLayout(); | ||||
|             SuspendLayout(); | ||||
|             //  | ||||
|             // groupTypeQuestion | ||||
|             //  | ||||
|             groupTypeQuestion.Controls.Add(groupResult); | ||||
|             groupTypeQuestion.Controls.Add(groupTypeInput); | ||||
|             groupTypeQuestion.Controls.Add(groupTypeSelect); | ||||
|             groupTypeQuestion.Controls.Add(btnConfirm); | ||||
|             groupTypeQuestion.Controls.Add(panel1); | ||||
|             groupTypeQuestion.Location = new Point(12, 3); | ||||
|             groupTypeQuestion.Name = "groupTypeQuestion"; | ||||
|             groupTypeQuestion.Size = new Size(350, 433); | ||||
|             groupTypeQuestion.TabIndex = 1; | ||||
|             groupTypeQuestion.TabStop = false; | ||||
|             groupTypeQuestion.Text = "看题"; | ||||
|             //  | ||||
|             // groupResult | ||||
|             //  | ||||
|             groupResult.Controls.Add(inputWrong); | ||||
|             groupResult.Controls.Add(label3); | ||||
|             groupResult.Controls.Add(inputRight); | ||||
|             groupResult.Controls.Add(label2); | ||||
|             groupResult.Controls.Add(inputJoin); | ||||
|             groupResult.Controls.Add(label1); | ||||
|             groupResult.Location = new Point(15, 252); | ||||
|             groupResult.Name = "groupResult"; | ||||
|             groupResult.Size = new Size(320, 59); | ||||
|             groupResult.TabIndex = 12; | ||||
|             groupResult.TabStop = false; | ||||
|             groupResult.Text = "答题结果"; | ||||
|             //  | ||||
|             // inputWrong | ||||
|             //  | ||||
|             inputWrong.ForeColor = Color.Red; | ||||
|             inputWrong.Location = new Point(252, 24); | ||||
|             inputWrong.Name = "inputWrong"; | ||||
|             inputWrong.Size = new Size(58, 23); | ||||
|             inputWrong.TabIndex = 5; | ||||
|             //  | ||||
|             // label3 | ||||
|             //  | ||||
|             label3.AutoSize = true; | ||||
|             label3.ForeColor = Color.Red; | ||||
|             label3.Location = new Point(218, 27); | ||||
|             label3.Name = "label3"; | ||||
|             label3.Size = new Size(32, 17); | ||||
|             label3.TabIndex = 4; | ||||
|             label3.Text = "错误"; | ||||
|             //  | ||||
|             // inputRight | ||||
|             //  | ||||
|             inputRight.ForeColor = Color.Green; | ||||
|             inputRight.Location = new Point(146, 24); | ||||
|             inputRight.Name = "inputRight"; | ||||
|             inputRight.Size = new Size(62, 23); | ||||
|             inputRight.TabIndex = 3; | ||||
|             //  | ||||
|             // label2 | ||||
|             //  | ||||
|             label2.AutoSize = true; | ||||
|             label2.ForeColor = Color.Green; | ||||
|             label2.Location = new Point(110, 27); | ||||
|             label2.Name = "label2"; | ||||
|             label2.Size = new Size(32, 17); | ||||
|             label2.TabIndex = 2; | ||||
|             label2.Text = "正确"; | ||||
|             //  | ||||
|             // inputJoin | ||||
|             //  | ||||
|             inputJoin.Location = new Point(39, 24); | ||||
|             inputJoin.Name = "inputJoin"; | ||||
|             inputJoin.Size = new Size(60, 23); | ||||
|             inputJoin.TabIndex = 1; | ||||
|             //  | ||||
|             // label1 | ||||
|             //  | ||||
|             label1.AutoSize = true; | ||||
|             label1.Location = new Point(4, 27); | ||||
|             label1.Name = "label1"; | ||||
|             label1.Size = new Size(32, 17); | ||||
|             label1.TabIndex = 0; | ||||
|             label1.Text = "参与"; | ||||
|             //  | ||||
|             // groupTypeInput | ||||
|             //  | ||||
|             groupTypeInput.Controls.Add(inputAnswer); | ||||
|             groupTypeInput.Location = new Point(15, 320); | ||||
|             groupTypeInput.Name = "groupTypeInput"; | ||||
|             groupTypeInput.Size = new Size(320, 56); | ||||
|             groupTypeInput.TabIndex = 11; | ||||
|             groupTypeInput.TabStop = false; | ||||
|             groupTypeInput.Text = "输入你的答案"; | ||||
|             //  | ||||
|             // inputAnswer | ||||
|             //  | ||||
|             inputAnswer.Location = new Point(12, 22); | ||||
|             inputAnswer.Name = "inputAnswer"; | ||||
|             inputAnswer.Size = new Size(298, 23); | ||||
|             inputAnswer.TabIndex = 0; | ||||
|             //  | ||||
|             // groupTypeSelect | ||||
|             //  | ||||
|             groupTypeSelect.Controls.Add(checkB); | ||||
|             groupTypeSelect.Controls.Add(checkF); | ||||
|             groupTypeSelect.Controls.Add(checkA); | ||||
|             groupTypeSelect.Controls.Add(checkC); | ||||
|             groupTypeSelect.Controls.Add(checkE); | ||||
|             groupTypeSelect.Controls.Add(checkD); | ||||
|             groupTypeSelect.Location = new Point(15, 317); | ||||
|             groupTypeSelect.Name = "groupTypeSelect"; | ||||
|             groupTypeSelect.Size = new Size(320, 56); | ||||
|             groupTypeSelect.TabIndex = 10; | ||||
|             groupTypeSelect.TabStop = false; | ||||
|             groupTypeSelect.Text = "选择你的答案"; | ||||
|             //  | ||||
|             // checkB | ||||
|             //  | ||||
|             checkB.AutoSize = true; | ||||
|             checkB.Location = new Point(65, 25); | ||||
|             checkB.Name = "checkB"; | ||||
|             checkB.Size = new Size(35, 21); | ||||
|             checkB.TabIndex = 5; | ||||
|             checkB.Text = "B"; | ||||
|             checkB.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // checkF | ||||
|             //  | ||||
|             checkF.AutoSize = true; | ||||
|             checkF.Location = new Point(277, 25); | ||||
|             checkF.Name = "checkF"; | ||||
|             checkF.Size = new Size(33, 21); | ||||
|             checkF.TabIndex = 9; | ||||
|             checkF.Text = "F"; | ||||
|             checkF.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // checkA | ||||
|             //  | ||||
|             checkA.AutoSize = true; | ||||
|             checkA.Location = new Point(12, 25); | ||||
|             checkA.Name = "checkA"; | ||||
|             checkA.Size = new Size(35, 21); | ||||
|             checkA.TabIndex = 4; | ||||
|             checkA.Text = "A"; | ||||
|             checkA.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // checkC | ||||
|             //  | ||||
|             checkC.AutoSize = true; | ||||
|             checkC.Location = new Point(118, 25); | ||||
|             checkC.Name = "checkC"; | ||||
|             checkC.Size = new Size(35, 21); | ||||
|             checkC.TabIndex = 8; | ||||
|             checkC.Text = "C"; | ||||
|             checkC.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // checkE | ||||
|             //  | ||||
|             checkE.AutoSize = true; | ||||
|             checkE.Location = new Point(225, 25); | ||||
|             checkE.Name = "checkE"; | ||||
|             checkE.Size = new Size(34, 21); | ||||
|             checkE.TabIndex = 6; | ||||
|             checkE.Text = "E"; | ||||
|             checkE.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // checkD | ||||
|             //  | ||||
|             checkD.AutoSize = true; | ||||
|             checkD.Location = new Point(170, 25); | ||||
|             checkD.Name = "checkD"; | ||||
|             checkD.Size = new Size(36, 21); | ||||
|             checkD.TabIndex = 7; | ||||
|             checkD.Text = "D"; | ||||
|             checkD.UseVisualStyleBackColor = true; | ||||
|             //  | ||||
|             // btnConfirm | ||||
|             //  | ||||
|             btnConfirm.Location = new Point(125, 387); | ||||
|             btnConfirm.Name = "btnConfirm"; | ||||
|             btnConfirm.Size = new Size(99, 32); | ||||
|             btnConfirm.TabIndex = 2; | ||||
|             btnConfirm.Text = "确定提交"; | ||||
|             btnConfirm.UseVisualStyleBackColor = true; | ||||
|             btnConfirm.Click += OnConfirm; | ||||
|             //  | ||||
|             // panel1 | ||||
|             //  | ||||
|             panel1.Controls.Add(inputQuestion); | ||||
|             panel1.Location = new Point(15, 28); | ||||
|             panel1.Name = "panel1"; | ||||
|             panel1.Size = new Size(320, 218); | ||||
|             panel1.TabIndex = 3; | ||||
|             //  | ||||
|             // inputQuestion | ||||
|             //  | ||||
|             inputQuestion.Dock = DockStyle.Fill; | ||||
|             inputQuestion.Location = new Point(0, 0); | ||||
|             inputQuestion.Multiline = true; | ||||
|             inputQuestion.Name = "inputQuestion"; | ||||
|             inputQuestion.Size = new Size(320, 218); | ||||
|             inputQuestion.TabIndex = 0; | ||||
|             //  | ||||
|             // MainForm | ||||
|             //  | ||||
|             AutoScaleDimensions = new SizeF(7F, 17F); | ||||
|             AutoScaleMode = AutoScaleMode.Font; | ||||
|             ClientSize = new Size(374, 448); | ||||
|             Controls.Add(groupTypeQuestion); | ||||
|             Icon = (Icon)resources.GetObject("$this.Icon"); | ||||
|             Name = "MainForm"; | ||||
|             Text = "互动答题"; | ||||
|             Load += OnLoad; | ||||
|             groupTypeQuestion.ResumeLayout(false); | ||||
|             groupResult.ResumeLayout(false); | ||||
|             groupResult.PerformLayout(); | ||||
|             groupTypeInput.ResumeLayout(false); | ||||
|             groupTypeInput.PerformLayout(); | ||||
|             groupTypeSelect.ResumeLayout(false); | ||||
|             groupTypeSelect.PerformLayout(); | ||||
|             panel1.ResumeLayout(false); | ||||
|             panel1.PerformLayout(); | ||||
|             ResumeLayout(false); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|         private GroupBox groupTypeQuestion; | ||||
|         private Button btnConfirm; | ||||
|         private Panel panel1; | ||||
|         private TextBox inputQuestion; | ||||
|         private CheckBox checkA; | ||||
|         private CheckBox checkB; | ||||
|         private CheckBox checkC; | ||||
|         private CheckBox checkD; | ||||
|         private CheckBox checkE; | ||||
|         private CheckBox checkF; | ||||
|         private GroupBox groupTypeSelect; | ||||
|         private GroupBox groupTypeInput; | ||||
|         private TextBox inputAnswer; | ||||
|         private GroupBox groupResult; | ||||
|         private Label label1; | ||||
|         private TextBox inputWrong; | ||||
|         private Label label3; | ||||
|         private TextBox inputRight; | ||||
|         private Label label2; | ||||
|         private TextBox inputJoin; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										349
									
								
								cmonitor.snatch.win/MainForm.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								cmonitor.snatch.win/MainForm.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| using cmonitor.libs; | ||||
| using System.Diagnostics; | ||||
| using System.Text; | ||||
| using System.Text.Json; | ||||
|  | ||||
| namespace cmonitor.snatch.win | ||||
| { | ||||
|     public partial class MainForm : Form | ||||
|     { | ||||
|         protected override CreateParams CreateParams | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 const int WS_EX_APPWINDOW = 0x40000; | ||||
|                 const int WS_EX_TOOLWINDOW = 0x80; | ||||
|                 CreateParams cp = base.CreateParams; | ||||
|                 cp.ExStyle &= (~WS_EX_APPWINDOW); | ||||
|                 cp.ExStyle |= WS_EX_TOOLWINDOW; | ||||
|                 return cp; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         SnatchQuestionInfo snatchQuesionInfo; | ||||
|         SnatchAnswerInfo snatchAnswerInfo; | ||||
|         private readonly ShareMemory shareMemory; | ||||
|         private int shareQuestionIndex; | ||||
|         private int shareAnswerIndex; | ||||
|         private string key = "SnatchAnswer"; | ||||
|         private DateTime startTime = new DateTime(1970, 1, 1); | ||||
|  | ||||
|         public MainForm(string shareMkey, int shareMLength, int shareItemMLength, int shareQuestionIndex, int shareAnswerIndex) | ||||
|         { | ||||
|             StartPosition = FormStartPosition.CenterScreen; | ||||
|             MaximizeBox = false; | ||||
|             MinimizeBox = false; | ||||
|             ControlBox = false; | ||||
|             ShowInTaskbar = false; | ||||
|             TopMost = true; | ||||
|             InitializeComponent(); | ||||
|  | ||||
|             this.shareQuestionIndex = shareQuestionIndex; | ||||
|             this.shareAnswerIndex = shareAnswerIndex; | ||||
|             this.shareMemory = new ShareMemory(shareMkey, shareMLength, shareItemMLength); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         CheckBox[] options = Array.Empty<CheckBox>(); | ||||
|         private void OnLoad(object sender, EventArgs e) | ||||
|         { | ||||
|             options = new CheckBox[] { checkA, checkB, checkC, checkD, checkE, checkF }; | ||||
|  | ||||
|             shareMemory.InitLocal(); | ||||
|             shareMemory.WriteRunning(shareQuestionIndex, true); | ||||
|             shareMemory.WriteClosed(shareQuestionIndex, false); | ||||
|             shareMemory.WriteRunning(shareAnswerIndex, true); | ||||
|             shareMemory.WriteClosed(shareAnswerIndex, false); | ||||
|             shareMemory.StateAction((index, state) => | ||||
|             { | ||||
|                 if (shareQuestionIndex == index) | ||||
|                 { | ||||
|                     if ((state & ShareMemoryState.Updated) == ShareMemoryState.Updated) | ||||
|                     { | ||||
|                         ReadQuestionMemory(); | ||||
|                         CheckState(); | ||||
|                     } | ||||
|                     if ((state & ShareMemoryState.Closed) == ShareMemoryState.Closed) | ||||
|                     { | ||||
|                         WriteAnswerConfirmIfState(SnatchState.Ask, false, string.Empty); | ||||
|                     } | ||||
|                 } | ||||
|                 else if (shareAnswerIndex == index) | ||||
|                 { | ||||
|                     if ((state & ShareMemoryState.Updated) == ShareMemoryState.Updated) | ||||
|                     { | ||||
|                         ReadAnswerMemory(); | ||||
|                         CheckState(); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             shareMemory.Loop(); | ||||
|             ReadMemory(); | ||||
|             CheckState(); | ||||
|         } | ||||
|  | ||||
|         private string GetAnswer() | ||||
|         { | ||||
|             if (snatchQuesionInfo.Type == SnatchType.Select) | ||||
|             { | ||||
|                 StringBuilder sb = new StringBuilder(); | ||||
|                 for (int i = 0; i < snatchQuesionInfo.Option; i++) | ||||
|                 { | ||||
|                     if (options[i].Checked) | ||||
|                         sb.Append((char)(i + 65)); | ||||
|                 } | ||||
|                 return sb.ToString(); | ||||
|             } | ||||
|             else if (snatchQuesionInfo.Type == SnatchType.Input) | ||||
|             { | ||||
|                 return inputAnswer.Text.Trim(); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|         private void OnConfirm(object sender, EventArgs e) | ||||
|         { | ||||
|             if (snatchQuesionInfo.End) | ||||
|             { | ||||
|                 MessageBox.Show($"答题已结束"); | ||||
|                 return; | ||||
|             } | ||||
|             if (snatchAnswerInfo.State == SnatchState.Confirm && snatchQuesionInfo.Repeat == false) | ||||
|             { | ||||
|                 MessageBox.Show($"已答题,不可重复作答"); | ||||
|                 return; | ||||
|             } | ||||
|             if (snatchAnswerInfo.Times > snatchQuesionInfo.Max) | ||||
|             { | ||||
|                 MessageBox.Show($"超过重复答题次数上线"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             string answer = GetAnswer(); | ||||
|             if (string.IsNullOrWhiteSpace(answer)) | ||||
|             { | ||||
|                 MessageBox.Show($"请给出你的答案"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             loading = true; | ||||
|             Task.Run(() => | ||||
|             { | ||||
|                 CheckBtn(); | ||||
|                 WriteAnswerConfirm(answer == snatchQuesionInfo.Correct, answer); | ||||
|  | ||||
|                 loading = false; | ||||
|                 CheckState(); | ||||
|             }); | ||||
|         } | ||||
|         private void CloseClear() | ||||
|         { | ||||
|             shareMemory.WriteRunning(shareQuestionIndex, false); | ||||
|             shareMemory.WriteClosed(shareQuestionIndex, true); | ||||
|             shareMemory.WriteRunning(shareAnswerIndex, false); | ||||
|             shareMemory.WriteClosed(shareAnswerIndex, true); | ||||
|  | ||||
|             Application.ExitThread(); | ||||
|             Application.Exit(); | ||||
|             Process.GetCurrentProcess().Kill(); | ||||
|         } | ||||
|  | ||||
|         private void ReadQuestionMemory() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 string result = shareMemory.GetItemValue(shareQuestionIndex); | ||||
|                 if (string.IsNullOrWhiteSpace(result)) | ||||
|                 { | ||||
|                     snatchQuesionInfo = new SnatchQuestionInfo { Question = "测试测试", Correct = "ABC", Option = 5, Type = SnatchType.Select }; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     snatchQuesionInfo = JsonSerializer.Deserialize<SnatchQuestionInfo>(result); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|                 CloseClear(); | ||||
|             } | ||||
|         } | ||||
|         private void ReadAnswerMemory() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 string result = shareMemory.GetItemValue(shareAnswerIndex); | ||||
|                 if (string.IsNullOrWhiteSpace(result)) | ||||
|                 { | ||||
|                     snatchAnswerInfo = new SnatchAnswerInfo { Result = false, ResultStr = "ABC", State = SnatchState.Ask, }; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     snatchAnswerInfo = JsonSerializer.Deserialize<SnatchAnswerInfo>(result); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|                 CloseClear(); | ||||
|             } | ||||
|         } | ||||
|         private void ReadMemory() | ||||
|         { | ||||
|             ReadQuestionMemory(); | ||||
|             ReadAnswerMemory(); | ||||
|         } | ||||
|         private void WriteAnswerConfirmIfState(SnatchState state, bool result, string resultStr) | ||||
|         { | ||||
|             if (snatchAnswerInfo.State == state) | ||||
|             { | ||||
|                 WriteAnswerConfirm(result, resultStr); | ||||
|             } | ||||
|         } | ||||
|         private void WriteAnswerConfirm(bool result, string resultStr) | ||||
|         { | ||||
|             snatchAnswerInfo.State = SnatchState.Confirm; | ||||
|             snatchAnswerInfo.Result = result; | ||||
|             snatchAnswerInfo.ResultStr = resultStr; | ||||
|             snatchAnswerInfo.Time = (long)(DateTime.UtcNow.Subtract(startTime)).TotalMilliseconds; | ||||
|             snatchAnswerInfo.Times++; | ||||
|             shareMemory.Update(shareAnswerIndex, key, JsonSerializer.Serialize(snatchAnswerInfo)); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         bool loading = false; | ||||
|         private void EnableBtn(string text) | ||||
|         { | ||||
|             this.Invoke(() => | ||||
|             { | ||||
|                 btnConfirm.Text = text; | ||||
|                 btnConfirm.Enabled = true; | ||||
|             }); | ||||
|         } | ||||
|         private void DisableBtn(string text) | ||||
|         { | ||||
|             this.Invoke(() => | ||||
|             { | ||||
|                 btnConfirm.Text = text; | ||||
|                 btnConfirm.Enabled = false; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         private void CheckOptions() | ||||
|         { | ||||
|             for (int i = 0; i < options.Length; i++) | ||||
|             { | ||||
|                 options[i].Visible = i < snatchQuesionInfo.Option; | ||||
|                 options[i].Checked = false; | ||||
|             } | ||||
|             if (string.IsNullOrWhiteSpace(snatchAnswerInfo.ResultStr) == false && snatchAnswerInfo.ResultStr.Length <= snatchQuesionInfo.Option) | ||||
|             { | ||||
|                 for (int i = 0; i < snatchAnswerInfo.ResultStr.Length; i++) | ||||
|                 { | ||||
|                     char option = snatchAnswerInfo.ResultStr[i]; | ||||
|                     if (option >= 'A' && option <= 'Z' && option - 'A' < options.Length) | ||||
|                     { | ||||
|                         options[(option - 'A')].Checked = true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         private void CheckBtn() | ||||
|         { | ||||
|             if (loading) | ||||
|             { | ||||
|                 DisableBtn("操作中.."); | ||||
|             } | ||||
|             else if (snatchAnswerInfo.State == SnatchState.Confirm) | ||||
|             { | ||||
|                 btnConfirm.ForeColor = (snatchAnswerInfo.Result ? Color.Green : Color.Red); | ||||
|                 EnableBtn(snatchAnswerInfo.Result ? "答题正确" : "答题错误"); | ||||
|             } | ||||
|             else if (snatchQuesionInfo.End) | ||||
|             { | ||||
|                 EnableBtn("已结束"); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 EnableBtn("确定提交"); | ||||
|             } | ||||
|         } | ||||
|         private void CheckState() | ||||
|         { | ||||
|             this.Invoke(() => | ||||
|             { | ||||
|                 CheckOptions(); | ||||
|  | ||||
|                 CheckBtn(); | ||||
|  | ||||
|                 groupTypeSelect.Visible = false; | ||||
|                 groupTypeInput.Visible = false; | ||||
|                 if (snatchQuesionInfo.Type == SnatchType.Select) | ||||
|                 { | ||||
|                     groupTypeSelect.Visible = true; | ||||
|                 } | ||||
|                 else if (snatchQuesionInfo.Type == SnatchType.Input) | ||||
|                 { | ||||
|                     groupTypeInput.Visible = true; | ||||
|                 } | ||||
|  | ||||
|                 inputQuestion.Text = snatchQuesionInfo.Question; | ||||
|  | ||||
|  | ||||
|                 inputJoin.Text = snatchQuesionInfo.Join.ToString(); | ||||
|                 inputRight.Text = snatchQuesionInfo.Right.ToString(); | ||||
|                 inputWrong.Text = snatchQuesionInfo.Wrong.ToString(); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         sealed class SnatchQuestionInfo | ||||
|         { | ||||
|             public SnatchType Type { get; set; } | ||||
|             /// <summary> | ||||
|             /// 问题 | ||||
|             /// </summary> | ||||
|             public string Question { get; set; } | ||||
|             /// <summary> | ||||
|             /// 正确答案 | ||||
|             /// </summary> | ||||
|             public string Correct { get; set; } | ||||
|             /// <summary> | ||||
|             /// 选项数 | ||||
|             /// </summary> | ||||
|             public int Option { get; set; } | ||||
|             /// <summary> | ||||
|             /// 最多答题数 | ||||
|             /// </summary> | ||||
|             public int Max { get; set; } = int.MaxValue; | ||||
|             /// <summary> | ||||
|             /// 已结束 | ||||
|             /// </summary> | ||||
|             public bool End { get; set; } = false; | ||||
|             /// <summary> | ||||
|             /// 重复答题 | ||||
|             /// </summary> | ||||
|             public bool Repeat { get; set; } = true; | ||||
|             public int Join { get; set; } = 0; | ||||
|             public int Right { get; set; } = 0; | ||||
|             public int Wrong { get; set; } = 0; | ||||
|         } | ||||
|         sealed class SnatchAnswerInfo | ||||
|         { | ||||
|             public SnatchState State { get; set; } | ||||
|             public bool Result { get; set; } | ||||
|             public long Time { get; set; } | ||||
|             public int Times { get; set; } | ||||
|             public string ResultStr { get; set; } | ||||
|         } | ||||
|         enum SnatchState : byte | ||||
|         { | ||||
|             None = 0, | ||||
|             Ask = 1, | ||||
|             Confirm = 2, | ||||
|         } | ||||
|         enum SnatchType : byte | ||||
|         { | ||||
|             None = 0, | ||||
|             Select = 1, | ||||
|             Input = 2, | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										400
									
								
								cmonitor.snatch.win/MainForm.resx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								cmonitor.snatch.win/MainForm.resx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,400 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <root> | ||||
|   <!-- | ||||
|     Microsoft ResX Schema  | ||||
|  | ||||
|     Version 2.0 | ||||
|  | ||||
|     The primary goals of this format is to allow a simple XML format | ||||
|     that is mostly human readable. The generation and parsing of the | ||||
|     various data types are done through the TypeConverter classes | ||||
|     associated with the data types. | ||||
|  | ||||
|     Example: | ||||
|  | ||||
|     ... ado.net/XML headers & schema ... | ||||
|     <resheader name="resmimetype">text/microsoft-resx</resheader> | ||||
|     <resheader name="version">2.0</resheader> | ||||
|     <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | ||||
|     <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | ||||
|     <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> | ||||
|     <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | ||||
|     <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | ||||
|         <value>[base64 mime encoded serialized .NET Framework object]</value> | ||||
|     </data> | ||||
|     <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | ||||
|         <comment>This is a comment</comment> | ||||
|     </data> | ||||
|  | ||||
|     There are any number of "resheader" rows that contain simple | ||||
|     name/value pairs. | ||||
|  | ||||
|     Each data row contains a name, and value. The row also contains a | ||||
|     type or mimetype. Type corresponds to a .NET class that support | ||||
|     text/value conversion through the TypeConverter architecture. | ||||
|     Classes that don't support this are serialized and stored with the | ||||
|     mimetype set. | ||||
|  | ||||
|     The mimetype is used for serialized objects, and tells the | ||||
|     ResXResourceReader how to depersist the object. This is currently not | ||||
|     extensible. For a given mimetype the value must be set accordingly: | ||||
|  | ||||
|     Note - application/x-microsoft.net.object.binary.base64 is the format | ||||
|     that the ResXResourceWriter will generate, however the reader can | ||||
|     read any of the formats listed below. | ||||
|  | ||||
|     mimetype: application/x-microsoft.net.object.binary.base64 | ||||
|     value   : The object must be serialized with | ||||
|             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | ||||
|             : and then encoded with base64 encoding. | ||||
|      | ||||
|     mimetype: application/x-microsoft.net.object.soap.base64 | ||||
|     value   : The object must be serialized with | ||||
|             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||||
|             : and then encoded with base64 encoding. | ||||
|  | ||||
|     mimetype: application/x-microsoft.net.object.bytearray.base64 | ||||
|     value   : The object must be serialized into a byte array | ||||
|             : using a System.ComponentModel.TypeConverter | ||||
|             : and then encoded with base64 encoding. | ||||
|     --> | ||||
|   <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> | ||||
|     <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> | ||||
|     <xsd:element name="root" msdata:IsDataSet="true"> | ||||
|       <xsd:complexType> | ||||
|         <xsd:choice maxOccurs="unbounded"> | ||||
|           <xsd:element name="metadata"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" use="required" type="xsd:string" /> | ||||
|               <xsd:attribute name="type" type="xsd:string" /> | ||||
|               <xsd:attribute name="mimetype" type="xsd:string" /> | ||||
|               <xsd:attribute ref="xml:space" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="assembly"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:attribute name="alias" type="xsd:string" /> | ||||
|               <xsd:attribute name="name" type="xsd:string" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="data"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||||
|                 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> | ||||
|               <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | ||||
|               <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | ||||
|               <xsd:attribute ref="xml:space" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|           <xsd:element name="resheader"> | ||||
|             <xsd:complexType> | ||||
|               <xsd:sequence> | ||||
|                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> | ||||
|               </xsd:sequence> | ||||
|               <xsd:attribute name="name" type="xsd:string" use="required" /> | ||||
|             </xsd:complexType> | ||||
|           </xsd:element> | ||||
|         </xsd:choice> | ||||
|       </xsd:complexType> | ||||
|     </xsd:element> | ||||
|   </xsd:schema> | ||||
|   <resheader name="resmimetype"> | ||||
|     <value>text/microsoft-resx</value> | ||||
|   </resheader> | ||||
|   <resheader name="version"> | ||||
|     <value>2.0</value> | ||||
|   </resheader> | ||||
|   <resheader name="reader"> | ||||
|     <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
|   </resheader> | ||||
|   <resheader name="writer"> | ||||
|     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | ||||
|   </resheader> | ||||
|   <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> | ||||
|   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | ||||
|     <value> | ||||
|         AAABAAEAAAAAAAEAIABdQAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAEAAAABAAgGAAAAXHKoZgAAQCRJ | ||||
|         REFUeNrtnXd8XMW5sJ/ZIq16lyzZsi1Z7sYFY9xxwwUINU7hkpBCQsKFG0joBGKZllySmwspBEJyk5BQ | ||||
|         EhIwfDHYuGKMK+7dlmXZkmVZVu9b5/tjJFuWzqrualfSPP6dn9Y7Z8+Zc3bnPe+88xbQaDQajUbT/xCB | ||||
|         7oDGx2RffCUu/pXN3hOAvNjatI+8+J5s/P+lVnlxn8uPr+kDaAEQzGQ3/hWEAjYkNiAMsDVuUQgSkEQD | ||||
|         4Y1bWIvXoUBI42YBrI1/QxpfAzgBB+BqfO1q/L8DsAP1QF3j1vx1FYJSJNVAQ2NbA9CAiQbM2JHAk4G+ | ||||
|         kRpvaAEQKLIvvjIhMWPGCsTiIRlIBlIa/yYDiUA8ENtsi0MNcAGYGo8lmm3+QDbbADyNr+uBcqCi2VYG | ||||
|         lADFwHkExUiKMVGMoAInTkJwk4yHSuDhQH0R/RstAHqKZwCw4iYeSAASEAxCMgIYDmRxaVA3bTbAHOiu | ||||
|         dxM3l7SDpq0MyUkEJ4DjSAqAEkyUYqIccPJUoLvdP9ACwNc8i7qrLqxIwoAkYDQwBhgFDAEGAmlAJPo7 | ||||
|         kEANUAicBU4DR4FDwBEkFxA0oKYm2gbhY/r7j883ZAPqSZ2KepKPAsYBVwAZQDQQgZp7a9rHBdQCVcAp | ||||
|         4ACCA0iOATnAOcCthUH30QKgKzwNgBkPscBQYCowBfWkz0LN1/W99S0SKEUJgKPADgTbgdMIKgA3Pwl0 | ||||
|         F3sf+kfaUX4CCEwIBgETUIN+NupJH4myqmt6Dgdq6nAQ2ARsR7APOIvEo7WDjqEFQFtkA4JwYBCSq5HM | ||||
|         RzARyARiAt09zWVUAieBvcB6BDuBAiR1Whh4RwuA5mQDM4HPMeFkIB5mA/OBeUA6l9bNNcGNE8gHNgDr | ||||
|         EHyKpBC1bKkNic3QAqCJxwAbSQgmI7kBuAb1pI8MdNc03aIGyAU+Af4N7AEuaCGg6L8CIPviKwtqae4G | ||||
|         4EZgGnrQ91VqgC0oQbASwRkcuAgHfhzorgWG/icAnkctLoURjeRK4GbgOpQ1PzTQ3dP0CHYgD/gQwfvA | ||||
|         HuqpIhp4ItBd61n6jwDIRtnpncQjmQ/cAcxCudlq+i8XgM3Am8A6lEtzv7ET9A8BsAwwkYhkIXAnavku | ||||
|         ItDd0gQVNShB8BcEa/BQyvJAd8n/9G0BkA2oJ/x1qIE/HT3wNW1TA2wFXkewijWU8G3g24Huln/omwJg | ||||
|         OSAIw8Ni4PvAXPT8XtM5GoCNwKtIViOo74vTgr4lAJTKFgpchYd7EFyHcsvVaLpKKZIPMfEKgl1I7CwL | ||||
|         dJd8R98QAE+hIs9TyEQ98e9ARdtpNL7iLPAGglc4xikyUZGfvZzeLwCyAYhCchOCB4BJ9P4Yek1w4gZ2 | ||||
|         A/+L4N9AdW/XBnqvAHgasGDCyXgk9wNL0Q48mp6hGvgnghexcRAHnt6awKT3CYDsi69igTuQ3I9gGJfS | ||||
|         Ymk0PYEHOAH8CngDFYzU6/wHepeq/DRgwgSMRPn03Y9gAL1RkGl6OwK1xDwP5Up+BChjLmrtoJfQewSA | ||||
|         SrVlxcMtSF4CFqFj8DWBxwqMB2agvApPMhdPbxECvUMALAMkKXh4CKVkDUM/9TXBg0CtOs1DJXI9wlxq | ||||
|         e4MQCO5BlH3x1ShUXt1b0Hn1NMGNC/gnsAzBcTwQzC7FwasBPIOy8nuYBfwWuDao+6vRKEyoDNCTgWPY | ||||
|         KGAuKjVJEBKcA2o5ILHiZinwEmqOFdzaikZzCQEMBmbipgg4wbzgtAsEnwDIBtR6/g9QekB6oLuk0XSR | ||||
|         RGAO4EZwgHk4gk0IBJcAeBoQRCN5AngEVSlHo+nNRKJWCKyY2Mk8HME0HQgeAbAMEMQjWQ7ciypuqdH0 | ||||
|         BUKAKUiigB3MoyFYNIHgEADZgCAJ+CnwXXTorqbvYUUZBuOQbGcudXwS6C4FgwDIBlQF3F+gknbo1Nua | ||||
|         vooZmIggFcGWYPAVCKwAUIk74oHngG+g1/g1fR8zqmZkLIItzKM+kEIgcAIgG4AolBj4LvrJr+k/mFBC | ||||
|         IALYzNzArQ4ERgBkA8o6+gRwH3rOr+l/mFE1Jk2BXB3oeQGQDShV/wfAw2hrv6b/YgUmIanBxM5ABBH1 | ||||
|         rABoSuLh4UsoJx+9zq/p74QCE5CcwspR5iJ7UhPoOQGgIvrAzTUIXgIG9dxlajRBTSQwEcke3JxhAT0W | ||||
|         O9BzWXRMgIkxwH+jwnk1Gs0lhiP5GWZGIXvupD2jAWQDMAD4HwQL0IE9Go0Rg4BUYBNzqekJe4D/BUA2 | ||||
|         oFwhHwG+g87dp9F4Q6ByXzhRy4NufwsB/w7Gp1HV2FUij+/5/XwaTe/HBHwPwc3sxO+1B/w7ID3AJMYC | ||||
|         jwMJ/r0UjabPkIDkcaYwGpd/T+S/KcAlN9+fAQv9exkaTZ8jFUkMJjb6M3rQPwJgOWDGhIe7UZ5+2sdf | ||||
|         o+ksgiygGCs7mYNf0o37Zwqg1vsnouL6bf66PxpNHycc+C+cTPTX0qDvNYBsAGJQnn5z/XRjNJr+QgIQ | ||||
|         hmA987D7WgvwrQaQffHVrY2bRqPpPrchuRUHPk8x7lsBIADBSOB+VKijRqPpPpHA/YQw3NcH9t0UQFn9 | ||||
|         Q5A8gnr6a28/jcZ3pAANmNjkSwch32kAHkAyBbgdPfg1Gl9jAv4DyWTcvj1o93kWsBCO5B5UjTSNRuN7 | ||||
|         BiH5PibCfFWGvPsCIBtVDc3NIuC6wN0bjaZfcAOqMja+EAK+mgIkAt8H4gNzTzSafkMCaqz5xLXeVwLg | ||||
|         BlQJJI1G43/m4iNtu3sCQFn+k4CvoT3+NJqewgZ8HUFCd/0Cui4AslEuv5JrgemBviMaTT9jBpJFuFFh | ||||
|         912ku1OAOFQ1H+30o9H0LJHA1zETh6frB+muAFgAzA70ndBo+inXIFnQnQN0TQBkAxAN3IF++vdOZLNN | ||||
|         01uJAG5HENVVW0DnPfZ+CtQDZuYh+QdqCVATbDQf3AKsZisWswWBwGwyYxZmROPX75ZuJBK3dOP2uHG6 | ||||
|         nXjcHvV50WzTBCMlwJdoyhaQ3bkPdz5Rhx0wYUFyG3rwBwfNn+ICYm2xDIweSIItgYHRA0mKTGJw9GBS | ||||
|         IlKwmCxEhUQRbYvGJJQCWOOoweF2UOuopdpRzdmqs5yqOEVJXQll9WUU1RRRWF2Iw+W47DyaoCARlXNz | ||||
|         M3Q+gVhXM/UMA5YE+sr7PRIswkJkWCRpUWmMTRrLrMGzmDRgEokRicTaYkkISyDEHNLpQ7s8LuqcdVTa | ||||
|         KympK+HIhSNsL9jOoQuHOFJyhPL6cuqd9WpnLQwCzXUIfguc6OwHO/fVZV989RBqMqBTffUkTWq9gFBL | ||||
|         KKOTRnPTiJu4euDVTE6bTFxYHFaT9eKT3de4PC7qnfXklOew+9xutuZvZd2pdZyuOI2UjWqIFgaBwAk8 | ||||
|         BvwS6NQ0oHNf1zIAUhG8DVwT6KvuV0iIDIkkMz6TGekzWDp6KZlxmQyJHeK3Ad8e9a56jpYcZdPpTXx0 | ||||
|         4iP2nd9HcU0xnu6sS2m6yicIbgfONY7TDtFxAfA04AYENwD/RHv+9QxSGfCmpU/ja1d8jRtH3EhKZErA | ||||
|         Br03ah217Di7gzcPvsnKEyspqi5SWoHWCHqKOuCLSFZhBn7SsQ91PCHIHEBgAh5Ae/75Hwnh1nBmDJnB | ||||
|         8nnLeWLWE8weMpuo0CiECL5RFWIOISMugwUZC5g2aBoWs4XiumJq7DWB7lp/wQpUIFiNRHY0YUjH5/Dq | ||||
|         gZOOR6v+fkWCWZgZkTSCe6++l/8Y9x/EhXWvirpbqqU9p8eJx+NRy35SUu+qJ9QcisVkQQiByWTCLMwX | ||||
|         3+sKESERzBs6j6kDp7K9YDt/O/A3/nn4n1Q1VGltwP/MxcRAIL+jH+jYV5J98dU3gJdR6Yo1vkZCSmQK | ||||
|         Xxv/Ne6efDdZ8VldUvWr7dUU1hSSX5nP6crT5JbnUlBVwNmqs1TaK6myV2F32XFLNyZhIiokihBzCJGh | ||||
|         kcSExjAqcRRDY4cyOHowiRGJpMekkxKegtVs7XRf6px1rD65mhc+e4HPCz/H5XZpQeA/alGhwn8DOmQM | ||||
|         7NhXobyMIpC8gor80/gYq7AyL3MeP5r+I+YNndeppTuH20FRTRHHS4/z2ZnP2HZ2G2erzpJflU9FfUWX | ||||
|         +iMQhFpDiQ+LJz0mnbFJY5k6cCpjksYwJmkMcba4Tk1Fjpce55+H/8lru14jrzxPV4n0H3/GxL1I6jpi | ||||
|         DOy4BiAYheRjID3QV9inkBAXFsddV97Fj6b/iNTI1A5/tMZRw/aC7fz7+L9Zn7ee3LJc6l31uN3uS99s | ||||
|         d5+2jUuPQgisFisR1giuTLuSO8ffyaTUSYxOHN3h6YJbutlwagMPr3mYvUV7A3G3+wN5CJYgOeY7DUAd | ||||
|         6JvA71HGBo0PEFIwMmkk2XOzuXnkzdgs7S+suDwu8iryeOPAG6zNXcuJkhOcrznfs+66EsJCwkiPTmfO | ||||
|         0Dl8ecyXmTZoGpEhkR36+P7z+/nltl/y9v63sXvsPdTpfoMTwV14+GtH4gPaXwX4H8CCGScPAhMDfXV9 | ||||
|         BgnXDruWX1//axYNW4TV1LZcdUs3R0uO8qsdv+KJdU+w4sgKTpefptZZq9TpnpxXCyWISmtL2XNuD6tz | ||||
|         V3Oi7AQWk4WB0QPbnb6kRKYwY/AMbFYbB84fUB6F2i7gK8xANSY+YF77qwHtC4CZgIsMVLGPlEBfXV/A | ||||
|         bDLzxTFf5JeLfsn4lPEXg3KMkEgKqwv59fZf89i6x1h5fCUldSVIIQMfpNN4/lpHLfuK9rEmdw05ZTkk | ||||
|         RySTEJ7QptEwwhrBzMEzSYtK4+CFg5TVlWkh4EsEHwEV3RMAfwZKAZiP4NtA553KNZdodOq5a9JdPL/g | ||||
|         eTLiMtrcvdZRy/pT63nw4wd5fd/rlNaW4hEe38zrQR2nRdRgd6hz1LG3aC8f5nzI2aqzjEseR4wtxuv+ | ||||
|         ZmFmbPJYMuMyOVp6lKLqIi0EfEMEsA04ymJgnfcd2xYAE1GRf4JvoZN+dpswaxj3T7ufZ+Y9Q1JEktf9 | ||||
|         pJQcLTnKY+se42ef/YyjF44q91ofDHyzycyoxFEszFrInCFzGJs8lmhbNPXOemodtd07R6NGUOOoYde5 | ||||
|         Xew6t4tIayRZ8VleDYVmYWZY/DBGJY7iaMlRzlad1UKg+4QCpzGzEReetrSAtgXAXEClH34UGBToq+rN | ||||
|         2Cw27p96P09d8xRRoVFe93N5XGw6vYl7P7qXVTmrfDo/TolM4dFZj7JszjLunnw3N4y4gS+M+AJfHP1F | ||||
|         JqdNptJeSV5FHh7ZfV9+ieR0xWnWnlpLjbOGUYmjiA6NNtzXJExkxGUwJnkMe8/v5Vz1OS0Euo9AsgKo | ||||
|         654AUMU+fwiEBfqKeitmYeb2K27nZ9f+jKgQ74O/2lHNr7b/ikfXPMqxkmO+m+NLSItO43df+B3fmfQd | ||||
|         kiOSL67hm4QJm8XG8IThXD3was5Wn+XIhSO+uXABDa4GtuZvJa8ij+HxwxkQOcCr/0BaVBrD4oaxo3AH | ||||
|         pXWlWgh0jwjgfaCouxrALcDN7e6rMUbCDSNu4KcLfsqAyAFedyupK+G5Tc/xiy2/oLy+3Kc/fovZwiMz | ||||
|         H+E7k77TpmdhfFg8wxOG8+mZT7lQe8FnfZBIjlw4wtazWxmTPIYhMUMMhYBJmBgcO5iEsAR2FO6guqFa | ||||
|         C4GuYwb2Abu6JgCyAXX77wGuCvTV9EokLM5azK+v/zXD4od53e1s9VkeW/sYf977Z98viXlgxuAZPDv/ | ||||
|         Wa8qeHMGRA7A5XGx6uQq394LAedrzrOzcCcJEQkMTxhuaBcwCzOjk0YTExrDxryNONwOLQS6hhkoBv4f | ||||
|         c8GbEPAuAOYBgjTgP9Hef51HwqikUby45EXGp4z3utuZyjP8cNUPeevAW7ikf/zkbxtzG18a86UO7y+E | ||||
|         4MMTH1Jt9/ETWMCFugt8fvZzYkJjGJs81qsQGJs8lip7FbvO7cItfVgOt3/RgOBDBDXeBIB3fVAtD2UB | ||||
|         WYG+il6HhPCQcB6e8TDTBk3zutu56nPcs/Ie/nX4X357ytmsNkYljOrUZ5IjkhkYNdBvt+d05Wme2/wc | ||||
|         7xx+x6vB0Wax8eD0B7ku6zqdubjrDEMyrK37ZywAltN000cByYG+it6GEIJ7rrqHr477qtd9SutL+enm | ||||
|         n7ImZ41fVVynx0mFvaJTn/FIj9+fuqcrTvPspmf5+OTHXvdJjUrlidlPkBWfpYVA10gBRiHBm1uwsQBQ | ||||
|         eedC0K6/nUfCNUOu4b6r7yPcahw1Xeus5eef/Zw/7P4DTun0a3fcLjfHSo6puXQHKasvo7C60O+36njJ | ||||
|         cR5d+yifnvnU6z5T0qbw+OzHiQmL0UKga0xEEOLt3rUVlGkDxqPpFEkRSTw661GGxg41bHd5XLy0/SVe | ||||
|         2v7Spay6fuZIyREVMNRBdpzdcSnAyJ8I2F+0nwdXP8iJMuOEtkIIlo5Zym2jbuuRe9UHGU8b6fuMBYBa | ||||
|         f04Chga6972NpWOWMnfoXK/tG/I28Jvtv6HB2dAz1m0T7CzcyR/2/AGXp/208UdLjvKH3X+4lOXX3wj4 | ||||
|         vPBzntv0HBUNFYa7RIdGc9eku8hK0FOBLjAUQaK335rxKsBcQIUBfRWd/LNjNFr9X1j4glcDWm55Lo+s | ||||
|         eYQDRQd6NCGG9EjOVJ4hKSKJ4fHDvQbpnK06y4OrH2Rj3sYeX3o7WXaSOFsc09KnGQZHDYoeRIOrgY2n | ||||
|         N/rEU7EfIYFNwAmjlYC2BMCtwHXo3C0dwmK28MTsJ7hp5E2G7bXOWrI3ZvPu4XdVJF9PIqCioYJNpzfh | ||||
|         8DjIjMvELMxYzVY8eKhsqOST05/w8JqH+fjkx8gAPGYdbgdHy44yJW0Kg2MGt74EIRgUPYjN+ZsprCrU | ||||
|         vgEdxwIcALYYCYDWtzEbUILhNeBbge59r0DC9PTp/P1Lfyc92thl4u1Db/OtFd+iwdUQ0H6GWEIYnjCc | ||||
|         cUnjyIjLUAOv5ChbC7ZSXudbD8TOYhImlmQt4U83/4nkCOPFp7/s+wv3rLynx+wnfYT/A74LeFpmCWrt | ||||
|         haF+AAlIhgS6170CqTLhfmfyd7wO/lPlp/jfrf/bc/N+bwj1pD10/hCHig5d9n7Acwuglh/X5K7hvaPv | ||||
|         8b3J3zPcZ1HmImYMmsG6k+u0btpxBiNIAC60bGh9C5UDUAKQFuhe9xbGpYxTDisGuD1u3jz4JnvO7Qn4 | ||||
|         ALuIQH3zTVuw9Atwupy8tus1jpceN2xPjUrl5pE3E2oNDXRXexNpSBKMZnaXC4BLWUQTAP+5gvUhQiwh | ||||
|         fGPCN7wm8zxRdoK/7P0LTrd/1/vbRXZiCyQC9hfv5/e7fu91unTLqFsYlTQq8H3tPaQhiTe6X5dPAcw0 | ||||
|         lf8aCHQsw2N/xgNjB4xlUeYir7u8eeBNTpadDNxT1qMMlJG2SOJscUSFRpESkUJyRDLJEcnYXXYKqgso | ||||
|         qyujvKGckroSapw11Nnr1FJgANRsp8vJimMruH3c7UxOm9yqfVDMIO644g72Fe0L0E3tdcRgIg038Czw | ||||
|         5KWGywWABEIROBhOUCmGQYqA2UNme430O1h8kH8c/odaturBjL1NfUuOSGZy2mRmDJrBnKFzVASesGA1 | ||||
|         W7Ga1ObBg9PlxCmduDwuqu3V7Cnaw6qcVewq3MXhksPYnfaLx+yp+5pXkcf7x95nUuqkViHMAsGizEW8 | ||||
|         EvcKuWW5+pfaPgJJFiYErsv1gNYCwIEFGB7oHvcGYmwx3DjiRsM2j/Tw7pF3OV5yvGfTdVvCmDJoCl8d | ||||
|         91UmDZjEqMRRxNpi2/xYqPnSfDopPInMuExuGnET+VX57D63m5UnVrLy+Eou1FzoMY3A7Xaz4ugKvjLu | ||||
|         K4xNGtuqPSs+iwkpE8gt1QKggwxH6fiXeYMZJWqzAMM6csR+jYSMuAwmDJhg2FxQVcB7R9/rmQq5jYU7 | ||||
|         pg6aytcmfI2vjP0KCeEJbWYbbg+r2UpmXCaZcZksyVrCraNu5U97/8S63HW+DxM2QiivxPW56w0FQERI | ||||
|         BF8Y8QU+yvkosEurvYcs1Ni+TABcLs/NgIloIDHQvQ12hEnw1XFfJTHc+Faty113Ka2XP5HKS+7Ja57k | ||||
|         raVvce+Ue0kMT+zW4G9JZEgkN428iT/f/Gf+ettfWZy1GFMPqAJOt5N3j76r0oMZMHPwTFIiUrQxsGMk | ||||
|         YmDXu/xb9ACSFHT+v7aRMDRmKAsyFhgOtDpnHevy1vnfWcWj3I9/f9PvWTZ3mdcAJF8RY4vh5pE38+qN | ||||
|         r3LXlXepqYOfB9++on3sOrfLsG1IzBAWDVvUySP2WyIwqOvRWgB4GICu/ts2jer/qETjRBs5ZTlsyd/i | ||||
|         1y6YhZn5w+bz2o2vsWTYEsyi/ZSNHumhyl5FQVUBx0uPs/vcbvad38ep8lOU1JWoKkMdYEjMEF5Y+AL3 | ||||
|         T7tfeez5SwgIKG8oZ23uWsPgJJvFxuS0yZhM2iOoA4QDrZJSXm4DUA+zFLQAaBsTjEse57UW3vaC7Zwq | ||||
|         P+U39d8kTHxl3Ff42bU/8+p92ITT46SsroytBVtZm7uWM5VnKKsvo8peRVlDGVaTlYSwBBLCE4i1xTI5 | ||||
|         bTILMhYwKmEU4dZwrxl8Y22xLJuzjCuSr+CJdU+QX5nvn+v1wNaCrRTWFBoGWU0cMJFB0YM4U3FGGwPb | ||||
|         pgMCQJGKFgBtYrPYmDPEuE6K0+1kw+kNTUlV/MINI25oM+oQ1NN++9nt/P3g31mTu4aCygKqGqpUY4t+ | ||||
|         5ZXnXXyKv3vkXV6KeImJAybyrYnfYvGwxV7rGIRbw7l93O3Y3XYe+vghVYrc19dsUsVE8yryDK83IzZD | ||||
|         CYByLQDaIYw2BcDTqDJgcbr+X3tEWCMYnTjasK3eVe+7vPotkXBFyhVkz8luc/AfLz3Oyztf5v2j75NX | ||||
|         kafebHL/9Ubj4HF5XBRWFVJYVci2gm0szFzINyd+k/kZ8w2LfppNZr405kvklOXw4tYXaXD73iJfba8m | ||||
|         pyyHmekzW7UlhCcwJmkMW874d8rVBzABKVQDzwE/vvSmwgPEEQ4kdf7Y/QgJ4weM91raa9e5Xf5JpyWV | ||||
|         B9wvFv2CK1Ov9LKLZPXJ1dzx7h38etuv1eDvSpBP42fK6sv4+8G/c8e7d/D8p8+rsl0GRIdG8+jMR7ll | ||||
|         9C1+sQdIKdlWsM0woYlZmJk5eCYhFl22sgMkE4Ot+UJgy2eCDYgLdC+DGqmMYN7y/e0r2ueXqjbh1nAe | ||||
|         mv4Q8zPmG7Y3uBp4++Db3P3B3Xxe8LlvioiCEgR1Zfx8y895fP3jnKo4Zbhbk01gevp0vwiBwxcOU+8y | ||||
|         XlVJi0zzWntQcxlxeAhr/v20FAChQExnjtgfSY9O9yoACqoKcLt8nFFXquIeX5/wdcMfusvj4g97/sB9 | ||||
|         K+/jTOUZ33vrCbW0+bd9f+ORNY+ocxgwMnEkd0++myhblM+FQF5FHrnluYZtKZEpWgB0jBjUGL+IkQYQ | ||||
|         G+heBjUmvDr/VNur1eDw8dM/MjSSH0z9AfFh8Ybt/zryL5755BnK6sv8agiTSFYcWcHj6x6nuLa4VbtA | ||||
|         cP3w61mYudDn565x1FBQVWDYFh8WT2pUqnYIap9YWqT4MxIAWgPwhlSqrjeHmxpnDedrfZxN1wNLspZ4 | ||||
|         TTS6p2gPyzYso7i6uEes4C7pYsXRFby882VDF9zkiGS+c+V3iAuL892AFFBlr+Jk+UnD5jBLmF8LmfQh | ||||
|         YmhHAISiNYA2iQqJ8pquqspepdbDfYWE+PB47rnqHsOqwmX1ZTy1/imOlR7r0bDdOkcdv9n5G1afXG3Y | ||||
|         PjN9JouzFvv0nC6PSy0zGhAdGq2csrQG0B6xeJ0CqHXrKHQW4DYJtYR6dQCqddRyoc53VXUBJqZOZMrA | ||||
|         KYZtq3JWsSFvQ8/fBAGltaX8bufvDFN5R4dGc/3w6wkP8aE7iUfVUbS77a2aTMJkuESpaUU4LeIBLgkA | ||||
|         AUji0ZnWvCNV6Kw3AVDvqu9UBZ6OsDBzoeH5zlSe4eWdL1PnqAvMvRCw+cxmr1rANYOvUV6KPnwqOzwO | ||||
|         3J7WBlaLyeL1O9FchoDLMwNdrgFANNqfqk1CzCFEWCMM26oaqnxXUEPCgKgBzBo8yzDgaG/RXnYW7gzo | ||||
|         t1Vrr+WN/W9Q2VDZqi0lMoVp6dO6cFTv1DvrvRY38eayrLkMAUQ1/81c7ggkiOj0IfsZZpPZ65JTlaPK | ||||
|         dzn1JYxIGMGIhBGtmpweJx/lfITD5Vtto9MI5fh0rPRYqyabxcb4ZN9Wlqt11HrVsGxmPXPtAAKIoFld | ||||
|         lUsCwAxIItEaQJsIITCbjCPvfFpOywRXpV1laHAsry9n0+lNgb4VIOBczTl2nN1h2Dw+ZTwJEQm+mQYI | ||||
|         NcXypgGEWXUEewcQQGTzSX7L+X4EWgC0iQmT19BbX6qhFpOFAZEDDNu2FmxV1XGCAOmRrM9bb7gkODR2 | ||||
|         qO/sAFJpFd60rx6rZdi7EbQI9DO1aNQaQDu4pdurGhodEu2zTDxmk9mr48/hC4epdFQGzTeVV5GH09M6 | ||||
|         7Xl0aDTRodE+O0+ENcKrtb/GURPo29AbaDXGjTQATRs43U6vPulmk9lng9JqsjIoapBhW0VDBdIdPE+8 | ||||
|         sroySmpLWr1vs9iwWXw3N08ITyDM0lrVd3vcVNmrAn0beguXjXEjDUDTBm7p9lrkI8Qc4jMNwGKyGEYc | ||||
|         Ot1OQzfcQOJwOyitb523L8wS5lMNINQcamh/sbvtlNSXdOGI/ZLLpvktNQBtSWmLxtp6dU7jtfe4sDgi | ||||
|         QnyjRJmEyXDw2N12ah0dS93VU9jddsPEnVazyjbkE5kolaGvZY0AUPN/t8cdNFOiIOeyMd5SA2g/sVw/ | ||||
|         p9peTXGd8RM40hrJgIgBPjF6SSkNDWsWkyXovN6sJqvXJ73dZffZKoA3/wtvGojGEGvz/7QUpzqmsh2q | ||||
|         HdVeVfDI0EgVleYDnB4n52rOtXo/xByitIzgMQFgs9hIjmy9XNngalCqeXf7KiHSFklWfJZhs8Pt8Bon | ||||
|         oGmFmTamAFoAtIVQP2ojzzeAOFscGbEZPhmcbo+bC7WtqjljEibibfFBpe5aTBbDYKXyhnLK68t90tfE | ||||
|         8EQmDpho2FbjqFGJSoLongQxl43xlgJATwHaweV2cbTkqKFDitVsJSHcN3Nel3R5VWsz4jKwhQSP59uA | ||||
|         yAGG6nmDs8HrikmnkBATGsPgmMGGzbnluXoVoOO0KQC0BtAB8irzDA2BAsHVA68mxhbTbS3A6XZ6TYAx | ||||
|         I32GSkoSJNOAOUPmYLO2FkiV9koq7T7wVxCQlZDl1fZx6MIhnwdh9VkkFmNXYG0E7DAnSk9Q7ag2bBub | ||||
|         NFYlw+guHnUeu6t1+GtmXCaTBkwK9G0AIDwknNlDZht6Rx6+cFglSPWBAJg+aLpXAbD73G5cLlcnD9pv | ||||
|         0VOAbiFUKK63/HQDowZ6NVZ19jy7z+3mQPGBVk1h1jBmpM8I/JzXowqkGKVIb3A1sCpnFfWO7k8BLCaL | ||||
|         YYFQgMqGSs5UnenkEfsxAgsm70bAIFEqg5tqRzVb87catkWGRKrB2V0EFNYUGkbaCQQ3jrxRDYoAfmNW | ||||
|         i5WlY5YyJHZIq7Z6Vz17ivZ0/yQSxiSNYVi8ccHqguoCztf4OA1bP6K5AJCAj9PZ9k3cbjeHLhzCIz2t | ||||
|         2oQQTE6dTExY91MrOl1OVuesNvQHGJs0lqVjlwauLp6EyamTueOKOwybDxYfNFzG7Mp5pqRNUasrBhwv | ||||
|         OU5+lZ/KkvVNXDR7bJgMGjXtIdUP3Ft67KvSrmJCygTwdPK4Bmwp2HKpuk8LvjH+GwHTAkItodw54U7S | ||||
|         otJatTndTt49/K5P6iNEhEawIHOBYRSgw+1g7am11NqDyzMyqJG4vBkBQQuAjiHgVMUpw/k5QGpUKgsy | ||||
|         FmC2dNOkIuBU+Sn+uv+vhsuOQ2KH8PCMh0mJSOlZIeCBxVmL+eKYLxo27z63m/ePve8TB6CB0QOZPXi2 | ||||
|         YXNJXUlw5EXoTQhcbeUD0FOAjiCgvK6cNSfXGC4/CQQLMhcQZ+t+amyPx8NbB97iYPHBVm0mYeKr477K | ||||
|         PVffg8XcQyu4HpiaPpXnFzxvmKzE6Xby6q5XfVMdWcLcIXO9lmHbfGazX6sw91Eue5JcnhJMagHQGTac | ||||
|         2uDVLXh8ynimD5re/ZM0ahuv7nrVMCOu1Wzlvqvv4+sTvo7VZO3CCTqBhMFxg3lqzlNerfKf5X/GRzkf | ||||
|         +eR0kbZIrh9+PaHm0FZtHunhk9OfBF1gVC/AiwCQrRs1bSCUB9onpz8xbI4KieLOCXeqIBkfqMIrj69k | ||||
|         8+nNhs0JYQk8P/957pxwp+Fg8cnlSsGk1En85vrfcMPwGwz3qbRX8tru1yiqLur+U9kD84bOY0HmAsPm | ||||
|         3PJctuTrisCdRuLGbWQENCMRWgB0hjpnHety1xk+mQEWZCxgztA53T+RgPyqfJZ/stxwWRCUO+4vF/+S | ||||
|         Fxa+oEJwfWUTkGqqsTBrIa/f+jpfGP4Fw91cHhev7HyFfx3+l09U8ojQCO6efLfXdN97ivaoe6HV/85y | ||||
|         2Ri/ZKWaiwBuACYGuoe9ieK6YmYPma1y37UgzBqGw+3g49yPDVNmdZbC6kKq7FXMGjzLsDhpqCWUiQMm | ||||
|         kh6dTrm9nAs1F3C6nF0bJBIswsLg2ME8MO0Bls1ZxvCE4V7zHq48vpIn1j+hAqV88PS/YcQNPDDtAUIt | ||||
|         rTWaOmcdz3/6PPuK9mkB0FkEOzHxARvVI6K5AABYCEzpynH7JULlB4gPj2f+0PmGySqSIpI4WHyQE6Un | ||||
|         uv1j9UgPh4oPYTaZmTV4lmF2HIvJwviU8SzOWszg2MGU28s5V3NO+Sy01Aqa+tPifbPZzPCE4Xxtwtd4 | ||||
|         8boXuXnkzW26N2/N38o9H97jm8KoEqLDosmem82EARMMd9mQt4H/2fo/Kh5DC4DOshn4iI3qPy01gLmA | ||||
|         D9zY+hfna85zbea1hlbx6NBoYmwxrM1dqwxW3RUCHg+HLhwiMjSSMUljDOf8QgiiQqK4KvUqlmQtYX7G | ||||
|         fDLiMvA0/rNarJhMJqSUhFhCiA6NJio0itSoVJYMX8IDUx/goZkP8eWxXyYlIsVQsDWxrWAbD615iH3n | ||||
|         fPc0vm30bfxw+g+xmlsbNasd1Tz/6fNsL9iuB3/X2AisaxIAzdeOJFBDU5VATccQcLriNP849A9GJo40 | ||||
|         tMQvyFjA0rFLeXnnyz45X1ldGY98/Agny06ybM4yr9mDhRAMjB7IwOiBLM5aTJW9itzyXM7XnqesrozS | ||||
|         +lIiQyJJjkwm0hpJWlQaQ2OHdijjkNOjvBSfWPcEB84f8Fnar6GxQ/mvqf9lOMUBJXBW5azywcn6Jc3H | ||||
|         ONBcADQAYdQ1lrbRAqATuDwu3jzwJreNvs0waYXNYuN7k7/HtoJt7C7c7ZPoOLvbzu8+/x0Xai/w+KzH | ||||
|         uSLlijY/YhImYm2xXJl6Zbevt8HVwOv7XufpTU9ztvKsz34tYdYwfjTjR0wdONWwvd5Vz1/2/sUnHob9 | ||||
|         FAlcFsd+aQowDzAxEbgefXs7h1DZb0LMISwatshQZU6JTMFmsbHu1DpV0ssHd9gjPRwtOcreor2kR6cz | ||||
|         KHqQ18IZvsAjPZyqOMWL21/kmU3PUFrrw4Eo4Qsjv8CT1zzp9em/MW8jP9/yc1UQVf9Cu4IHWAHsam0D | ||||
|         mA/AGOAmdIXgziNVZNrktMleA1dGJIyguK6YXed2+ayGoEd6KKgqYMOpDZyuPE2MLYbUyFSv5cu6Sl5F | ||||
|         Hq/vf52HP36Yfx/7N/XOep8O/mHxw3hpyUteQ6kr7ZU8/cnT7CjYoQd/15HAO0j20+i+culXMgcQDAOW | ||||
|         ogVA5xHKQFXRUMH8jPmG6cGtZitjk8eyv3g/p8p868JaZa/i88LPWXdqHWerz5IckUxUSBQWk6VLJcsk | ||||
|         kgZnA2cqz/DPI//kx+t/zP/t/j+Ka4tx48MU3FKlU392/rMsyVri1eD48s6Xefnzl3FJ7arSDTwI/obk | ||||
|         WGsBMBcwkQx8DZ0YpMvkVuQSY4th+qDphj/mWFssWfFZ7D63m6IaH3jMNdF4nMr6SnYU7GBlzko2nd5E | ||||
|         QVUB9c56wq3hRIVGtXsYu8vOoQuH+PDEh/xmx294YcsLvH3gbU5XnFbn8PHTN9QSygPTH+Deq+81tPqD | ||||
|         KoX+yNpHKK4p1k//7uFC8AqSM00C4NLtXAbAJASfAO3/UjTGNKqzf7r5T8weMtvLLpKPTnzEQx8/xJEL | ||||
|         R/zzo242w0gITyArPov0mHTSo9OJD4snPiye1KhUquxVVDZUUlxbTH5VPkU1RZwqP8WZyjOX0pH5adBZ | ||||
|         zVbum3Ify+YuIybUOH9CWX0Z3/7g27x/9H3/dKJ/UYl61O8lW71xyWKkvuSGxp20AOgqAk6WneS/P/tv | ||||
|         shKySI1MNdhFsGjYIh6Z+QgPffyQf6zazY5XWl9KaX4p2/O3g0mtCJiFGbPJjEd68EgPbulGeuSlRWA/ | ||||
|         PO2bYxZmbh55M09e86TXwQ/wzuF3+OiEb4KLNFSgxvhFWnoCRgO3AskdPqSmNY0RfG7p5poh1xj6BpiE | ||||
|         idFJo4kKjWLH2R2+Nap56VPT8SUSj/Tg8rhwS/elzEY9MPCbWDhsIb9Y9AsGRQ/yus+GUxt4dO2jqvCo | ||||
|         Vv19wRngDaDCyBMQVN2wG4HBnTuupiUej4fDFw6TEJ7A5NTJhoY4i8nCpAGTiA2LZU/RHq+ZhvsMUl3z | ||||
|         nRPv5OcLf95m8tTc8lzuX3W/9vf3LceAt4Ga1gJgHiCwAtcBIwLd016PUAa1nLIcRiaOJDMu01AImE1m | ||||
|         xqeMJys+i2Mlx/p0gstQSyj3Xn0vz89/vs0SavmV+dy/6n7W5q7ts/ciQOwD/gk0GPsBmBBIrgUmdP7Y | ||||
|         mlYIKK0rZX/xfsanjPda2cZisjA8YTijE0dzsOSgiqfvS/6YEmJsMfxg6g946pqniLXFet21rL6MH6// | ||||
|         MW8feLvvXH/wsA0TKwBXawGwENiOkzRmAT5IZaMBQKhgoSYh4G3OaxImhsQOYWHmQirtleSU5ah0Y719 | ||||
|         EEjIjM/k+fnP859T/tNrfD+oMN8XPnuB3+/6vV7v9w9rcPERJmgtANYB/wGofAALA93TPoWAc1Xn2Hd+ | ||||
|         H9MGTSMlMsV4NyGIC4tjRvoMbFYbR0qOUGOv6Z1CQKpKxreMvoWXlrzE9cOvbzPIqN5Zz693/JoXPnvB | ||||
|         N/UENS2RwApMbGlaAoSWDj9zARgGLKZFHXFNNxFQWFXIrnO7uCLlijat3xEhEcxMn8mk1EnkV+WTX5mP | ||||
|         lLJ3CIJG/4Nh8cN4bPZjPHnNk2TFZ7XpjVjRUMELW17ghc9e8EnItMaQOpQBcH/T0x+MBcAA1EpAeMeO | ||||
|         q+kwjUJgb9FexiWPY2D0QK8DwyRMZMZmsiBzAcPjh1NYU8iF2gvBLQgkRNuiWZK1hJ8v+jlfGvMlQ5fo | ||||
|         5hRWF/Lkhid55fNXdIIP/1KJ4HUEud4FgFoJiAS+BHS/tI2mNQLOVZ/j83OfkxSRxIiEEYaFNUFNCWJC | ||||
|         Y5icNpm5Q+YSbg2nqLaIivoKFdcVLINFqiKhS7KW8JM5P+HhmQ+3+9QHFWB030f38daBt3C6u5i6TNNR | ||||
|         SoHfA8VtCwD1NdwBJAa6x30WAedrz/PpmU8JtYQyKnEUNoutjd0FieGJzB48m3kZ84ixxVDrqqW8rhy3 | ||||
|         x4eBOZ3Fo6z712ZeyzPznuGBaQ8wOW1yhzIT7y3ayw9X/5APT3yoIiP14Pc35zDxG0zUsuHSm5ff9mxA | ||||
|         OQOtRacG8z8SQiwhfGXsV3hwxoOqnFiHPibJr8hnxbEVrDu1ji35WyirL8Pj9vjPk0+qTQiBLcTG0Nih | ||||
|         3DTiJqanT2fe0Hkq/XkHqHXU8u7Rd3lx24u+SY6i6SibUcb9huZGQCMBYAX+CHw90D3uT0wbNI2nrnmK | ||||
|         +Rnz29QGmiORVNmrOFZyjLW5a9l8ZjMnSk9QUF1Ag7NFQdHODLSWSUJNZqJDo8mIy+DK1Cv58pgvMyZ5 | ||||
|         DEnhSR1KH9ZETlkOv9z6S/66/6+9d3Wj9/IX4LuAsz0BIIAngacD3eN+hVRRe9+d/F3unXJvl5J6VNur | ||||
|         yS3P5VjpMfYW7WXf+X3kV+ZzvvY8Da4GHG7HxeAfj/QogyLK4GgxWzAJEyZhItQcSnxYPENjh3JV6lWM | ||||
|         Sx5HUkQSIxNHkh6d3maSUCMcbgfvH3ufn23+GXvO7QluQ2bf5cfY+Cl2ZGPkL9Dya1hOk3Hpq8Cb6K+p | ||||
|         Z5EqRHZc8ji+OfGb3D7udq918drD5XFR76yn3lVPaX0pBZUFnK48Tb2rnjpnHQ2uBmqdqqxWVEgUKREp | ||||
|         hFvDsVlsDIkdwpCYIYRaQomwRnQ5zZjb4+Z42XFe2/Uar+97XaUQ06lmAoEEvoLkHczATy41XD7A/wAU | ||||
|         ADALWImKDtT0NI22gWszr+X+qfd7LQQSrLg9bo6XHuftQ2/zzqF3OFZyDI8vaqVrukoFkhuALSy/vOFy | ||||
|         HfMDmnwBIlDJQfVKQCAQ4JZuTpSeYO2pteSW52ISJhLDEwmzhgW6d15xSzXwf7vztzy54UlWHFmhfBdE | ||||
|         T9Yu1xiQi+DPCEqbLwHC5XUBmlMKnAVGBbrn/RoBRTVF/HH3H3nv6HuMSRrDtyd+m3lD5zEweqBfMwB3 | ||||
|         htK6UnLKc1iVs4q3D75NTmkOLo+rx3ILaNrlLGpMt6ItAXA60L3WKCSS0tpSPq35lO0F2xmdOJprM69l | ||||
|         SdYSZg6eSZglMFpBg6uBNw68wTuH3mHb2W1U2atUViE98ION04RThkEN29Zm5o3AXCTq6a+ChDWBp3FQ | ||||
|         uaWb8zXn2Za/jfV56xmXPI7hCcMD0qWSuhKWb1zO2pNrL1VI1gM/2HABb+NkS3PrfxNt6ZAHgWogNtBX | ||||
|         oGmBACklaVFphpWIQD2ddxTuwGa2kRmXidVkxWwyYxZmTCYTAoFJmC6mB5NSXkwPVu+sp6KhgryKPMob | ||||
|         yhmRMIJJAya1OkdSRBIzBs9g/an1gb4jGu/UAIe8NRoLACXFjyC1AAhaJCzKXMSAyAGGzRvzNvL9f3+f | ||||
|         WmctcbY4om3RJEckExMaQ2RIJCGmECJCInC4HWpZ0N1Alb2KKnsV+ZX51DpqaXA1YHfbuXvy3UxImdBq | ||||
|         /d8szCzJWsKf9/6ZgsoC/fQPTiqBo94ajQWAMtqWAqeAdDTBhYTkyGTmZ8z36pSz7tQ6TperXP4ltSXd | ||||
|         Ot3qnNXcNekuxiWPa9U2Pnk8YxLHUFChBUCQkosXAyC0Pb+vB/YHuvcaY2YNmcW0QdMM23LKclhzcs3l | ||||
|         WX67sR0tOcrqk6sNzxUVGsXSMUsJsXbcJVjTo+zHRIM34WwsAAQgcaKSCGqCjBBLCDeNuMmrT8CGvA0c | ||||
|         LD7osyeylJI1J9dc9BxsyeKsxYxMGImPyh1qfIcE9uLC6e1Rb/z2Mpp+PEeB84G+Ck0zJGTEZjAvY55h | ||||
|         s91t572j76kwYR+y69wutuRvMWwbEDmAuUPnagEQfBQhOY4AnjLewfsUQKl/J4GcQF+FphkClo5dysDo | ||||
|         gYbNuwt3s/fcXp+fs7SulE/yPrlURKQZIeYQlmQtITEyUQuB4OIkgpNtaYLeBYCK/y6iDQuipoeRkBaZ | ||||
|         xuLMxYZZhFweFyuOrfBt0dGmU0vJu0feJbc817B95uCZTB04NdB3SHM5R8jmPG1kZfMuALIBJQZ2Ao5A | ||||
|         X4kGkDB+wHimDJxi2Hym8gwrj6+8GObrUwScKDvBp6c/NWyOCY3hxpE3djqEWeM37MAOsoGHve/UES+/ | ||||
|         HShnAk2AsVgs3DLqFq8JQ7YVbONYyTG/Lce53C5Wn1yt8vcZMG3QNAZGDdTTgOCgBsGO9nbqiADIR9UU | ||||
|         0wQSCVckX8GizEWGzTWOGt45/I4KwvEjWwu2suvcLsO2EfEjuGHEDdofIDg4gqSwvZ3aFgACMFOByiem | ||||
|         CTALMhcwNHaoYduOszvYmr/Vvx0Qqm7fB8c+MBQ0YdYwrsu6joSwBK0FBJ7PgPL2dmpbAFgBNy5gG3oa | ||||
|         EDik8rtfPGyxYaptj/SwLnddjxQWlVKy+uRqLtReMGyfMXgGIxJ0bdkAU41kG5J214LbFgBP0LQcuAc4 | ||||
|         Geir6s/MSJ/h1fPvXPU5Vp1c1TMdEXC89DifF35u2JwQlsCto2/V04DAkouJPZigeQJQIzoa6nsa7RUY | ||||
|         MIRJcNvo27wW1tyQt4FDxYd6bNDV2Gt479h7qnipAdMGTSMlIkVPAwLHXhI4Q0b7O7YvAJYBEg+qfKiz | ||||
|         3f01HUd2YPPAmMQxTB1kvMZe76zng2MfYHfaO3Y8H22b8jZxoPiAYZ+uSruKxVmLO3Ysja9xIljDBSR3 | ||||
|         tr9zZ3JK7QAKgSGBvsJej1QGs+TIZBLDEtssoeXyuLhxxI0Mixtm2F7WUEZ6dDpLxy3tdLru7iCEoKKh | ||||
|         wrAtzBLGzSNvJqcsB7vbjvCimtQ4aiisLqTGXqOThvqOAiQ7O6oNdmy35YAgHA8vA98I9BX2ZoQQjEka | ||||
|         w2MzH2N+xvx28/pJJOGWcKJCowzb3dJNg6vBP84/7WA1WQm1GJcBc7gdVNor2+yX2+PmWOkxXt31Ku8d | ||||
|         ee9SViFNd/g/TNyHpN4oA1BLOqYBKHWtDlUybCkQ0aHPaS5HQlZCFq/c8AozB8/0+mTsDGZhJsIafF9H | ||||
|         iDmEpPD2axqkRqUyacAkYkJjeG33a4axBpoOUwOsxUN9Rz/QMZ0xm6bVgE2oJCGaLmAymbjv6vuYNXiW | ||||
|         TwZ/XyHGFsMPp/9QJRzRdoHukIvgUwTtWv+b6PikUWkBBcAngb7K3kpkSCTXDL4m0N0ISjJjM7ky9cpA | ||||
|         d6O3sxFJYWeEaGetRh5UxaC6QF9pr0PCoOhBXufy/R2r2UpaVJr2H+g6dcCHSDydGdUd3zX74qu9qAhB | ||||
|         TWcQUFxbTHl9u96Z/RK3dHPkwhE9Beg624F9CC6r/dcendMArICdc8D/Q/sEdJqSuhL+fujv2tBlwN6i | ||||
|         vewp2hPobvRWnMAHSIo6q0F1Lnh7PbAQEJSiagcmBPrKexUScityGRo7lFGJo3p03T6YyS3PZfkny9ly | ||||
|         ZoueAnSNHGAZgvKOGv+a6HxxOaWi5QIfAYEpSdNbEVBUXcSDqx9ka8FWZgyawcjEkYbZffoD1Y5qdhbu | ||||
|         5K2Db6lIRj34u8qHdLGUX+dv+XJodNqai+AddAXhziPBJEyEhYQRZgnrt0uCbummxlGDw+XQg7/rXED5 | ||||
|         5mwCOrz810TXbrs6SRTwF+DWQN+BXk1/N3rpgd9d/oXgW0B1Rzz/WtK1SWg2oOoGvgXUdukYGoWPinf0 | ||||
|         2k3THWqAt5BdG/zQ3cq/grXAp906hkaj6SqfoEzzXabrAsAEuCkHXkdrARpNT1MD/JUOpP1qi64LgJ9c | ||||
|         /PRaYEuXj6PRaLrCZ6ix12nDX3O6NwVQJ76A0gIaAn1HNJp+QgOCvwKl3Rn80F0BAE1BQqvQQUIaTU+x | ||||
|         vnHMdZvuCwBlzS0BXgXKAntfNJo+TynwKi5KsXb/YN0XANkXX61GeSRpNBp/IVmJ5GMswI+7fzjfOKNn | ||||
|         ozIGCV6B9quRaDSaLlGA4BUEDd2d+zfhu2gUAUh2Am+CzvCo0fgYCbyNiV2+dKDynQDIBgQOBH8A9vfw | ||||
|         zdFo+jp7gdfw4Oiq158Rvo1HVSsCx4CX0M5BGo2vqAFeBI77+sC+jUPdCMwFVOLQTGC8f++LRtMveAv4 | ||||
|         X8Duq7l/E74PRN8IzMUO5AHz0UlDNJrucAx4CDjt68EPvp4CXM5e1FRAJxDVaLpGHfAitsZcf37AP6lo | ||||
|         NgLzAMEJJEMRTPDTDdJo+jJvAL/A5btlv5b4LxfVRmAuDQiOAtOBVL+dS6Ppe3wO/Ag466/BD/6dAjRx | ||||
|         BHgOFTSk0Wjapxg1Zo75+0T+zUa5kaZVgRwgHJhFzwgdjaa34gJ+AfwR8Pjz6Q/+FgDQJAQ8wGFUafEx | ||||
|         6GRQGo0RHuAdBM8gqPH34IeeEADQZBSsRbAfmAwM7pHzajS9i80IfgTk+9Lbry16Vh33cBx4HDjRo+fV | ||||
|         aIIfNTZcvvf2a4ueq0ixEbU0CAVAETAHCL7C9hpNz3Me5ezzMSa6leKrs/RsSZqNwDwkgmOo+c4MIKRH | ||||
|         +6DRBBfVwHOY+Qs9YPRrSc/XpNpIk1FwPxAKTKErJco0mt5PPfC/mPgV0NBT8/7mBKYo3UZgLg5gBxAN | ||||
|         XBmwvmg0gcEOvAw8i6QmEIMfAjnoNgLzcCDYgaovOBHtI6DpH7iAPyLJBqpYHriOBPapuxGYSz1KE0gB | ||||
|         xga8TxqNf3GiCno8iaA0kIMfgmGwbQTmUItaA40CJqBtApq+iR34PSZ+jKAkUGp/cwIvAEBVFJhPHYIt | ||||
|         KMPgRPBF0mONJmioA36LYDlQHgyDH4JFAIDSBObTgGArEoEyDIYGulsajQ+oBn6JiecRVAXL4IdgEgAA | ||||
|         G4A5OICdqJs2EYgMdLc0mm5wHngW+BWS2mAa/BBsAgCaVgecCHYBuSghoNOKaXojx4GHEPzVl7n8fUnw | ||||
|         CQBQQmABHqwcwc1eYDSQho4i1PQOPMBW4L8IZTUSNz8JdJeMCU4BAGo6MBuAM6hSyKnACLSvgCa4cQHv | ||||
|         Afcj2IMTgk3tb07veKJmAzAAuBf4HpAU6C5pNAZcAF5BefgVBaPK35Lg1QCasxG4lhpMbEaSAwxHCYTe | ||||
|         IcA0fR0J7EXwKBZew0RVsKr8LekdAgBgPSqIyMQxlOdALJCF9hfQBJY64O/AD3GxGQ/uYFb5W9J7BAA0 | ||||
|         LRNKoKTxf+eRDEcQh9YGND2LB0kOgmeBF4ACTMhAu/Z2lt47aJ4GrJhwMAHJA8AX0QlGND1DLfAvBC8S | ||||
|         wj6ceHqLyt+S3isAmsgGVEjxrcADqHqEeqVA4w88wD5Uxav3gKreYOhri941BTBiI021CPdjYj0SCWSg | ||||
|         PQg1vuU88EdMPIZkA34o1BkIer8G0Bw1/7IhuRr4PrAYiA90tzS9mjJgFYJXUWHrAcnc4y/6lgBoYjkg | ||||
|         CMfDYuBuVHkSW6C7pelVNKD0y1cxsRpJfV8a+E30TQEAzTOrJgJLgDtRNQr11EDTFjUoN97XgY8QlPbF | ||||
|         gd9E3xUAzVkGmEhAshD4BqpEmRYEmiYkyrL/KYLXgTV4Ap+tpyfoHwIAmmsEccAC4D9Q0QaJge6aJqCU | ||||
|         AJuANxCsx0oFDno0N38g6T8CoInngSogjGgkk4FbgOtQdQt1jYL+gQM4DXyEWs7bhco/0W8GfhP9TwA0 | ||||
|         8SzwTeCPWJBkADcBXwCuRlUy1vQ96lCW/H8DHwCnUNF7/W7gN9F/BUBL/geoYgCCq1CCYBYwFO1d2Nup | ||||
|         BfKAzcBKJDuJpogHA92t4EALgOZkAzFALWbcpCOZA8xHLSOmobMV9xZcwFnUMt561Bw/H3AD/fZpb4QW | ||||
|         AG2RDQgigHRgKpIFKFfjTCAq0N3TXEY1cArJXgTrgB0I8pHU6gHvHS0AOsovAImJOoYgmQBMRzIbwSjU | ||||
|         NEEbEHsWB0q9PwJ8CmwD9iI5A3j6wxKeL9ACoLNkX3xlQRKHIANV4PQqYCQwDLW0qAOSfIsHlXEnFzgG | ||||
|         fI5gB5JTCCoAFxKt3ncSLQB8QTagAqsGoKYHw4ErUFWOMlGWhUi0DaGjuFAeeZVITiLYj2B/Y/z9SSRF | ||||
|         BKCUdl9ECwBfk43yKzNjxYMNldJ8FDAOldR0MDAIGIgSDP39O5BAJVDQuOWjnvCHgKNIShHUE44LF/BE | ||||
|         oLvbt+jvP76e4zkAzLiIQZKImiYMRE0bRqLSm8UDYc02G70/ZNuNCqypb7aVASeA4wiOIylAeeSVoISB | ||||
|         Wz/dewYtAAJJNqC+AwtmrEhi8ZCMIBlJMqpicjJKWMSj8iA2bXEoISG4ZG8QzTZ/IJttoOblEjWoy4GK | ||||
|         ZlsZakAXA+cRFCMpxkQxUIEbJwIXNBbJ1gQELQCCmWdR35Cb0MbphI1LmoENtRSZgMqIFN64hbV4HYZK | ||||
|         nGpF2SCsLTZQJasdqLm3s/Gvo3GzowZ4XePW/HUVglIk1ainfNOTvgETDZixI4EnA30jNd7QAqCvkX3x | ||||
|         lbj4VzZ7T6Ce2eKyfeTF92Tj/y+1yov7XH58jUaj0Wg0Gk2v5P8D5M/bzdE8cNIAAAAASUVORK5CYII= | ||||
| </value> | ||||
|   </data> | ||||
| </root> | ||||
							
								
								
									
										32
									
								
								cmonitor.snatch.win/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								cmonitor.snatch.win/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| namespace cmonitor.snatch.win | ||||
| { | ||||
|     internal static class Program | ||||
|     { | ||||
|         /// <summary> | ||||
|         ///  The main entry point for the application. | ||||
|         /// </summary> | ||||
|         [STAThread] | ||||
|         static void Main(string[] arg) | ||||
|         { | ||||
|             string shareMkey = "cmonitor/share"; | ||||
|             int shareMLength = 10; | ||||
|             int shareItemMLength = 1024; | ||||
|             int shareQuestionIndex = 5; | ||||
|             int shareAnswerIndex = 6; | ||||
|             if (arg.Length > 0) | ||||
|             { | ||||
|                 shareMkey = arg[0]; | ||||
|                 shareMLength = int.Parse(arg[1]); | ||||
|                 shareItemMLength = int.Parse(arg[2]); | ||||
|                 shareQuestionIndex = int.Parse(arg[3]); | ||||
|                 shareAnswerIndex = int.Parse(arg[4]); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // To customize application configuration such as set high DPI settings or default font, | ||||
|             // see https://aka.ms/applicationconfiguration. | ||||
|             ApplicationConfiguration.Initialize(); | ||||
|             Application.Run(new MainForm(shareMkey, shareMLength, shareItemMLength, shareQuestionIndex, shareAnswerIndex)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										79
									
								
								cmonitor.snatch.win/app.manifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								cmonitor.snatch.win/app.manifest
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||||
|   <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> | ||||
|   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> | ||||
|     <security> | ||||
|       <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> | ||||
|         <!-- UAC 清单选项 | ||||
|              如果想要更改 Windows 用户帐户控制级别,请使用 | ||||
|              以下节点之一替换 requestedExecutionLevel 节点。 | ||||
|  | ||||
|         <requestedExecutionLevel  level="asInvoker" uiAccess="false" /> | ||||
|         <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" /> | ||||
|         <requestedExecutionLevel  level="highestAvailable" uiAccess="false" /> | ||||
|  | ||||
|             指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。 | ||||
|             如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此 | ||||
|             元素。 | ||||
|         --> | ||||
|         <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> | ||||
|       </requestedPrivileges> | ||||
|     </security> | ||||
|   </trustInfo> | ||||
|  | ||||
|   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | ||||
|     <application> | ||||
|       <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的 | ||||
|            Windows 版本的列表。取消评论适当的元素, | ||||
|            Windows 将自动选择最兼容的环境。 --> | ||||
|  | ||||
|       <!-- Windows Vista --> | ||||
|       <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> | ||||
|  | ||||
|       <!-- Windows 7 --> | ||||
|       <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> | ||||
|  | ||||
|       <!-- Windows 8 --> | ||||
|       <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> | ||||
|  | ||||
|       <!-- Windows 8.1 --> | ||||
|       <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> | ||||
|  | ||||
|       <!-- Windows 10 --> | ||||
|       <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> | ||||
|  | ||||
|     </application> | ||||
|   </compatibility> | ||||
|  | ||||
|   <!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行 | ||||
|        自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需 | ||||
|        选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应 | ||||
|        在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。 | ||||
|         | ||||
|        将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation --> | ||||
|   <!-- | ||||
|   <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||||
|     <windowsSettings> | ||||
|       <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> | ||||
|       <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> | ||||
|     </windowsSettings> | ||||
|   </application> | ||||
|   --> | ||||
|  | ||||
|   <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) --> | ||||
|   <!-- | ||||
|   <dependency> | ||||
|     <dependentAssembly> | ||||
|       <assemblyIdentity | ||||
|           type="win32" | ||||
|           name="Microsoft.Windows.Common-Controls" | ||||
|           version="6.0.0.0" | ||||
|           processorArchitecture="*" | ||||
|           publicKeyToken="6595b64144ccf1df" | ||||
|           language="*" | ||||
|         /> | ||||
|     </dependentAssembly> | ||||
|   </dependency> | ||||
|   --> | ||||
|  | ||||
| </assembly> | ||||
							
								
								
									
										22
									
								
								cmonitor.snatch.win/cmonitor.snatch.win.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								cmonitor.snatch.win/cmonitor.snatch.win.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
| 	<PropertyGroup> | ||||
| 		<OutputType>WinExe</OutputType> | ||||
| 		<TargetFrameworks>net7.0-windows;net8.0-windows</TargetFrameworks> | ||||
| 		<Nullable>disable</Nullable> | ||||
| 		<UseWindowsForms>true</UseWindowsForms> | ||||
| 		<ImplicitUsings>enable</ImplicitUsings> | ||||
| 		<Configurations>Debug;Release;ReleaseLinux</Configurations> | ||||
| 		<ApplicationIcon>favicon.ico</ApplicationIcon> | ||||
| 		<ApplicationManifest>app.manifest</ApplicationManifest> | ||||
| 	</PropertyGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <Content Include="favicon.ico" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| 	<ItemGroup> | ||||
| 	  <ProjectReference Include="..\cmonitor.libs\cmonitor.libs.csproj" /> | ||||
| 	</ItemGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										8
									
								
								cmonitor.snatch.win/cmonitor.snatch.win.csproj.user
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cmonitor.snatch.win/cmonitor.snatch.win.csproj.user
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup> | ||||
|     <Compile Update="MainForm.cs"> | ||||
|       <SubType>Form</SubType> | ||||
|     </Compile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
							
								
								
									
										
											BIN
										
									
								
								cmonitor.snatch.win/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cmonitor.snatch.win/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 16 KiB | 
| @@ -1,7 +1,7 @@ | ||||
| import { sendWebsocketMsg } from './request' | ||||
|  | ||||
| export const shareUpdate = (name, item) => { | ||||
| export const shareUpdate = (names, item) => { | ||||
|     return sendWebsocketMsg('share/update', { | ||||
|         name, item | ||||
|         names, item | ||||
|     }); | ||||
| } | ||||
							
								
								
									
										26
									
								
								cmonitor.web/src/apis/snatch.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								cmonitor.web/src/apis/snatch.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import { sendWebsocketMsg } from './request' | ||||
|  | ||||
|  | ||||
| export const addGroup = (data) => { | ||||
|     return sendWebsocketMsg('snatch/AddGroup', data); | ||||
| } | ||||
| export const delGroup = (username, id) => { | ||||
|     return sendWebsocketMsg('snatch/DeleteGroup', { | ||||
|         username, id | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export const add = (data) => { | ||||
|     return sendWebsocketMsg('snatch/add', data); | ||||
| } | ||||
| export const del = (username, groupid, id) => { | ||||
|     return sendWebsocketMsg('snatch/del', { | ||||
|         username, groupid, id | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export const update = (names, question) => { | ||||
|     return sendWebsocketMsg('snatch/update', { | ||||
|         names, item: question | ||||
|     }); | ||||
| } | ||||
| @@ -34,9 +34,16 @@ export default { | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| // @media (min-width: 768px) { | ||||
| // .main-wrap { | ||||
| // background-color: #1c77ac !important; | ||||
| // background-image: none !important; | ||||
| // // background-image: url('../assets/bg.jpg') !important; | ||||
| // } | ||||
| // } | ||||
| @media (min-width: 768px) { | ||||
|     .main-wrap { | ||||
|         background-image: url('../assets/bg.jpg') !important; | ||||
|         max-width: 39rem; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,14 +1,15 @@ | ||||
| <template> | ||||
|     <div class="device-list-wrap absolute flex flex-column flex-nowarp" id="device-list-wrap"> | ||||
|         <div class="content flex-1 flex"> | ||||
|             <div class="items flex-1 relative scrollbar-1"> | ||||
|                 <Items></Items> | ||||
|             </div> | ||||
|             <div class="active-device flex flex-column" v-if="globalData.pc"> | ||||
|                 <div class="head"> | ||||
|         <div class="content flex-1 flex flex-column"> | ||||
|             <div class="head" v-if="globalData.pc"> | ||||
|  | ||||
|                 <Head></Head> | ||||
|             </div> | ||||
|             <div class="items flex-1 relative scrollbar-1"> | ||||
|                 <Items></Items> | ||||
|             </div> | ||||
|             <!-- <div class="active-device flex flex-column" v-if="globalData.pc"> | ||||
|                 | ||||
|  | ||||
|                 <div class="flex-1 prev"> | ||||
|  | ||||
| @@ -19,7 +20,7 @@ | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             </div> --> | ||||
|         </div> | ||||
|         <div class="foot" v-if="!globalData.pc"> | ||||
|             <div class="foot-options"> | ||||
| @@ -68,24 +69,35 @@ export default { | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| @media (min-width: 768px) { | ||||
|     .active-device { | ||||
|         width: calc(100% - 41rem) !important; | ||||
|     } | ||||
| // @media (min-width: 768px) { | ||||
| // .active-device { | ||||
| // // width: calc(100% - 41rem) !important; | ||||
| // } | ||||
|  | ||||
|     .items { | ||||
|         height: 100%; | ||||
|         padding: 1rem 0 !important; | ||||
|         box-sizing: border-box; | ||||
|         border-right: 1px solid #999; | ||||
|         background-color: rgba(255, 255, 255, 0.3); | ||||
|     } | ||||
|  | ||||
|     .foot { | ||||
|         display: none; | ||||
|     } | ||||
| } | ||||
| // .items { | ||||
| // padding: 1rem 1rem 0 1rem !important; | ||||
| // height: auto; | ||||
| // width: 80.6rem; | ||||
| // // padding: 1rem 0 !important; | ||||
| // box-sizing: border-box; | ||||
| // // border-right: 1px solid #999; | ||||
| // // background-color: rgba(255, 255, 255, 0.3); | ||||
| // display: flex; | ||||
| // display: -ms-flex; | ||||
| // display: -o-flex; | ||||
| // flex-wrap: wrap; | ||||
| // justify-content: space-between; | ||||
| // } | ||||
|  | ||||
| // .foot { | ||||
| // display: none; | ||||
| // } | ||||
| // } | ||||
| // @media (min-width: 768px) { | ||||
| // .items { | ||||
| // max-width: 39rem; | ||||
| // } | ||||
| // } | ||||
| .device-list-wrap { | ||||
|     .content { | ||||
|         position: relative; | ||||
|   | ||||
| @@ -58,7 +58,7 @@ export default { | ||||
|             showEdit: false, | ||||
|             list: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user) { | ||||
|                 if (user && user.Windows) { | ||||
|                     if (state.group == 0 && user.Windows.length > 0) { | ||||
|                         state.group = user.Windows[0].ID; | ||||
|                     } | ||||
|   | ||||
| @@ -62,7 +62,7 @@ export default { | ||||
|             showEdit: false, | ||||
|             groups: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user) { | ||||
|                 if (user && user.Windows) { | ||||
|                     if (state.group == 0 && user.Windows.length > 0) { | ||||
|                         state.group = user.Windows[0].ID; | ||||
|                     } | ||||
|   | ||||
| @@ -80,6 +80,14 @@ export default { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         .inner { | ||||
|             padding: 0.6rem; | ||||
|  | ||||
|             &>div { | ||||
|                 padding: 0.6rem 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -58,7 +58,7 @@ export default { | ||||
|             showEdit: false, | ||||
|             list: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user) { | ||||
|                 if (user && user.Processs) { | ||||
|                     if (state.group == 0 && user.Processs.length > 0) { | ||||
|                         state.group = user.Processs[0].ID; | ||||
|                     } | ||||
|   | ||||
| @@ -81,7 +81,7 @@ export default { | ||||
|             showEdit: false, | ||||
|             groups: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user) { | ||||
|                 if (user && user.Processs) { | ||||
|                     if (state.group == 0 && user.Processs.length > 0) { | ||||
|                         state.group = user.Processs[0].ID; | ||||
|                     } | ||||
|   | ||||
| @@ -58,7 +58,7 @@ export default { | ||||
|             showEdit: false, | ||||
|             list: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user) { | ||||
|                 if (user && user.Rules) { | ||||
|                     if (state.group == 0 && user.Rules.length > 0) { | ||||
|                         state.group = user.Rules[0].ID; | ||||
|                     } | ||||
|   | ||||
| @@ -43,7 +43,7 @@ export default { | ||||
|             loading: false, | ||||
|             group: 0, | ||||
|             groups: computed(() => { | ||||
|                 if (user.value) { | ||||
|                 if (user.value && user.value.Rules) { | ||||
|                     if (state.group == 0 && user.value.Rules.length > 0) { | ||||
|                         state.group = user.value.Rules[0].ID; | ||||
|                     } | ||||
| @@ -52,7 +52,7 @@ export default { | ||||
|                 return []; | ||||
|             }), | ||||
|             rule: computed(() => { | ||||
|                 if (user) { | ||||
|                 if (user && user.value.Rules) { | ||||
|                     let rule = user.value.Rules.filter(c => c.ID == state.group)[0]; | ||||
|                     if (rule) { | ||||
|                         return rule; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|     <el-dialog class="options" title="设置" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%"> | ||||
|     <el-dialog class="options-center" title="设置" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%"> | ||||
|         <div class="setting-wrap"> | ||||
|             <el-form ref="ruleFormRef" :model="state.form" :rules="state.rules" label-width="100px"> | ||||
|                 <el-form-item label="报告延迟(ms)" prop="ReportDelay"> | ||||
|   | ||||
							
								
								
									
										19
									
								
								cmonitor.web/src/views/device/plugins/share/Index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								cmonitor.web/src/views/device/plugins/share/Index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| <template> | ||||
|     <div> | ||||
|         <!-- <ChooseDig v-if="pluginState.setting.showSetting" v-model="pluginState.setting.showSetting"></ChooseDig> --> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { injectPluginState } from '../../provide'; | ||||
| // import ChooseDig from './ChooseDig.vue' | ||||
| export default { | ||||
|     components: {}, | ||||
|     setup() { | ||||
|         const pluginState = injectPluginState(); | ||||
|         return { pluginState } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped></style> | ||||
| @@ -52,7 +52,7 @@ export default { | ||||
|             state.loading = true; | ||||
|             let value = JSON.parse(JSON.stringify(props.data.Share.Lock.Value)); | ||||
|             value.val = 'reject'; | ||||
|             shareUpdate(props.data.MachineName, { | ||||
|             shareUpdate([props.data.MachineName], { | ||||
|                 index: props.data.Share.Lock.Index, | ||||
|                 value: JSON.stringify(value) | ||||
|             }).then((res) => { | ||||
| @@ -72,7 +72,7 @@ export default { | ||||
|             let value = JSON.parse(JSON.stringify(props.data.Share.Lock.Value)); | ||||
|             value.val = 'confirm'; | ||||
|             props.data.Share.Lock.Value.notify = false; | ||||
|             shareUpdate(props.data.MachineName, { | ||||
|             shareUpdate([props.data.MachineName], { | ||||
|                 index: props.data.Share.Lock.Index, | ||||
|                 value: JSON.stringify(value) | ||||
|             }).then((res) => { | ||||
| @@ -94,7 +94,7 @@ export default { | ||||
|         const handleStarChange = () => { | ||||
|             state.loading = true; | ||||
|             let value = JSON.parse(JSON.stringify(props.data.Share.Lock.Value)); | ||||
|             shareUpdate(props.data.MachineName, { | ||||
|             shareUpdate([props.data.MachineName], { | ||||
|                 index: props.data.Share.Lock.Index, | ||||
|                 value: JSON.stringify(value) | ||||
|             }).then((res) => { | ||||
|   | ||||
| @@ -47,7 +47,6 @@ export default { | ||||
|     }, | ||||
|     init() { | ||||
|     }, | ||||
|     lockTypes: { code: '代码', lock: '锁屏', cmonitor: '班长', flag: '学习目标', class: '课程', 'remark-block': '图形化点评', 'remark-cpp': 'C++点评' }, | ||||
|     update(item, report) { | ||||
|         if (!report.Share) return; | ||||
|  | ||||
| @@ -64,7 +63,7 @@ export default { | ||||
|                 item.Share.Lock.Value.star1 = json.star1 || 0; | ||||
|                 item.Share.Lock.Value.star2 = json.star2 || 0; | ||||
|                 item.Share.Lock.Value.star3 = json.star3 || 0; | ||||
|                 item.Share.Lock.TypeText = this.lockTypes[json.type]; | ||||
|                 item.Share.Lock.TypeText = json.typeText; | ||||
|             } | ||||
|         } | ||||
|         if (report.Share.KeyBoard) { | ||||
|   | ||||
| @@ -0,0 +1,36 @@ | ||||
| <template> | ||||
|     <div class="item"> | ||||
|         <div class="subitem"> | ||||
|             <span class="label">互动抢答</span> | ||||
|             <el-button @click="handleSnatchUse">开始</el-button> | ||||
|             <el-button @click="handleSnatchQuestion">录题</el-button> | ||||
|         </div> | ||||
|     </div> | ||||
|     <SnatchTemplate v-if="pluginState.shareSnatch.showTemplate" v-model="pluginState.shareSnatch.showTemplate"></SnatchTemplate> | ||||
|     <SnatchUse v-if="pluginState.shareSnatch.showUse" v-model="pluginState.shareSnatch.showUse"></SnatchUse> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { injectPluginState } from '@/views/device/provide'; | ||||
| import SnatchTemplate from './template/Template.vue' | ||||
| import SnatchUse from './use/Use.vue' | ||||
| export default { | ||||
|     components: { SnatchTemplate, SnatchUse }, | ||||
|     setup() { | ||||
|  | ||||
|         const pluginState = injectPluginState(); | ||||
|  | ||||
|  | ||||
|         const handleSnatchQuestion = () => { | ||||
|             pluginState.value.shareSnatch.showTemplate = true; | ||||
|         } | ||||
|         const handleSnatchUse = () => { | ||||
|             pluginState.value.shareSnatch.showUse = true; | ||||
|         } | ||||
|  | ||||
|         return { pluginState, handleSnatchUse, handleSnatchQuestion } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped></style> | ||||
							
								
								
									
										41
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| export default { | ||||
|     field() { | ||||
|         return { | ||||
|             ShareSnatch: { | ||||
|                 Question: { Index: 0, Value: { Type: 1, Question: '', Correct: '', Option: 0, Max: 0, End: false, Repeat: false, Join: 0, Right: 0, Wrong: 0 } }, | ||||
|                 Answer: { Index: 0 }, | ||||
|             } | ||||
|         }; | ||||
|     }, | ||||
|     state: { | ||||
|         shareSnatch: { | ||||
|             showTemplate: false, | ||||
|             showUse: true | ||||
|         } | ||||
|     }, | ||||
|     init() { | ||||
|     }, | ||||
|     update(item, report) { | ||||
|         if (!report.Share) return; | ||||
|  | ||||
|         console.log(report.Share); | ||||
|  | ||||
|         if (report.Share.SnatchQuestion) { | ||||
|             item.ShareSnatch.Question.Index = report.Share.SnatchQuestion.Index; | ||||
|             const json = JSON.parse(report.Share.SnatchQuestion.Value); | ||||
|             item.ShareSnatch.Question.Value.Type = json.Type; | ||||
|             item.ShareSnatch.Question.Value.Question = json.Question; | ||||
|             item.ShareSnatch.Question.Value.Correct = json.Correct; | ||||
|             item.ShareSnatch.Question.Value.Option = json.Option; | ||||
|             item.ShareSnatch.Question.Value.Max = json.Max; | ||||
|             item.ShareSnatch.Question.Value.End = json.End; | ||||
|             item.ShareSnatch.Question.Value.Repeat = json.Repeat; | ||||
|             item.ShareSnatch.Question.Value.Join = json.Join; | ||||
|             item.ShareSnatch.Question.Value.Right = json.Right; | ||||
|             item.ShareSnatch.Question.Value.Wrong = json.Wrong; | ||||
|         } | ||||
|         if (report.Share.SnatchAnswer) { | ||||
|             item.ShareSnatch.Answer.Index = report.Share.SnatchAnswer.Index; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,135 @@ | ||||
| <template> | ||||
|     <div class="snatchs-items-wrap flex flex-nowrap flex-column"> | ||||
|         <div class="head t-c flex"> | ||||
|             <el-button @click="handleAdd()">添加项</el-button> | ||||
|         </div> | ||||
|         <div class="flex-1"> | ||||
|             <div class="prevs-wrap"> | ||||
|                 <el-table :data="state.list" size="small" border stripe style="width: 100%" height="50vh"> | ||||
|                     <el-table-column prop="Name" label="名称" /> | ||||
|                     <el-table-column label="操作" width="110"> | ||||
|                         <template #default="scope"> | ||||
|                             <template v-if="scope.row.ID > 1"> | ||||
|                                 <el-button size="small" @click="handleAdd(scope.row)"> | ||||
|                                     <el-icon> | ||||
|                                         <EditPen /> | ||||
|                                     </el-icon> | ||||
|                                 </el-button> | ||||
|                                 <el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)"> | ||||
|                                     <template #reference> | ||||
|                                         <el-button size="small" type="danger"> | ||||
|                                             <el-icon> | ||||
|                                                 <Delete /> | ||||
|                                             </el-icon> | ||||
|                                         </el-button> | ||||
|                                     </template> | ||||
|                                 </el-popconfirm> | ||||
|                             </template> | ||||
|                         </template> | ||||
|                     </el-table-column> | ||||
|                 </el-table> | ||||
|             </div> | ||||
|         </div> | ||||
|         <el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="80%"> | ||||
|             <div> | ||||
|                 <el-input v-model="state.currentItem.Name" size="large" placeholder="分组名称" /> | ||||
|             </div> | ||||
|             <template #footer> | ||||
|                 <el-button @click="handleEditCancel">取 消</el-button> | ||||
|                 <el-button type="success" plain :loading="state.loading" @click="handleEditSubmit">确 定</el-button> | ||||
|             </template> | ||||
|         </el-dialog> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive } from '@vue/reactivity'; | ||||
| import { computed } from '@vue/runtime-core'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { addGroup, delGroup } from '@/apis/snatch' | ||||
| import { injectGlobalData } from '@/views/provide'; | ||||
| export default { | ||||
|     setup() { | ||||
|  | ||||
|         const globalData = injectGlobalData();; | ||||
|         const state = reactive({ | ||||
|             loading: false, | ||||
|             currentItem: { ID: 0, Name: '' }, | ||||
|             showEdit: false, | ||||
|             list: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user && user.Snatchs) { | ||||
|                     if (state.group == 0 && user.Snatchs.length > 0) { | ||||
|                         state.group = user.Snatchs[0].ID; | ||||
|                     } | ||||
|                     return user.Snatchs; | ||||
|                 } | ||||
|                 return []; | ||||
|             }) | ||||
|         }); | ||||
|  | ||||
|         const handleAdd = (item) => { | ||||
|             item = item || { Name: '', ID: 0 }; | ||||
|             state.currentItem.Name = item.Name; | ||||
|             state.currentItem.ID = item.ID; | ||||
|             state.showEdit = true; | ||||
|         } | ||||
|         const handleDel = (item) => { | ||||
|             state.loading = true; | ||||
|             delGroup(globalData.value.username, item.ID).then((error) => { | ||||
|                 state.loading = false; | ||||
|                 if (error) { | ||||
|                     ElMessage.error(error); | ||||
|                 } else { | ||||
|                     ElMessage.success('操作成功!'); | ||||
|                     globalData.value.updateRuleFlag = Date.now(); | ||||
|                 } | ||||
|             }).catch((e) => { | ||||
|                 state.loading = false; | ||||
|                 ElMessage.error('操作失败!'); | ||||
|             }) | ||||
|         } | ||||
|         const handleEditCancel = () => { | ||||
|             state.showEdit = false; | ||||
|         } | ||||
|         const handleEditSubmit = () => { | ||||
|             state.currentItem.Name = state.currentItem.Name.replace(/^\s|\s$/g, ''); | ||||
|             if (!state.currentItem.Name) { | ||||
|                 return; | ||||
|             } | ||||
|             state.loading = true; | ||||
|             addGroup({ | ||||
|                 UserName: globalData.value.username, | ||||
|                 Group: state.currentItem | ||||
|             }).then((error) => { | ||||
|                 state.loading = false; | ||||
|                 if (error) { | ||||
|                     ElMessage.error(error); | ||||
|                 } else { | ||||
|                     ElMessage.success('操作成功!'); | ||||
|                     state.showEdit = false; | ||||
|                     globalData.value.updateRuleFlag = Date.now(); | ||||
|                 } | ||||
|             }).catch((e) => { | ||||
|                 state.loading = false; | ||||
|                 ElMessage.error('操作失败!'); | ||||
|             }) | ||||
|         } | ||||
|         return { state, handleAdd, handleDel, handleEditCancel, handleEditSubmit } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| .snatchs-items-wrap { | ||||
|     .head { | ||||
|         width: 100%; | ||||
|         padding-bottom: 1rem; | ||||
|     } | ||||
|  | ||||
|     .prevs-wrap { | ||||
|         height: 100%; | ||||
|         position: relative; | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,229 @@ | ||||
| <template> | ||||
|     <div class="snatchs-items-wrap flex flex-nowrap flex-column"> | ||||
|         <div class="head t-c flex"> | ||||
|             <el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem"> | ||||
|                 <el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" /> | ||||
|             </el-select> | ||||
|             <span class="flex-1"></span> | ||||
|             <el-button @click="handleAdd()">添加项</el-button> | ||||
|         </div> | ||||
|         <div class="flex-1"> | ||||
|             <div class="prevs-wrap"> | ||||
|                 <el-table :data="state.list" size="small" border stripe style="width: 100%" height="50vh"> | ||||
|                     <el-table-column prop="Name" label="名称"></el-table-column> | ||||
|                     <el-table-column label="操作" width="110"> | ||||
|                         <template #default="scope"> | ||||
|                             <el-button size="small" @click="handleAdd(scope.row)"> | ||||
|                                 <el-icon> | ||||
|                                     <EditPen /> | ||||
|                                 </el-icon> | ||||
|                             </el-button> | ||||
|                             <el-popconfirm title="删除不可逆,是否确定?" @confirm="handleDel(scope.row)"> | ||||
|                                 <template #reference> | ||||
|                                     <el-button size="small" type="danger"> | ||||
|                                         <el-icon> | ||||
|                                             <Delete /> | ||||
|                                         </el-icon> | ||||
|                                     </el-button> | ||||
|                                 </template> | ||||
|                             </el-popconfirm> | ||||
|                         </template> | ||||
|                     </el-table-column> | ||||
|                 </el-table> | ||||
|             </div> | ||||
|         </div> | ||||
|         <el-dialog :title="`${state.currentItem.ID==0?'添加项':'修改项'}`" destroy-on-close v-model="state.showEdit" center :close-on-click-modal="false" align-center width="94%"> | ||||
|             <div> | ||||
|                 <el-form ref="formDom" :rules="state.rules" :model="state.currentItem" label-width="0"> | ||||
|                     <el-form-item prop="Name"> | ||||
|                         <el-input v-model="state.currentItem.Name" placeholder="名称" maxlength="30" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item prop="Question"> | ||||
|                         <el-input type="textarea" resize="none" rows="6" v-model="state.currentItem.Question" placeholder="题目内容" maxlength="250" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|  | ||||
|                     <el-form-item> | ||||
|                         <el-row> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item prop="Type"> | ||||
|                                     <el-select style="width:90%;" v-model="state.currentItem.Type" placeholder="类别"> | ||||
|                                         <el-option v-for="item in state.types" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label-width="0" prop="Repeat"> | ||||
|                                     <el-checkbox v-model="state.currentItem.Repeat" label="重复答题" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label="上限" label-width="4rem" prop="Max"> | ||||
|                                     <el-input v-model="state.currentItem.Max" placeholder="最多答题多少次" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|  | ||||
|                         </el-row> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 1"> | ||||
|                         <ul style="width:100%;"> | ||||
|                             <template v-for="(item,index) in state.currentItem.Options" :key="index"> | ||||
|                                 <li class="flex" style="margin-bottom:.6rem"> | ||||
|                                     <span>{{String.fromCharCode(index+65)}}、</span> | ||||
|                                     <el-input style="width:12rem;" v-model="item.Text" placeholder="" /> | ||||
|                                     <span class="flex-1"></span> | ||||
|                                     <div> | ||||
|                                         <el-checkbox size="small" v-model="item.Value" label="答案" style="margin-right:.6rem" /> | ||||
|                                         <el-button size="small" @click="handleAddOption(index)">添加</el-button> | ||||
|                                         <el-button size="small" @click="handleDelOption(index)">删除</el-button> | ||||
|                                     </div> | ||||
|                                 </li> | ||||
|                             </template> | ||||
|                         </ul> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 2"> | ||||
|                         <el-input v-model="state.currentItem.Correct" placeholder="简答题答案" /> | ||||
|                     </el-form-item> | ||||
|                 </el-form> | ||||
|             </div> | ||||
|             <template #footer> | ||||
|                 <el-button @click="handleEditCancel">取 消</el-button> | ||||
|                 <el-button type="success" plain :loading="state.loading" @click="handleEditSubmit">确 定</el-button> | ||||
|             </template> | ||||
|         </el-dialog> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive, ref } from '@vue/reactivity'; | ||||
| import { computed } from '@vue/runtime-core'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { add, del } from '@/apis/snatch' | ||||
| import { injectGlobalData } from '@/views/provide'; | ||||
| export default { | ||||
|     setup() { | ||||
|         const globalData = injectGlobalData();; | ||||
|         const state = reactive({ | ||||
|             loading: false, | ||||
|             group: 0, | ||||
|             currentItem: { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }, | ||||
|             rules: { | ||||
|                 Name: [ | ||||
|                     { required: true, message: '名称必填', trigger: 'blur' } | ||||
|                 ], | ||||
|                 Question: [ | ||||
|                     { required: true, message: '内容必填', trigger: 'blur' } | ||||
|                 ], | ||||
|             }, | ||||
|             types: [ | ||||
|                 { label: '选择题', value: 1 }, | ||||
|                 { label: '简答题', value: 2 }, | ||||
|             ], | ||||
|             showEdit: false, | ||||
|             groups: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user && user.Snatchs) { | ||||
|                     if (state.group == 0 && user.Snatchs.length > 0) { | ||||
|                         state.group = user.Snatchs[0].ID; | ||||
|                     } | ||||
|                     return user.Snatchs; | ||||
|                 } | ||||
|                 return []; | ||||
|             }), | ||||
|             list: computed(() => { | ||||
|                 let group = state.groups.filter(c => c.ID == state.group)[0]; | ||||
|                 if (group) return group.List; | ||||
|                 return []; | ||||
|             }) | ||||
|         }); | ||||
|  | ||||
|         const handleAdd = (item) => { | ||||
|             item = item || { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }; | ||||
|             state.currentItem.Name = item.Name; | ||||
|             state.currentItem.Type = item.Type; | ||||
|             state.currentItem.ID = item.ID; | ||||
|             state.currentItem.Question = item.Question; | ||||
|             state.currentItem.Options = item.Options; | ||||
|             state.currentItem.Correct = item.Correct; | ||||
|             state.currentItem.Max = item.Max; | ||||
|             state.currentItem.Repeat = item.Repeat; | ||||
|             state.showEdit = true; | ||||
|         } | ||||
|         const handleDel = (item) => { | ||||
|             state.loading = true; | ||||
|             del(globalData.value.username, state.group, item.ID).then((error) => { | ||||
|                 state.loading = false; | ||||
|                 if (error) { | ||||
|                     ElMessage.error(error); | ||||
|                 } else { | ||||
|                     ElMessage.success('操作成功!'); | ||||
|                     globalData.value.updateRuleFlag = Date.now(); | ||||
|                 } | ||||
|             }).catch((e) => { | ||||
|                 state.loading = false; | ||||
|                 ElMessage.error('操作失败!'); | ||||
|             }) | ||||
|         } | ||||
|         const handleEditCancel = () => { | ||||
|             state.showEdit = false; | ||||
|         } | ||||
|  | ||||
|         const formDom = ref(null); | ||||
|         const handleEditSubmit = () => { | ||||
|             formDom.value.validate((valid) => { | ||||
|                 if (!valid) return; | ||||
|  | ||||
|                 state.loading = true; | ||||
|                 const json = JSON.parse(JSON.stringify(state.currentItem)); | ||||
|                 json.Max = +json.Max; | ||||
|                 json.Type = +json.Type; | ||||
|                 json.Name = json.Name.replace(/^\s|\s$/g, ''); | ||||
|                 json.Correct = json.Correct.replace(/^\s|\s$/g, ''); | ||||
|                 if (json.Type == 2 && !json.Correct) { | ||||
|                     return; | ||||
|                 } | ||||
|                 add({ | ||||
|                     UserName: globalData.value.username, | ||||
|                     GroupID: state.group, | ||||
|                     Item: json | ||||
|                 }).then((error) => { | ||||
|                     state.loading = false; | ||||
|                     if (error) { | ||||
|                         ElMessage.error(error); | ||||
|                     } else { | ||||
|                         ElMessage.success('操作成功!'); | ||||
|                         state.showEdit = false; | ||||
|                         globalData.value.updateRuleFlag = Date.now(); | ||||
|                     } | ||||
|                 }).catch((e) => { | ||||
|                     state.loading = false; | ||||
|                     ElMessage.error('操作失败!'); | ||||
|                 }); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         const handleAddOption = (index) => { | ||||
|             if (state.currentItem.Options.length >= 6) return; | ||||
|             state.currentItem.Options.splice(index + 1, 0, { Text: '', Value: false }); | ||||
|         } | ||||
|         const handleDelOption = (index) => { | ||||
|             if (state.currentItem.Options.length <= 1) return; | ||||
|             state.currentItem.Options.splice(index, 1); | ||||
|         } | ||||
|         return { state, formDom, handleAdd, handleDel, handleEditCancel, handleEditSubmit, handleAddOption, handleDelOption } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| .snatchs-items-wrap { | ||||
|     .head { | ||||
|         width: 100%; | ||||
|         padding-bottom: 1rem; | ||||
|     } | ||||
|  | ||||
|     .prevs-wrap { | ||||
|         height: 100%; | ||||
|         position: relative; | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,50 @@ | ||||
| <template> | ||||
|     <el-dialog class="options" title="互动抢答模板" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%"> | ||||
|         <el-tabs type="border-card"> | ||||
|             <el-tab-pane label="模板分组"> | ||||
|                 <Groups></Groups> | ||||
|             </el-tab-pane> | ||||
|             <el-tab-pane label="模板列表"> | ||||
|                 <Items></Items> | ||||
|             </el-tab-pane> | ||||
|         </el-tabs> | ||||
|         <template #footer> | ||||
|             <el-button @click="handleCancel">取 消</el-button> | ||||
|         </template> | ||||
|     </el-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive } from '@vue/reactivity'; | ||||
| import { watch } from '@vue/runtime-core'; | ||||
| import Groups from './Groups.vue' | ||||
| import Items from './Items.vue' | ||||
| export default { | ||||
|     props: ['modelValue'], | ||||
|     emits: ['update:modelValue'], | ||||
|     components: { Groups, Items }, | ||||
|     setup(props, { emit }) { | ||||
|  | ||||
|         const state = reactive({ | ||||
|             show: props.modelValue, | ||||
|             loading: false, | ||||
|         }); | ||||
|         watch(() => state.show, (val) => { | ||||
|             if (!val) { | ||||
|                 setTimeout(() => { | ||||
|                     emit('update:modelValue', val); | ||||
|                 }, 300); | ||||
|             } | ||||
|         }); | ||||
|         const handleCancel = () => { | ||||
|             state.show = false; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return { | ||||
|             state, handleCancel | ||||
|         } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
| <style lang="stylus" scoped></style> | ||||
							
								
								
									
										232
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/use/Info.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/use/Info.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| <template> | ||||
|     <div class="snatchs-items-wrap flex flex-nowrap flex-column"> | ||||
|         <div class="flex-1"> | ||||
|             <div class="prevs-wrap"> | ||||
|                 <el-form ref="formDom" :rules="state.rules" :model="state.currentItem" label-width="0"> | ||||
|                     <el-form-item> | ||||
|                         <el-row class="w-100"> | ||||
|                             <el-col :span="12"> | ||||
|                                 <el-form-item> | ||||
|                                     <el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem"> | ||||
|                                         <el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="12"> | ||||
|                                 <el-form-item> | ||||
|                                     <el-select @change="handleItemChange" v-model="state.item" placeholder="选择一个模板" style="width:13rem"> | ||||
|                                         <el-option v-for="item in state.list" :key="item.ID" :label="item.Name" :value="item.ID" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                         </el-row> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item prop="Name"> | ||||
|                         <el-input v-model="state.currentItem.Name" placeholder="名称" maxlength="30" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item prop="Question"> | ||||
|                         <el-input type="textarea" resize="none" rows="4" v-model="state.currentItem.Question" placeholder="题目内容" maxlength="250" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|  | ||||
|                     <el-form-item> | ||||
|                         <el-row class="w-100"> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item prop="Type"> | ||||
|                                     <el-select style="width:90%;" v-model="state.currentItem.Type" placeholder="类别"> | ||||
|                                         <el-option v-for="item in state.types" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label-width="0" prop="Repeat"> | ||||
|                                     <el-checkbox v-model="state.currentItem.Repeat" label="重复答题" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label="上限" label-width="4rem" prop="Max"> | ||||
|                                     <el-input v-model="state.currentItem.Max" placeholder="最多答题多少次" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|  | ||||
|                         </el-row> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 1"> | ||||
|                         <ul class="w-100"> | ||||
|                             <template v-for="(item,index) in state.currentItem.Options" :key="index"> | ||||
|                                 <li class="flex" style="margin-bottom:.6rem"> | ||||
|                                     <span>{{String.fromCharCode(index+65)}}、</span> | ||||
|                                     <el-input style="width:11rem;" v-model="item.Text" placeholder="" /> | ||||
|                                     <span class="flex-1"></span> | ||||
|                                     <div> | ||||
|                                         <el-checkbox size="small" v-model="item.Value" label="答案" style="margin-right:.6rem" /> | ||||
|                                         <el-button size="small" @click="handleAddOption(index)">添加</el-button> | ||||
|                                         <el-button size="small" @click="handleDelOption(index)">删除</el-button> | ||||
|                                     </div> | ||||
|                                 </li> | ||||
|                             </template> | ||||
|                         </ul> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 2"> | ||||
|                         <el-input v-model="state.currentItem.Correct" placeholder="简答题答案" /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item> | ||||
|                         <div class="t-c w-100"> | ||||
|                             <el-button type="success" :loading="state.loading" @click="handleEditSubmit">确定开始</el-button> | ||||
|                         </div> | ||||
|                     </el-form-item> | ||||
|                 </el-form> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive, ref } from '@vue/reactivity'; | ||||
| import { computed, onMounted } from '@vue/runtime-core'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { update } from '@/apis/snatch' | ||||
| import { injectGlobalData } from '@/views/provide'; | ||||
| import { injectPluginState } from '@/views/device/provide'; | ||||
| export default { | ||||
|     setup() { | ||||
|         const globalData = injectGlobalData(); | ||||
|         const pluginState = injectPluginState(); | ||||
|         const state = reactive({ | ||||
|             loading: false, | ||||
|             group: 0, | ||||
|             item: 0, | ||||
|             currentItem: { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }, | ||||
|             rules: { | ||||
|                 Name: [ | ||||
|                     { required: true, message: '名称必填', trigger: 'blur' } | ||||
|                 ], | ||||
|                 Question: [ | ||||
|                     { required: true, message: '内容必填', trigger: 'blur' } | ||||
|                 ], | ||||
|             }, | ||||
|             types: [ | ||||
|                 { label: '选择题', value: 1 }, | ||||
|                 { label: '简答题', value: 2 }, | ||||
|             ], | ||||
|             groups: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user && user.Snatchs) { | ||||
|                     if (state.group == 0 && user.Snatchs.length > 0) { | ||||
|                         state.group = user.Snatchs[0].ID; | ||||
|                     } | ||||
|                     return user.Snatchs; | ||||
|                 } | ||||
|                 return []; | ||||
|             }), | ||||
|             list: computed(() => { | ||||
|                 let group = state.groups.filter(c => c.ID == state.group)[0]; | ||||
|                 if (group) { | ||||
|                     if (state.item == 0 && group.List.length > 0) { | ||||
|                         state.item = group.List[0].ID; | ||||
|                     } | ||||
|                     return group.List; | ||||
|                 } | ||||
|                 return []; | ||||
|             }) | ||||
|         }); | ||||
|  | ||||
|         const handleItemChange = () => { | ||||
|             const item = state.list.filter(c => c.ID == state.item)[0] || { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }; | ||||
|             state.currentItem.Type = item.Type; | ||||
|             state.currentItem.ID = item.ID; | ||||
|             state.currentItem.Name = item.Name; | ||||
|             state.currentItem.Question = item.Question; | ||||
|             state.currentItem.Options = item.Options; | ||||
|             state.currentItem.Correct = item.Correct; | ||||
|             state.currentItem.Max = item.Max; | ||||
|             state.currentItem.Repeat = item.Repeat; | ||||
|         } | ||||
|         onMounted(() => { | ||||
|             handleItemChange(); | ||||
|         }); | ||||
|  | ||||
|         const formDom = ref(null); | ||||
|         const handleEditSubmit = () => { | ||||
|             formDom.value.validate((valid) => { | ||||
|                 if (!valid) { | ||||
|                     return; | ||||
|                 } | ||||
|                 const names = pluginState.value.command.devices.map(c => c.MachineName); | ||||
|                 if (names.length == 0) { | ||||
|                     ElMessage.error('请至少选择一个设备'); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const json = JSON.parse(JSON.stringify(state.currentItem)); | ||||
|                 json.Max = +json.Max; | ||||
|                 json.Type = +json.Type; | ||||
|                 json.Name = json.Name.replace(/^\s|\s$/g, ''); | ||||
|                 json.Correct = json.Correct.replace(/^\s|\s$/g, ''); | ||||
|                 const corrects = json.Options.reduce((arr, value, index) => { | ||||
|                     if (value.Value) arr.push(String.fromCharCode(index + 65)); | ||||
|                     return arr; | ||||
|                 }, []).join(''); | ||||
|  | ||||
|                 if (json.Type == 1 && corrects.length <= 0) { | ||||
|                     ElMessage.error('至少有一个正确答案'); | ||||
|                     return; | ||||
|                 } else if (json.Type == 2 && !json.Correct) { | ||||
|                     ElMessage.error('请输入正确答案'); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const question = { | ||||
|                     Type: json.Type, | ||||
|                     Question: json.Question, | ||||
|                     Correct: json.Type == 1 ? corrects : json.Correct, | ||||
|                     Option: json.Options.length, | ||||
|                     Max: json.Max, | ||||
|                     End: false, | ||||
|                     Repeat: json.Repeat, | ||||
|                     Join: names.length, | ||||
|                     Right: 0, | ||||
|                     Wrong: 0, | ||||
|                 } | ||||
|  | ||||
|                 state.loading = true; | ||||
|                 update(names, question).then((res) => { | ||||
|                     state.loading = false; | ||||
|                     if (res) { | ||||
|                         ElMessage.success('操作成功!'); | ||||
|                     } else { | ||||
|                         ElMessage.error('操作失败!'); | ||||
|                     } | ||||
|                 }).catch((e) => { | ||||
|                     state.loading = false; | ||||
|                     ElMessage.error('操作失败!'); | ||||
|                 }); | ||||
|  | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         const handleAddOption = (index) => { | ||||
|             if (state.currentItem.Options.length >= 6) return; | ||||
|             state.currentItem.Options.splice(index + 1, 0, { Text: '', Value: false }); | ||||
|         } | ||||
|         const handleDelOption = (index) => { | ||||
|             if (state.currentItem.Options.length <= 1) return; | ||||
|             state.currentItem.Options.splice(index, 1); | ||||
|         } | ||||
|         return { state, formDom, handleEditSubmit, handleItemChange, handleAddOption, handleDelOption } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| .snatchs-items-wrap { | ||||
|     .head { | ||||
|         width: 100%; | ||||
|         padding-bottom: 1rem; | ||||
|     } | ||||
|  | ||||
|     .prevs-wrap { | ||||
|         height: 100%; | ||||
|         position: relative; | ||||
|     } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										232
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/use/Item.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								cmonitor.web/src/views/device/plugins/share/snatch/use/Item.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| <template> | ||||
|     <div class="snatchs-items-wrap flex flex-nowrap flex-column"> | ||||
|         <div class="flex-1"> | ||||
|             <div class="prevs-wrap"> | ||||
|                 <el-form ref="formDom" :rules="state.rules" :model="state.currentItem" label-width="0"> | ||||
|                     <el-form-item> | ||||
|                         <el-row class="w-100"> | ||||
|                             <el-col :span="12"> | ||||
|                                 <el-form-item> | ||||
|                                     <el-select v-model="state.group" placeholder="选择一个分组" style="width:13rem"> | ||||
|                                         <el-option v-for="item in state.groups" :key="item.ID" :label="item.Name" :value="item.ID" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="12"> | ||||
|                                 <el-form-item> | ||||
|                                     <el-select @change="handleItemChange" v-model="state.item" placeholder="选择一个模板" style="width:13rem"> | ||||
|                                         <el-option v-for="item in state.list" :key="item.ID" :label="item.Name" :value="item.ID" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                         </el-row> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item prop="Name"> | ||||
|                         <el-input v-model="state.currentItem.Name" placeholder="名称" maxlength="30" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item prop="Question"> | ||||
|                         <el-input type="textarea" resize="none" rows="4" v-model="state.currentItem.Question" placeholder="题目内容" maxlength="250" show-word-limit /> | ||||
|                     </el-form-item> | ||||
|  | ||||
|                     <el-form-item> | ||||
|                         <el-row class="w-100"> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item prop="Type"> | ||||
|                                     <el-select style="width:90%;" v-model="state.currentItem.Type" placeholder="类别"> | ||||
|                                         <el-option v-for="item in state.types" :key="item.value" :label="item.label" :value="item.value" /> | ||||
|                                     </el-select> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label-width="0" prop="Repeat"> | ||||
|                                     <el-checkbox v-model="state.currentItem.Repeat" label="重复答题" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|                             <el-col :span="8"> | ||||
|                                 <el-form-item label="上限" label-width="4rem" prop="Max"> | ||||
|                                     <el-input v-model="state.currentItem.Max" placeholder="最多答题多少次" /> | ||||
|                                 </el-form-item> | ||||
|                             </el-col> | ||||
|  | ||||
|                         </el-row> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 1"> | ||||
|                         <ul class="w-100"> | ||||
|                             <template v-for="(item,index) in state.currentItem.Options" :key="index"> | ||||
|                                 <li class="flex" style="margin-bottom:.6rem"> | ||||
|                                     <span>{{String.fromCharCode(index+65)}}、</span> | ||||
|                                     <el-input style="width:11rem;" v-model="item.Text" placeholder="" /> | ||||
|                                     <span class="flex-1"></span> | ||||
|                                     <div> | ||||
|                                         <el-checkbox size="small" v-model="item.Value" label="答案" style="margin-right:.6rem" /> | ||||
|                                         <el-button size="small" @click="handleAddOption(index)">添加</el-button> | ||||
|                                         <el-button size="small" @click="handleDelOption(index)">删除</el-button> | ||||
|                                     </div> | ||||
|                                 </li> | ||||
|                             </template> | ||||
|                         </ul> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item v-if="state.currentItem.Type == 2"> | ||||
|                         <el-input v-model="state.currentItem.Correct" placeholder="简答题答案" /> | ||||
|                     </el-form-item> | ||||
|                     <el-form-item> | ||||
|                         <div class="t-c w-100"> | ||||
|                             <el-button type="success" :loading="state.loading" @click="handleEditSubmit">确定开始</el-button> | ||||
|                         </div> | ||||
|                     </el-form-item> | ||||
|                 </el-form> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive, ref } from '@vue/reactivity'; | ||||
| import { computed, onMounted } from '@vue/runtime-core'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { update } from '@/apis/snatch' | ||||
| import { injectGlobalData } from '@/views/provide'; | ||||
| import { injectPluginState } from '@/views/device/provide'; | ||||
| export default { | ||||
|     setup() { | ||||
|         const globalData = injectGlobalData(); | ||||
|         const pluginState = injectPluginState(); | ||||
|         const state = reactive({ | ||||
|             loading: false, | ||||
|             group: 0, | ||||
|             item: 0, | ||||
|             currentItem: { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }, | ||||
|             rules: { | ||||
|                 Name: [ | ||||
|                     { required: true, message: '名称必填', trigger: 'blur' } | ||||
|                 ], | ||||
|                 Question: [ | ||||
|                     { required: true, message: '内容必填', trigger: 'blur' } | ||||
|                 ], | ||||
|             }, | ||||
|             types: [ | ||||
|                 { label: '选择题', value: 1 }, | ||||
|                 { label: '简答题', value: 2 }, | ||||
|             ], | ||||
|             groups: computed(() => { | ||||
|                 let user = globalData.value.usernames[globalData.value.username]; | ||||
|                 if (user && user.Snatchs) { | ||||
|                     if (state.group == 0 && user.Snatchs.length > 0) { | ||||
|                         state.group = user.Snatchs[0].ID; | ||||
|                     } | ||||
|                     return user.Snatchs; | ||||
|                 } | ||||
|                 return []; | ||||
|             }), | ||||
|             list: computed(() => { | ||||
|                 let group = state.groups.filter(c => c.ID == state.group)[0]; | ||||
|                 if (group) { | ||||
|                     if (state.item == 0 && group.List.length > 0) { | ||||
|                         state.item = group.List[0].ID; | ||||
|                     } | ||||
|                     return group.List; | ||||
|                 } | ||||
|                 return []; | ||||
|             }) | ||||
|         }); | ||||
|  | ||||
|         const handleItemChange = () => { | ||||
|             const item = state.list.filter(c => c.ID == state.item)[0] || { ID: 0, Name: '', Type: 1, Question: '', Options: [{ Text: '', Value: false }], Correct: '', Max: 65535, Repeat: true }; | ||||
|             state.currentItem.Type = item.Type; | ||||
|             state.currentItem.ID = item.ID; | ||||
|             state.currentItem.Name = item.Name; | ||||
|             state.currentItem.Question = item.Question; | ||||
|             state.currentItem.Options = item.Options; | ||||
|             state.currentItem.Correct = item.Correct; | ||||
|             state.currentItem.Max = item.Max; | ||||
|             state.currentItem.Repeat = item.Repeat; | ||||
|         } | ||||
|         onMounted(() => { | ||||
|             handleItemChange(); | ||||
|         }); | ||||
|  | ||||
|         const formDom = ref(null); | ||||
|         const handleEditSubmit = () => { | ||||
|             formDom.value.validate((valid) => { | ||||
|                 if (!valid) { | ||||
|                     return; | ||||
|                 } | ||||
|                 const names = pluginState.value.command.devices.map(c => c.MachineName); | ||||
|                 if (names.length == 0) { | ||||
|                     ElMessage.error('请至少选择一个设备'); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const json = JSON.parse(JSON.stringify(state.currentItem)); | ||||
|                 json.Max = +json.Max; | ||||
|                 json.Type = +json.Type; | ||||
|                 json.Name = json.Name.replace(/^\s|\s$/g, ''); | ||||
|                 json.Correct = json.Correct.replace(/^\s|\s$/g, ''); | ||||
|                 const corrects = json.Options.reduce((arr, value, index) => { | ||||
|                     if (value.Value) arr.push(String.fromCharCode(index + 65)); | ||||
|                     return arr; | ||||
|                 }, []).join(''); | ||||
|  | ||||
|                 if (json.Type == 1 && corrects.length <= 0) { | ||||
|                     ElMessage.error('至少有一个正确答案'); | ||||
|                     return; | ||||
|                 } else if (json.Type == 2 && !json.Correct) { | ||||
|                     ElMessage.error('请输入正确答案'); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const question = { | ||||
|                     Type: json.Type, | ||||
|                     Question: json.Question, | ||||
|                     Correct: json.Type == 1 ? corrects : json.Correct, | ||||
|                     Option: json.Options.length, | ||||
|                     Max: json.Max, | ||||
|                     End: false, | ||||
|                     Repeat: json.Repeat, | ||||
|                     Join: names.length, | ||||
|                     Right: 0, | ||||
|                     Wrong: 0, | ||||
|                 } | ||||
|  | ||||
|                 state.loading = true; | ||||
|                 update(names, question).then((res) => { | ||||
|                     state.loading = false; | ||||
|                     if (res) { | ||||
|                         ElMessage.success('操作成功!'); | ||||
|                     } else { | ||||
|                         ElMessage.error('操作失败!'); | ||||
|                     } | ||||
|                 }).catch((e) => { | ||||
|                     state.loading = false; | ||||
|                     ElMessage.error('操作失败!'); | ||||
|                 }); | ||||
|  | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         const handleAddOption = (index) => { | ||||
|             if (state.currentItem.Options.length >= 6) return; | ||||
|             state.currentItem.Options.splice(index + 1, 0, { Text: '', Value: false }); | ||||
|         } | ||||
|         const handleDelOption = (index) => { | ||||
|             if (state.currentItem.Options.length <= 1) return; | ||||
|             state.currentItem.Options.splice(index, 1); | ||||
|         } | ||||
|         return { state, formDom, handleEditSubmit, handleItemChange, handleAddOption, handleDelOption } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| .snatchs-items-wrap { | ||||
|     .head { | ||||
|         width: 100%; | ||||
|         padding-bottom: 1rem; | ||||
|     } | ||||
|  | ||||
|     .prevs-wrap { | ||||
|         height: 100%; | ||||
|         position: relative; | ||||
|     } | ||||
| } | ||||
| </style> | ||||
| @@ -0,0 +1,50 @@ | ||||
| <template> | ||||
|     <el-dialog class="options" title="使用互动答题" destroy-on-close v-model="state.show" center :close-on-click-modal="false" align-center width="94%"> | ||||
|         <div style="border:1px solid #ddd;padding:.6rem"> | ||||
|             <Info v-if="running"></Info> | ||||
|             <Item v-else></Item> | ||||
|         </div> | ||||
|         <template #footer> | ||||
|             <el-button @click="handleCancel">取 消</el-button> | ||||
|         </template> | ||||
|     </el-dialog> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { reactive } from '@vue/reactivity'; | ||||
| import { computed, watch } from '@vue/runtime-core'; | ||||
| import Item from './Item.vue' | ||||
| import Info from './Info.vue' | ||||
| import { injectPluginState } from '@/views/device/provide'; | ||||
| export default { | ||||
|     props: ['modelValue'], | ||||
|     emits: ['update:modelValue'], | ||||
|     components: { Item, Info }, | ||||
|     setup(props, { emit }) { | ||||
|  | ||||
|         const pluginState = injectPluginState(); | ||||
|         console.log(pluginState.value); | ||||
|         const running = computed(() => pluginState.value.ShareSnatch.Question.End == false); | ||||
|         const state = reactive({ | ||||
|             show: props.modelValue, | ||||
|             loading: false, | ||||
|         }); | ||||
|         watch(() => state.show, (val) => { | ||||
|             if (!val) { | ||||
|                 setTimeout(() => { | ||||
|                     emit('update:modelValue', val); | ||||
|                 }, 300); | ||||
|             } | ||||
|         }); | ||||
|         const handleCancel = () => { | ||||
|             state.show = false; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return { | ||||
|             running, state, handleCancel | ||||
|         } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
| <style lang="stylus" scoped></style> | ||||
| @@ -115,13 +115,13 @@ export default { | ||||
| </script> | ||||
|  | ||||
| <style lang="stylus" scoped> | ||||
| @media (min-width: 768px) { | ||||
|     .device-item { | ||||
|         width: 39rem !important; | ||||
|         background-color: rgba(255, 255, 255, 1) !important; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // @media (min-width: 768px) { | ||||
| // .device-item { | ||||
| // width: 39rem !important; | ||||
| // background-color: rgba(255, 255, 255, 1) !important; | ||||
| // margin: 0 0 0.6rem 0 !important; | ||||
| // } | ||||
| // } | ||||
| .device-item { | ||||
|     // border: 1px solid #ddd; | ||||
|     font-size: 1.6rem; | ||||
|   | ||||
| @@ -112,6 +112,9 @@ export default { | ||||
|                     globalData.value.currentDevice = globalData.value.devices[middleItem.index]; | ||||
|                 } | ||||
|  | ||||
|                 if (globalData.value.pc) { | ||||
|  | ||||
|                 } else { | ||||
|                     for (let i = 0; i < items.length; i++) { | ||||
|                         let style = 'z-index:9;background-color:rgba(255,255,255,1);'; | ||||
|                         const dist = Math.abs((middleItem.index - i)); | ||||
| @@ -126,6 +129,8 @@ export default { | ||||
|                         } | ||||
|                         items[i].style = style; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 //有哪些需要报告 | ||||
|                 const reportDoms = doms.filter(item => item.index >= middleItem.index - 2 && item.index <= middleItem.index + 2).map(c => c.index); | ||||
|   | ||||
| @@ -20,10 +20,10 @@ export const provideGlobalData = () => { | ||||
|         }), | ||||
|         currentDevice: { MachineName: '' }, | ||||
|         reportNames: [], | ||||
|         pc: window.innerWidth > 768 | ||||
|         pc: false,//window.innerWidth > 768 | ||||
|     }); | ||||
|     window.addEventListener('resize', () => { | ||||
|         globalData.value.pc = window.innerWidth > 768; | ||||
|         globalData.value.pc = false;// window.innerWidth > 768; | ||||
|     }); | ||||
|  | ||||
|     provide(globalDataSymbol, globalData); | ||||
|   | ||||
| @@ -38,6 +38,8 @@ using System.Text.Json.Serialization; | ||||
| using cmonitor.server.client.reports.keyboard; | ||||
| using cmonitor.server.client.reports.wallpaper; | ||||
| using common.libs.winapis; | ||||
| using cmonitor.server.client.reports.snatch; | ||||
| using cmonitor.server.service.messengers.snatch; | ||||
|  | ||||
|  | ||||
| namespace cmonitor | ||||
| @@ -198,6 +200,11 @@ namespace cmonitor | ||||
|             else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ISystem, SystemLinux>(); | ||||
|             else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ISystem, SystemMacOS>(); | ||||
|  | ||||
|             serviceCollection.AddSingleton<SnatchReport>(); | ||||
|             if (OperatingSystem.IsWindows()) serviceCollection.AddSingleton<ISnatch, SnatchWindows>(); | ||||
|             else if (OperatingSystem.IsLinux()) serviceCollection.AddSingleton<ISnatch, SnatchLinux>(); | ||||
|             else if (OperatingSystem.IsMacOS()) serviceCollection.AddSingleton<ISnatch, SnatchMacOS>(); | ||||
|  | ||||
|             serviceCollection.AddSingleton<ShareReport>(); | ||||
|             serviceCollection.AddSingleton<CommandReport>(); | ||||
|  | ||||
| @@ -223,6 +230,7 @@ namespace cmonitor | ||||
|             serviceCollection.AddSingleton<SettingMessenger>(); | ||||
|             serviceCollection.AddSingleton<KeyboardMessenger>(); | ||||
|             serviceCollection.AddSingleton<SystemMessenger>(); | ||||
|             serviceCollection.AddSingleton<SnatchMessenger>(); | ||||
|  | ||||
|             //api | ||||
|             serviceCollection.AddSingleton<RuleConfig>(); | ||||
| @@ -242,6 +250,7 @@ namespace cmonitor | ||||
|             serviceCollection.AddSingleton<SettingClientService>(); | ||||
|             serviceCollection.AddSingleton<SystemClientService>(); | ||||
|             serviceCollection.AddSingleton<KeyboardClientService>(); | ||||
|             serviceCollection.AddSingleton<SnatchClientService>(); | ||||
|  | ||||
|  | ||||
|             //web | ||||
| @@ -265,7 +274,7 @@ namespace cmonitor | ||||
|                 config.ScreenDelay = int.Parse(dic["screen-delay"]); | ||||
|                 config.Elevated = dic.ContainsKey("elevated"); | ||||
|  | ||||
|                 Logger.Instance.Debug($"config:{config.ToJson()}"); | ||||
|                 Logger.Instance.Debug($"config:{config.ToJsonFormat()}"); | ||||
|                 //Logger.Instance.Debug($"args:{string.Join(" ", args)}"); | ||||
|  | ||||
|                 config.IsCLient = dic.ContainsKey("mode") && dic["mode"].Contains("client"); | ||||
| @@ -371,6 +380,9 @@ namespace cmonitor | ||||
|         public const int ShareMemoryLLockIndex = 3; | ||||
|         //SAS | ||||
|         public const int ShareMemorySASIndex = 4; | ||||
|         //抢答,问题,和回答分开存,为了保证数据安全性 | ||||
|         public const int ShareSnatchQuestionIndex = 5; | ||||
|         public const int ShareSnatchAnswerIndex = 6; | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| using common.libs.database; | ||||
| using cmonitor.server.client.reports.snatch; | ||||
| using common.libs.database; | ||||
| using MemoryPack; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
|  | ||||
| namespace cmonitor.server.api | ||||
| @@ -16,8 +18,9 @@ namespace cmonitor.server.api | ||||
|             { | ||||
|                 UserNames = new Dictionary<string, UserNameInfo> { { "snltty", new UserNameInfo { | ||||
|                      Rules = new List<RulesInfo>{ new RulesInfo { ID = 1, Name = "默认" } }, | ||||
|                      Processs = new  List<GroupInfo>{ new GroupInfo { ID = 1, Name = "默认" } }, | ||||
|                       Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 1, Name = "默认" } }, | ||||
|                      Processs = new  List<GroupInfo>{ new GroupInfo { ID = 2, Name = "默认" } }, | ||||
|                       Windows = new List<WindowGroupInfo> { new WindowGroupInfo { ID = 3, Name = "默认" } }, | ||||
|                        Snatchs = new List<SnatchGroupInfo>{ new SnatchGroupInfo { ID=4, Name="默认" } } | ||||
|                 } } } | ||||
|             }; | ||||
|             UserNames = config.UserNames; | ||||
| @@ -26,7 +29,7 @@ namespace cmonitor.server.api | ||||
|         } | ||||
|  | ||||
|         public Dictionary<string, UserNameInfo> UserNames { get; set; } = new Dictionary<string, UserNameInfo>(); | ||||
|         private uint maxid = 0; | ||||
|         private uint maxid = 100; | ||||
|         public uint MaxID | ||||
|         { | ||||
|             get => maxid; set | ||||
| @@ -341,6 +344,122 @@ namespace cmonitor.server.api | ||||
|             return string.Empty; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public string AddSnatchGroup(UpdateSnatchGroupInfo updateGroupInfo) | ||||
|         { | ||||
|             lock (lockObj) | ||||
|             { | ||||
|                 if (UserNames.TryGetValue(updateGroupInfo.UserName, out UserNameInfo userNameInfo) == false) | ||||
|                 { | ||||
|                     return "不存在此管理用户"; | ||||
|                 } | ||||
|                 if (userNameInfo.Windows.FirstOrDefault(c => c.Name == updateGroupInfo.Group.Name && c.ID != updateGroupInfo.Group.ID) != null) | ||||
|                 { | ||||
|                     return "已存在同名记录"; | ||||
|                 } | ||||
|  | ||||
|                 //添加 | ||||
|                 if (updateGroupInfo.Group.ID == 0) | ||||
|                 { | ||||
|                     updateGroupInfo.Group.ID = Interlocked.Increment(ref maxid); | ||||
|                     userNameInfo.Snatchs.Add(updateGroupInfo.Group); | ||||
|                     Save(); | ||||
|                     return string.Empty; | ||||
|                 } | ||||
|  | ||||
|                 //修改 | ||||
|                 SnatchGroupInfo old = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == updateGroupInfo.Group.ID); | ||||
|                 if (old == null) | ||||
|                 { | ||||
|                     return "不存在记录,无法修改"; | ||||
|                 } | ||||
|                 old.Name = updateGroupInfo.Group.Name; | ||||
|                 Save(); | ||||
|             } | ||||
|  | ||||
|             return string.Empty; | ||||
|         } | ||||
|         public string DeleteSnatchGroup(DeleteSnatchGroupInfo deleteGroupInfo) | ||||
|         { | ||||
|             lock (lockObj) | ||||
|             { | ||||
|                 if (UserNames.TryGetValue(deleteGroupInfo.UserName, out UserNameInfo userNameInfo) == false) | ||||
|                 { | ||||
|                     return "不存在此管理用户"; | ||||
|                 } | ||||
|  | ||||
|                 userNameInfo.Snatchs.Remove(userNameInfo.Snatchs.FirstOrDefault(c => c.ID == deleteGroupInfo.ID)); | ||||
|  | ||||
|                 Save(); | ||||
|             } | ||||
|  | ||||
|             return string.Empty; | ||||
|         } | ||||
|         public string AddSnatch(AddSnatchItemInfo updateItem) | ||||
|         { | ||||
|             lock (lockObj) | ||||
|             { | ||||
|                 if (UserNames.TryGetValue(updateItem.UserName, out UserNameInfo userNameInfo) == false) | ||||
|                 { | ||||
|                     return "不存在此管理用户"; | ||||
|                 } | ||||
|                 SnatchGroupInfo group = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == updateItem.GroupID); | ||||
|                 if (group == null) | ||||
|                 { | ||||
|                     return "不存在此分组"; | ||||
|                 } | ||||
|                 if (group.List.FirstOrDefault(c => c.Name == updateItem.Item.Name && c.ID != updateItem.Item.ID) != null) | ||||
|                 { | ||||
|                     return "已存在同名记录"; | ||||
|                 } | ||||
|  | ||||
|                 //添加 | ||||
|                 if (updateItem.Item.ID == 0) | ||||
|                 { | ||||
|                     updateItem.Item.ID = Interlocked.Increment(ref maxid); | ||||
|                     group.List.Add(updateItem.Item); | ||||
|                     Save(); | ||||
|                     return string.Empty; | ||||
|                 } | ||||
|  | ||||
|                 //修改 | ||||
|                 SnatchItemInfo old = group.List.FirstOrDefault(c => c.ID == updateItem.Item.ID); | ||||
|                 if (old == null) | ||||
|                 { | ||||
|                     return "不存在记录,无法修改"; | ||||
|                 } | ||||
|                 old.Type = updateItem.Item.Type; | ||||
|                 old.Name = updateItem.Item.Name; | ||||
|                 old.Question = updateItem.Item.Question; | ||||
|                 old.Options = updateItem.Item.Options; | ||||
|                 old.Correct = updateItem.Item.Correct; | ||||
|                 old.Max = updateItem.Item.Max; | ||||
|                 old.Repeat = updateItem.Item.Repeat; | ||||
|               | ||||
|                 Save(); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|         public string DelSnatch(DeletedSnatchItemInfo deletedFileNameInfo) | ||||
|         { | ||||
|             lock (lockObj) | ||||
|             { | ||||
|                 if (UserNames.TryGetValue(deletedFileNameInfo.UserName, out UserNameInfo userNameInfo) == false) | ||||
|                 { | ||||
|                     return "不存在此管理用户"; | ||||
|                 } | ||||
|                 SnatchGroupInfo group = userNameInfo.Snatchs.FirstOrDefault(c => c.ID == deletedFileNameInfo.GroupID); | ||||
|                 if (group == null) | ||||
|                 { | ||||
|                     return "不存在此分组"; | ||||
|                 } | ||||
|  | ||||
|                 group.List.Remove(group.List.FirstOrDefault(c => c.ID == deletedFileNameInfo.ID)); | ||||
|                 Save(); | ||||
|             } | ||||
|             return string.Empty; | ||||
|         } | ||||
|  | ||||
|         public void Save() | ||||
|         { | ||||
|             configDataProvider.Save(this).Wait(); | ||||
| @@ -353,6 +472,7 @@ namespace cmonitor.server.api | ||||
|         public List<GroupInfo> Processs { get; set; } = new List<GroupInfo>(); | ||||
|         public List<string> Devices { get; set; } = new List<string>(); | ||||
|         public List<WindowGroupInfo> Windows { get; set; } = new List<WindowGroupInfo>(); | ||||
|         public List<SnatchGroupInfo> Snatchs { get; set; } = new List<SnatchGroupInfo>(); | ||||
|     } | ||||
|     public sealed class UpdateDevicesInfo | ||||
|     { | ||||
| @@ -464,4 +584,69 @@ namespace cmonitor.server.api | ||||
|         public uint GroupID { get; set; } | ||||
|         public uint ID { get; set; } | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     public sealed class SnatchGroupInfo | ||||
|     { | ||||
|         public uint ID { get; set; } | ||||
|         public string Name { get; set; } | ||||
|         public List<SnatchItemInfo> List { get; set; } = new List<SnatchItemInfo>(); | ||||
|     } | ||||
|     public sealed class UpdateSnatchGroupInfo | ||||
|     { | ||||
|         public string UserName { get; set; } | ||||
|         public SnatchGroupInfo Group { get; set; } | ||||
|     } | ||||
|     public sealed class DeleteSnatchGroupInfo | ||||
|     { | ||||
|         public string UserName { get; set; } | ||||
|         public uint ID { get; set; } | ||||
|     } | ||||
|     public sealed class AddSnatchItemInfo | ||||
|     { | ||||
|         public string UserName { get; set; } | ||||
|         public uint GroupID { get; set; } | ||||
|         public SnatchItemInfo Item { get; set; } | ||||
|     } | ||||
|     public sealed class DeletedSnatchItemInfo | ||||
|     { | ||||
|         public string UserName { get; set; } | ||||
|         public uint GroupID { get; set; } | ||||
|         public uint ID { get; set; } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public sealed class SnatchItemInfo | ||||
|     { | ||||
|         public uint ID { get; set; } | ||||
|         public string Name { get; set; } | ||||
|  | ||||
|         public SnatchType Type { get; set; } | ||||
|         /// <summary> | ||||
|         /// 问题 | ||||
|         /// </summary> | ||||
|         public string Question { get; set; } | ||||
|         /// <summary> | ||||
|         /// 选项数 | ||||
|         /// </summary> | ||||
|         public List<SnatchItemOptionInfo> Options { get; set; } | ||||
|         /// <summary> | ||||
|         /// 答案 | ||||
|         /// </summary> | ||||
|         public string Correct { get; set; } | ||||
|         /// <summary> | ||||
|         /// 最多答题次数 | ||||
|         /// </summary> | ||||
|         public int Max { get; set; } | ||||
|         /// <summary> | ||||
|         /// 重复答题 | ||||
|         /// </summary> | ||||
|         public bool Repeat { get; set; } | ||||
|     } | ||||
|     public sealed class SnatchItemOptionInfo | ||||
|     { | ||||
|         public string Text { get; set;} | ||||
|         public bool Value { get; set; } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,24 +19,28 @@ namespace cmonitor.server.api.services | ||||
|         public async Task<bool> Update(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             ShareUpdateInfo info = param.Content.DeJson<ShareUpdateInfo>(); | ||||
|             if(signCaching.Get(info.Name,out SignCacheInfo cache)) | ||||
|             byte[] bytes = MemoryPackSerializer.Serialize(info.Item); | ||||
|             for (int i = 0; i < info.Names.Length; i++) | ||||
|             { | ||||
|                 return await messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 if (signCaching.Get(info.Names[i], out SignCacheInfo cache)) | ||||
|                 { | ||||
|                     await messengerSender.SendOnly(new MessageRequestWrap | ||||
|                     { | ||||
|                         Connection = cache.Connection, | ||||
|                         MessengerId = (ushort)ShareMessengerIds.Update, | ||||
|                      Payload = MemoryPackSerializer.Serialize(info.Item) | ||||
|                         Payload = bytes | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public sealed class ShareUpdateInfo | ||||
|     { | ||||
|         public string Name { get; set; } | ||||
|         public string[] Names { get; set; } | ||||
|         public ShareItemInfo Item { get; set; } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										65
									
								
								cmonitor/server/api/services/SnatchClientService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								cmonitor/server/api/services/SnatchClientService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| using cmonitor.server.client.reports.snatch; | ||||
| using cmonitor.server.service; | ||||
| using cmonitor.server.service.messengers.sign; | ||||
| using cmonitor.server.service.messengers.snatch; | ||||
| using common.libs.extends; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.server.api.services | ||||
| { | ||||
|     public sealed class SnatchClientService : IClientService | ||||
|     { | ||||
|         private readonly MessengerSender messengerSender; | ||||
|         private readonly RuleConfig ruleConfig; | ||||
|         private readonly SignCaching signCaching; | ||||
|         public SnatchClientService(RuleConfig ruleConfig, MessengerSender messengerSender, SignCaching signCaching) | ||||
|         { | ||||
|             this.ruleConfig = ruleConfig; | ||||
|             this.messengerSender = messengerSender; | ||||
|             this.signCaching = signCaching; | ||||
|         } | ||||
|  | ||||
|         public string AddGroup(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             return ruleConfig.AddSnatchGroup(param.Content.DeJson<UpdateSnatchGroupInfo>()); | ||||
|         } | ||||
|         public string DeleteGroup(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             return ruleConfig.DeleteSnatchGroup(param.Content.DeJson<DeleteSnatchGroupInfo>()); | ||||
|         } | ||||
|         public string Add(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             return ruleConfig.AddSnatch(param.Content.DeJson<AddSnatchItemInfo>()); | ||||
|         } | ||||
|         public string Del(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             return ruleConfig.DelSnatch(param.Content.DeJson<DeletedSnatchItemInfo>()); | ||||
|         } | ||||
|  | ||||
|         public async Task<bool> Update(ClientServiceParamsInfo param) | ||||
|         { | ||||
|             SnatchUpdateInfo info = param.Content.DeJson<SnatchUpdateInfo>(); | ||||
|             byte[] bytes = MemoryPackSerializer.Serialize(info.Item); | ||||
|             for (int i = 0; i < info.Names.Length; i++) | ||||
|             { | ||||
|                 if (signCaching.Get(info.Names[i], out SignCacheInfo cache)) | ||||
|                 { | ||||
|                     await messengerSender.SendOnly(new MessageRequestWrap | ||||
|                     { | ||||
|                         Connection = cache.Connection, | ||||
|                         MessengerId = (ushort)SnatchMessengerIds.Update, | ||||
|                         Payload = bytes | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class SnatchUpdateInfo | ||||
|     { | ||||
|         public string[] Names { get; set; } | ||||
|         public SnatchQuestionInfo Item { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -55,7 +55,7 @@ namespace cmonitor.server.client | ||||
|             IPAddress[] ips = new IPAddress[] { config.Server }; | ||||
|  | ||||
|             if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG) | ||||
|                 Logger.Instance.Info($"get ip:{ips.ToJson()}"); | ||||
|                 Logger.Instance.Info($"get ip:{ips.ToJsonFormat()}"); | ||||
|  | ||||
|             if (ips.Length == 0) return; | ||||
|             foreach (IPAddress ip in ips) | ||||
|   | ||||
| @@ -105,7 +105,7 @@ namespace cmonitor.server.client.reports | ||||
|             if (reportObj.Count > 0) | ||||
|             { | ||||
|  | ||||
|                 string json = reportObj.ToJsonDefault(); | ||||
|                 string json = reportObj.ToJson(); | ||||
|                 byte[] res = MemoryPackSerializer.Serialize(json); | ||||
|                 await messengerSender.SendOnly(new MessageRequestWrap | ||||
|                 { | ||||
|   | ||||
| @@ -182,7 +182,7 @@ namespace cmonitor.server.client.reports.active | ||||
|                 } | ||||
|  | ||||
|                 activeWindowInfo.Title = buff.ToString(); | ||||
|                 activeWindowInfo.FileName = filename; | ||||
|                 activeWindowInfo.FileName = Path.GetFileName(filename); | ||||
|                 activeWindowInfo.Desc = desc; | ||||
|                 activeWindowInfo.Pid = id; | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,7 @@ using common.libs.helpers; | ||||
|  | ||||
| namespace cmonitor.server.client.reports.screen | ||||
| { | ||||
|     public sealed class ScreenWIndowsDxgi | ||||
|     public sealed class ScreenWindowsDxgi | ||||
|     { | ||||
|         private Adapter1 adapter; | ||||
|         private Device mDevice; | ||||
| @@ -37,10 +37,10 @@ namespace cmonitor.server.client.reports.screen | ||||
|  | ||||
|         private readonly Config config; | ||||
|  | ||||
|         public ScreenWIndowsDxgi(int whichMonitor, Config config) | ||||
|         public ScreenWindowsDxgi(int whichMonitor, Config config) | ||||
|             : this(0, whichMonitor, config) { } | ||||
|  | ||||
|         public ScreenWIndowsDxgi(int whichGraphicsCardAdapter, int whichOutputDevice, Config config) | ||||
|         public ScreenWindowsDxgi(int whichGraphicsCardAdapter, int whichOutputDevice, Config config) | ||||
|         { | ||||
|             this.whichGraphicsCardAdapter = whichGraphicsCardAdapter; | ||||
|             this.whichOutputDevice = whichOutputDevice; | ||||
|   | ||||
| @@ -7,11 +7,11 @@ namespace cmonitor.server.client.reports.screen | ||||
| { | ||||
|     public sealed class ScreenWindows : IScreen | ||||
|     { | ||||
|         private readonly ScreenWIndowsDxgi dxgiDesktop; | ||||
|         private readonly ScreenWindowsDxgi dxgiDesktop; | ||||
|         private readonly ScreenWindowsGdi gdiDesktop; | ||||
|         public ScreenWindows(Config config) | ||||
|         { | ||||
|             dxgiDesktop = new ScreenWIndowsDxgi(0, config); | ||||
|             dxgiDesktop = new ScreenWindowsDxgi(0, config); | ||||
|             gdiDesktop = new ScreenWindowsGdi(config); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -64,6 +64,10 @@ namespace cmonitor.server.client.reports.share | ||||
|         { | ||||
|             return dic.TryGetValue(key, out item); | ||||
|         } | ||||
|         public bool GetShareRunning(int index) | ||||
|         { | ||||
|             return shareMemory.ReadRunning(index); | ||||
|         } | ||||
|         public void UpdateShare(ShareItemInfo shareItemInfo) | ||||
|         { | ||||
|             if (shareMemory != null) | ||||
| @@ -78,7 +82,7 @@ namespace cmonitor.server.client.reports.share | ||||
|  | ||||
|         private void ShareMemoryStateChanged(int index, ShareMemoryState state) | ||||
|         { | ||||
|             if (index == 0 && state == ShareMemoryState.Closed) | ||||
|             if (index == 0 && (state & ShareMemoryState.Closed) == ShareMemoryState.Closed) | ||||
|             { | ||||
|                 shareMemory.WriteClosed(0, false); | ||||
|                 shareMemory.WriteRunning(0, false); | ||||
|   | ||||
							
								
								
									
										62
									
								
								cmonitor/server/client/reports/snatch/ISnatch.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								cmonitor/server/client/reports/snatch/ISnatch.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.server.client.reports.snatch | ||||
| { | ||||
|     public interface ISnatch | ||||
|     { | ||||
|         public void Set(SnatchQuestionInfo snatchQuestionInfo); | ||||
|     } | ||||
|  | ||||
|     [MemoryPackable] | ||||
|     public sealed partial class SnatchQuestionInfo | ||||
|     { | ||||
|         public SnatchType Type { get; set; } | ||||
|         /// <summary> | ||||
|         /// 问题 | ||||
|         /// </summary> | ||||
|         public string Question { get; set; } | ||||
|         /// <summary> | ||||
|         /// 正确答案 | ||||
|         /// </summary> | ||||
|         public string Correct { get; set; } | ||||
|         /// <summary> | ||||
|         /// 选项数 | ||||
|         /// </summary> | ||||
|         public int Option { get; set; } | ||||
|         /// <summary> | ||||
|         /// 最多答题次数 | ||||
|         /// </summary> | ||||
|         public int Max { get; set; } = int.MaxValue; | ||||
|         /// <summary> | ||||
|         /// 已结束 | ||||
|         /// </summary> | ||||
|         public bool End { get; set; } = false; | ||||
|         /// <summary> | ||||
|         /// 重复答题 | ||||
|         /// </summary> | ||||
|         public bool Repeat { get; set; } = true; | ||||
|         public int Join { get; set; } = 0; | ||||
|         public int Right { get; set; } = 0; | ||||
|         public int Wrong { get; set; } = 0; | ||||
|     } | ||||
|     public sealed class SnatchAnswerInfo | ||||
|     { | ||||
|         public SnatchState State { get; set; } | ||||
|         public bool Result { get; set; } | ||||
|         public long Time { get; set; } | ||||
|         public string ResultStr { get; set; } | ||||
|     } | ||||
|  | ||||
|     public enum SnatchState : byte | ||||
|     { | ||||
|         None = 0, | ||||
|         Ask = 1, | ||||
|         Confirm = 2, | ||||
|     } | ||||
|     public enum SnatchType : byte | ||||
|     { | ||||
|         None = 0, | ||||
|         Select = 1, | ||||
|         Input = 2, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								cmonitor/server/client/reports/snatch/SnatchLinux.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								cmonitor/server/client/reports/snatch/SnatchLinux.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| namespace cmonitor.server.client.reports.snatch | ||||
| { | ||||
|     public sealed class SnatchLinux : ISnatch | ||||
|     { | ||||
|         public void Set(SnatchQuestionInfo snatchQuestionInfo) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								cmonitor/server/client/reports/snatch/SnatchMacOS.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								cmonitor/server/client/reports/snatch/SnatchMacOS.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| namespace cmonitor.server.client.reports.snatch | ||||
| { | ||||
|     public sealed class SnatchMacOS : ISnatch | ||||
|     { | ||||
|         public void Set(SnatchQuestionInfo snatchQuestionInfo) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								cmonitor/server/client/reports/snatch/SnatchReport.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								cmonitor/server/client/reports/snatch/SnatchReport.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| namespace cmonitor.server.client.reports.snatch | ||||
| { | ||||
|     public sealed class SnatchReport : IReport | ||||
|     { | ||||
|         public string Name => "Snatch"; | ||||
|  | ||||
|         private readonly ISnatch snatch; | ||||
|  | ||||
|         public SnatchReport(ISnatch snatch) | ||||
|         { | ||||
|             this.snatch = snatch; | ||||
|             snatch.Set(new SnatchQuestionInfo { Correct = string.Empty, End = true, Join=0, Max=0, Option=0, Question=string.Empty, Repeat=false, Right=0, Type= SnatchType.Select,Wrong=0}); | ||||
|         } | ||||
|  | ||||
|         public object GetReports(ReportType reportType) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         public void Update(SnatchQuestionInfo snatchQuestionInfo) | ||||
|         { | ||||
|             snatch.Set(snatchQuestionInfo); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										49
									
								
								cmonitor/server/client/reports/snatch/SnatchWindows.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								cmonitor/server/client/reports/snatch/SnatchWindows.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| using cmonitor.server.client.reports.share; | ||||
| using common.libs; | ||||
| using common.libs.extends; | ||||
|  | ||||
| namespace cmonitor.server.client.reports.snatch | ||||
| { | ||||
|     public sealed class SnatchWindows : ISnatch | ||||
|     { | ||||
|         private readonly Config config; | ||||
|         private readonly ShareReport shareReport; | ||||
|         public SnatchWindows(Config config, ShareReport shareReport) | ||||
|         { | ||||
|             this.config = config; | ||||
|             this.shareReport = shareReport; | ||||
|         } | ||||
|  | ||||
|         public void Set(SnatchQuestionInfo snatchQuestionInfo) | ||||
|         { | ||||
|             bool running = shareReport.GetShareRunning(Config.ShareSnatchQuestionIndex); | ||||
|             //更新问题 | ||||
|             shareReport.UpdateShare(new ShareItemInfo | ||||
|             { | ||||
|                 Index = Config.ShareSnatchQuestionIndex, | ||||
|                 Key = "SnatchQuestion", | ||||
|                 Value = snatchQuestionInfo.ToJson() | ||||
|             }); | ||||
|             //未启动,并且未结束 | ||||
|             if (running == false && snatchQuestionInfo.End == false) | ||||
|             { | ||||
|                 //启动 | ||||
|                 shareReport.UpdateShare(new ShareItemInfo | ||||
|                 { | ||||
|                     Index = Config.ShareSnatchAnswerIndex, | ||||
|                     Key = "SnatchAnswer", | ||||
|                     Value = new SnatchAnswerInfo | ||||
|                     { | ||||
|                         Result = false, | ||||
|                         ResultStr = string.Empty, | ||||
|                         State = SnatchState.Ask, | ||||
|                         Time = 0, | ||||
|                     }.ToJson() | ||||
|                 }); | ||||
|                 CommandHelper.Windows(string.Empty, new string[] { | ||||
|                         $"start cmonitor.snatch.win.exe {config.ShareMemoryKey} {config.ShareMemoryLength} {config.ShareMemoryItemSize} {Config.ShareSnatchQuestionIndex} {Config.ShareSnatchAnswerIndex}" | ||||
|                     }); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								cmonitor/server/service/messengers/snatch/SnatchMessenger.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								cmonitor/server/service/messengers/snatch/SnatchMessenger.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| using cmonitor.server.client.reports.snatch; | ||||
| using MemoryPack; | ||||
|  | ||||
| namespace cmonitor.server.service.messengers.snatch | ||||
| { | ||||
|     public sealed class SnatchMessenger : IMessenger | ||||
|     { | ||||
|         private readonly SnatchReport snatchReport; | ||||
|  | ||||
|         public SnatchMessenger(SnatchReport snatchReport) | ||||
|         { | ||||
|             this.snatchReport = snatchReport; | ||||
|         } | ||||
|  | ||||
|         [MessengerId((ushort)SnatchMessengerIds.Update)] | ||||
|         public void Update(IConnection connection) | ||||
|         { | ||||
|             SnatchQuestionInfo question = MemoryPackSerializer.Deserialize<SnatchQuestionInfo>(connection.ReceiveRequestWrap.Payload.Span); | ||||
|             snatchReport.Update(question); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| namespace cmonitor.server.service.messengers.snatch | ||||
| { | ||||
|     public enum SnatchMessengerIds : ushort | ||||
|     { | ||||
|         Update = 1600, | ||||
|  | ||||
|         None = 1699 | ||||
|     } | ||||
| } | ||||
| @@ -85,7 +85,7 @@ namespace common.libs.database | ||||
|                 //Logger.Instance.Error($"save:{fileName}"); | ||||
|                 //Logger.Instance.Error(model.ToJsonIndented()); | ||||
|  | ||||
|                 await File.WriteAllTextAsync(fileName, model.ToJsonIndented(), Encoding.UTF8).ConfigureAwait(false); | ||||
|                 await File.WriteAllTextAsync(fileName, model.ToJsonFormat(), Encoding.UTF8).ConfigureAwait(false); | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|   | ||||
| @@ -24,18 +24,14 @@ namespace common.libs.extends | ||||
|             WriteIndented = true, | ||||
|             Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() } | ||||
|         }; | ||||
|         public static string ToJsonDefault(this object obj) | ||||
|         public static string ToJson(this object obj) | ||||
|         { | ||||
|             return JsonSerializer.Serialize(obj); | ||||
|         } | ||||
|         public static string ToJson(this object obj) | ||||
|         public static string ToJsonFormat(this object obj) | ||||
|         { | ||||
|             return JsonSerializer.Serialize(obj, jsonSerializerOptions); | ||||
|         } | ||||
|         public static string ToJsonIndented(this object obj) | ||||
|         { | ||||
|             return JsonSerializer.Serialize(obj, jsonSerializerOptionsIndented); | ||||
|         } | ||||
|         public static T DeJson<T>(this string json) | ||||
|         { | ||||
|             return JsonSerializer.Deserialize<T>(json, options: jsonSerializerOptions); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 snltty
					snltty