本篇文章介绍我们的登录注册功能
登录
实现功能
- 提醒输入,并对不规范的用户名、密码进行提示
- 账号、密码正确提示登录成功并跳转到主页面
- 登录失败进行提示
前端实现
<template>
<div class="login-container">
<el-card class="login-card">
<h2 class="login-title">用户登录</h2>
<el-form :model="loginForm" :rules="loginRules" ref="loginFormRef" @keyup.enter="handleLogin">
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入用户名" :prefix-icon="User" clearable />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" placeholder="请输入密码" :prefix-icon="Lock" show-password clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" class="login-btn" @click="handleLogin" :loading="loading">
登录
</el-button>
</el-form-item>
</el-form>
<div class="register-link">
<span>还没有账号?</span>
<el-button type="text" @click="handleRegister">立即注册</el-button>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import { User, Lock } from '@element-plus/icons-vue'
import axios from 'axios'
const router = useRouter()
const loginForm = ref({
username: '',
password: ''
})
const loginRules = ref({
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 16, message: '长度在 3 到 16 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
]
})
const loginFormRef = ref(null)
const loading = ref(false)
const handleLogin = async () => {
try {
console.log(loginForm.value);
const isValid = await loginFormRef.value.validate()
if (!isValid) return
loading.value = true
const { data: res } = await axios.post('http://localhost:8080/api/user/login', {
username: loginForm.value.username,
password: loginForm.value.password
})
if (res.code === 200) {
localStorage.setItem('token', res.data.token)
const redirect = router.currentRoute.value.query.redirect || '/home'
await router.isReady()
ElMessage.success({
message: '登录成功',
duration: 1500,
onClose: () => router.push(redirect)
})
} else {
throw new Error(res.message || '登录失败')
}
} catch (error) {
const errorMsg = error.response?.data?.message || error.message
ElMessage.error({
message: `登录失败: ${errorMsg}`,
showClose: true
})
} finally {
loading.value = false
}
}
const handleRegister = () => {
router.push('/register')
}
</script>
<style scoped>
.login-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 97.5vh;
background-color: #f5f7fa;
}
.login-card {
width: 400px;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.login-title {
text-align: center;
margin-bottom: 30px;
color: #409eff;
}
.login-btn {
width: 100%;
margin-top: 10px;
}
.register-link {
text-align: center;
margin-top: 15px;
font-size: 14px;
color: #606266;
}
.register-link .el-button {
padding: 0;
margin-left: 5px;
}
</style>
后端实现
@PostMapping("/login")
public ResponseMessage login(@RequestBody UserDto userDto){
User loginUser = userService.login(userDto);
return ResponseMessage.success(loginUser);
}
@Override
public User login(UserDto userDto) {
if (userDto.getUsername() == null || userDto.getUsername().trim().isEmpty()) {
throw new CustomException("用户名不能为空");
}
if (userDto.getPassword() == null || userDto.getPassword().trim().isEmpty()) {
throw new CustomException("密码不能为空");
}
// 查询数据库中是否存在该用户名和密码
Optional<User> userOpt = userRepository.findByUsernameAndPassword(
userDto.getUsername(),
userDto.getPassword()
);
if (userOpt.isPresent()) {
return userOpt.get();
} else {
throw new CustomException("用户名或密码错误");
}
}
注册
实现功能
- 提醒输入,并对不规范的用户名、密码邮箱进行提示
- 正确提示登录成功并跳转到登录页面
- 注册失败进行提示
前端实现
<template>
<div class="register-container">
<el-card class="register-card">
<h2 class="register-title">用户注册</h2>
<el-form :model="registerForm" :rules="registerRules" ref="registerFormRef" @keyup.enter="handleRegister">
<el-form-item prop="username">
<el-input v-model="registerForm.username" placeholder="请输入用户名" prefix-icon="User" clearable />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="registerForm.password" placeholder="请输入密码" prefix-icon="Lock" show-password
clearable />
</el-form-item>
<el-form-item prop="confirmPassword">
<el-input v-model="registerForm.confirmPassword" placeholder="请确认密码" prefix-icon="Lock"
show-password clearable />
</el-form-item>
<el-form-item prop="email">
<el-input v-model="registerForm.email" placeholder="请输入邮箱" prefix-icon="Message" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" class="register-btn" @click="handleRegister" :loading="loading">
注册
</el-button>
</el-form-item>
</el-form>
<div class="login-link">
<span>已有账号?</span>
<el-button type="text" @click="handleLogin">立即登录</el-button>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import { User, Lock, Message } from '@element-plus/icons-vue'
import axios from 'axios';
const router = useRouter()
const registerForm = ref({
username: '',
password: '',
confirmPassword: '',
email: ''
})
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== registerForm.value.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
const registerRules = ref({
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 16, message: '长度在 3 到 16 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
],
confirmPassword: [
{ required: true, validator: validatePass2, trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' }
]
})
const registerFormRef = ref(null)
const loading = ref(false)
const handleRegister = async () => {
try {
const valid = await registerFormRef.value.validate();
if (valid) {
loading.value = true;
const { data: res } =await axios.post('http://localhost:8080/api/user/register', {
username: registerForm.value.username,
password: registerForm.value.password,
email: registerForm.value.email
});
if(res.code === 200) {
ElMessage.success(' 注册成功');
router.push('/login');
} else {
throw new Error(res.message || '注册失败')
}
}
} catch (error) {
ElMessage.error(error.response?.data?.message || '注册失败');
} finally {
loading.value = false;
}
};
const handleLogin = () => {
router.push('/login')
}
</script>
<style scoped>
.register-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 97.5vh;
background-color: #f5f7fa;
}
.register-card {
width: 400px;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.register-title {
text-align: center;
margin-bottom: 30px;
color: #409eff;
}
.register-btn {
width: 100%;
margin-top: 10px;
}
.login-link {
text-align: center;
margin-top: 15px;
font-size: 14px;
color: #606266;
}
.login-link .el-button {
padding: 0;
margin-left: 5px;
}
</style>
后端实现
@PostMapping("/register")
public ResponseMessage register(@RequestBody UserDto userDto){
User loginUser =userService.add(userDto);
return ResponseMessage.success(loginUser);
}
@Override
public User add(UserDto userDto) {
if (userDto.getUsername() == null || userDto.getUsername().trim().isEmpty()) {
throw new CustomException("用户名不能为空");
}
// 检查用户名是否已存在
Optional<User> existingUser = userRepository.findByUsername(userDto.getUsername());
if (existingUser.isPresent()) {
throw new CustomException("用户名已存在,请更换");
}
User user = new User();
if (userDto.getPassword() == "") {
userDto.setPassword("123456");
}
BeanUtils.copyProperties(userDto, user);
return userRepository.save(user);
}