login.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <div class="root">
  3. <div class="logo">
  4. <img alt="RunForge" src="/logo.svg" height="40">
  5. <span class="title">RunForge | 用户登录</span>
  6. </div>
  7. <a-form size="large" :model="form" :rules="[]" class="form" @submit="handleSubmit">
  8. <a-form-item field="username" hide-label>
  9. <a-input placeholder="请输入用户名" allow-clear v-model="form.username">
  10. <template #prefix>
  11. <icon-user />
  12. </template>
  13. </a-input>
  14. </a-form-item>
  15. <a-form-item field="password" hide-label>
  16. <a-input-password placeholder="请输入密码" allow-clear v-model="form.password">
  17. <template #prefix>
  18. <icon-lock />
  19. </template>
  20. </a-input-password>
  21. </a-form-item>
  22. <a-form-item field="captcha" hide-label>
  23. <a-input placeholder="请输入验证码" allow-clear v-model="form.captcha">
  24. <template #prefix>
  25. <icon-check-circle />
  26. </template>
  27. <template #append>
  28. <img alt="!点我重试" :src="ImageCaptcha" class="captcha" @click="getCaptcha()" v-if="!captchaLoading">
  29. <icon-loading v-else />
  30. </template>
  31. </a-input>
  32. </a-form-item>
  33. <div class="forgetpass">
  34. <a-button type="text" @click="emit('changeMode', 'uniLogin')">快捷登录</a-button>
  35. <!-- <div class="tip">由于业务变更 现无法通过QQ/微信快捷登录<br>快捷登录用户可在注册新账号后提交工单联系客服找回原账号</div> -->
  36. <a-button type="text" @click="emit('changeMode', 'register')">注册账号</a-button>
  37. </div>
  38. <a-button :style="{ marginTop: '15px' }" class="formitem" type="primary" html-type="submit"
  39. :loading="loading">登录</a-button>
  40. </a-form>
  41. </div>
  42. </template>
  43. <script setup>
  44. import { getImageCaptcha } from '@/api/login'
  45. import { Notification } from '@arco-design/web-vue'
  46. import { ref, reactive } from 'vue'
  47. import { useUserStore } from '@/store/modules/user'
  48. import { timeFix } from '@/utils/util'
  49. import { useRoute, useRouter } from 'vue-router'
  50. const route = useRoute()
  51. const router = useRouter()
  52. const emit = defineEmits(['changeMode'])
  53. const from = route.query.from
  54. const userStore = useUserStore()
  55. let captchaLoading = ref(false)
  56. let CaptchaId = ref('')
  57. let ImageCaptcha = ref('')
  58. let loading = ref(false)
  59. let form = reactive({
  60. username: '',
  61. password: '',
  62. captcha: ''
  63. })
  64. const getCaptcha = async () => {
  65. try {
  66. captchaLoading.value = true
  67. const res = await getImageCaptcha()
  68. if (!res || res.code != 0)
  69. return requestFailed('获取图片验证码失败!' + res?.msg ?? '')
  70. ImageCaptcha.value = res.data.img
  71. CaptchaId.value = res.data.id
  72. } catch (error) {
  73. requestFailed('获取图片验证码失败!')
  74. } finally {
  75. captchaLoading.value = false
  76. }
  77. }
  78. getCaptcha()
  79. const handleSubmit = async ({ values, errors }) => {
  80. if (!values.username || !values.password || !values.captcha)
  81. return requestFailed('请填写所有信息')
  82. loading.value = true
  83. let data = { ...values, id: CaptchaId.value }
  84. data.password = btoa(data.password)
  85. userStore.login(data)
  86. .then((res) => { loginSuccess(res) })
  87. .catch((err) => {
  88. getCaptcha()
  89. requestFailed(err.message)
  90. })
  91. .finally(() => {
  92. form.captcha = ''
  93. loading.value = false
  94. })
  95. }
  96. const loginSuccess = (res) => {
  97. Notification.success({
  98. title: `${timeFix()},${res.username}`,
  99. content: '欢迎回来!',
  100. duration: 2000
  101. })
  102. // setTimeout(() => { router.push(from || '/')}, 2000)
  103. router.push(from || '/')
  104. }
  105. const requestFailed = (msg) => {
  106. Notification.error({
  107. title: '错误',
  108. content: msg || '请求出现错误,请稍后再试',
  109. })
  110. }
  111. </script>
  112. <style scoped>
  113. .root {
  114. display: flex;
  115. gap: 40px;
  116. flex-direction: column;
  117. align-items: center;
  118. justify-content: center;
  119. }
  120. .form {
  121. width: 100%;
  122. }
  123. .formitem {
  124. width: 350px;
  125. min-height: 35px
  126. }
  127. .logo {
  128. display: flex
  129. }
  130. .logo .title {
  131. color: #FE82A5;
  132. font-size: 1.8em;
  133. font-weight: bold;
  134. margin-left: 15px;
  135. font-family: Alimama ShuHeiTi, -apple-system, BlinkMacSystemFont;
  136. }
  137. .tip {
  138. color: #777;
  139. font-size: 0.9em;
  140. text-align: left;
  141. margin-bottom: 20px;
  142. margin-left: -8px;
  143. }
  144. .forgetpass {
  145. width: 100%;
  146. margin-top: -10px;
  147. display: flex;
  148. justify-content: space-between;
  149. }
  150. .captcha {
  151. max-height: 35px;
  152. margin-right: -10px;
  153. }
  154. </style>