mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-11 16:57:12 +08:00
feat: 支持邮箱登录
在个人中心-安全设置中绑定邮箱后,才支持邮箱登录
This commit is contained in:
@@ -6,7 +6,6 @@ const BASE_URL = '/auth';
|
||||
|
||||
export interface LoginReq {
|
||||
phone?: string;
|
||||
email?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
captcha: string;
|
||||
@@ -17,8 +16,17 @@ export interface LoginRes {
|
||||
token: string;
|
||||
}
|
||||
|
||||
export function login(req: LoginReq) {
|
||||
return axios.post<LoginRes>(`${BASE_URL}/login`, req);
|
||||
export function accountLogin(req: LoginReq) {
|
||||
return axios.post<LoginRes>(`${BASE_URL}/account`, req);
|
||||
}
|
||||
|
||||
export interface EmailLoginReq {
|
||||
email: string;
|
||||
captcha: string;
|
||||
}
|
||||
|
||||
export function emailLogin(req: EmailLoginReq) {
|
||||
return axios.post<LoginRes>(`${BASE_URL}/email`, req);
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
@@ -34,9 +42,9 @@ export function listRoute() {
|
||||
}
|
||||
|
||||
export function socialAuth(source: string) {
|
||||
return axios.get<string>(`${BASE_URL}/${source}`);
|
||||
return axios.get<string>(`/oauth/${source}`);
|
||||
}
|
||||
|
||||
export function socialLogin(source: string, req: any) {
|
||||
return axios.post<LoginRes>(`${BASE_URL}/${source}`, req);
|
||||
return axios.post<LoginRes>(`/oauth/${source}`, req);
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import {
|
||||
login as userLogin,
|
||||
LoginReq,
|
||||
EmailLoginReq,
|
||||
accountLogin as userAccountLogin,
|
||||
emailLogin as userEmailLogin,
|
||||
socialLogin as userSocialLogin,
|
||||
logout as userLogout,
|
||||
getUserInfo,
|
||||
LoginReq,
|
||||
} from '@/api/auth/login';
|
||||
import { getImageCaptcha as getCaptcha } from '@/api/common/captcha';
|
||||
import { setToken, clearToken } from '@/utils/auth';
|
||||
@@ -42,10 +44,21 @@ const useUserStore = defineStore('user', {
|
||||
return getCaptcha();
|
||||
},
|
||||
|
||||
// 用户登录
|
||||
async login(req: LoginReq) {
|
||||
// 账号登录
|
||||
async accountLogin(req: LoginReq) {
|
||||
try {
|
||||
const res = await userLogin(req);
|
||||
const res = await userAccountLogin(req);
|
||||
setToken(res.data.token);
|
||||
} catch (err) {
|
||||
clearToken();
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
// 邮箱登录
|
||||
async emailLogin(req: EmailLoginReq) {
|
||||
try {
|
||||
const res = await userEmailLogin(req);
|
||||
setToken(res.data.token);
|
||||
} catch (err) {
|
||||
clearToken();
|
||||
|
@@ -124,7 +124,7 @@
|
||||
if (!errors) {
|
||||
loading.value = true;
|
||||
userStore
|
||||
.login({
|
||||
.accountLogin({
|
||||
username: values.username,
|
||||
password: encryptByRsa(values.password) || '',
|
||||
captcha: values.captcha,
|
||||
|
@@ -6,6 +6,7 @@
|
||||
layout="vertical"
|
||||
size="large"
|
||||
class="login-form"
|
||||
@submit="handleLogin"
|
||||
>
|
||||
<a-form-item field="email" hide-label>
|
||||
<a-input
|
||||
@@ -32,7 +33,7 @@
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
<a-button class="btn" :loading="loading" type="primary" html-type="submit"
|
||||
>{{ $t('login.button') }}(即将开放)
|
||||
>{{ $t('login.button') }}
|
||||
</a-button>
|
||||
</a-form>
|
||||
</template>
|
||||
@@ -40,11 +41,15 @@
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, ref, toRefs, reactive, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ValidatedError } from '@arco-design/web-vue';
|
||||
import { useUserStore } from '@/store';
|
||||
import { LoginReq } from '@/api/auth/login';
|
||||
import { EmailLoginReq } from '@/api/auth/login';
|
||||
import { getMailCaptcha } from '@/api/common/captcha';
|
||||
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const loading = ref(false);
|
||||
const captchaLoading = ref(false);
|
||||
@@ -54,7 +59,10 @@
|
||||
const captchaBtnNameKey = ref('login.captcha.get');
|
||||
const captchaBtnName = computed(() => t(captchaBtnNameKey.value));
|
||||
const data = reactive({
|
||||
form: {} as LoginReq,
|
||||
form: {
|
||||
email: '',
|
||||
captcha: '',
|
||||
} as EmailLoginReq,
|
||||
rules: {
|
||||
email: [
|
||||
{ required: true, message: t('login.email.error.required.email') },
|
||||
@@ -85,26 +93,76 @@
|
||||
if (!valid) {
|
||||
captchaLoading.value = true;
|
||||
captchaBtnNameKey.value = 'login.captcha.ing';
|
||||
captchaLoading.value = false;
|
||||
captchaDisable.value = true;
|
||||
captchaBtnNameKey.value = `${t(
|
||||
'login.captcha.get'
|
||||
)}(${(captchaTime.value -= 1)}s)`;
|
||||
captchaTimer.value = window.setInterval(() => {
|
||||
captchaTime.value -= 1;
|
||||
captchaBtnNameKey.value = `${t('login.captcha.get')}(${
|
||||
captchaTime.value
|
||||
}s)`;
|
||||
if (captchaTime.value < 0) {
|
||||
window.clearInterval(captchaTimer.value);
|
||||
captchaTime.value = 60;
|
||||
captchaBtnNameKey.value = t('login.captcha.get');
|
||||
captchaDisable.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
getMailCaptcha({
|
||||
email: form.value.email,
|
||||
})
|
||||
.then((res) => {
|
||||
captchaLoading.value = false;
|
||||
captchaDisable.value = true;
|
||||
captchaBtnNameKey.value = `${t(
|
||||
'login.captcha.get'
|
||||
)}(${(captchaTime.value -= 1)}s)`;
|
||||
captchaTimer.value = window.setInterval(() => {
|
||||
captchaTime.value -= 1;
|
||||
captchaBtnNameKey.value = `${t('login.captcha.get')}(${
|
||||
captchaTime.value
|
||||
}s)`;
|
||||
if (captchaTime.value <= 0) {
|
||||
window.clearInterval(captchaTimer.value);
|
||||
captchaTime.value = 60;
|
||||
captchaBtnNameKey.value = t('login.captcha.get');
|
||||
captchaDisable.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
proxy.$message.success(res.msg);
|
||||
})
|
||||
.catch(() => {
|
||||
resetCaptcha();
|
||||
captchaLoading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param errors 表单验证错误
|
||||
* @param values 表单数据
|
||||
*/
|
||||
const handleLogin = ({
|
||||
errors,
|
||||
values,
|
||||
}: {
|
||||
errors: Record<string, ValidatedError> | undefined;
|
||||
values: Record<string, any>;
|
||||
}) => {
|
||||
if (loading.value) return;
|
||||
if (!errors) {
|
||||
loading.value = true;
|
||||
userStore
|
||||
.emailLogin({
|
||||
email: values.email,
|
||||
captcha: values.captcha,
|
||||
})
|
||||
.then(() => {
|
||||
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
||||
router.push({
|
||||
name: (redirect as string) || 'Workplace',
|
||||
query: {
|
||||
...othersQuery,
|
||||
},
|
||||
});
|
||||
proxy.$notification.success(t('login.success'));
|
||||
})
|
||||
.catch(() => {
|
||||
form.value.captcha = '';
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@@ -77,7 +77,7 @@ export default {
|
||||
// update-email
|
||||
'userCenter.securitySettings.email.label': 'Email',
|
||||
'userCenter.securitySettings.email.tip':
|
||||
'Used to receive messages, verify identity',
|
||||
'It is used to receive messages, verify identity, and support email login after binding',
|
||||
'userCenter.securitySettings.email.content': 'Unbound',
|
||||
|
||||
'userCenter.securitySettings.updateEmail.modal.title': 'Update email',
|
||||
|
@@ -72,7 +72,8 @@ export default {
|
||||
|
||||
// update-email
|
||||
'userCenter.securitySettings.email.label': '安全邮箱',
|
||||
'userCenter.securitySettings.email.tip': '用于接收消息、验证身份',
|
||||
'userCenter.securitySettings.email.tip':
|
||||
'用于接收消息、验证身份,绑定后可支持邮箱登录',
|
||||
'userCenter.securitySettings.email.content': '未绑定',
|
||||
|
||||
'userCenter.securitySettings.updateEmail.modal.title': '修改邮箱',
|
||||
|
Reference in New Issue
Block a user