index.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import { ElButton, ElIcon, ElLink } from 'element-plus'
  2. import QrcodeVue from 'qrcode.vue'
  3. import { defineComponent } from 'vue'
  4. import styles from './index.module.less'
  5. import Cookies from 'js-cookie'
  6. import request from '@/helpers/request'
  7. import { state } from '@/state'
  8. import { getCodeBaseUrl, setAuth } from '@/helpers/utils'
  9. import { CircleCheck } from '@element-plus/icons-vue'
  10. import logoIco from '@/common/images/logo.png'
  11. export const getAssetsHomeFile = (fileName: string) => {
  12. const path = `../../images/${fileName}`
  13. const modules = import.meta.globEager('../../images/*')
  14. return modules[path].default
  15. }
  16. export default defineComponent({
  17. name: 'qrCode',
  18. props: {
  19. loginType: {
  20. type: String
  21. },
  22. onChange: {
  23. type: Function,
  24. default: (type: string) => {}
  25. },
  26. onClose: {
  27. type: Function,
  28. default: () => {}
  29. }
  30. },
  31. data() {
  32. return {
  33. qrCode: '',
  34. isScan: false, // 是否扫码
  35. scanCode: '',
  36. codeTimerOut: false, // 是否超时或登录过期
  37. // 状态 no_scan 未扫码 scanned 已扫码 succeed 登录成功 filed 登录失败
  38. codeStatus: 'no_scan' as 'no_scan' | 'scanned' | 'succeed' | 'filed' // 扫码状态
  39. }
  40. },
  41. async mounted() {
  42. try {
  43. const scanCode = sessionStorage.getItem('scanCode')
  44. await this.getCode(scanCode)
  45. const str = this.loginType === 'TEACHER' ? 'teacher' : 'student'
  46. this.qrCode = `${getCodeBaseUrl(`/${str}`)}/#/scanLogin?code=${
  47. this.scanCode
  48. }`
  49. console.log(this.qrCode)
  50. state.loginPopupTimer = setInterval(async () => {
  51. await this.getList()
  52. }, 5000)
  53. } catch {
  54. //
  55. }
  56. },
  57. methods: {
  58. async getCode(code?: string) {
  59. try {
  60. const res = await request.get('/api-auth/getQRLoginCode', {
  61. params: {
  62. clientId: 'website',
  63. clientSecret: 'website',
  64. code
  65. }
  66. })
  67. this.scanCode = res.data.code
  68. this.codeStatus = res.data.codeStatus
  69. sessionStorage.setItem('scanCode', res.data.code)
  70. } catch {}
  71. },
  72. async getList() {
  73. try {
  74. console.log(this.scanCode)
  75. const res = await request.get('/api-auth/pollingQRLoginCode', {
  76. params: {
  77. code: this.scanCode
  78. }
  79. })
  80. console.log(res, 'getlist')
  81. const result = res.data
  82. // 判断是否有数据,如果没有数据则认定为超时
  83. if (!result) {
  84. this.codeTimerOut = true
  85. this.removeTimer()
  86. return
  87. }
  88. this.codeStatus = result.codeStatus
  89. if (result.codeStatus === 'succeed') {
  90. this.removeTimer()
  91. const { authentication, userType } = result
  92. const token =
  93. authentication.token_type + ' ' + authentication.access_token
  94. setAuth(
  95. JSON.stringify({
  96. token,
  97. loginUserType: userType
  98. })
  99. )
  100. this.onClose()
  101. window.location.reload()
  102. } else if (result.codeStatus === 'filed') {
  103. this.removeTimer()
  104. } else if (result.codeStatus === 'scanned') {
  105. this.isScan = true
  106. }
  107. } catch {
  108. console.log('error')
  109. this.codeTimerOut = true
  110. this.removeTimer()
  111. }
  112. },
  113. removeTimer() {
  114. // 取消定时器
  115. this.codeStatus = 'no_scan'
  116. this.isScan = false
  117. clearInterval(state.loginPopupTimer)
  118. }
  119. },
  120. render() {
  121. return (
  122. <div class={'text-center pt-4'}>
  123. {/* <div
  124. class={'absolute top-2 right-2 z-10'}
  125. onClick={() => {
  126. this.removeTimer()
  127. this.onChange('login')
  128. }}
  129. >
  130. <img
  131. src={getAssetsHomeFile('icon_pc_login.png')}
  132. class="w-14 h-14 cursor-pointer"
  133. />
  134. </div> */}
  135. {this.isScan ? (
  136. <>
  137. <ElIcon
  138. class="mx-auto w-[138px] h-[138px] align-middle"
  139. size={70}
  140. color="var(--el-color-primary)"
  141. >
  142. <CircleCheck />
  143. </ElIcon>
  144. <p class="text-lg text-[#666] mt-6">扫码成功</p>
  145. <p class="font-semibold text-[#1A1A1A] text-[20px] pt-4">
  146. 请在手机上根据提示确认登录
  147. </p>
  148. <ElLink
  149. type="primary"
  150. underline={false}
  151. class="m-auto mt-3"
  152. onClick={async () => {
  153. const scanCode = sessionStorage.getItem('scanCode')
  154. await this.getCode(scanCode || '')
  155. this.isScan = false
  156. }}
  157. >
  158. 返回扫描二维码
  159. </ElLink>
  160. </>
  161. ) : (
  162. <>
  163. <div class="mx-auto w-[192px] h-[192px] relative overflow-hidden rounded-[10px]">
  164. <QrcodeVue
  165. value={this.qrCode}
  166. size={192}
  167. class="p-2.5 border-4 border-[#2DC7AA] box-border rounded-[10px]"
  168. />
  169. {/* 手动在中间添加图标 */}
  170. <div class="absolute w-[192px] h-[192px] top-0 left-0 flex items-center justify-center">
  171. <img src={logoIco} class="w-9 h-9" />
  172. </div>
  173. {/* 登录是否过期 */}
  174. {this.codeTimerOut && (
  175. <div class="absolute inset-0 bg-black bg-opacity-75 flex items-center justify-center flex-col">
  176. <p class="text-white text-sm pb-2">二维码已失效</p>
  177. <ElButton
  178. type="primary"
  179. size="small"
  180. onClick={async () => {
  181. this.codeTimerOut = false
  182. await this.getCode()
  183. state.loginPopupTimer = setInterval(async () => {
  184. await this.getList()
  185. }, 5000)
  186. }}
  187. >
  188. 点击刷新
  189. </ElButton>
  190. </div>
  191. )}
  192. </div>
  193. <div class="flex items-center justify-center pt-8 font-normal">
  194. {/* <img
  195. class="w-9 h-9 align-middle mr-4"
  196. src={getAssetsHomeFile('icon_scan.png')}
  197. />
  198. <div class={['text-left leading-[22px]']}>
  199. <p>
  200. 打开<span class={styles.txt}>酷乐秀学生端APP</span>
  201. </p>
  202. <p>扫一扫登录</p>
  203. </div> */}
  204. <div class="text-lg text-[#333] text-center">
  205. 打开
  206. {this.loginType === 'TEACHER' ? '酷乐秀学院' : '酷乐秀'}
  207. App扫一扫登录
  208. </div>
  209. </div>
  210. </>
  211. )}
  212. </div>
  213. )
  214. }
  215. })