2024-1-8 学习笔记——首页制作
遇到的BUG
前端控制台爆错误:
16:55:56 [vite] http proxy error:
Error: connect ECONNREFUSED ::1:8080
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16)
发现是后台RuoYiApplication没有正常运行
后端控制台提示:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field roleService in com.fs.system.service.impl.SysPermissionService required a bean of type 'com.fs.system.service.ISysRoleService' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.fs.system.service.ISysRoleService' in your configuration.
Process finished with exit code 1
翻译后如下:
应用程序无法启动
说明:
com.fs.system.service.impl.SysPermissionService中的字段roleService需要类型为“com.fs.systems.service.ISysRoleService”的bean,但找不到该bean。
注入点具有以下注释:
-@org.springframework.beans.factory.annotation.Autowired(必需=true)
操作:
请考虑在配置中定义类型为“com.fs.system.service.ISysRoleService”的bean。
进程已完成,退出代码为1
也就是ISysRoleService没有注入到SpringBoot的bean中
解决方法就是
在ISysRoleService的实现类SysRoleServiceImpl上
添加@Service注解
/*
* 角色业务层
* */
@Service
public class SysRoleServiceImpl implements ISysRoleService {
...
}
添加完成后,还是有问题,后端编译(build)不通过
Some problems were encountered while building the effective model for com.fs:ruoyi-common:jar:1.0-SNAPSHOT
'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ com.fs:ruoyi-parent:1.0-SNAPSHOT, D:\IdeaProjects\ruoyi-parent\pom.xml, line 98, column 21
Some problems were encountered while building the effective model for com.fs:ruoyi-system:jar:1.0-SNAPSHOT
'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ com.fs:ruoyi-parent:1.0-SNAPSHOT, D:\IdeaProjects\ruoyi-parent\pom.xml, line 98, column 21
Some problems were encountered while building the effective model for com.fs:ruoyi-parent:pom:1.0-SNAPSHOT
'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 98, column 21
It is highly recommended to fix these problems because they threaten the stability of your build.
For this reason, future Maven versions might no longer support building such malformed projects.
翻译后如下:
在为com.fs:ruoyi-common:jar:1.0-SNAPSHOT构建有效模型时遇到了一些问题
org.apache.maven.plugins:maven编译器插件丢失。@com.fs:ruoyi parent:1.0-SNAPSHOT,D:\IdeaProjects\ruoyi parent\pom.xml,第98行,第21列
在为com.fs:ruoyi system:jar:1.0-SNAPSHOT构建有效模型时遇到了一些问题
org.apache.maven.plugins:maven编译器插件丢失。@com.fs:ruoyi parent:1.0-SNAPSHOT,D:\IdeaProjects\ruoyi parent\pom.xml,第98行,第21列
在为com.fs:ruoyi-parent:pom:1.0-SNAPSHOT构建有效模型时遇到了一些问题
org.apache.maven.plugins:maven编译器插件丢失。@第98行,第21列
强烈建议修复这些问题,因为它们会威胁到构建的稳定性。
因此,未来的Maven版本可能不再支持构建这种格式错误的项目。
解决方法:右键根目录rouyi-parent,从根目录开始编译
这样就能编译通过了
但还是有问题
前端点击登录后页面一直不进行跳转
点击F12查看网络
发送的3个请求均返回了200的http码,即响应成功
在前端中寻找问题,发现构建首页的后台传过来的路由菜单,子路由的path路径中没有"/",导致不能正确构建首页的路由菜单
最终导致无法渲染首页
再去后端查找原因
发现问题出在:我自己写的service方法,获取子节点的时候没有调用老师的代码中的getChildPerms方法,导致不能正确获得子节点路由
修改前:第14行,返回值
/*
* 根据用户ID查询菜单
* */
@Override
public List<SysMenu> selectMenuTreeByUserId(Long userId) {
List<SysMenu> menus = null;
if (SecurityUtils.isAdmin(userId)) { // 如果是超级管理员,就查询全部的菜单树信息
menus = menuMapper.selectMenuTreeAll();
} else { // 如果不是超级管理员,就查询对应的菜单树信息
menus = menuMapper.selectMenuTreeByUserId(userId);
}
return menus; // ←!!!←
}
修改后:第14行,返回值
/*
* 根据用户ID查询菜单
* */
@Override
public List<SysMenu> selectMenuTreeByUserId(Long userId) {
List<SysMenu> menus = null;
if (SecurityUtils.isAdmin(userId)) { // 如果是超级管理员,就查询全部的菜单树信息
menus = menuMapper.selectMenuTreeAll();
} else { // 如果不是超级管理员,就查询对应的菜单树信息
menus = menuMapper.selectMenuTreeByUserId(userId);
}
return getChildPerms(menus, 0);
}
修改返回值后正常运行
我忘记去寻找子节点的子节点,导致了该bug
路由守卫的触发
每次访问主页的时候,触发路由守卫
前端获取用户的角色信息和权限信息
然后选择性的展示或隐藏某些功能
路由守卫的操作
路由守卫在permission.js中打开
定义了router.beforeEach方法
因为我们需要知道用户的角色信息和权限信息,以选择性的展示或隐藏某些功能
所以router.beforeEach中调用了一个GetInfo方法,该方法在store/modules/user.js下
GetInfo({ commit, state }) { ... }
该方法获取用户的信息并返回一个数组
router.beforeEach方法
router.beforeEach方法:添加一个全局的前置钩子函数,这个函数会在路由切换开始时调用。
在前端路由跳转中,路由跳转前都是会经过beforeEach,而beforeEach可以通过next来控制到底去哪个路由。
根据这个特性我们就可以在beforeEach中设置一些条件来控制路由的重定向。
常见的使用场景有:
1、验证用户是否登录(若未登录,且当前非登录页面,则自动重定向登录页面);
2、用户权限;
3、用户输入的路路径是否存在,不存在的情况下如何处理,重定向到哪个页面。
数据库部分
为什么部门表和角色表挂钩?
一个部门对应多个用户信息
如果我们要新增1000名员工信息,直接添加信息就要添加1000次
但如果这1000名角色属于10个表,我们就只用添加10次
万能口诀:一对多
一中的主键当多中的外键
根据用户查询角色
其实讲半天就是根据已有的信息,减少查询的表的数量
如果一个用户有角色,就三表联查
如果一个用户没有角色,就五表联查(前提是用户可以没有角色,也没有默认角色)
SQl查询语句放在mapper层中
Mapper层
角色查询
根据用户id查询对应的角色
SELECT
r.role_id,
r.role_name,
r.role_key,
r.role_sort,
r.data_scope,
r.menu_check_strictly,
r.dept_check_strictly,
r.STATUS,
r.del_flag,
r.create_time,
r.remark
FROM
sys_user u,
sys_user_role ur,
sys_role r
WHERE
u.user_id = 2
AND u.user_id = ur.user_id
AND ur.role_id = r.role_id
菜单权限查询
根据角色id查询对应的菜单权限
SELECT DISTINCT
m.perms
FROM
sys_role r,
sys_role_menu rm,
sys_menu m
WHERE
r.role_id = 2
AND r.role_id = rm.role_id
AND rm.menu_id = m.menu_id
AND m.`status` = '0'
根据用户id查询对应的菜单权限
SELECT DISTINCT
m.perms
FROM
sys_user u,
sys_user_role ur,
sys_role r,
sys_role_menu rm,
sys_menu m
WHERE
u.user_id = 2
AND u.user_id = ur.user_id
AND ur.role_id = r.role_id
AND r.role_id = rm.role_id
AND rm.menu_id = m.menu_id
AND m.`status` = '0'
五个表联查:用户表→用户/角色中间表→角色表→角色/菜单中间表→菜单表
SQL多表联查
左连接 LEFT JOIN
SELECT
t1.c1, t1.c2, t2.c1, t2.c2
FROM
t1
LEFT JOIN
t2 ON t1.c1 = t2.c1
会将左侧表中的数据全部取出来。不管右侧是否存在能关联上的数据。
SQL排序
升序 ASC,降序 DESC
SELECT * FROM 表名
ORDER BY 列名 ASC;
SELECT * FROM 表名
ORDER BY 列名1 ASC, 列名2 DESC;
Service层
spring推荐直接写service实现类,先定义一个接口再去实现它没什么问题,但是我们永远只有一个实现类,这个接口毫无意义。所以spring推荐直接写实现类
角色信息去重业务
查询出来的数据可能是有重复的
查询出数据库的List集合,遍历并放入Set集合中自动去重
权限信息去重业务
同理
思路
一:排列好菜单的父子结构,一会封装进我们的Vo
- 先sql查询出menu表中的菜单并做简单的排序,得到List
- 以menuList和parent_id=0的两个参数作为递归方法的参数,从而在递归中将父菜单对应的子菜单中的菜单封装进我们vo中的children
二:对字段进行改造(因为前端需求的并不是表里面的原封的数据)
Controller层
为了方便Controller调用方便,我们将查询用户角色、查询用户菜单权限的业务封装到一个Service业务中