用户多部门切换部门,MySQL根据多个部门id递归获取所有上级(祖级)、获取部门的全路径(全结构名称)

背景

之前做过的项目,都是一个用户就一个部门的,现在碰到个一个用户在多个部门的需求,而且需要可以切换不同部门查看不同数据

就比如说一个大公司下面有多个子公司,每个子公司有好多部门、子部门等等,然后有部分用户就和多个子公司/部门都有关联,有些数据就需要根据当前用户选择的部门进行过滤。

实现

1、用户部门关联

首先就是用户和多部门关联,数据库要怎么保存。之前不是单部门的嘛,用户表和部门表关联就是用的一个dept_id字段;现在多部门我也不打算新建表存储关联关系,而是在原有的dept_id字段上,改个数据类型,比如由varchar改为longtext,然后多个部门之间用逗号隔开。

2、切换部门

其次就是切换部门,用户登录的时候查询用户信息,拿到了用户的部门id,根据部门id去递归获取所有上级。

因为我们切换部门的时候每次只能选中一个部门,而且这个部门需要显示全路径(比如:A公司/子公司1/开发部A公司/子公司1/办公室),所以为了后续好获取全路径,我们需要加一个checked属性,用户的部门id checked值为1,也就是true,其他的上级则为0,也就是false。

递归上级

根据多个部门id,递归所有上级,sql查询如下:

<select id="parentDeptList" resultType="com.entity.sys.vo.DeptVo">SELECT id,GROUP_CONCAT(DISTINCT `name`) `name`,GROUP_CONCAT(DISTINCT parent_id) parent_id,MAX(checked) checkedFROM(WITH RECURSIVE temp_dept(id,name,parent_id,checked) AS (<!--查询指定部门-->SELECT id,name,parent_id,1 checkedFROM sys_deptWHERE FIND_IN_SET(id,#{deptId})UNION ALL<!--递归查询父部门-->SELECT d.id,d.name,d.parent_id,0 checkedFROM sys_dept dJOIN temp_dept c ON d.id = c.parent_id)SELECT id,name,parent_id,checkedFROM temp_dept<!--不加条件则获取它的所有父节点,包括它本身--><!--WHERE parent_id IN (SELECT id FROM sys_dept WHERE parent_id = 'ROOT')-->) aGROUP BY id
</select>

查询结果用一个实体类接收:

@Data
public class DeptVo {private String id;private String parentId;private String name;/*** 部门id全称:1/2/5/13*/private String fullId;/*** 部门名称全称:A公司/子公司1/开发部/开发一组*/private String fullName;/*** 是否选中*/private Boolean checked;public DeptVo() {}public DeptVo(String id, String name, String fullId, String fullName,Boolean checked) {this.id = id;this.name = name;this.fullId = fullId;this.fullName = fullName;this.checked = checked;}
}

获取部门的全路径名称

拿到了查询结果,现在我们就可以来处理和获取部门的全路径名称了:

/*** 递归查询,根据当前部门id(可能有多个)获取所有上级*/
public List<DeptVo> parentDeptList(String id){List<DeptVo> deptList = baseMapper.parentDeptList(id);List<DeptVo> result = new ArrayList<>();int count = 0;for (DeptVo node : deptList) {if (node.getChecked()) {generateFullIdAndFullName(deptList, node);// 默认选中第一个部门if (count == 0) node.setChecked(true);else node.setChecked(false);result.add(node);count++;}}return result;
}private static void generateFullIdAndFullName(List<DeptVo> nodeList, DeptVo currentNode) {StringBuilder fullIdBuilder = new StringBuilder();StringBuilder fullNameBuilder = new StringBuilder();generateFullIdAndFullNameRecursive(nodeList, currentNode, fullIdBuilder, fullNameBuilder);currentNode.setFullId(fullIdBuilder.toString());currentNode.setFullName(fullNameBuilder.toString());
}private static void generateFullIdAndFullNameRecursive(List<DeptVo> nodeList, DeptVo currentNode, StringBuilder fullIdBuilder, StringBuilder fullNameBuilder) {fullIdBuilder.insert(0, currentNode.getId());fullNameBuilder.insert(0, currentNode.getName());if (!"ROOT".equals(currentNode.getParentId())) {fullIdBuilder.insert(0, "/");fullNameBuilder.insert(0, "/");for (DeptVo node : nodeList) {if (node.getId().equals(currentNode.getParentId())) {generateFullIdAndFullNameRecursive(nodeList, node, fullIdBuilder, fullNameBuilder);break;}}}
}

比如说用户A有id为4、5、6、7、8这几个部门,像这种的话就是新增/编辑用户时,用户选择部门时任意一级的部门都可以选,所以就会出现下面图片中的示例:单独选了营销部,但是又选了营销部下面的营销一部。这种情况就不做:切换部门时,查询所在部门及子部门数据。也就是只查询所在部门数据,子部门数据不查询,不然切换部门这个功能的意义不大。

在这里插入图片描述

然后上面的数据的输出结果如下:

在这里插入图片描述

将结果设置到用户信息中

能正确拿到数据后,我们在用户信息中,增加一个字段:

@TableField(exist = false)
private List<DeptVo> deptArr;

parentDeptList 方法返回的数据设置到 deptArr 中,最后将用户信息存储到缓存中。用户登录成功,获取登录用户信息,就可以拿到 deptArr 了,切换时也是在这个列表进行切换选哪一个。

切换部门

切换部门时,前端传选中的部门的id,后端拿到当前登录用户的 deptArr 列表,匹配前端传过来的id,将匹配到的那一条数据的 checked 设置为true,其他的则设置为false:

/*** 切换部门* @param id 部门id*/
@GetMapping(value = "/qhbmsctk")
public ResultUtil qhbmsctk(String id,HttpServletRequest request){// 获取当前登录用户SysUser loginUser = LoginUtil.getLoginUser();List<DeptVo> deptArr = loginUser.getDeptArr();List<DeptVo> collect = deptArr.stream().peek(obj -> {if (obj.getId().equals(id)) {obj.setChecked(true); // 设置checked为true如果id等于前端传过来的deptId}else {obj.setChecked(false);}}).collect(Collectors.toList());loginUser.setDeptArr(collect);// 切换成功后,可以重新生成token重新登录(静默登录),也可以将更新后的用户信息重新更新到缓存中// 看自己实际需求选哪一种方式return ResultUtil.success();
}

切换成功后,可以重新生成token重新登录(静默登录),也可以将更新后的用户信息重新更新到缓存中,看自己实际需求选哪一种方式。

/*** 获取当前用户选中的部门*/
public DeptVo getCheckedDept(SysUser loginUser){loginUser = loginUser == null ? LoginUtil.getLoginUser() : loginUser;List<DeptVo> list = loginUser.getDeptArr();DeptVo vo = list.stream().filter(t -> t.getChecked()).findFirst().orElse(null);if (vo == null){throw new ExceptionVo(-1,"获取当前选中部门失败");}return vo;
}

3、数据过滤

数据过滤有两种过滤方式:1、根据部门id过滤(根据当前用户选中的部门id去过滤数据);2、根据当前用户id过滤(只查询当前用户创建的数据)。

第一种的话,没什么好说的,拿到当前用户选中的部门的id就行。

第二种呢就不能只根据用户id去过滤,因为用户是多部门的,所以需要用 用户id+选中的部门id 去过滤数据。这里的话要过滤数据的表在刚开始设计字段的时候,有两种方式:1、可以设计两个字段:create_id(创建人id)、create_dept(创建人部门id),通过这两个字段去过滤数据;2、也可以只设计一个字段,但是这个字段要包含创建人id创建人部门idcreate_id(由创建人id和创建人部门id组合而成),比如:userid#deptid,两个id之间用某个分隔符隔开,后续哪怕需要单独用的用户id也好、部门id也好,都可以很方便的截取出来。(我后面选择的是第二种方式。)

最后

大家如果有类似的需求要做,可以参考一下,我这里也是记录一下自己的实现方案,方便以后再碰到可以直接把代码拿过来用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/283136.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

万用表革新升级,WT588F02BP-14S语音芯片助力智能测量新体验v

万能表功能&#xff1a; 万能表是一款集多功能于一体的电子测量工具&#xff0c;能够精准测量电压、电流、电阻等参数&#xff0c;广泛应用于电气、电子、通信等领域。其操作简便、测量准确&#xff0c;是工程师们进行电路调试、故障排查的得力助手&#xff0c;为提升工作效率…

Sphinx + Readthedocs 避坑速通指南

博主在学习使用 Sphinx 和 Read the docs 的过程中&#xff0c; 碰到了许多奇葩的 bug, 使得很简单的任务花费了很长的时间才解决&#xff0c;现在在这里做一个分享&#xff0c;帮助大家用更少的时间高效上线文档的内容。 总的来说&#xff0c; 任务分为两个部分&#xff1a; …

[音视频学习笔记]七、自制音视频播放器Part2 - VS + Qt +FFmpeg 写一个简单的视频播放器

前言 话不多说&#xff0c;重走霄骅登神路 前一篇文章 [音视频学习笔记]六、自制音视频播放器Part1 -新版本ffmpeg&#xff0c;Qt VS2022&#xff0c;都什么年代了还在写传统播放器&#xff1f; 本文相关代码仓库&#xff1a; MediaPlay-FFmpeg - Public 转载雷神的两个流程…

python_BeautifulSoup爬取汽车评论数据

爬取的网站&#xff1a; 完整代码在文章末尾 https://koubei.16888.com/57233/0-0-0-2 使用方法&#xff1a; from bs4 import BeautifulSoup 拿到html后使用find_all()拿到文本数据&#xff0c;下图可见&#xff0c;数据标签为&#xff1a; content_text soup.find_all…

手机网页关键词视频爬虫采集软件可导出视频分享链接|视频无水印批量下载工具

全新音视频批量下载工具&#xff0c;为您解放视频管理烦恼&#xff01; 现如今&#xff0c;音上涌现出大量精彩的视频内容&#xff0c;但是要想高效地获取、管理和分享这些视频却是一件颇具挑战的事情。针对这一难题&#xff0c;我们自主研发了全新的音视频批量下载工具&#x…

基于javaSpringboot+mybatis+layui的装修验收管理系统设计和实现

基于javaSpringbootmybatislayui的装修验收管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留…

Day41:WEB攻防-ASP应用HTTP.SYS短文件文件解析Access注入数据库泄漏

目录 ASP-默认安装-MDB数据库泄漏下载 ASP-中间件-CVE&短文件&解析&写权限 HTTP.SYS&#xff08;CVE-2015-1635&#xff09;主要用作蓝屏破坏&#xff0c;跟权限不挂钩 IIS短文件(iis全版本都可能有这个问题) IIS文件解析 IIS写权限 ASP-SQL注入-SQLMAP使用…

WPF 立体Border

WPF 立体Border &#xff0c;用来划分各个功能区块 在资源文件中&#xff0c;添加如下样式代码&#xff1a; <Style x:Key"BaseBorder" TargetType"Border"><Setter Property"Background" Value"White" /><Setter Prop…

Mac nvm install failed python: not found

报错 $>./configure --prefix/Users/xxx/.nvm/versions/node/v12.22.12 < ./configure: line 3: exec: python: not found nvm: install v12.22.12 failed!解决方法 到 App 文件夹&#xff0c;并且打开 cd /System/Applications/Utilities/ open .记得改完 Rosetta 之…

(done) 机器学习中的方差 variance 和 偏差 bias 怎么理解?

来源&#xff1a;https://blog.csdn.net/weixin_41479678/article/details/116230631 情况1属于&#xff1a;低 bias&#xff0c;高 variance (和 human performance 相近&#xff0c;但和 验证集dev set 相远) 通常意味着模型训练轮数太多 情况2属于&#xff1a;高 bias&#…

【Django框架学习笔记】超详细的Python后端开发Django框架学习笔记

十二&#xff0c;Django框架 可以以下链接获取Django框架学习笔记,md文档和pdf文档 Django框架超详细的学习笔记&#xff0c;点击我获取 12.1 命令行操作 # 创建django项目 django-admin startproject aini# 启动项目 cd /mysite python3 manage.py runserver## 创建应用 …

GraphPad Prism 10:一站式数据分析解决方案

GraphPad Prism 10是一款功能强大的数据分析和可视化软件&#xff0c;广泛应用于生命科学研究、医学、生物、化学等多个领域。以下是对其详细功能的介绍&#xff1a; 首先&#xff0c;GraphPad Prism 10具有出色的数据可视化功能。它支持各种类型的图表和图形&#xff0c;包括…

MySQL 搭建双主复制服务 并 通过 HAProxy 负载均衡

一、MySQL 搭建双主复制高可用服务 在数据库管理中&#xff0c;数据的备份和同步是至关重要的环节&#xff0c;而双主复制&#xff08;Dual Master Replication&#xff09;作为一种高可用性和数据同步的解决方案&#xff0c;通过让两个数据库实例同时充当主服务器和从服务器&…

python的OA公文发文管理系统flask-django-php-nodejs

采用结构化的分析设计&#xff0c;该方法要求结合一定的图表&#xff0c;在模块化的基础上进行系统的开发工作。在设计中采用“自下而上”的思想&#xff0c;在OA公文发文管理系统实现了用户、公文分类、公文信息、待办提醒等的功能性。系统根据现有的管理模块进行开发和扩展&a…

两台电脑简单的通信过程详解(经过两个路由器,不同网段)

一、eNSP拓扑图 二、配置4台电脑的IP地址、子网掩码、网关地址。 三、配置路由器 1.AR1-接口对应IP <Huawei>sys #进入系统视图 [Huawei]int g0/0/0 #进入0/0/0接口 [Huawei-GigabitEthernet0/0/0]ip address 192.168.0.1 24 #配置ip和掩码 [Huawei-GigabitEthernet0…

智慧城市的发展趋势与挑战:未来展望

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。智慧城市通过集成应用先进的信息通信技术&#xff0c;实现城市管理、服务、运行的智能化&#xff0c;为城市的可持续发展注入了新的活力。然而&#xff0c;在智慧城市的发展过程中&#xff0c;也面临…

LabVIEW焓差试验室流量计现场自动校准系统

LabVIEW焓差试验室流量计现场自动校准系统 在现代工业和科研领域&#xff0c;流量计的准确性对于保证生产过程的质量和效率非常重要。开发了一种基于LabVIEW的焓差试验室流量计现场自动校准系统&#xff0c;通过提高流量计校准的准确性和效率。 在空调器空气焓值法能效测量装…

iOS图片占内存大小与什么有关?

1. 问&#xff1a;一张图片所占内存大小跟什么有关&#xff1f; 图片所占内存大小&#xff0c;与图片的宽高有关 我们平时看到的png、jpg、webp这些图片格式&#xff0c;其实都是图片压缩格式。通过对应的算法来优化了大小以节省网络传输与本地保存所需的资源。 但是当我们加…

Avalonia(11.0.2)+.NET6 打包运行到银河麒麟V10桌面系统

操作系统配置 项目结构 .net版本 这次我们是在银河麒麟V10系统上打包运行Avalonia(11.0.2)+.NET6.0的程序 开始打包 准备Linux下的桌面快捷方式以及图标 调整AvaloniaApplication2.Desktop.csproj的配置项,重点看下图红色线圈出来的部分,里面涉及到了LinuxPath的设置。完整的配…

JS08-DOM节点完整版

DOM节点 查找节点 父节点 <div class="father"><div class="son">儿子</div></div><script>let son = document.querySelector(.son)console.log(son.parentNode);son.parentNode.style.display = none</script>通过…