mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	重构:重构登录页面前端代码
This commit is contained in:
		| @@ -2,25 +2,29 @@ import axios from 'axios'; | |||||||
| import type { RouteRecordNormalized } from 'vue-router'; | import type { RouteRecordNormalized } from 'vue-router'; | ||||||
| import { UserState } from '@/store/modules/login/types'; | import { UserState } from '@/store/modules/login/types'; | ||||||
|  |  | ||||||
|  | const BASE_URL = '/auth'; | ||||||
|  |  | ||||||
| export interface LoginReq { | export interface LoginReq { | ||||||
|   username: string; |   username: string; | ||||||
|   password: string; |   password: string; | ||||||
|   captcha: string; |   captcha: string; | ||||||
|   uuid: string; |   uuid: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface LoginRes { | export interface LoginRes { | ||||||
|   token: string; |   token: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function login(req: LoginReq) { | export function login(req: LoginReq) { | ||||||
|   return axios.post<LoginRes>('/auth/login', req); |   return axios.post<LoginRes>(`${BASE_URL}/login`, req); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function logout() { | export function logout() { | ||||||
|   return axios.post('/auth/logout'); |   return axios.post(`${BASE_URL}/logout`); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function getUserInfo() { | export function getUserInfo() { | ||||||
|   return axios.get<UserState>('/auth/user/info'); |   return axios.get<UserState>(`${BASE_URL}/user/info`); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function getMenuList() { | export function getMenuList() { | ||||||
|   | |||||||
| @@ -2,66 +2,46 @@ | |||||||
|   <div class="login-form-wrapper"> |   <div class="login-form-wrapper"> | ||||||
|     <div class="login-form-title">{{ $t('login.form.title') }}</div> |     <div class="login-form-title">{{ $t('login.form.title') }}</div> | ||||||
|     <div class="login-form-sub-title">{{ $t('login.form.subTitle') }}</div> |     <div class="login-form-sub-title">{{ $t('login.form.subTitle') }}</div> | ||||||
|     <div class="login-form-error-msg">{{ errorMessage }}</div> |  | ||||||
|     <a-form |     <a-form | ||||||
|       ref="formRef" |       ref="formRef" | ||||||
|       :model="formData" |       :model="form" | ||||||
|       :rules="rules" |       :rules="rules" | ||||||
|       class="login-form" |  | ||||||
|       layout="vertical" |       layout="vertical" | ||||||
|  |       class="login-form" | ||||||
|       @submit="handleLogin" |       @submit="handleLogin" | ||||||
|     > |     > | ||||||
|       <a-form-item |       <a-form-item field="username" hide-label> | ||||||
|         field="username" |  | ||||||
|         :validate-trigger="['change', 'blur']" |  | ||||||
|         hide-label |  | ||||||
|       > |  | ||||||
|         <a-input |         <a-input | ||||||
|           v-model="formData.username" |           v-model="form.username" | ||||||
|           :placeholder="$t('login.form.placeholder.username')" |           :placeholder="$t('login.form.placeholder.username')" | ||||||
|           size="large" |  | ||||||
|           max-length="50" |           max-length="50" | ||||||
|  |           size="large" | ||||||
|         > |         > | ||||||
|           <template #prefix> |           <template #prefix><icon-user /></template> | ||||||
|             <icon-user /> |  | ||||||
|           </template> |  | ||||||
|         </a-input> |         </a-input> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item |       <a-form-item field="password" hide-label> | ||||||
|         field="password" |  | ||||||
|         :validate-trigger="['change', 'blur']" |  | ||||||
|         hide-label |  | ||||||
|       > |  | ||||||
|         <a-input-password |         <a-input-password | ||||||
|           v-model="formData.password" |           v-model="form.password" | ||||||
|           :placeholder="$t('login.form.placeholder.password')" |           :placeholder="$t('login.form.placeholder.password')" | ||||||
|           size="large" |  | ||||||
|           allow-clear |  | ||||||
|           max-length="32" |           max-length="32" | ||||||
|  |           allow-clear | ||||||
|  |           size="large" | ||||||
|         > |         > | ||||||
|           <template #prefix> |           <template #prefix><icon-lock /></template> | ||||||
|             <icon-lock /> |  | ||||||
|           </template> |  | ||||||
|         </a-input-password> |         </a-input-password> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-form-item |       <a-form-item class="login-form-captcha" field="captcha" hide-label> | ||||||
|         class="login-form-captcha" |  | ||||||
|         field="captcha" |  | ||||||
|         :validate-trigger="['change', 'blur']" |  | ||||||
|         hide-label |  | ||||||
|       > |  | ||||||
|         <a-input |         <a-input | ||||||
|           v-model="formData.captcha" |           v-model="form.captcha" | ||||||
|           :placeholder="$t('login.form.placeholder.captcha')" |           :placeholder="$t('login.form.placeholder.captcha')" | ||||||
|  |           allow-clear | ||||||
|           size="large" |           size="large" | ||||||
|           style="width: 63%" |           style="width: 63%" | ||||||
|           allow-clear |  | ||||||
|         > |         > | ||||||
|           <template #prefix> |           <template #prefix><icon-check-circle /></template> | ||||||
|             <icon-check-circle /> |  | ||||||
|           </template> |  | ||||||
|         </a-input> |         </a-input> | ||||||
|         <img :src="captchaImgBase64" @click="getCaptcha" :alt="$t('login.form.captcha')"> |         <img :src="captchaImgBase64" :alt="$t('login.form.captcha')" @click="getCaptcha"> | ||||||
|       </a-form-item> |       </a-form-item> | ||||||
|       <a-space :size="16" direction="vertical"> |       <a-space :size="16" direction="vertical"> | ||||||
|         <div class="login-form-remember-me"> |         <div class="login-form-remember-me"> | ||||||
| @@ -73,7 +53,7 @@ | |||||||
|             {{ $t('login.form.rememberMe') }} |             {{ $t('login.form.rememberMe') }} | ||||||
|           </a-checkbox> |           </a-checkbox> | ||||||
|         </div> |         </div> | ||||||
|         <a-button type="primary" size="large" html-type="submit" long :loading="loading"> |         <a-button :loading="loading" type="primary" size="large" long html-type="submit"> | ||||||
|           {{ $t('login.form.login') }} |           {{ $t('login.form.login') }} | ||||||
|         </a-button> |         </a-button> | ||||||
|       </a-space> |       </a-space> | ||||||
| @@ -82,23 +62,23 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
|   import { ref, reactive, computed, onMounted } from 'vue'; | import { getCurrentInstance, ref, toRefs, reactive, computed } from "vue"; | ||||||
|   import { useRouter } from 'vue-router'; |   import { FieldRule, ValidatedError } from '@arco-design/web-vue'; | ||||||
|   import { FieldRule, Message } from '@arco-design/web-vue'; |   import { LoginReq } from '@/api/auth/login'; | ||||||
|   import { ValidatedError } from '@arco-design/web-vue/es/form/interface'; |  | ||||||
|   import { useI18n } from 'vue-i18n'; |   import { useI18n } from 'vue-i18n'; | ||||||
|   // import debug from '@/utils/env'; |   import { useRouter } from 'vue-router'; | ||||||
|   import { encryptByRsa } from '@/utils/encrypt'; |  | ||||||
|   import { useStorage } from '@vueuse/core'; |   import { useStorage } from '@vueuse/core'; | ||||||
|   import { useLoginStore } from '@/store'; |   import { useLoginStore } from '@/store'; | ||||||
|   import useLoading from '@/hooks/loading'; |   import { encryptByRsa } from '@/utils/encrypt'; | ||||||
|  |   // import debug from '@/utils/env'; | ||||||
|  |  | ||||||
|  |   const { proxy } = getCurrentInstance() as any; | ||||||
|  |  | ||||||
|  |   const captchaImgBase64 = ref(''); | ||||||
|  |   const loginStore = useLoginStore(); | ||||||
|  |   const loading = ref(false); | ||||||
|   const { t } = useI18n(); |   const { t } = useI18n(); | ||||||
|   const router = useRouter(); |   const router = useRouter(); | ||||||
|   const { loading, setLoading } = useLoading(); |  | ||||||
|   const loginStore = useLoginStore(); |  | ||||||
|   const errorMessage = ref(''); |  | ||||||
|   const captchaImgBase64 = ref(''); |  | ||||||
|   const loginConfig = useStorage('login-config', { |   const loginConfig = useStorage('login-config', { | ||||||
|     rememberMe: true, |     rememberMe: true, | ||||||
|     username: 'admin', // 演示默认值 |     username: 'admin', // 演示默认值 | ||||||
| @@ -106,59 +86,56 @@ | |||||||
|     // username: !debug ? '' : 'admin', // 演示默认值 |     // username: !debug ? '' : 'admin', // 演示默认值 | ||||||
|     // password: !debug ? '' : 'admin123', // 演示默认值 |     // password: !debug ? '' : 'admin123', // 演示默认值 | ||||||
|   }); |   }); | ||||||
|   const formData = reactive({ |  | ||||||
|  |   const data = reactive({ | ||||||
|  |     // 表单数据 | ||||||
|  |     form: { | ||||||
|       username: loginConfig.value.username, |       username: loginConfig.value.username, | ||||||
|       password: loginConfig.value.password, |       password: loginConfig.value.password, | ||||||
|       captcha: '', |       captcha: '', | ||||||
|       uuid: '', |       uuid: '', | ||||||
|   }); |     } as LoginReq, | ||||||
|   const rules = computed((): Record<string, FieldRule[]> => { |     // 表单验证规则 | ||||||
|  |     rules: computed((): Record<string, FieldRule[]> => { | ||||||
|       return { |       return { | ||||||
|       username: [ |         username: [{ required: true, message: t('login.form.error.required.username') }], | ||||||
|         { required: true, message: t('login.form.error.required.username') } |         password: [{ required: true, message: t('login.form.error.required.password') }], | ||||||
|       ], |         captcha: [{ required: true, message: t('login.form.error.required.captcha') }], | ||||||
|       password: [ |  | ||||||
|         { required: true, message: t('login.form.error.required.password') } |  | ||||||
|       ], |  | ||||||
|       captcha: [ |  | ||||||
|         { required: true, message: t('login.form.error.required.captcha') } |  | ||||||
|       ], |  | ||||||
|       } |       } | ||||||
|  |     }), | ||||||
|   }); |   }); | ||||||
|  |   const { form, rules } = toRefs(data); | ||||||
|  |  | ||||||
|   // 获取验证码 |   /** | ||||||
|   const getCaptcha = async () => { |    * 获取验证码 | ||||||
|     const { data } = await loginStore.getImgCaptcha() |    */ | ||||||
|     formData.uuid = data.uuid |   const getCaptcha = () => { | ||||||
|     captchaImgBase64.value = data.img |     loginStore.getImgCaptcha().then((res) => { | ||||||
|   } |       form.value.uuid = res.data.uuid; | ||||||
|   onMounted(() => { |       captchaImgBase64.value = res.data.img; | ||||||
|     getCaptcha(); |     }); | ||||||
|   }) |  | ||||||
|  |  | ||||||
|   // 记住我 |  | ||||||
|   const setRememberMe = (value: boolean) => { |  | ||||||
|     loginConfig.value.rememberMe = value; |  | ||||||
|   }; |   }; | ||||||
|  |   getCaptcha(); | ||||||
|  |  | ||||||
|   // 登录处理 |   /** | ||||||
|   const handleLogin = async ({ |    * 登录 | ||||||
|     errors, |    * | ||||||
|     values, |    * @param errors 表单验证错误 | ||||||
|   }: { |    * @param values 表单数据 | ||||||
|  |    */ | ||||||
|  |   const handleLogin = ({ errors, values, }: { | ||||||
|     errors: Record<string, ValidatedError> | undefined; |     errors: Record<string, ValidatedError> | undefined; | ||||||
|     values: Record<string, any>; |     values: Record<string, any>; | ||||||
|   }) => { |   }) => { | ||||||
|     if (loading.value) return; |     if (loading.value) return; | ||||||
|     if (!errors) { |     if (!errors) { | ||||||
|       setLoading(true); |       loading.value = true; | ||||||
|       try { |       loginStore.login({ | ||||||
|         await loginStore.login({ |  | ||||||
|         username: values.username, |         username: values.username, | ||||||
|         password: encryptByRsa(values.password) || '', |         password: encryptByRsa(values.password) || '', | ||||||
|         captcha: values.captcha, |         captcha: values.captcha, | ||||||
|         uuid: values.uuid |         uuid: values.uuid | ||||||
|         }); |       }).then(() => { | ||||||
|         const { redirect, ...othersQuery } = router.currentRoute.value.query; |         const { redirect, ...othersQuery } = router.currentRoute.value.query; | ||||||
|         router.push({ |         router.push({ | ||||||
|           name: (redirect as string) || 'Workplace', |           name: (redirect as string) || 'Workplace', | ||||||
| @@ -166,21 +143,32 @@ | |||||||
|             ...othersQuery, |             ...othersQuery, | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
|         Message.success(t('login.form.login.success')); |  | ||||||
|         const { rememberMe } = loginConfig.value; |         const { rememberMe } = loginConfig.value; | ||||||
|         const { username } = values; |         const { username } = values; | ||||||
|         loginConfig.value.username = rememberMe ? username : ''; |         loginConfig.value.username = rememberMe ? username : ''; | ||||||
|       } catch (err) { |         proxy.$message.success(t('login.form.login.success')); | ||||||
|         await getCaptcha(); |       }).catch(() => { | ||||||
|       } finally { |         getCaptcha(); | ||||||
|         setLoading(false); |       }).finally(() => { | ||||||
|       } |         loading.value = false; | ||||||
|  |       }); | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * 记住我 | ||||||
|  |    * | ||||||
|  |    * @param value 是否记住我 | ||||||
|  |    */ | ||||||
|  |   const setRememberMe = (value: boolean) => { | ||||||
|  |     loginConfig.value.rememberMe = value; | ||||||
|  |   }; | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="less" scoped> | <style lang="less" scoped> | ||||||
|   .login-form { |   .login-form { | ||||||
|  |     margin-top: 32px; | ||||||
|  |  | ||||||
|     &-wrapper { |     &-wrapper { | ||||||
|       width: 320px; |       width: 320px; | ||||||
|     } |     } | ||||||
| @@ -198,12 +186,6 @@ | |||||||
|       line-height: 24px; |       line-height: 24px; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     &-error-msg { |  | ||||||
|       height: 32px; |  | ||||||
|       color: rgb(var(--red-6)); |  | ||||||
|       line-height: 32px; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     &-captcha img { |     &-captcha img { | ||||||
|       width: 111px; |       width: 111px; | ||||||
|       height: 36px; |       height: 36px; | ||||||
|   | |||||||
| @@ -1,10 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="container"> |   <div class="container"> | ||||||
|     <div class="logo"> |     <div class="logo"> | ||||||
|       <img |       <img src="/logo.svg" alt="logo" /> | ||||||
|         alt="logo" |  | ||||||
|         src="/logo.svg" |  | ||||||
|       /> |  | ||||||
|       <div class="logo-text">{{ $t('title') }}</div> |       <div class="logo-text">{{ $t('title') }}</div> | ||||||
|     </div> |     </div> | ||||||
|     <LoginBanner /> |     <LoginBanner /> | ||||||
| @@ -67,9 +64,7 @@ | |||||||
|       font-size: 20px; |       font-size: 20px; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| </style> |  | ||||||
|  |  | ||||||
| <style lang="less" scoped> |  | ||||||
|   @media (max-width: @screen-lg) { |   @media (max-width: @screen-lg) { | ||||||
|     .container { |     .container { | ||||||
|       .banner { |       .banner { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user