flameLogin.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <div class="box" :style="{'background-image': 'url(' + logoBgUrl + ')'}">
  3. <div class="content">
  4. <div class="login-content">
  5. <v-card height="392px" class="carousel mr-3" style="width: 792px; border-radius: 8px;">
  6. <v-carousel show-arrows="hover" cycle :model-value="0">
  7. <v-carousel-item v-for="(item, i) in carouselList" :key="i" @click="handleClick(item)">
  8. <div style="height: 392px; overflow: hidden;" :class="{'cursor-pointer': item.link}">
  9. <v-img :src="item.img" :lazy-src="item.src" cover style="height: 100%; overflow: hidden;">
  10. <template v-slot:placeholder>
  11. <v-row align="center" class="fill-height ma-0" justify="center">
  12. <v-progress-circular color="grey-lighten-5" indeterminate></v-progress-circular>
  13. </v-row>
  14. </template>
  15. </v-img>
  16. </div>
  17. </v-carousel-item>
  18. </v-carousel>
  19. </v-card>
  20. <div class="login-card">
  21. <div class="login-tab">
  22. <v-tabs v-model="tab" align-tabs="center" color="primary" class="mb-10">
  23. <v-tab :value="0">老师手机验证码登录</v-tab>
  24. </v-tabs>
  25. <phoneFrom ref="phoneRef" openVerify @handleEnter="handleLogin"></phoneFrom>
  26. </div>
  27. <div class="font-size-14">
  28. <span class="float-right color-error cursor-pointer border-bottom-error" @click="router.push('/register/school')">还没有登录账户?去注册</span>
  29. </div>
  30. <v-btn :loading="loginLoading" color="primary" class="white--text mt-5" min-width="350" @click.stop="handleLogin">
  31. {{ $t('login.login') }}
  32. </v-btn>
  33. <div class="login-tips mt-3">
  34. <v-icon v-if="isAgree" size="25" color="primary" class="mr-1" @click="isAgree = !isAgree">mdi-check-circle</v-icon>
  35. <v-icon v-else size="25" color="grey" class="mr-1" @click="isAgree = !isAgree">mdi-circle-outline</v-icon>
  36. {{ $t('login.agreeLogin') }}
  37. <span class="color" style="cursor: pointer;" @click="windowOpen('/userAgreement')"> [{{ $t('login.userAgreement') }}] </span>和
  38. <span class="color" style="cursor: pointer;" @click="windowOpen('/privacyPolicy')">[{{ $t('login.privacyPolicy') }}]</span>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="aboutBox">
  43. <about :showBanner="false"></about>
  44. </div>
  45. </div>
  46. <navBar :showLoginBtn="false" class="navBar"></navBar>
  47. </div>
  48. <Verify
  49. ref="verify"
  50. captchaType="blockPuzzle"
  51. :imgSize="{ width: '400px', height: '200px' }"
  52. mode="pop"
  53. @success="verifySuccess"
  54. />
  55. </template>
  56. <script setup>
  57. defineOptions({ name: 'login-index' })
  58. import { ref } from 'vue'
  59. import phoneFrom from '@/components/VerificationCode'
  60. import { useUserStore } from '@/store/user'
  61. import { useRouter } from 'vue-router'
  62. import { useI18n } from '@/hooks/web/useI18n'
  63. import { getWebContent } from '@/api/common'
  64. import Snackbar from '@/plugins/snackbar'
  65. import Confirm from '@/plugins/confirm'
  66. import navBar from '@/layout/personal/navBar.vue'
  67. import about from '@/views/about/index.vue'
  68. import Verify from '@/components/Verifition'
  69. // 获取轮播图、背景图
  70. const logoBgUrl = ref('')
  71. const preferred = ref({})
  72. const carouselList = ref([])
  73. const getSystemWebContent = async () => {
  74. const data = await getWebContent()
  75. logoBgUrl.value = data.pcLoginBackground && data.pcLoginBackground.length ? data.pcLoginBackground[0].img : 'https://minio.menduner.com/dev/menduner/login-bgc.jpg'
  76. carouselList.value = data.pcLoginCarousel || []
  77. preferred.value = data.appPreferredGroup || {}
  78. }
  79. getSystemWebContent()
  80. const handleClick = (item) => {
  81. if (!item.link) return
  82. if (item.link.includes('http')) return window.open(item.link)
  83. // 优选集团
  84. if (preferred.value && Object.keys(preferred.value).length > 0 && preferred.value[item.link]) window.open(`/recruit/personal/advertisement/${item.link}`)
  85. else window.open(`/recruit/personal/company/details/${item.link}?key=briefIntroduction`)
  86. }
  87. const { t } = useI18n()
  88. const router = useRouter()
  89. const tab = ref(0)
  90. const isAgree = ref(false)
  91. // 验证码登录
  92. const phoneRef = ref()
  93. const loginLoading = ref(false)
  94. const userStore = useUserStore()
  95. const handleLogin = async () => {
  96. const { valid } = await phoneRef.value.phoneForm.validate()
  97. if (!valid) return
  98. if (!isAgree.value) return Snackbar.warning('请阅读并勾选底部协议')
  99. const params = {
  100. ...phoneRef.value.loginData,
  101. chooseRole: false,
  102. schoolRegister: true
  103. }
  104. loginLoading.value = true
  105. try {
  106. if (!params.captchaVerification && captchaStr.value) params.captchaVerification = captchaStr.value
  107. if (!params.captchaVerification) {
  108. getCode() // 验证码组件
  109. return
  110. }
  111. await userStore.handleSmsLogin(params)
  112. // Snackbar.success(t('login.loginSuccess'))
  113. } catch (err) {
  114. console.log(err)
  115. captchaStr.value = '' // 清空人机验证
  116. if (!err.code || (err?.message && err.message.includes('timeout'))) return
  117. // 登录未注册过的账号跳转注册
  118. const text = err.code === 1100016002 ? '您的手机号还未注册过' : '您的邮箱还未注册过'
  119. Confirm('系统提示', `${text},去注册?`, {
  120. cancelCallback: true
  121. }).then(() => {
  122. localStorage.setItem('flameLoginAccount', phoneRef.value.loginData.phone)
  123. router.push('/register/school')
  124. }).catch(() => {})
  125. } finally {
  126. loginLoading.value = false
  127. }
  128. }
  129. // 获取验证码
  130. const verify = ref()
  131. const getCode = async () => {
  132. // 弹出验证码 // 已开启:则展示验证码;只有完成验证码的情况,才进行登录
  133. verify.value.show()
  134. }
  135. const captchaStr = ref('')
  136. const verifySuccess = (params) => {
  137. captchaStr.value = params.captchaVerification
  138. handleLogin()
  139. }
  140. const windowOpen = (url) => {
  141. if (url) window.open(url)
  142. }
  143. </script>
  144. <style lang="scss" scoped>
  145. .box {
  146. position: relative;
  147. width: 100%;
  148. height: 100vh;
  149. background-size: cover;
  150. overflow: hidden;
  151. .navBar {
  152. position: absolute;
  153. top: 0;
  154. }
  155. }
  156. .content {
  157. width: 100%;
  158. height: 100%;
  159. overflow-y: auto;
  160. }
  161. .login-content {
  162. display: flex;
  163. align-items: center;
  164. justify-content: center;
  165. width: 100%;
  166. height: 78vh;
  167. // height: calc(100vh - 50px);
  168. margin-top: 50px;
  169. }
  170. .login-change {
  171. position: absolute;
  172. top: 0;
  173. right: 0;
  174. margin: 15px 44px;
  175. border-bottom: 1px solid orange;
  176. color: orange;
  177. cursor: pointer;
  178. font-weight: 400;
  179. &:hover {
  180. color: #fbb93e;
  181. }
  182. }
  183. .login-card {
  184. position: relative;
  185. width: 450px;
  186. background-color: #fff;
  187. border-radius: 8px;
  188. padding: 36px 50px;
  189. }
  190. .left {
  191. display: flex;
  192. }
  193. .login-tips {
  194. width: 100%;
  195. font-size: 12px;
  196. display: flex;
  197. justify-content: center;
  198. align-items: center;
  199. }
  200. .tips:hover {
  201. border-bottom: 1px solid #666;
  202. }
  203. .color {
  204. color: var(--v-primary-base);
  205. }
  206. .aboutBox {
  207. width: 100%;
  208. background-color: #fff;
  209. }
  210. .carousel {
  211. :deep(.v-window) {
  212. height: 392px !important;
  213. }
  214. }
  215. </style>