ruoyi若依平台——部门管理部分源码分析

news2024/10/22 15:39:45

来都来了给我点个赞和收藏关注一下在走呗~~~~🌹🌹🌹

目录

数据库结构:

一、部门查询

二、部门新增

三、后端

Controller——SysDeptController部门CRUD:

1.获取部门列表信息:

2.排除特定节点的部门列表

3.查询部门详情:

4.新增部门:

5.修改部门:

6.删除部门:

domain——部门实体类— SysDept

Mapper——SysDeptMapper

Service

1.SysDeptServiceImpl

2.IsysDeptService


若依框架是一款基于Java的轻量级开源快速开发框架,主要基于Spring Boot、Spring Security和Mybatis Plus框架技术。若依框架内部采用分模块设计,代码清晰简单易于维护,同时提供多种组件,如代码生成、前后端分离、数据权限管理等,可以快速开发出完整的项目。

若依框架具有以下特性:

  • 完全响应式布局,支持电脑、平板、手机等所有主流设备。

  • 强大的一键生成功能,包括控制器、模型、视图、菜单等。

  • 支持多数据源,简单配置即可实现切换。

  • 支持按钮及数据权限,可自定义部门数据权限。

  • 对常用js插件进行二次封装,使js代码变得简洁,更加易维护。

  • 完善的XSS防范及脚本过滤,彻底杜绝XSS攻击。

  • Maven多项目依赖,模块及插件分项目,尽量松耦合,方便模块升级、增减模块。

  • 国际化支持,服务端及客户端支持。

  • 完善的日志记录体系简单注解即可实现。

  • 支持服务监控,数据监控,缓存监控功能。

若依中部门管理功能:配置系统组织机构(公司,部门,小组)树结构展现支持数据权限

数据库结构:

5f29a9d2f1214b76932234269896147b.png


一、部门查询

注意:部门管理是有数据权限的,比如A用户所在的公司是深圳总公司,那么A登录后看到的部门也是深圳总公司。A用户再深圳总公司下增删改查部门,其他公司的用户是看不到的。

1cfef28446824b049883849347887a39.png

二、部门新增

这里需要注意ancestors字段是如何新增的,通过传入上级部门(parent_id),查询到了ancestors。然后拼上前端传过来的dept_id

03f81193bf39401a817eefffefa91654.png

85e51ae80c4e49a09fe2c803cc3a83bf.png

三、后端

Controller——SysDeptController部门CRUD:

主要功能:

1.获取部门列表信息:

  • list方法:根据权限返回所有部门信息列表

     /**
         * 获取部门列表
         */
        @PreAuthorize("@ss.hasPermi('system:dept:list')")
        @GetMapping("/list")
        public AjaxResult list(SysDept dept)
        {
            List<SysDept> depts = deptService.selectDeptList(dept);
            return success(depts);
        }
    
    • 功能:获取所有部门信息

      • 权限校验:需要有system:dept:list权限

      • 返回结果:部门列表

2.排除特定节点的部门列表

  • excludeChild方法:返回除指定部门及其子部门以外的所有部门信息
  • /**
         * 查询部门列表(排除节点)
         */
        @PreAuthorize("@ss.hasPermi('system:dept:list')")
        @GetMapping("/list/exclude/{deptId}")
        //@PathVariable将url中的模板变量绑定到函数参数上,将提取的值赋给Long deptId参数
        public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
        {
            //获取系统中的部门信息列表
            List<SysDept> depts = deptService.selectDeptList(new SysDept());
            depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
            return success(depts);
        }

在上述代码中,通过查询部门对象的id是否与给定的deptId相等,将部门对象的祖先id字符串d.getAncestors()与给定的deptId进行比较,如果相等则删除该部门对象。

  • 功能:返回除指定部门及其子部门之外的所有部门信息

    • 权限校验:需要有system:dept:list权限

    • 返回结果:排除指定部门及其子部门后的部门列表

3.查询部门详情:

getInfo方法:通过部门Id获取具体的部门信息。

/**
     * 根据部门编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId)
    {
        //验证指定的id部门是否在当前用户的可访问范围内
        deptService.checkDeptDataScope(deptId);
        return success(deptService.selectDeptById(deptId));
    }

通过验证指定的id部门是否在当前用户的可访问范围内,然后通过deptService.selectDeptById(deptId)方法获取部门信息,并将查询到的部门信息成功响应的AjaxResult对象并返回给客户端。

  • 功能:通过部门id获取部门详细信息。

    • 权限校验:需要有system:dept:query权限

    • 返回结果:指定部门详细信息。

4.新增部门:

add方法:允许创建新的部门,前提是部门名称必须唯一。

在这里通过判断部门名称是否已经存在,如果存在则返回错误信息;如果不存在,获取当前的用户名并设置到部门对象createBy属性中,然后通过toAjax方法返回对应的AjaxResult对象给前端

/**
     * 新增部门
     */
    @PreAuthorize("@ss.hasPermi('system:dept:add')")    //检查当前用户是否具有操作权限
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    //@PostMapping和@RequestBody注解用于接收前端传递过来的JSON数据,并将其转换为Java对象
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDept dept)
    {
        //判断部门名称是否已经存在,如果存在返回错误信息
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        //获取当前用户名并设置到部门对象createBy属性中
        dept.setCreateBy(getUsername());
        //通过toAjax方法返回相应的AjaxResult对象给前端
        return toAjax(deptService.insertDept(dept));
    }
  • 功能:创建新的部门。

  • 权限校验:需要有system:dept:add权限。

  • 返回结果:操作结果(成功或失败)。

5.修改部门:

edit方法:更新现有的部门信息,确保部门名称唯一且父部门不是自身。

在这里通过@RequestBody注解接收前端传入的部门对象SysDept。并且对部门名称唯一性,父部门,子部门进行校验,确保了部门信息的安全性和一致性

 /**
     * 修改部门
     */
    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDept dept)
    {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        //验证部门的唯一性,如果已存在,返回错误信息
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        //检查父部门是否为本身,如果父部门id与当前部门id相同,返回错误信息
        else if (dept.getParentId().equals(deptId))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
        }
        else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
        {
            return error("该部门包含未停用的子部门!");
        }
        dept.setUpdateBy(getUsername());
        return toAjax(deptService.updateDept(dept));
    }
  • 功能:更新现有部门信息。

  • 权限校验:需要有system:dept:edit权限。

  • 返回结果:操作结果(成功或失败)。

6.删除部门:

remove方法:删除指定部门,前提是该部门没有子部门或关联用户。

/**
     * 删除部门
     */
    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId)
    {
        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return toAjax(deptService.deleteDeptById(deptId));
    }
  • 功能:删除指定部门。

  • 权限校验:需要有system:dept:remove权限。

  • 返回结果:操作结果(成功或失败)。

domain——部门实体类— SysDept

在部门实体类中主要包括部门的基本信息(部门id,父部门id,部门名称等);验证注解(确保字段如部门名称,显示顺序等符合特定规则);部门状态(包括部门的状态正常/启用,显示顺序符合特定规则);附加信息(如负责人,联系电话,邮箱等);父部门名称(存储父部门的名称);子部门列表(维护一个子部门列表,便于表示部门间的层级关系)。

SysDept类是一个典型的业务实体类,它封装了部门的相关数据,并提供了相应的访问接口和数据校验机制。

验证注解:使用了javax.validation.constraints包下的多个注解来校验字段的有效性,例如@NotBlank、@Size、@Email等,确保数据的合法性。

toString方法重写:通过覆盖toString方法,利用ToStringBuilder来自动生成包含所有字段信息的字符串表示形式,便于调试和日志输出。

在这里为什么要使用append方法?

1.简化字符串构造:ToStringBuilder提供的append方法可以方便的将对象的各个属性逐个添加到字符串内,避免了手动拼接字符串的繁琐工作。

2.格式统一:使用ToStringBuilder可以保证生成的字符串格式一致,方便阅读和调试。尤其是当对象有很多属性时,这种方式可以自动处理好格式化问题。

3.性能优化:相比于直接使用字符串拼接(如+操作符),ToStringBuilder内部实现了更高效的字符串构建机制,减少了不必要的临时对象创建,提高了性能。

4.可配置性:ToStringBuilder允许配置不同的样式(如ToStringStyle.MULTI_LINE_STYLE),可以根据需求生成不同样式的字符串表示形式。

/**
 * 部门表 sys_dept
 * 
 * @author ruoyi
 */
public class SysDept extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 部门ID */
    private Long deptId;

    /** 父部门ID */
    private Long parentId;

    /** 祖级列表 */
    private String ancestors;

    /** 部门名称 */
    private String deptName;

    /** 显示顺序 */
    private Integer orderNum;

    /** 负责人 */
    private String leader;

    /** 联系电话 */
    private String phone;

    /** 邮箱 */
    private String email;

    /** 部门状态:0正常,1停用 */
    private String status;

    /** 删除标志(0代表存在 2代表删除) */
    private String delFlag;

    /** 父部门名称 */
    private String parentName;
    
    /** 子部门 */
    private List<SysDept> children = new ArrayList<SysDept>();

    public Long getDeptId()
    {
        return deptId;
    }

    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }

    public Long getParentId()
    {
        return parentId;
    }

    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }

    public String getAncestors()
    {
        return ancestors;
    }

    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }

    @NotBlank(message = "部门名称不能为空")
    @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
    public String getDeptName()
    {
        return deptName;
    }

    public void setDeptName(String deptName)
    {
        this.deptName = deptName;
    }

    @NotNull(message = "显示顺序不能为空")
    public Integer getOrderNum()
    {
        return orderNum;
    }

    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }

    public String getLeader()
    {
        return leader;
    }

    public void setLeader(String leader)
    {
        this.leader = leader;
    }

    @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
    public String getPhone()
    {
        return phone;
    }

    public void setPhone(String phone)
    {
        this.phone = phone;
    }

    @Email(message = "邮箱格式不正确")
    @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
    public String getEmail()
    {
        return email;
    }

    public void setEmail(String email)
    {
        this.email = email;
    }

    public String getStatus()
    {
        return status;
    }

    public void setStatus(String status)
    {
        this.status = status;
    }

    public String getDelFlag()
    {
        return delFlag;
    }

    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }

    public String getParentName()
    {
        return parentName;
    }

    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }

    public List<SysDept> getChildren()
    {
        return children;
    }

    public void setChildren(List<SysDept> children)
    {
        this.children = children;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("deptId", getDeptId())
            .append("parentId", getParentId())
            .append("ancestors", getAncestors())
            .append("deptName", getDeptName())
            .append("orderNum", getOrderNum())
            .append("leader", getLeader())
            .append("phone", getPhone())
            .append("email", getEmail())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .toString();
    }
}

Mapper——SysDeptMapper

该接口定义了与部门管理相关的数据库操作方法:

  • 查询部门列表
    • selectDeptList(SysDept dept): 根据提供的部门信息对象 dept 查询部门列表。
  • 根据角色ID查询部门树信息
    • selectDeptListByRoleId(Long roleId, boolean deptCheckStrictly): 根据角色ID (roleId) 和部门树选择策略 (deptCheckStrictly) 查询部门ID列表。
  • 根据部门ID查询部门信息
    • selectDeptById(Long deptId): 根据部门ID (deptId) 查询单个部门的详细信息。
  • 查询所有子部门
    • selectChildrenDeptById(Long deptId): 根据部门ID (deptId) 查询该部门的所有子部门列表。
  • 查询正常状态的子部门数量
    • selectNormalChildrenDeptById(Long deptId): 根据部门ID (deptId) 查询该部门下的正常状态子部门数量。
  • 检查部门是否有子部门
    • hasChildByDeptId(Long deptId): 检查指定部门ID (deptId) 的部门是否有子部门。
  • 检查部门是否存在用户
    • checkDeptExistUser(Long deptId): 检查指定部门ID (deptId) 的部门下是否存在用户。
  • 校验部门名称是否唯一
    • checkDeptNameUnique(String deptName, Long parentId): 校验给定的部门名称 (deptName) 在其父部门 (parentId) 下是否唯一。
  • 新增部门信息
    • insertDept(SysDept dept): 插入新的部门信息到数据库。
  • 修改部门信息
    • updateDept(SysDept dept): 更新部门信息。
  • 修改部门状态为正常
    • updateDeptStatusNormal(Long[] deptIds): 批量将多个部门的状态设置为正常。
  • 更新部门及其子部门信息
    • updateDeptChildren(List<SysDept> depts): 更新部门及其子部门的信息。
  • 删除部门信息
    • deleteDeptById(Long deptId): 根据部门ID (deptId) 删除部门信息。
/**
 * 部门管理 数据层
 * 
 * @author ruoyi
 */
public interface SysDeptMapper
{
    /**
     * 查询部门管理数据
     * 
     * @param dept 部门信息
     * @return 部门信息集合
     */
    public List<SysDept> selectDeptList(SysDept dept);

    /**
     * 根据角色ID查询部门树信息
     * 
     * @param roleId 角色ID
     * @param deptCheckStrictly 部门树选择项是否关联显示
     * @return 选中部门列表
     */
    public List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);

    /**
     * 根据部门ID查询信息
     * 
     * @param deptId 部门ID
     * @return 部门信息
     */
    public SysDept selectDeptById(Long deptId);

    /**
     * 根据ID查询所有子部门
     * 
     * @param deptId 部门ID
     * @return 部门列表
     */
    public List<SysDept> selectChildrenDeptById(Long deptId);

    /**
     * 根据ID查询所有子部门(正常状态)
     * 
     * @param deptId 部门ID
     * @return 子部门数
     */
    public int selectNormalChildrenDeptById(Long deptId);

    /**
     * 是否存在子节点
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    public int hasChildByDeptId(Long deptId);

    /**
     * 查询部门是否存在用户
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    public int checkDeptExistUser(Long deptId);

    /**
     * 校验部门名称是否唯一
     * 
     * @param deptName 部门名称
     * @param parentId 父部门ID
     * @return 结果
     */
    public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);

    /**
     * 新增部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    public int insertDept(SysDept dept);

    /**
     * 修改部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    public int updateDept(SysDept dept);

    /**
     * 修改所在部门正常状态
     * 
     * @param deptIds 部门ID组
     */
    public void updateDeptStatusNormal(Long[] deptIds);

    /**
     * 修改子元素关系
     * 
     * @param depts 子元素
     * @return 结果
     */
    public int updateDeptChildren(@Param("depts") List<SysDept> depts);

    /**
     * 删除部门管理信息
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    public int deleteDeptById(Long deptId);
}

Service

1.SysDeptServiceImpl

该Java类实现了部门管理服务接口ISysDeptService,提供了多个方法用于管理和操作部门信息。主要功能包括:

  • 查询部门列表:根据部门信息筛选并返回部门列表。
  • 构建部门树结构:将部门列表转化为树形结构,方便前端展示。
  • 根据角色ID查询部门:查找与特定角色关联的部门列表。
  • 查询部门详情:通过部门ID获取详细信息。
  • 检查部门是否包含子部门或用户:验证部门下是否存在子部门或用户。
  • 校验部门名称唯一性和数据权限:确保部门名称在同级内唯一,并检查用户对部门的数据访问权限。
  • 增删改部门信息:实现部门信息的创建、更新和删除操作,同时处理相关联的数据变更。
  • 递归子部门:辅助方法,用于构建部门树时递归查找子部门
/**
 * 部门管理 服务实现
 * 
 * @author ruoyi
 */
@Service
public class SysDeptServiceImpl implements ISysDeptService
{
    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    /**
     * 查询部门管理数据
     * 
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    //数据权限过滤
    @DataScope(deptAlias = "d")
    public List<SysDept> selectDeptList(SysDept dept)
    {
        return deptMapper.selectDeptList(dept);
    }

    /**
     * 查询部门树结构信息
     * 
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    @Override
    public List<TreeSelect> selectDeptTreeList(SysDept dept)
    {
        //获取当前类的AOP代理对象,并存储
        List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
        return buildDeptTreeSelect(depts);
    }

    /**
     * 构建前端所需要树结构
     * 
     * @param depts 部门列表
     * @return 树结构列表
     */
    @Override
    public List<SysDept> buildDeptTree(List<SysDept> depts)
    {
        List<SysDept> returnList = new ArrayList<SysDept>();
        //提取部门id,使用java8流式api从depts列表中提取所有部门id到tempList中
        List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        //遍历部门列表
        for (SysDept dept : depts)
        {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId()))
            {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = depts;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     * 
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts)
    {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 根据角色ID查询部门树信息
     * 
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    @Override
    public List<Long> selectDeptListByRoleId(Long roleId)
    {
        SysRole role = roleMapper.selectRoleById(roleId);
        return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
    }

    /**
     * 根据部门ID查询信息
     * 
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Override
    public SysDept selectDeptById(Long deptId)
    {
        return deptMapper.selectDeptById(deptId);
    }

    /**
     * 根据ID查询所有子部门(正常状态)
     * 
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public int selectNormalChildrenDeptById(Long deptId)
    {
        return deptMapper.selectNormalChildrenDeptById(deptId);
    }

    /**
     * 是否存在子节点
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public boolean hasChildByDeptId(Long deptId)
    {
        //调用deptMapper的hashChildByDeptId方法查询指定部门ID下是否有子部门,如果查询结果数量大于0,表示存在子部门,返回true,否则返回false
        int result = deptMapper.hasChildByDeptId(deptId);
        return result > 0;
    }

    /**
     * 查询部门是否存在用户
     * 
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkDeptExistUser(Long deptId)
    {
        int result = deptMapper.checkDeptExistUser(deptId);
        return result > 0;
    }

    /**
     * 校验部门名称是否唯一
     * 
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public boolean checkDeptNameUnique(SysDept dept)
    {
        //将部门id转换位Long类型,默认值为-1
        Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
        SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
        if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验部门是否有数据权限
     * 
     * @param deptId 部门id
     */
    @Override
    public void checkDeptDataScope(Long deptId)
    {
        if (!SysUser.isAdmin(SecurityUtils.getUserId()) && StringUtils.isNotNull(deptId))
        {
            SysDept dept = new SysDept();
            dept.setDeptId(deptId);
            List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
            if (StringUtils.isEmpty(depts))
            {
                throw new ServiceException("没有权限访问部门数据!");
            }
        }
    }

    /**
     * 新增保存部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertDept(SysDept dept)
    {
        SysDept info = deptMapper.selectDeptById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus()))
        {
            throw new ServiceException("部门停用,不允许新增");
        }
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        return deptMapper.insertDept(dept);
    }

    /**
     * 修改保存部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int updateDept(SysDept dept)
    {
        SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId());
        SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
        {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }
        int result = deptMapper.updateDept(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
                && !StringUtils.equals("0", dept.getAncestors()))
        {
            // 如果该部门是启用状态,则启用该部门的所有上级部门
            updateParentDeptStatusNormal(dept);
        }
        return result;
    }

    /**
     * 修改该部门的父级部门状态
     * 
     * @param dept 当前部门
     */
    private void updateParentDeptStatusNormal(SysDept dept)
    {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        deptMapper.updateDeptStatusNormal(deptIds);
    }

    /**
     * 修改子元素关系
     * 
     * @param deptId 被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors)
    {
        List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
        for (SysDept child : children)
        {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0)
        {
            deptMapper.updateDeptChildren(children);
        }
    }

    /**
     * 删除部门管理信息
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int deleteDeptById(Long deptId)
    {
        return deptMapper.deleteDeptById(deptId);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDept> list, SysDept t)
    {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDept> getChildList(List<SysDept> list, SysDept t)
    {
        List<SysDept> tlist = new ArrayList<SysDept>();
        Iterator<SysDept> it = list.iterator();
        while (it.hasNext())
        {
            SysDept n = (SysDept) it.next();
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDept> list, SysDept t)
    {
        return getChildList(list, t).size() > 0;
    }
}

2.IsysDeptService

该Java接口定义了一系列与部门管理相关的服务方法,具体功能如下:

  • 查询部门管理数据
    • 方法:selectDeptList(SysDept dept)
    • 功能:根据提供的部门信息对象查询符合条件的所有部门信息,并返回一个部门信息列表。
  • 查询部门树结构信息
    • 方法:selectDeptTreeList(SysDept dept)
    • 功能:根据部门信息对象获取部门树形结构的数据列表。
  • 构建前端所需树结构
    • 方法:buildDeptTree(List<SysDept> depts)
    • 功能:接收一个部门列表作为参数,并将其转换为前端展示所需的树形结构。
  • 构建前端所需下拉树结构
    • 方法:buildDeptTreeSelect(List<SysDept> depts)
    • 功能:将部门列表转换成适合前端选择框使用的树形结构。
  • 根据角色ID查询部门树信息
    • 方法:selectDeptTreeListByRoleId(Long roleId)
    • 功能:通过角色ID来获取该角色相关的部门树信息。
  • 根据部门ID查询信息
    • 方法:selectDeptById(Long deptId)
    • 功能:通过部门ID查询并返回具体的部门信息对象。
  • 查询正常状态下的子部门数量
    • 方法:selectNormalChildrenDeptById(Long deptId)
    • 功能:统计指定部门ID下的所有正常状态的子部门数量。
  • 判断部门是否有子节点
    • 方法:hasChildByDeptId(Long deptId)
    • 功能:检查指定部门ID的部门是否有子部门,并返回布尔值结果。
  • 检查部门是否存在用户
    • 方法:checkDeptExistUser(Long deptId)
    • 功能:验证指定部门ID的部门下是否存在用户,并返回布尔值结果。
  • 校验部门名称是否唯一
    • 方法:checkDeptNameUnique(SysDept dept)
    • 功能:验证给定部门信息中的名称在整个系统中是否唯一。
  • 校验部门是否有数据权限
    • 方法:checkDeptDataScope(Long deptId)
    • 功能:确保当前操作者对指定部门ID的部门具有相应的数据访问权限。
  • 新增保存部门信息
    • 方法:insertDept(SysDept dept)
    • 功能:将新的部门信息保存到数据库中,并返回操作结果。
  • 修改保存部门信息
    • 方法:updateDept(SysDept dept)
    • 功能:更新现有部门的信息,并返回操作结果。
  • 删除部门管理信息
    • 方法:deleteDeptById(Long deptId)
    • 功能:根据部门ID从数据库中删除对应的部门记录,并返回操作结果。
/**
 * 部门管理 服务层
 * 
 * @author ruoyi
 */
public interface ISysDeptService
{
    /**
     * 查询部门管理数据
     * 
     * @param dept 部门信息
     * @return 部门信息集合
     */
    public List<SysDept> selectDeptList(SysDept dept);

    /**
     * 查询部门树结构信息
     * 
     * @param dept 部门信息
     * @return 部门树信息集合
     */
    public List<TreeSelect> selectDeptTreeList(SysDept dept);

    /**
     * 构建前端所需要树结构
     * 
     * @param depts 部门列表
     * @return 树结构列表
     */
    public List<SysDept> buildDeptTree(List<SysDept> depts);

    /**
     * 构建前端所需要下拉树结构
     * 
     * @param depts 部门列表
     * @return 下拉树结构列表
     */
    public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts);

    /**
     * 根据角色ID查询部门树信息
     * 
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    public List<Long> selectDeptListByRoleId(Long roleId);

    /**
     * 根据部门ID查询信息
     * 
     * @param deptId 部门ID
     * @return 部门信息
     */
    public SysDept selectDeptById(Long deptId);

    /**
     * 根据ID查询所有子部门(正常状态)
     * 
     * @param deptId 部门ID
     * @return 子部门数
     */
    public int selectNormalChildrenDeptById(Long deptId);

    /**
     * 是否存在部门子节点
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    public boolean hasChildByDeptId(Long deptId);

    /**
     * 查询部门是否存在用户
     * 
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    public boolean checkDeptExistUser(Long deptId);

    /**
     * 校验部门名称是否唯一
     * 
     * @param dept 部门信息
     * @return 结果
     */
    public boolean checkDeptNameUnique(SysDept dept);

    /**
     * 校验部门是否有数据权限
     * 
     * @param deptId 部门id
     */
    public void checkDeptDataScope(Long deptId);

    /**
     * 新增保存部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    public int insertDept(SysDept dept);

    /**
     * 修改保存部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    public int updateDept(SysDept dept);

    /**
     * 删除部门管理信息
     * 
     * @param deptId 部门ID
     * @return 结果
     */
    public int deleteDeptById(Long deptId);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ 算法学习——1.8 单调栈算法

单调栈&#xff08;Monotonic Stack&#xff09;是一种在解决一些数组或者链表相关问题时非常有用的数据结构和算法。在C中&#xff0c;单调栈通常用于解决一些需要快速找到元素左右第一个比当前元素大或小的问题。 定义&#xff1a; 单调栈实际上是一个栈&#xff0c;但是与普…

《大规模语言模型从理论到实践》第一轮学习--强化学习(RLHF、PPO)

个人学习笔记,如有错误欢迎指出。 一、强化学习的意义 RLHF(Reinforcement Learning from Human Feedback):强化学习(Reinforcement Learning)结合人类反馈(Human Feedback)来微调大语言模型。 大语言模型的训练步骤包括:预训练、指令微调(SFT)、对齐。 对齐(a…

NVM 安装步骤

NVM 安装步骤 文章目录 NVM 安装步骤一、NVM 是什么二、用途三、安装步骤详解1. 下载与安装2. 验证安装3. 安装Node.js4. 使用安装的Node.js版本5. 验证Node.js安装 四、NVM 常用命令1. 查看已安装的Node.js版本2. 安装指定版本的Node.js3. 卸载指定版本的Node.js4. 切换到已安…

Redis面试题——第四篇

1. Redis主从复制的常见拓扑结构有哪些 一主多从&#xff1a;这是最基本的拓扑结构&#xff0c;包含一个主节点和多个从节点&#xff0c;所有写操作都在主节点上执行&#xff0c;而读操作可以在从节点上进行&#xff0c;以提高读取速度和负载均衡。 树状主从结构&#xff1a;从…

小米澎湃工具箱,一键获取权限

Hyper工具箱已初步支持魅族设备一键获取权限&#xff0c;配置扫描与ROM包索引均已适配Flyme。 支持小米、魅族手机 功能不止刷机、获取权限更多功能下载体验&#xff01; 下载&#xff1a;https://pan.quark.cn/s/4e78f870813f

试着了解YOLOx

在特征提取上来说&#xff0c;主干部分使用了focus网络结构&#xff0c;对特征点进行了划分&#xff0c;将特征点信息堆叠到通道上。 同时采用CSPnet结构&#xff0c;在残差网络堆叠的同时&#xff0c;构建大的残差边&#xff0c;经过少量处理直接连接到最后。 过去的YOLO将分…

数据库系统概论之关系数据库标准语言SQL(一)【超详细】

教材&#xff1a; 数据库系统概论&#xff08;第6版&#xff09;王珊,杜小勇,陈红编著 目录 一、SQL概述 1.1 SQL 的产生与发展 1.2 SQL的特点 1.3 SQL的基本概念 二、数据定义 2.1 数据库的定义 2.2 数据表的定义 2.3 模式的定义 一、SQL概述 1974年IBM为关系DBMS设…

组合式二值编码

论文名称&#xff1a;《A Practical Approach to 3D Scanning in the Presence ofInterreflections, Subsurface Scattering and Defocus》 简介&#xff1a;组合式二值编码&#xff08;包含传统格雷码&#xff0c;XOR-02&#xff0c;XOR-04&#xff0c;minSW&#xff09;&…

Java学习Day25:基础篇15:反射

Java 反射&#xff08;Reflection&#xff09; 1.前置反应 是 Java 编程语言的一个强大特性&#xff0c;它允许程序在运行时检查或修改类的行为。这包括获取类的信息&#xff08;如字段、方法、构造函数等&#xff09;&#xff0c;以及动态地创建对象、调用方法、访问和修改字…

linux的学习第二天

1.vmware的功能&#xff1a; 快照 创建快照&#xff1a; 拍摄此虚拟机的快照&#xff1a;记录保存虚拟机的当前状态&#xff0c;如果系统出现故障&#xff0c;可以通过快照还原&#xff08;错删系统时可以找到快照的系统状态&#xff0c;然后恢复系统&#xff09; 恢复快照…

java项目之精品在线试题库系统设计与实现源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的精品在线试题库系统设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 精品在线试…

sentinel dashboard分布式改造落地设计实现解释(二)-分布式discovery组件

discovery discovery负责维护app/机器资料库&#xff0c;transport健康检测&#xff0c; transport上下线处理。discovery关键是分布式存储&#xff0c;后续研究一下raft&#xff0c;其复制&#xff0c;状态机&#xff0c;快照技术&#xff0c;但个人觉得&#xff0c;discover…

软件分享 | 截图工具 Snipaste

今天分享&#xff1a; 今日分享的是一款截图界的神器——Snipaste&#xff01; 特点&#xff1a; &#x1f3a8; 超清截图&#xff1a; Snipaste的截图功能&#xff0c;清晰度超乎你的想象。无论是工作文档还是游戏画面&#xff0c;都能一键捕捉&#xff0c;细节尽在掌握。 …

Excel:将一列拆分成多列

实现的效果是&#xff1a; 操作步骤如下&#xff1a; 1.选中列 → 点击菜单栏中的"数据" → 分列 2.选择"分列符号"&#xff0c;点击下一步 3.我想要按照空格分列&#xff0c;就选择空格 4.点击完成&#xff0c;就可以实现分列的效果了

uniapp学习(004-2 组件 Part.2生命周期)

零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战&#xff0c;开发打包微信小程序、抖音小程序、H5、安卓APP客户端等 总时长 23:40:00 共116P 此文章包含第31p-第p35的内容 文章目录 组件生命周期我们主要使用的三种生命周期setup(创建组件时执行)不可以操作dom节点…

Shell编程-if判断

作者介绍&#xff1a;简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们前面学习了那么多命令&#xff0c;以及涉及到部分逻辑判断的问题。从简单来说&#xff0c;他就是Shell编…

【XYFrame unity框架使用文档】封装unity小框架工具集 —— XYFrame

文章目录 XYFrame介绍优点获取框架源码引入的第三方插件作者信息技术交流群反馈企鹅裙画饼使用文档导入文件目录启动1、单例模式不继承MonoBehaviour的单例模式基类继承MonoBehaviour的单例模式基类 2、Mono管理器3、事件管理系统4、工具类封装unity协程工具&#xff0c;避免 G…

每周心赏|必备AI神器第二弹

大家的假期都是怎么度过的&#xff1f;是已经玩嗨了&#xff1f;还是在家葛优躺&#xff0c;感叹时间飞逝呢&#xff1f; 别急&#xff0c;假期还没完全说拜拜呢&#xff01;赶紧抓住假期最后的尾巴&#xff0c;和AI神器一起&#xff0c;把快乐放大&#xff0c;不留遗憾&#x…

prompt learning

prompt learning 对于CLIP&#xff08;如上图所示&#xff09;而言&#xff0c;对其prompt构造的更改就是在zero shot应用到下游任务的时候对其输入的label text进行一定的更改&#xff0c;比如将“A photo of a{obj}”改为“[V1][V2]…[Vn][Class]”这样可学习的V1-Vn的token…

Docker配置网站环境

Mysql 先安装mysql 启动并后台运行&#xff1a;run -d 容器名称&#xff1a;--name 设置端口映射&#xff1a;-p 主机端口&#xff1a;容器端口 环境变量&#xff1a;-e 最后指定镜像名称 sudo docker run -d \--name mysql\-p 3306:3306\-e MYSQL_ROOT_PASSWORD123456\…