login.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <!--
  2. * @FileDescription: 登录
  3. * @Author: 黄琪勇
  4. * @Date:2024-03-19 17:13:28
  5. -->
  6. <template>
  7. <div class="login">
  8. <div class="loginCon">
  9. <div class="decoration">
  10. <img class="xiaoren" src="@/img/loginErr/xiaoren.png" />
  11. <img class="star" src="@/img/loginErr/star.png" />
  12. <img class="bStar" src="@/img/loginErr/bStar.png" />
  13. <img class="music" src="@/img/loginErr/music.png" />
  14. <img class="yun" src="@/img/loginErr/yun.png" />
  15. </div>
  16. <div class="loginBox">
  17. <img v-show="qrcodeStatus === 2" class="scanned" src="@/img/loginErr/scanned.png" />
  18. <div v-show="qrcodeStatus !== 2" v-loading="!uuid" class="qrcodeBox">
  19. <div class="qrCodeCon" :class="{ refresh: qrcodeStatus === 3 }">
  20. <qrcode-vue class="qrCode" v-if="uuid" :value="qrcode" :size="164" />
  21. <img @click="handleRefresh" src="@/img/loginErr/refresh.png" />
  22. </div>
  23. </div>
  24. <div class="dsc">
  25. <img src="@/img/loginErr/jiantou1.png" />
  26. <div>{{ qrcodeStatus === 2 ? "扫码完成,请在手机上操作" : "使用客户端扫描二维码登录乐教通" }}</div>
  27. <img src="@/img/loginErr/jiantou2.png" />
  28. </div>
  29. <div class="refreshBtn" @click="handleRefresh">{{ qrcodeStatus === 2 ? "重新扫码" : "刷新二维码" }}</div>
  30. </div>
  31. </div>
  32. </div>
  33. </template>
  34. <script setup lang="ts">
  35. import { createQrcodeApi, queryQrcodeStatusApi } from "@/api/user.api"
  36. import { httpAjax } from "@/plugin/httpAjax"
  37. import QrcodeVue from "qrcode.vue"
  38. import { ref, computed } from "vue"
  39. import userStore from "@/store/modules/user"
  40. import { useRouter } from "vue-router"
  41. const userStoreHook = userStore()
  42. const router = useRouter()
  43. const uuid = ref<string>("")
  44. const qrcode = computed(() => {
  45. return JSON.stringify({ action: "login", uuid: uuid.value })
  46. })
  47. const qrcodeStatus = ref<1 | 2 | 3>(1) // 1 未扫码 2 扫码完成 3 二维码过期
  48. let _time: number
  49. handleCreateQrcode()
  50. function handleCreateQrcode() {
  51. httpAjax(createQrcodeApi).then(res => {
  52. if (res.code === 200) {
  53. uuid.value = res.data.uuid
  54. handleQrcodeStatus()
  55. }
  56. })
  57. }
  58. function handleQrcodeStatus() {
  59. httpAjax(queryQrcodeStatusApi, uuid.value as string).then(res => {
  60. if (res.code === 200) {
  61. const { status } = res.data
  62. if (status === "FINISH") {
  63. // 登录成功
  64. userStoreHook.login(res.data).then(() => {
  65. router.push({ path: "/" })
  66. })
  67. return
  68. }
  69. if (status === "SCANNED") {
  70. // 扫码完成
  71. qrcodeStatus.value = 2
  72. } else if (status === "VERIFIED") {
  73. // 已验证
  74. qrcodeStatus.value = 2
  75. } else if (status === "EXPIRED") {
  76. // 二维码过期
  77. qrcodeStatus.value = 3
  78. return
  79. } else if (status === "NOT_SCAN") {
  80. // 未扫码
  81. qrcodeStatus.value = 1
  82. }
  83. _time = setTimeout(() => {
  84. clearTimeout(_time)
  85. handleQrcodeStatus()
  86. }, 3000)
  87. } else if (res.code === 5440) {
  88. // 二维码过期
  89. qrcodeStatus.value = 3
  90. }
  91. })
  92. }
  93. function handleRefresh() {
  94. _time && clearTimeout(_time)
  95. handleCreateQrcode()
  96. }
  97. </script>
  98. <style lang="scss" scoped>
  99. .login {
  100. width: 100%;
  101. height: 100%;
  102. min-height: 640px;
  103. min-width: 1280px;
  104. background: url("@/img/loginErr/bg.png") no-repeat;
  105. background-size: cover;
  106. display: flex;
  107. align-items: center;
  108. justify-content: center;
  109. .loginCon {
  110. width: 74%;
  111. display: flex;
  112. justify-content: space-between;
  113. }
  114. .loginBox {
  115. width: 440px;
  116. height: 498px;
  117. background: url("@/img/loginErr/loginBox.png") no-repeat;
  118. background-size: cover;
  119. z-index: 2;
  120. display: flex;
  121. flex-direction: column;
  122. align-items: center;
  123. .scanned {
  124. margin-top: 132px;
  125. width: 114px;
  126. height: 189px;
  127. }
  128. .qrcodeBox {
  129. margin-top: 154px;
  130. width: 188px;
  131. height: 188px;
  132. display: flex;
  133. justify-content: center;
  134. align-items: center;
  135. background: url("@/img/loginErr/border.png") no-repeat;
  136. background-size: cover;
  137. .qrCodeCon {
  138. position: relative;
  139. &.refresh {
  140. background-color: rgba(255, 255, 255, 0.8);
  141. > .qrCode {
  142. opacity: 0.3;
  143. }
  144. > img {
  145. cursor: pointer;
  146. position: absolute;
  147. left: 50%;
  148. top: 50%;
  149. transform: translate(-50%, -50%);
  150. display: block;
  151. }
  152. }
  153. > img {
  154. display: none;
  155. }
  156. }
  157. }
  158. .dsc {
  159. margin-top: 28px;
  160. display: flex;
  161. justify-content: center;
  162. align-items: center;
  163. > div {
  164. width: 240px;
  165. text-align: center;
  166. font-size: 16px;
  167. color: #777;
  168. margin: 0 14px;
  169. }
  170. > img {
  171. width: 33px;
  172. height: 18px;
  173. }
  174. }
  175. .refreshBtn {
  176. margin-top: 14px;
  177. line-height: 22px;
  178. font-size: 16px;
  179. color: #f67146;
  180. display: inline;
  181. font-weight: bold;
  182. cursor: pointer;
  183. &:hover {
  184. opacity: $opacity-hover;
  185. }
  186. }
  187. }
  188. .decoration {
  189. margin-top: -8px;
  190. position: relative;
  191. z-index: 1;
  192. width: 523px;
  193. height: 412px;
  194. .xiaoren {
  195. position: absolute;
  196. top: 0;
  197. left: 0;
  198. width: 100%;
  199. height: 100%;
  200. z-index: 1;
  201. }
  202. .star {
  203. position: absolute;
  204. right: 0;
  205. top: 0;
  206. width: 26px;
  207. height: 38px;
  208. }
  209. .bStar {
  210. position: absolute;
  211. left: -20px;
  212. top: 178px;
  213. width: 60px;
  214. height: 58px;
  215. }
  216. .music {
  217. position: absolute;
  218. right: -26px;
  219. top: 24px;
  220. width: 28px;
  221. height: 56px;
  222. }
  223. .yun {
  224. position: absolute;
  225. width: 346px;
  226. height: 240px;
  227. bottom: -160px;
  228. left: 40px;
  229. z-index: 0;
  230. }
  231. }
  232. }
  233. </style>