2024-02-22 10:23:38 +08:00
|
|
|
<template>
|
|
|
|
|
<Form v-show="getShow" ref="formRef" :model="formData" :rules="getFormRules" class="p-4 enter-x form-box" @keypress.enter="handleLogin">
|
|
|
|
|
<div>
|
|
|
|
|
<FormItem class="enter-x" name="account">
|
|
|
|
|
<label class="form-title"> {{ t('账号') }}</label>
|
|
|
|
|
<Input v-model:value="formData.account" :placeholder="t('账号')" class="fix-auto-fill" size="large" style="height: 58px">
|
|
|
|
|
<template #prefix>
|
|
|
|
|
<IconFontSymbol class="user-icon" icon="yonghu-xianxing" />
|
|
|
|
|
</template>
|
|
|
|
|
</Input>
|
|
|
|
|
</FormItem>
|
|
|
|
|
<FormItem class="enter-x" name="password">
|
|
|
|
|
<label class="form-title"> {{ t('密码') }}</label>
|
|
|
|
|
<InputPassword v-model:value="formData.password" :placeholder="t('密码')" size="large" style="height: 58px" visibilityToggle>
|
|
|
|
|
<template #prefix>
|
|
|
|
|
<IconFontSymbol class="user-icon" icon="mima" />
|
|
|
|
|
</template>
|
|
|
|
|
</InputPassword>
|
|
|
|
|
</FormItem>
|
|
|
|
|
|
2024-07-19 17:47:11 +08:00
|
|
|
<FormItem v-if="getAppEnvConfig().VITE_TENANT_ENABLED" name="tenantCode" class="enter-x">
|
|
|
|
|
<label class="form-title"> {{ t('租户码') }}</label>
|
|
|
|
|
<Input
|
|
|
|
|
size="large"
|
|
|
|
|
visibilityToggle
|
|
|
|
|
v-model:value="formData.tenantCode"
|
|
|
|
|
:placeholder="t('租户码')"
|
|
|
|
|
style="height: 58px"
|
|
|
|
|
>
|
|
|
|
|
<template #prefix>
|
|
|
|
|
<IconFontSymbol icon="zuzhiguanli" class="user-icon" />
|
|
|
|
|
</template>
|
|
|
|
|
</Input>
|
|
|
|
|
</FormItem>
|
2024-02-22 10:23:38 +08:00
|
|
|
<ARow class="enter-x">
|
|
|
|
|
<ACol :span="12">
|
|
|
|
|
<FormItem>
|
|
|
|
|
<!-- No logic, you need to deal with it yourself -->
|
|
|
|
|
<Checkbox v-model:checked="rememberMe" class="f-16" size="small">
|
|
|
|
|
{{ t('记住我') }}
|
|
|
|
|
</Checkbox>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</ACol>
|
|
|
|
|
<!-- <ACol :span="12">
|
|
|
|
|
<FormItem :style="{ 'text-align': 'right' }">
|
|
|
|
|
No logic, you need to deal with it yourself
|
|
|
|
|
<Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
|
|
|
|
|
{{ t('忘记密码?') }}
|
|
|
|
|
</Button>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</ACol> -->
|
|
|
|
|
</ARow>
|
|
|
|
|
|
|
|
|
|
<FormItem class="enter-x">
|
2024-02-22 20:23:43 +08:00
|
|
|
<Button :loading="loading" :style="{ 'border-radius': '8px' }" block class="sub-button" type="primary" @click="handleLogin">
|
2024-02-22 10:23:38 +08:00
|
|
|
{{ t('登录') }}
|
|
|
|
|
</Button>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</div>
|
|
|
|
|
</Form>
|
|
|
|
|
</template>
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import { reactive, ref, unref, computed, onMounted } from 'vue';
|
|
|
|
|
import { Checkbox, Form, Input, Row, Col, Button } from 'ant-design-vue';
|
|
|
|
|
|
|
|
|
|
import { useI18n } from '/@/hooks/web/useI18n';
|
|
|
|
|
import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
|
|
|
|
|
|
|
import { useUserStore } from '/@/store/modules/user';
|
|
|
|
|
import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from '/@/views/sys/login/useLogin';
|
|
|
|
|
import { useDesign } from '/@/hooks/web/useDesign';
|
|
|
|
|
import { Base64 } from 'js-base64';
|
|
|
|
|
|
|
|
|
|
import IconFontSymbol from '/@/components/IconFontSymbol/Index.vue';
|
|
|
|
|
import { useRouter } from 'vue-router';
|
2024-07-19 17:47:11 +08:00
|
|
|
import { getAppEnvConfig } from '/@/utils/env';
|
2024-02-22 10:23:38 +08:00
|
|
|
|
|
|
|
|
const ACol = Col;
|
|
|
|
|
const ARow = Row;
|
|
|
|
|
const FormItem = Form.Item;
|
|
|
|
|
const InputPassword = Input.Password;
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
const { notification, createErrorModal } = useMessage();
|
|
|
|
|
const { prefixCls } = useDesign('login');
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
|
|
const { currentRoute } = useRouter();
|
|
|
|
|
|
|
|
|
|
const { getLoginState } = useLoginState();
|
|
|
|
|
const { getFormRules } = useFormRules();
|
|
|
|
|
|
|
|
|
|
const formRef = ref();
|
|
|
|
|
// const iframeRef = ref();
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
const rememberMe = ref(false);
|
|
|
|
|
|
|
|
|
|
const formData = reactive({
|
2024-10-25 11:20:38 +08:00
|
|
|
account: '',
|
|
|
|
|
password: '',
|
2024-07-19 17:47:11 +08:00
|
|
|
tenantCode: 'system'
|
2024-02-22 10:23:38 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
//如果是第三方登录跳转回来 会携带token
|
|
|
|
|
if (currentRoute.value.query.token) {
|
|
|
|
|
try {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
const userInfo = await userStore.oauthLogin({
|
|
|
|
|
token: currentRoute.value.query.token as string,
|
|
|
|
|
mode: 'none' //不要默认的错误提示
|
|
|
|
|
});
|
|
|
|
|
if (userInfo) {
|
|
|
|
|
notification.success({
|
|
|
|
|
message: t('登录成功'),
|
|
|
|
|
description: `${t('欢迎回来')}: ${userInfo.name}`,
|
|
|
|
|
duration: 3
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
createErrorModal({
|
|
|
|
|
title: t('错误提示'),
|
|
|
|
|
content: (error as unknown as Error).message || t('网络异常,请检查您的网络连接是否正常!'),
|
|
|
|
|
getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body
|
|
|
|
|
});
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//如果第三方登录 登录错误 会携带错误信息
|
|
|
|
|
if (currentRoute.value.query.error) {
|
|
|
|
|
createErrorModal({
|
|
|
|
|
title: t('错误提示'),
|
|
|
|
|
content: t(currentRoute.value.query.error as string),
|
|
|
|
|
getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
const loginInfo = window.localStorage.getItem('USER__LOGIN__INFO__');
|
|
|
|
|
if (loginInfo) {
|
|
|
|
|
formData.account = Base64.decode(JSON.parse(loginInfo).account);
|
|
|
|
|
formData.password = Base64.decode(JSON.parse(loginInfo).password);
|
2024-07-19 17:47:11 +08:00
|
|
|
formData.tenantCode = Base64.decode(JSON.parse(loginInfo).tenantCode);
|
2024-02-22 10:23:38 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { validForm } = useFormValid(formRef);
|
|
|
|
|
|
|
|
|
|
//onKeyStroke('Enter', handleLogin);
|
|
|
|
|
|
|
|
|
|
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
|
|
|
|
|
|
|
|
|
|
async function handleLogin() {
|
|
|
|
|
const data = await validForm();
|
|
|
|
|
if (!data) return;
|
|
|
|
|
try {
|
|
|
|
|
loading.value = true;
|
|
|
|
|
const userInfo = await userStore.login({
|
|
|
|
|
password: data.password,
|
|
|
|
|
userName: data.account,
|
2024-07-19 17:47:11 +08:00
|
|
|
tenantCode: data.tenantCode,
|
2024-02-22 10:23:38 +08:00
|
|
|
deviceType: 0, //pc-0,app-1
|
|
|
|
|
mode: 'none' //不要默认的错误提示
|
|
|
|
|
});
|
|
|
|
|
if (userInfo) {
|
|
|
|
|
notification.success({
|
|
|
|
|
message: t('登录成功'),
|
|
|
|
|
description: `${t('欢迎回来')}: ${userInfo.name}`,
|
|
|
|
|
duration: 3
|
|
|
|
|
});
|
|
|
|
|
if (rememberMe.value) {
|
|
|
|
|
const info = {
|
|
|
|
|
account: Base64.encode(data.account),
|
2024-07-19 17:47:11 +08:00
|
|
|
password: Base64.encode(data.password),
|
|
|
|
|
tenantCode: Base64.encode(data.tenantCode)
|
2024-02-22 10:23:38 +08:00
|
|
|
};
|
|
|
|
|
window.localStorage.setItem('USER__LOGIN__INFO__', JSON.stringify(info));
|
|
|
|
|
} else {
|
|
|
|
|
window.localStorage.removeItem('USER__LOGIN__INFO__');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
createErrorModal({
|
|
|
|
|
title: t('错误提示'),
|
|
|
|
|
content: (error as unknown as Error).message || t('网络异常,请检查您的网络连接是否正常!'),
|
|
|
|
|
getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body
|
|
|
|
|
});
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
.form-box {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.f-16 {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.ant-checkbox-inner) {
|
|
|
|
|
border-color: #ced5f2;
|
|
|
|
|
width: 18px;
|
|
|
|
|
height: 18px;
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.ant-form-item input[type='checkbox']) {
|
|
|
|
|
width: 18px;
|
|
|
|
|
height: 18px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-title {
|
|
|
|
|
line-height: 40px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sub-button {
|
2024-02-22 20:23:43 +08:00
|
|
|
height: 48px;
|
2024-02-22 10:23:38 +08:00
|
|
|
font-size: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ant-form label {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.user-icon {
|
|
|
|
|
font-size: 26px;
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
color: #707c92;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ant-input-affix-wrapper {
|
|
|
|
|
border-color: #ced5f2;
|
|
|
|
|
border-style: none none solid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.ant-input-password-icon) {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
color: #707c92;
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.ant-input-affix-wrapper-lg) {
|
|
|
|
|
padding-left: 0;
|
|
|
|
|
}
|
|
|
|
|
</style>
|