qrcode.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <div class="qrcodeLogin">
  3. <div class="qrcodeLogin-center">
  4. <div class="login-title"><img src="@/assets/images/login/login.png" /></div>
  5. <Transition :enter-active-class="proxy?.animate.error.enter">
  6. <div class="qrcodeLogin-box" :key="key">
  7. <div class="tab">
  8. <div class="li" :class="{ 'current': type == 1 }" @click="changeType(1)">扫码登录</div>
  9. <div class="li" :class="{ 'current': type == 2 }" @click="changeType(2)">密码登录</div>
  10. </div>
  11. <div class="qrcodeLogin-content">
  12. <div class="qrcodeBox" v-show="type == 1 ? true : false">
  13. <div class="pic"><img :src="erweima" @click="getMobile" /></div>
  14. <div class="name">使用微信扫一扫</div>
  15. </div>
  16. <div class="login-input-box" v-show="type == 2 ? true : false">
  17. <div class="login-item">
  18. <input class="login-input" type="text" placeholder="请输入设备ID" v-model.trim="loginForm.deviceid" />
  19. </div>
  20. <div class="login-item">
  21. <input class="login-input" type="text" placeholder="请输入帐号" v-model.trim="loginForm.username" />
  22. </div>
  23. <div class="login-item">
  24. <input class="login-input" type="password" autocomplete="off" placeholder="请输入密码"
  25. v-model.trim="loginForm.password" />
  26. </div>
  27. <div @click="getLogin" class="login-btn">
  28. <el-icon class="is-loading" v-if="loading">
  29. <Loading />
  30. </el-icon>
  31. 登 录
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. </Transition>
  37. </div>
  38. </div>
  39. </template>
  40. <script setup name="QrcodeLogin" lang="ts">
  41. import { useWebSocket } from '@/utils/handWs';
  42. import QRCode from 'qrcode';
  43. import CryptoJS from 'crypto-js';
  44. const { handWs, startLogin } = useWebSocket();
  45. const { proxy } = getCurrentInstance() as any;
  46. const router = useRouter();
  47. const route = useRoute();
  48. interface DataType {
  49. erweima: string,
  50. sid: string,
  51. listenWs: boolean,
  52. loginForm: {
  53. username: string,
  54. password: string,
  55. deviceid: string,
  56. },
  57. loading: boolean,
  58. key: number,
  59. type: number,
  60. }
  61. const data = reactive<DataType>({
  62. erweima: '',
  63. sid: '',
  64. listenWs: false, //是否监听手势
  65. loginForm: {
  66. username: '',
  67. password: '',
  68. deviceid: '',
  69. },
  70. loading: false,
  71. key: 0,
  72. type: 1
  73. });
  74. const { erweima, sid, listenWs, loginForm, loading, key, type } = toRefs(data);
  75. /**
  76. * 手势
  77. */
  78. const getHandWs = () => {
  79. //加载手势WS
  80. handWs((e: any) => {
  81. //发送设备
  82. if (e?.wksid) {
  83. console.log('e.wksid', e.wksid);
  84. listenWs.value = true;
  85. sid.value = e.wksid;
  86. //登录码
  87. getErweima();
  88. //连接登录
  89. startLogin();
  90. }
  91. if (listenWs.value == false) {
  92. return false;
  93. }
  94. //接收百度语音token
  95. if (e?.bdapi_token) {
  96. // console.log("e.bdapi_token", e.bdapi_token)
  97. let tok = e.bdapi_token;
  98. localStorage.setItem('tok', tok);
  99. }
  100. //获取信息
  101. if (e?.data?.token) {
  102. //保存token
  103. let token = e.data.token;
  104. localStorage.setItem('token', token);
  105. let deviceid = e?.data?.deviceid;
  106. localStorage.setItem('deviceid', deviceid);
  107. //刷新
  108. window.location.reload();
  109. }
  110. //自动登录
  111. if (route.query?.auto) {
  112. type.value = 2;
  113. getLogin();
  114. }
  115. });
  116. };
  117. /**
  118. * 获取二维码
  119. */
  120. const getErweima = () => {
  121. QRCode.toDataURL(`${location.origin}/#/login/mobile?sid=${sid.value}`).then((res: any) => {
  122. erweima.value = res;
  123. });
  124. };
  125. // 登录
  126. const getLogin = () => {
  127. let deviceid = loginForm.value.deviceid;
  128. let username = loginForm.value.username;
  129. let password = loginForm.value.password;
  130. if (!deviceid || !username || !password) {
  131. proxy?.$modal.msgWarning('设备ID、账号、密码不能为空');
  132. key.value++;
  133. return false;
  134. }
  135. loading.value = true;
  136. proxy?.$modal.loading();
  137. let params = {
  138. sid: sid.value,
  139. deviceid,
  140. username,
  141. password
  142. };
  143. proxy?.$http.common
  144. .qrlogin(params)
  145. .then((res: any) => {
  146. if (res.access_token) {
  147. //保存token
  148. let token = res.access_token;
  149. let passwordStr = CryptoJS.AES.encrypt(password, 'trops').toString();
  150. localStorage.setItem('loginType', "2");
  151. localStorage.setItem('token', token);
  152. if (deviceid) {
  153. localStorage.setItem('deviceid', deviceid);
  154. } else {
  155. localStorage.removeItem('deviceid');
  156. }
  157. localStorage.setItem('username', username);
  158. localStorage.setItem('password', passwordStr);
  159. }
  160. })
  161. .catch(() => {
  162. key.value++;
  163. })
  164. .finally(() => {
  165. proxy?.$modal?.closeLoading();
  166. loading.value = false;
  167. });
  168. };
  169. /**
  170. * 切换登录类型
  171. */
  172. const changeType = (data: number) => {
  173. type.value = data;
  174. if (type.value == 2 && sid.value == undefined && !sid.value) {
  175. proxy?.$modal.msgError('缺少SID,重新获取!');
  176. //刷新
  177. window.location.reload();
  178. }
  179. };
  180. /**
  181. * 跳转手机登录页
  182. */
  183. const getMobile = () => {
  184. let routeUrl: any = router.resolve({ path: '/login/mobile', query: { sid: sid.value } });
  185. window.open(routeUrl.href, '_blank');
  186. };
  187. onMounted(() => {
  188. let token = localStorage.getItem('token');
  189. let deviceid = localStorage.getItem('deviceid');
  190. let username = localStorage.getItem('username');
  191. let password = localStorage.getItem('password');
  192. if (deviceid) {
  193. loginForm.value.deviceid = deviceid;
  194. }
  195. if (username) {
  196. loginForm.value.username = username;
  197. }
  198. if (password) {
  199. let myPassword = CryptoJS.AES.decrypt(password, 'trops').toString(CryptoJS.enc.Utf8);
  200. loginForm.value.password = myPassword;
  201. }
  202. localStorage.removeItem('ip');
  203. getHandWs();
  204. });
  205. onBeforeUnmount(() => {
  206. listenWs.value = false;
  207. });
  208. onMounted(() => {
  209. //测试环境默认密码
  210. if (import.meta.env.DEV) {
  211. // loginForm.value.deviceid = '25821975';
  212. // loginForm.value.username = 'manage1';
  213. // loginForm.value.password = 'trops@2022';
  214. }
  215. });
  216. </script>
  217. <style lang="scss" scoped>
  218. .qrcodeLogin {
  219. width: 100%;
  220. height: 100vh;
  221. display: flex;
  222. align-items: center;
  223. justify-content: center;
  224. .qrcodeLogin-center {
  225. .login-title {
  226. text-align: center;
  227. img {
  228. width: 8rem;
  229. }
  230. margin-bottom: 1.2rem;
  231. }
  232. .qrcodeLogin-box {
  233. background: linear-gradient(41deg, #1d2f3d -83%, #304453 95%);
  234. box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.2);
  235. border-radius: 1.6rem;
  236. .tab {
  237. display: flex;
  238. font-size: 1.2rem;
  239. text-align: center;
  240. height: 4rem;
  241. line-height: 4rem;
  242. .li {
  243. width: 50%;
  244. color: #ffffff;
  245. border-bottom: 1px solid #f1f1f1;
  246. cursor: pointer;
  247. }
  248. .current {
  249. color: #14f287;
  250. border-bottom: 1px solid #14f287;
  251. }
  252. }
  253. .qrcodeLogin-content {
  254. width: 13rem;
  255. height: calc(13rem + 1rem + 2rem);
  256. padding: 2rem 5rem;
  257. .qrcodeBox {
  258. text-align: center;
  259. .pic {
  260. width: 100%;
  261. margin-bottom: 1rem;
  262. img {
  263. width: 100%;
  264. }
  265. }
  266. .name {
  267. color: #ffffff;
  268. font-size: 1.4rem;
  269. }
  270. }
  271. .login-input-box {
  272. display: flex;
  273. justify-content: center;
  274. align-items: center;
  275. flex-direction: column;
  276. width: 100%;
  277. .login-item {
  278. width: 100%;
  279. margin-bottom: 1.2rem;
  280. display: flex;
  281. justify-content: center;
  282. .login-input {
  283. width: 100%;
  284. height: 2.9rem;
  285. line-height: 2.9rem;
  286. border-radius: 0.83rem;
  287. padding: 0 1rem;
  288. text-align: center;
  289. font-size: 1.65rem;
  290. opacity: 1;
  291. background: #eaeaea;
  292. box-sizing: border-box;
  293. border: 1px solid #ffffff;
  294. box-shadow: inset 0px 0px 10px 1px rgba(78, 78, 78, 0.5899);
  295. }
  296. }
  297. .login-btn {
  298. width: 100%;
  299. height: 3.59rem;
  300. line-height: 3.59rem;
  301. border-radius: 0.83rem;
  302. font-size: 2rem;
  303. opacity: 1;
  304. text-align: center;
  305. background: radial-gradient(141% 126% at 5% 93%, #8effa9 0%, #07ffe7 100%);
  306. box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.3);
  307. cursor: pointer;
  308. display: flex;
  309. align-items: center;
  310. justify-content: center;
  311. .is-loading {
  312. margin-right: 5px;
  313. }
  314. }
  315. }
  316. }
  317. }
  318. }
  319. }
  320. </style>