houzhongjian
2024-08-08 820397e43a0b64d35c6d31d2a55475061438593b
提交 | 用户 | 时间
820397 1 <template>
H 2   <el-form
3     v-show="getShow"
4     ref="formSmsLogin"
5     :model="loginData.loginForm"
6     :rules="rules"
7     class="login-form"
8     label-position="top"
9     label-width="120px"
10     size="large"
11   >
12     <el-row style="margin-right: -10px; margin-left: -10px">
13       <!-- 租户名 -->
14       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
15         <el-form-item>
16           <LoginFormTitle style="width: 100%" />
17         </el-form-item>
18       </el-col>
19       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
20         <el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName">
21           <el-input
22             v-model="loginData.loginForm.tenantName"
23             :placeholder="t('login.tenantNamePlaceholder')"
24             :prefix-icon="iconHouse"
25             type="primary"
26             link
27           />
28         </el-form-item>
29       </el-col>
30       <!-- 手机号 -->
31       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
32         <el-form-item prop="mobileNumber">
33           <el-input
34             v-model="loginData.loginForm.mobileNumber"
35             :placeholder="t('login.mobileNumberPlaceholder')"
36             :prefix-icon="iconCellphone"
37           />
38         </el-form-item>
39       </el-col>
40       <!-- 验证码 -->
41       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
42         <el-form-item prop="code">
43           <el-row :gutter="5" justify="space-between" style="width: 100%">
44             <el-col :span="24">
45               <el-input
46                 v-model="loginData.loginForm.code"
47                 :placeholder="t('login.codePlaceholder')"
48                 :prefix-icon="iconCircleCheck"
49               >
50                 <!-- <el-button class="w-[100%]"> -->
51                 <template #append>
52                   <span
53                     v-if="mobileCodeTimer <= 0"
54                     class="getMobileCode"
55                     style="cursor: pointer"
56                     @click="getSmsCode"
57                   >
58                     {{ t('login.getSmsCode') }}
59                   </span>
60                   <span v-if="mobileCodeTimer > 0" class="getMobileCode" style="cursor: pointer">
61                     {{ mobileCodeTimer }}秒后可重新获取
62                   </span>
63                 </template>
64               </el-input>
65               <!-- </el-button> -->
66             </el-col>
67           </el-row>
68         </el-form-item>
69       </el-col>
70       <!-- 登录按钮 / 返回按钮 -->
71       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
72         <el-form-item>
73           <XButton
74             :loading="loginLoading"
75             :title="t('login.login')"
76             class="w-[100%]"
77             type="primary"
78             @click="signIn()"
79           />
80         </el-form-item>
81       </el-col>
82       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
83         <el-form-item>
84           <XButton
85             :loading="loginLoading"
86             :title="t('login.backLogin')"
87             class="w-[100%]"
88             @click="handleBackLogin()"
89           />
90         </el-form-item>
91       </el-col>
92     </el-row>
93   </el-form>
94 </template>
95 <script lang="ts" setup>
96 import type { RouteLocationNormalizedLoaded } from 'vue-router'
97
98 import { useIcon } from '@/hooks/web/useIcon'
99
100 import { setTenantId, setToken } from '@/utils/auth'
101 import { usePermissionStore } from '@/store/modules/permission'
102 import { getTenantIdByName, sendSmsCode, smsLogin } from '@/api/login'
103 import LoginFormTitle from './LoginFormTitle.vue'
104 import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
105 import { ElLoading } from 'element-plus'
106
107 defineOptions({ name: 'MobileForm' })
108
109 const { t } = useI18n()
110 const message = useMessage()
111 const permissionStore = usePermissionStore()
112 const { currentRoute, push } = useRouter()
113 const formSmsLogin = ref()
114 const loginLoading = ref(false)
115 const iconHouse = useIcon({ icon: 'ep:house' })
116 const iconCellphone = useIcon({ icon: 'ep:cellphone' })
117 const iconCircleCheck = useIcon({ icon: 'ep:circle-check' })
118 const { validForm } = useFormValid(formSmsLogin)
119 const { handleBackLogin, getLoginState } = useLoginState()
120 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.MOBILE)
121
122 const rules = {
123   tenantName: [required],
124   mobileNumber: [required],
125   code: [required]
126 }
127 const loginData = reactive({
128   codeImg: '',
129   tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
130   token: '',
131   loading: {
132     signIn: false
133   },
134   loginForm: {
135     uuid: '',
136     tenantName: 'iailab',
137     mobileNumber: '',
138     code: ''
139   }
140 })
141 const smsVO = reactive({
142   smsCode: {
143     mobile: '',
144     scene: 21
145   },
146   loginSms: {
147     mobile: '',
148     code: ''
149   }
150 })
151 const mobileCodeTimer = ref(0)
152 const redirect = ref<string>('')
153 const getSmsCode = async () => {
154   await getTenantId()
155   smsVO.smsCode.mobile = loginData.loginForm.mobileNumber
156   await sendSmsCode(smsVO.smsCode).then(async () => {
157     message.success(t('login.SmsSendMsg'))
158     // 设置倒计时
159     mobileCodeTimer.value = 60
160     let msgTimer = setInterval(() => {
161       mobileCodeTimer.value = mobileCodeTimer.value - 1
162       if (mobileCodeTimer.value <= 0) {
163         clearInterval(msgTimer)
164       }
165     }, 1000)
166   })
167 }
168 watch(
169   () => currentRoute.value,
170   (route: RouteLocationNormalizedLoaded) => {
171     redirect.value = route?.query?.redirect as string
172   },
173   {
174     immediate: true
175   }
176 )
177 // 获取租户 ID
178 const getTenantId = async () => {
179   if (loginData.tenantEnable === 'true') {
180     const res = await getTenantIdByName(loginData.loginForm.tenantName)
181     setTenantId(res)
182   }
183 }
184 // 登录
185 const signIn = async () => {
186   await getTenantId()
187   const data = await validForm()
188   if (!data) return
189   ElLoading.service({
190     lock: true,
191     text: '正在加载系统中...',
192     background: 'rgba(0, 0, 0, 0.7)'
193   })
194   loginLoading.value = true
195   smsVO.loginSms.mobile = loginData.loginForm.mobileNumber
196   smsVO.loginSms.code = loginData.loginForm.code
197   await smsLogin(smsVO.loginSms)
198     .then(async (res) => {
199       setToken(res)
200       if (!redirect.value) {
201         redirect.value = '/'
202       }
203       push({ path: redirect.value || permissionStore.addRouters[0].path })
204     })
205     .catch(() => {})
206     .finally(() => {
207       loginLoading.value = false
208       setTimeout(() => {
209         const loadingInstance = ElLoading.service()
210         loadingInstance.close()
211       }, 400)
212     })
213 }
214 </script>
215
216 <style lang="scss" scoped>
217 :deep(.anticon) {
218   &:hover {
219     color: var(--el-color-primary) !important;
220   }
221 }
222
223 .smsbtn {
224   margin-top: 33px;
225 }
226 </style>