<template>
<div class="bg">
<div style="position: relative;margin-left:300px;margin-top:250px;">
<div class="logo"></div>
<div class="name">
XXXX平台
</div>
<div class="beian">
XXXXX科技有限公司 丨 京ICP备XXXX号-X
<p>增值电信业务经营许可证 京XXXX</p>
</div>
</div>
<!--登录-->
<div class="form" style="position: absolute;right:300px;top:100px;" v-if="navIndex == 0">
<div class="title2">欢迎登录</div>
<div class="tips2">账号密码登录</div>
<div class="tips3"></div>
<div class="formField">
<v-form ref="signInForm" style="margin-top: 100px;">
<v-text-field :label="$t('username')" :rules="formRules.account" clearable
v-model="formData.account"
variant="underlined"></v-text-field>
<v-text-field :append-inner-icon="passwordInputType === 'password' ? 'visibility' : 'visibility_off'" :label="$t('password')" :rules="formRules.password"
:type="passwordInputType" @click:append-inner="passwordInputType = passwordInputType === 'password' ? 'text' : 'password'" @keyup.enter="submit" clearable
v-model="formData.password"
variant="underlined"></v-text-field>
</v-form>
<div class="text-red" v-if="errorMsg">{{ errorMsg }}</div>
<div class="mt-5 d-flex justify-space-between">
<div class="container">
<input @click="remberPassWord" color="primary" type="checkbox" v-model="rememberMe" variant="text">记住密码
<v-btn @click="navIndex= 1" color="primary" variant="text">手机号注册</v-btn>
</div>
<div @click="submit" class="btn" loading="submitting" style="color: #ffffff !important;">登录</div>
</div>
</div>
</div>
<!--注册-->
<div class="form" style="position: absolute;right:300px;top:100px;" v-if="navIndex == 1">
<div class="title2">账号注册</div>
<div style="margin-top:20px;">
<v-form ref="signUpForm">
<v-text-field :error-messages="fieldErrors.phone" :label="$t('手机号码')"
:rules="formRules2.phone"
@update:modelValue="handleFieldUpdate('phone')" clearable
v-model="formData2.phone"
variant="underlined"></v-text-field>
<v-text-field :error-messages="fieldErrors.password" :label="$t('password')"
:rules="formRules2.password"
@update:modelValue="handleFieldUpdate('password')" clearable
v-model="formData2.password"
variant="underlined"></v-text-field>
<v-text-field :error-messages="fieldErrors.password2" :label="$t('confirmPassword')"
:rules="formRules2.password2"
@update:modelValue="handleFieldUpdate('password2')" clearable
v-model="formData2.password2"
variant="underlined"></v-text-field>
<v-text-field :error-messages="fieldErrors.activationCode" :label="$t('激活码')"
:rules="formRules2.activationCode"
@update:modelValue="handleFieldUpdate('activationCode')" clearable
v-model="formData2.activationCode"
variant="underlined"></v-text-field>
</v-form>
<div class="text-red" v-if="errorMsg">{{ errorMsg }}</div>
<div class="mt-5 d-flex justify-space-between">
<v-btn @click="navIndex = 0" color="primary" variant="text">返回登录</v-btn>
<div @click="submit2" class="btn" loading="submitting2" style="color: #ffffff !important;">提交注册
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
const {$i18n} = useNuxtApp();
definePageMeta({
layout: 'vuetify-app'
});
const formData = ref({
account: '',
password: ''
});
//记住密码属性
const rememberMe = ref(false);
const formData2 = ref({
username: '',
phone: '',
activationCode: '',
password: '',
password2: '',
code: '',
});
const fieldErrors = ref({
username: '',
phone: '',
password: '',
password2: '',
code: '',
});
const formRules2 = ref({
username: [
v => !!v || $i18n.t('请输入你的昵称'),
v => v.length >= 4 || $i18n.t('Username must be at least 4 characters')
],
activationCode: [
v => !!v || $i18n.t('请输入激活码'),
v => v.length >= 19 || $i18n.t('Username must be at least 4 characters')
],
phone: [
v => !!v || $i18n.t('请输入你的手机'),
v => /^1[3456789]\d{9}$/.test(v) || '手机号码格式不正确'
],
password: [
v => !!v || $i18n.t('请输入你的密码'),
v => v.length >= 6 || $i18n.t('密码至少是6位数')
],
password2: [
v => !!v || $i18n.t('请输入你的密码'),
v => v.length >= 6 || $i18n.t('密码至少是6位数'),
v => v === formData2.value.password || $i18n.t('两次密码输入要一直')
],
code: [
v => !!v || $i18n.t('Please enter your code'),
],
});
const submitting2 = ref(false);
const signUpForm = ref(null);
//页面初始化加载,记住的用户名和密码,用户点击记住密码checkbox,系统将用户名和密码记录到localStorage
onBeforeMount(() => {
const savedLogin = localStorage.getItem('login');
if (savedLogin) {
formData.value = JSON.parse(savedLogin);
}
const savedRememberMe = localStorage.getItem('rememberMe');
if (savedRememberMe) {
rememberMe.value = savedRememberMe === 'true';
}
});
const submit2 = async () => {
errorMsg.value = null;
const {valid} = await signUpForm.value.validate();
if (valid) {
if (submitting2.value == true) {
// 如果已经点击过了,不再执行后续操作并返回
console.log("请勿重复点击");
} else {
submitting2.value = true;
const {data} = await useMyFetch('/api/register', {
method: 'POST',
body: JSON.stringify(formData2.value)
});
if (data.value.status === 200) {
errorMsg.value = data.value.msg;
setTimeout(() => {
setUser();
navigateTo('/account/signin')
}, 500)
} else {
errorMsg.value = data.value.msg;
submitting2.value = false;
}
}
}
};
const handleFieldUpdate = (field) => {
fieldErrors.value[field] = ''
};
const navIndex = ref(0);
const formRules = ref({
account: [
v => !!v || $i18n.t('Username is required')
],
password: [
v => !!v || $i18n.t('Password is required')
]
});
const errorMsg = ref(null);
const signInForm = ref(null);
const submitting = ref(false);
const route = useRoute();
const passwordInputType = ref('password');
const remberPassWord = async () => {
//记住登录用户名和密码
if (!rememberMe.value) {
localStorage.setItem('login', JSON.stringify(formData.value));
localStorage.setItem('rememberMe', true);
} else {
localStorage.removeItem('login');
localStorage.removeItem('rememberMe');
}
}
const submit = async () => {
errorMsg.value = null;
const {valid} = await signInForm.value.validate();
if (valid) {
submitting.value = true;
const {data, error} = await useMyFetch('/api/login', {
method: 'POST',
body: JSON.stringify(formData.value)
});
submitting.value = false;
console.log("登陆返回数据:", data.value);
if (data.value.status === 200) {
localStorage.setItem('token', data.value.data.token);
localStorage.setItem('expires_time', data.value.data.expires_time);
setUser(data.value.token);
const callback = route.query.callback ? decodeURIComponent(route.query.callback) : '/';
location.href = "/"
} else {
errorMsg.value = data.value.msg
}
}
};
let qrcodeData = ref();
let qrcodeDialog = ref(false);
let interval = ref('');
let uuid = ref('');
</script>
<style scoped>
* {
color: #000 !important;
}
input, .formField >>> .v-application, .v-text-field input, .v-field__input {
color: #000 !important;
}
button[type="submit"] {
width: 100%;
padding: 10px;
border: none;
background-color: #5cb85c;
color: white;
cursor: pointer;
border-radius: 4px;
}
.bg {
width: 100%;
height: 100vh;
background-image: url(../images/bg.jpg);
background-position: left;
background-size: cover;
-webkit-filter: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#00FFFFFF", endColorstr="#FFFFFFFF", GradientType=1);
}
.form .btn {
/* 矩形备份 2 */
position: absolute;
left: 40px;
top: 510px;
width: 320px;
height: 44px;
border-radius: 6px;
opacity: 1;
text-align: center;
line-height: 44px;
color: #fff;
background: #2469F1;
}
.form {
/* 矩形 */
position: relative;
padding: 20px;
width: 400px;
height: 575px;
border-radius: 10px;
opacity: 1;
background: #FFFFFF;
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.06);
}
.title2 {
/* 欢迎登录 */
font-size: 24px;
font-weight: 500;
line-height: 29px;
letter-spacing: 0px;
color: #000000;
}
.tips2 {
/* 账号密码登录 */
position: absolute;
left: 20px;
top: 77px;
width: 84px;
height: 17px;
opacity: 1;
font-family: PingFang SC;
font-size: 14px;
font-weight: 500;
line-height: 17px;
letter-spacing: 0px;
color: #000000;
}
.tips3 {
/* 矩形 */
/* 矩形 */
position: absolute;
left: 20px;
top: 107px;
width: 84px;
height: 2px;
opacity: 1;
background: #2469F1;
}
.logo {
position: absolute;
left: 0px;
top: 40px;
width: 80px;
height: 77px;
opacity: 1;
background: url(../images/yuzhouxiong.png);
background-size: 100%;
}
.name {
position: absolute;
left: 95px;
top: 55px;
width: 517px;
height: 56px;
opacity: 1;
font-family: PingFang SC;
font-size: 56px;
font-weight: 600;
line-height: 56px;
letter-spacing: 4px;
color: #000000;
}
.beian {
position: absolute;
left: 0px;
top: 385px;
width: 415px;
height: 48px;
opacity: 1;
font-family: PingFang SC;
font-size: 14px;
font-weight: normal;
line-height: 24px;
letter-spacing: 0px;
color: #666666;
}
.container {
height: 100px;
border: 0px solid #000;
font-size: small;
}
</style>
vue 记住密码功能
于 2024-04-09 15:57:51 首次发布