功能27:实现用户登录
text
功能26:新增一个新员工培训页面
功能25:角色管理
功能24:菜单管理
功能23:从后端获取路由/菜单数据
功能22:用户管理
功能21:使用axios发送请求
功能20:使用分页插件
功能19:集成MyBatis-Plus
功能18:创建后端工程
功能17:菜单管理
功能16:角色管理
功能15:用户管理
功能14:使用本地SVG图标库
功能13:侧边栏加入Logo
功能12:折叠/展开侧边栏
功能11:实现面包屑功能
功能10:添加首页菜单项
功能9:退出登录功能
功能8:页面权限控制
功能7:路由全局前置守卫
功能6:动态添加路由记录
功能5:侧边栏菜单动态显示
功能4:首页使用Layout布局
功能3:点击登录按钮实现页面跳转
功能2:静态登录界面
功能1:创建前端项目
前言
将登录的功能对接后端。
一.操作步骤
1.修改登录模板
src\views\login.vue
html
<template>
<div class="login-container">
<div class="login-box">
<h2 class="title">用户登录</h2>
<el-form ref="loginForm" :model="formData" :rules="rules" @submit.prevent="handleLogin">
<el-form-item prop="username">
<el-input v-model="formData.username" placeholder="请输入用户名" :prefix-icon="User" />
</el-form-item>
<el-form-item prop="password">
<el-input v-model="formData.password" type="password" placeholder="请输入密码" show-password :prefix-icon="Lock" />
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit" class="login-btn">
登录
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { User, Lock } from '@element-plus/icons-vue'
import { useRouter, useRoute } from 'vue-router'
import useUserStore from '@/stores/user'
const userStore = useUserStore()
const router = useRouter()
const route = useRoute()
// 表单数据
const formData = ref({
username: "",
password: "",
});
// 表单引用
const loginForm = ref(null)
// 验证规则
const rules = {
username: [
{ required: true, message: '用户名不能为空', trigger: 'blur' }
],
password: [
{ required: true, message: '密码不能为空', trigger: 'blur' }
]
}
const redirect = ref(undefined);
watch(route, (newRoute) => {
redirect.value = newRoute.query && newRoute.query.redirect;
}, { immediate: true });
// 登录处理
const handleLogin = async () => {
try {
// 表单验证
await loginForm.value.validate()
// 这里添加实际登录逻辑
try {
await userStore.login(formData.value)
router.push({ path: redirect.value || "/" });
ElMessage.success('登录成功!')
} catch (error) {
ElMessage.error('登录失败')
}
} catch (error) {
ElMessage.error('请正确填写表单')
}
}
</script>
<style scoped>
.login-container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: url('@/assets/images/login-background.jpg') no-repeat center center;
background-size: cover;
}
.login-box {
width: 400px;
padding: 40px;
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.title {
text-align: center;
margin-bottom: 30px;
color: #333;
}
.login-btn {
width: 100%;
margin-top: 10px;
}
.el-form-item {
margin-bottom: 28px;
}
</style>
2.修改Store
src\stores\user.js
js
import { defineStore } from 'pinia'
import { setToken, removeToken } from '@/utils/auth'
import { ref } from 'vue'
import { login as loginApi } from '@/api/login'
const useUserStore = defineStore('user', () => {
const permissions = ref(['*:*:*'])
// 异步操作
const login = async (userInfo) => {
const username = userInfo.username.trim()
const password = userInfo.password
const res = await loginApi(username, password)
setToken(res.token)
}
const logout = async () => {
await removeToken()
}
return {
permissions,
login, logout
}
})
export default useUserStore
3.API
src\api\login.js
js
import request from '@/utils/request'
// 登录方法
export const login = (userName, password) => {
const data = {
userName,
password
}
return request({
url: '/login',
method: 'post',
data: data
})
}
// 获取路由
export const getRouters = () => {
return request({
url: '/getRouters',
method: 'get'
})
}
后端
4.修改Controller
src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
登录逻辑,根据前端发送的用户名,查询数据库,如果查询到用户则简单比较数据库里的密码和前端发送的密码。(这是一个一堆Bug的逻辑)
java
@RestController
public class SysLoginController {
@Autowired
private ISysMenuService menuService;
@Autowired
private ISysUserService sysUserService;
@PostMapping("/login")
public AjaxResult login(@RequestBody SysUserDTO userDTO) {
LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (userDTO.getUserName() != null) {
lambdaQueryWrapper.eq(SysUser::getUserName, userDTO.getUserName());
}
SysUser sysUser = sysUserService.getOne(lambdaQueryWrapper);
if (sysUser != null && sysUser.getPassword().equals(userDTO.getPassword())) {
AjaxResult ajax = AjaxResult.success();
// 生成令牌
String token = "test-admin";
ajax.put(Constants.TOKEN, token);
return ajax;
} else {
throw new RuntimeException();
}
}
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping("getRouters")
public AjaxResult getRouters() {
return AjaxResult.success(menuService.buildMenus(1L));
}
}
5.DTO
src/main/java/com/ruoyi/common/core/domain/dto/SysUserDTO.java
增加一个password字段,接收登录时的密码。
java
/** 密码 */
private String password;
6.常量
src/main/java/com/ruoyi/common/constant/Constants.java
java
/**
* 令牌
*/
public static final String TOKEN = "token";
二.功能验证
在用户界面新增用户zhangsan,密码123456
将正在登录的用户注销,使用新增用户zhangsan登录。
三.思考
在后端服务器,如何判断每个请求是来自哪个用户呢?相同的请求,例如之前的获取路由/菜单数据接口,不同的用户请求,可能需要返回不同的数据。