重构:重构登录页面前端代码
This commit is contained in:
parent
d035d5a362
commit
35e2964b49
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user