登录注册

This commit is contained in:
陈红丽 2024-08-16 12:46:20 +08:00
parent 7f2bdf6279
commit 5b9d5ec1b3
5 changed files with 531 additions and 147 deletions

View File

@ -11,7 +11,7 @@
<el-input v-model="formInline.username" placeholder="请输入登录账号"> <el-input v-model="formInline.username" placeholder="请输入登录账号">
<template #prefix> <template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695"> <el-icon class="el-input__icon" size="18" color="#808695">
<User /> <PersonOutline />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
@ -67,6 +67,18 @@
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="flex items-center justify-between">
<div class="flex items-center">
<span>其他登录方式</span>
<el-icon class="el-input__icon" size="22" color="#165DFF" style="margin:0 10px 0 10px;cursor: pointer;">
<GithubFilled />
</el-icon>
<el-icon class="el-input__icon" size="22" color="#165DFF" style="cursor: pointer;">
<AlipayCircleFilled />
</el-icon>
</div>
<div style="cursor: pointer;" @click="goRegister">注册账号</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -77,7 +89,8 @@
import { ResultEnum } from '@/enums/httpEnum'; import { ResultEnum } from '@/enums/httpEnum';
import {getInfoCaptcha} from '@/api/system/user'; import {getInfoCaptcha} from '@/api/system/user';
import { PageEnum } from '@/enums/pageEnum'; import { PageEnum } from '@/enums/pageEnum';
import { SafetyCertificateOutlined } from '@vicons/antd'; import { PersonOutline } from '@vicons/ionicons5';
import { SafetyCertificateOutlined,GithubFilled,AlipayCircleFilled } from '@vicons/antd';
const captchaImg=ref('') const captchaImg=ref('')
// //
@ -88,6 +101,7 @@
key:string; key:string;
} }
const emit = defineEmits(['backLogin']);
const formRef = ref(); const formRef = ref();
const loading = ref(false); const loading = ref(false);
@ -102,7 +116,7 @@
}); });
const rules = { const rules = {
username: { required: true, message: '请输入用户名', trigger: 'blur' }, username: { required: true, message: '请输入登录账号', trigger: 'blur' },
password: { required: true, message: '请输入密码', trigger: 'blur' }, password: { required: true, message: '请输入密码', trigger: 'blur' },
code: { required: true, message: '请输入验证码', trigger: 'blur' } code: { required: true, message: '请输入验证码', trigger: 'blur' }
}; };
@ -152,6 +166,9 @@
formInline.key=key formInline.key=key
captchaImg.value=captcha captchaImg.value=captcha
} }
const goRegister =()=>{
emit('backLogin',false);
}
getCaptcha() getCaptcha()

View File

@ -0,0 +1,154 @@
<template>
<el-form ref="formRef" :show-label="false" :show-require-mark="false" size="large" :model="formInline" :rules="rules">
<el-form-item prop="mobile">
<el-input v-model="formInline.mobile" placeholder="请输入手机号码">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<Iphone />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input @keyup.enter="handleSubmit" v-model.trim="formInline.code" placeholder="验证码">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<SafetyCertificateOutlined />
</el-icon>
</template>
<template #suffix>
<el-button type="text" :disabled="isGetCode" @click="getCode">
{{ codeMsg }}<span v-if="isGetCode">s</span>
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item :show-label="false">
<el-button class="w-full" type="primary" @click="handleSubmit" size="large" :loading="loading">
登录
</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { ElMessage } from 'element-plus';
import { ResultEnum } from '@/enums/httpEnum';
import { getInfoCaptcha } from '@/api/system/user';
import { PageEnum } from '@/enums/pageEnum';
import { SafetyCertificateOutlined } from '@vicons/antd';
const captchaImg = ref('')
//
interface FormState {
username: string;
password: string;
code: string;
key: string;
}
const formRef = ref();
const loading = ref(false);
const codeMsg: any = ref('获取验证码');
const isGetCode = ref(false);
const autoLogin = ref(true);
const LOGIN_NAME = PageEnum.BASE_LOGIN_NAME;
const formInline = reactive({
mobile: '',
code: '',
key: ''
});
const rules = {
mobile: { required: true, message: '请输入手机号码', trigger: 'blur' },
code: { required: true, message: '请输入验证码', trigger: 'blur' }
};
const userStore = useUserStore();
const router = useRouter();
const route = useRoute();
function getCode() {
if (!formInline.mobile) {
formRef.value.validateField('mobile')
return
}
codeMsg.value = 60;
isGetCode.value = true;
let time = setInterval(() => {
codeMsg.value--;
if (codeMsg.value <= 0) {
clearInterval(time);
codeMsg.value = '获取验证码';
isGetCode.value = false;
}
}, 1000);
}
const handleSubmit = () => {
if (!formRef.value) return;
formRef.value.validate(async (valid) => {
if (valid) {
loading.value = true;
const params: FormState = {
username: formInline.username,
password: formInline.password,
code: formInline.code,
key: formInline.key
};
try {
const { code, msg } = await userStore.login(params);
if (code == ResultEnum.SUCCESS) {
const toPath = decodeURIComponent((route.query?.redirect || '/') as string);
ElMessage.success('登录成功,即将进入系统');
if (route.name === LOGIN_NAME) {
router.replace('/');
} else router.replace(toPath);
} else {
ElMessage.error(msg || '登录失败');
}
} finally {
loading.value = false;
}
} else {
ElMessage({
message: '请填写完整信息',
type: 'error',
});
}
});
};
const getCaptcha = async () => {
let { key, captcha } = await getInfoCaptcha();
formInline.key = key
captchaImg.value = captcha
}
getCaptcha()
</script>
<style lang="scss" scoped>
.forget {
margin-bottom: 16px;
margin-top: -10px;
}
</style>
<style lang="scss">
input:-webkit-autofill,
textarea:-webkit-autofill,
select:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
background-color: transparent !important;
background-image: none;
transition: background-color 50000s ease-in-out 0s;
}
</style>

View File

@ -0,0 +1,176 @@
<template>
<el-form
ref="formRef"
:show-label="false"
:show-require-mark="false"
size="large"
:model="formInline"
:rules="rules"
class="register-form"
>
<el-form-item prop="username">
<el-input v-model="formInline.username" placeholder="请输入用户名">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<PersonOutline />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="mobile">
<div class="flex w-full">
<el-input class="order-first" v-model="formInline.mobile" placeholder="请输入手机号码">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<MobileOutlined />
</el-icon>
</template>
</el-input>
<el-button class="order-last ml-3" :disabled="isGetCode" round @click="getCode"
>{{ codeMsg }}<span v-if="isGetCode">s</span>
</el-button>
</div>
</el-form-item>
<el-form-item prop="code">
<el-input v-model="formInline.code" placeholder="请输入验证码">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<SafetyOutlined />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<div class="flex w-full">
<el-input
v-model="formInline.password"
type="password"
show-password
placeholder="请输入密码"
>
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<LockClosedOutline />
</el-icon>
</template>
</el-input>
<el-input
v-model="formInline.retPassword"
type="password"
show-password
placeholder="请再次输入密码"
@keyup.enter="handleSubmit"
class="ml-3"
>
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<LockClosedOutline />
</el-icon>
</template>
</el-input>
</div>
</el-form-item>
<el-form-item :show-label="false" class="mb-0">
<el-button
class="w-full"
type="primary"
@click="handleSubmit"
size="large"
:loading="loading"
round
>
注册
</el-button>
</el-form-item>
<div class="flex items-center justify-between">
<div class="flex-initial">
<el-checkbox v-model="formInline.agreement">我同意隐私协议</el-checkbox>
</div>
<div class="flex-initial" style="margin-left: auto">
<a href="javascript:" @click="backLogin">返回登录</a>
</div>
</div>
</el-form>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { PersonOutline, LockClosedOutline } from '@vicons/ionicons5';
import { MobileOutlined, SafetyOutlined } from '@vicons/antd';
const formRef = ref();
const loading = ref(false);
const codeMsg: any = ref('获取验证码');
const isGetCode = ref(false);
const emit = defineEmits(['backLogin']);
const formInline = reactive({
username: '',
password: '',
retPassword: '',
mobile: '',
code: '',
agreement: false,
});
const rules = {
username: { required: true, message: '请输入用户名', trigger: 'blur' },
mobile: { required: true, message: '请输入手机号码', trigger: 'blur' },
code: { required: true, message: '请输入短信验证码', trigger: 'blur' },
password: { required: true, message: '请输入密码', trigger: 'blur' },
retPassword: { required: true, message: '请输入确认密码', trigger: 'blur' },
agreement: {
required: true,
type: 'boolean',
trigger: 'change',
message: '请先勾选协议',
validator: (_, value) => value === true,
},
};
const handleSubmit = () => {
loading.value = true;
formRef.value.validate(async (valid) => {
if (valid) {
ElMessage.success('注册准备就绪');
loading.value = false;
} else {
loading.value = false;
ElMessage({
message: '请填写完整信息',
type: 'error',
});
}
});
};
const backLogin = () => {
emit('backLogin');
};
function getCode() {
codeMsg.value = 60;
isGetCode.value = true;
let time = setInterval(() => {
codeMsg.value--;
if (codeMsg.value <= 0) {
clearInterval(time);
codeMsg.value = '获取验证码';
isGetCode.value = false;
}
}, 1000);
}
</script>
<style lang="scss" scoped>
.register-form {
.el-input {
--el-input-border-radius: 20px !important;
}
}
</style>

View File

@ -1,13 +1,6 @@
<template> <template>
<el-form <el-form ref="formRef" :show-label="false" :show-require-mark="false" size="large" :model="formInline" :rules="rules"
ref="formRef" class="register-form">
:show-label="false"
:show-require-mark="false"
size="large"
:model="formInline"
:rules="rules"
class="register-form"
>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="formInline.username" placeholder="请输入用户名"> <el-input v-model="formInline.username" placeholder="请输入用户名">
<template #prefix> <template #prefix>
@ -18,68 +11,49 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="mobile"> <el-form-item prop="mobile">
<div class="flex w-full"> <el-input v-model="formInline.mobile" placeholder="请输入手机号码">
<el-input class="order-first" v-model="formInline.mobile" placeholder="请输入手机号码">
<template #prefix> <template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695"> <el-icon class="el-input__icon" size="18" color="#808695">
<MobileOutlined /> <Iphone />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
<el-button class="order-last ml-3" :disabled="isGetCode" round @click="getCode"
>{{ codeMsg }}<span v-if="isGetCode">s</span>
</el-button>
</div>
</el-form-item> </el-form-item>
<el-form-item prop="code"> <el-form-item prop="code">
<el-input v-model="formInline.code" placeholder="请输入验证码"> <el-input v-model.trim="formInline.code" placeholder="验证码">
<template #prefix> <template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695"> <el-icon class="el-input__icon" size="18" color="#808695">
<SafetyOutlined /> <SafetyCertificateOutlined />
</el-icon> </el-icon>
</template> </template>
<template #suffix>
<el-button type="text" :disabled="isGetCode" @click="getCode">
{{ codeMsg }}<span v-if="isGetCode">s</span>
</el-button>
</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<div class="flex w-full"> <el-input v-model="formInline.password" type="password" show-password placeholder="请输入密码">
<el-input
v-model="formInline.password"
type="password"
show-password
placeholder="请输入密码"
>
<template #prefix> <template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695"> <el-icon class="el-input__icon" size="18" color="#808695">
<LockClosedOutline /> <Lock />
</el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item prop="retPassword">
<el-input v-model="formInline.retPassword" type="password" show-password placeholder="请再次输入密码">
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<Lock />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
<el-input
v-model="formInline.retPassword"
type="password"
show-password
placeholder="请再次输入密码"
@keyup.enter="handleSubmit"
class="ml-3"
>
<template #prefix>
<el-icon class="el-input__icon" size="18" color="#808695">
<LockClosedOutline />
</el-icon>
</template>
</el-input>
</div>
</el-form-item> </el-form-item>
<el-form-item :show-label="false" class="mb-0"> <el-form-item :show-label="false" class="mb-0">
<el-button <el-button class="w-full" type="primary" @click="handleSubmit" size="large" :loading="loading">
class="w-full"
type="primary"
@click="handleSubmit"
size="large"
:loading="loading"
round
>
注册 注册
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -88,37 +62,34 @@
<div class="flex-initial"> <div class="flex-initial">
<el-checkbox v-model="formInline.agreement">我同意隐私协议</el-checkbox> <el-checkbox v-model="formInline.agreement">我同意隐私协议</el-checkbox>
</div> </div>
<div class="flex-initial" style="margin-left: auto">
<a href="javascript:" @click="backLogin">返回登录</a>
</div>
</div> </div>
</el-form> </el-form>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { PersonOutline, LockClosedOutline } from '@vicons/ionicons5'; import { PersonOutline } from '@vicons/ionicons5';
import { MobileOutlined, SafetyOutlined } from '@vicons/antd'; import { SafetyCertificateOutlined } from '@vicons/antd';
const formRef = ref(); const formRef = ref();
const loading = ref(false); const loading = ref(false);
const codeMsg: any = ref('获取验证码'); const codeMsg: any = ref('获取验证码');
const isGetCode = ref(false); const isGetCode = ref(false);
const emit = defineEmits(['backLogin']); const emit = defineEmits(['backLogin']);
const formInline = reactive({ const formInline = reactive({
username: '', username: '',
password: '', password: '',
retPassword: '', retPassword: '',
mobile: '', mobile: '',
code: '', code: '',
agreement: false, agreement: false,
}); });
const rules = { const rules = {
username: { required: true, message: '请输入用户名', trigger: 'blur' }, username: { required: true, message: '请输入用户名', trigger: 'blur' },
mobile: { required: true, message: '请输入手机号码', trigger: 'blur' }, mobile: { required: true, message: '请输入手机号码', trigger: 'blur' },
code: { required: true, message: '请输入短信验证码', trigger: 'blur' }, code: { required: true, message: '请输入短信验证码', trigger: 'blur' },
@ -131,10 +102,11 @@
message: '请先勾选协议', message: '请先勾选协议',
validator: (_, value) => value === true, validator: (_, value) => value === true,
}, },
}; };
const handleSubmit = () => { const handleSubmit = () => {
loading.value = true; loading.value = true;
backLogin()
formRef.value.validate(async (valid) => { formRef.value.validate(async (valid) => {
if (valid) { if (valid) {
ElMessage.success('注册准备就绪'); ElMessage.success('注册准备就绪');
@ -147,13 +119,17 @@
}); });
} }
}); });
}; };
const backLogin = () => { const backLogin = () => {
emit('backLogin'); emit('backLogin',true);
}; };
function getCode() { function getCode() {
if (!formInline.mobile) {
formRef.value.validateField('mobile')
return
}
codeMsg.value = 60; codeMsg.value = 60;
isGetCode.value = true; isGetCode.value = true;
let time = setInterval(() => { let time = setInterval(() => {
@ -164,13 +140,7 @@
isGetCode.value = false; isGetCode.value = false;
} }
}, 1000); }, 1000);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.register-form {
.el-input {
--el-input-border-radius: 20px !important;
}
}
</style>

View File

@ -9,13 +9,27 @@
<div class="login-form"> <div class="login-form">
<div class="login-form-container"> <div class="login-form-container">
<div class="account-top"> <div class="account-top">
<div class="account-top-desc">用户登录</div> <div class="account-top-desc">{{loginFlag?'用户登录':'用户注册'}}</div>
</div> </div>
<template v-if="loginFlag">
<div class="account-tab-box"> <div class="account-tab-box">
<div :class="activeIndex==index?'active':''" v-for="(item,index) in tabData" @click="handleClick(index)" :key="index">{{item}}</div> <div :class="activeIndex==index?'active':''" v-for="(item,index) in tabData" @click="handleClick(index)" :key="index">{{item}}</div>
</div> </div>
<LoginForm v-if="activeIndex === 0" ref="LoginFormRef" /> <LoginForm v-if="activeIndex === 0" @backLogin="goLogin"/>
<QrcodeForm v-else></QrcodeForm> <PhoneForm v-else-if="activeIndex === 1"/>
<QrcodeForm v-else-if="activeIndex === 2"></QrcodeForm>
</template>
<template v-else>
<RegisterForm @backLogin="goLogin"></RegisterForm>
</template>
</div>
<div class="corner-box" @click="handleCornerClick">
<el-icon class="el-input__icon" size="34" color="#ffffff" v-if="loginFlag">
<UserAddOutlined />
</el-icon>
<el-icon class="el-input__icon" size="34" color="#ffffff" v-else>
<ArrowUndoOutline />
</el-icon>
</div> </div>
</div> </div>
</div> </div>
@ -24,15 +38,31 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { ref ,computed} from 'vue';
import LoginForm from './LoginForm2.vue'; import LoginForm from './LoginForm2.vue';
import PhoneForm from './PhoneForm.vue';
import QrcodeForm from './QrcodeForm.vue'; import QrcodeForm from './QrcodeForm.vue';
import RegisterForm from './RegisterForm2.vue';
import { UserAddOutlined } from '@vicons/antd';
import { ArrowUndoOutline } from '@vicons/ionicons5';
import { useDesignSettingStore } from '@/store/modules/designSetting';
const designStore = useDesignSettingStore();
//
const getAppTheme = computed(() => {
return designStore.appTheme;
});
const loginFlag = ref(true)
const activeIndex = ref(0) const activeIndex = ref(0)
const tabData =ref(['密码登录','扫码登录']) const tabData =ref(['账号登录','手机号登录','扫码登录'])
const handleClick =(index)=>{ const handleClick =(index)=>{
activeIndex.value = index activeIndex.value = index
} }
const handleCornerClick = ()=>{
loginFlag.value = !loginFlag.value
}
const goLogin = (type)=>{
loginFlag.value = type
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -57,7 +87,7 @@
&-wrap-login { &-wrap-login {
width: 920px; width: 920px;
height: 462px; height: 500px;
background: #fff; background: #fff;
border-radius: 10px; border-radius: 10px;
overflow: hidden; overflow: hidden;
@ -97,6 +127,7 @@
.login-form { .login-form {
width: 400px; width: 400px;
position: relative;
&-container { &-container {
margin: auto; margin: auto;
width: 100%; width: 100%;
@ -107,6 +138,26 @@
padding-bottom: 15px; padding-bottom: 15px;
text-align: center; text-align: center;
} }
.corner-box {
position:absolute;
top:0;
right:0;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
right: 0;
top: 0;
width: 80px;
height: 80px;
border-radius: 0 0 0 150%;
background: v-bind(getAppTheme);
cursor: pointer;
>i {
margin-right: -20px;
margin-top: -10px;
}
}
} }
@media (max-width: 680px) { @media (max-width: 680px) {
@ -130,7 +181,6 @@
} }
.account-tab-box { .account-tab-box {
display: flex; display: flex;
width:160px;
height:34px; height:34px;
margin-bottom: 18px; margin-bottom: 18px;
background-color: #f5f5f5; background-color: #f5f5f5;
@ -171,3 +221,20 @@
} }
} }
</style> </style>
<style lang="scss">
.account {
.el-button--primary {
background-color: v-bind(getAppTheme);
}
.el-button--text{
padding:0;
}
.el-checkbox__input.is-checked+.el-checkbox__label,.el-button--text {
color: v-bind(getAppTheme);
}
.el-checkbox__input.is-checked .el-checkbox__inner {
background-color: v-bind(getAppTheme);
color: v-bind(getAppTheme);
}
}
</style>