前言

本文主要介绍基于SpringBoot+MyBatisPlus+Vue实现组织架构功能,效果图如下:

vue3 组织架构带照片插件 vue实现组织架构图_vue.js

后端代码实现

1.数据库表设计

该功能模块主要涉及了5张表,分别为员工表、部门表、员工部门关联表、职位表、员工职位关联表,具体的结构设计如下:

//员工表
CREATE TABLE `tb_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `realname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '真实姓名',
  `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码',
  `secret_key` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码密钥',
  `phone` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系方式',
  `gender` tinyint(1) NULL DEFAULT NULL COMMENT '性别,0男1女',
  `status` tinyint(1) NULL DEFAULT NULL COMMENT '账号状态,0注销1正常2冻结',
  `email` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `index_phone_unique`(`phone`) USING BTREE,
  UNIQUE INDEX `index_username_unique`(`username`) USING BTREE,
  UNIQUE INDEX `email_UNIQUE`(`email`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

//部门表
CREATE TABLE `tb_dept`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `parent_id` int(11) NULL DEFAULT NULL,
  `dept_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `del_flag` tinyint(1) NULL DEFAULT 1 COMMENT '0已删除1未删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

//员工部门关系表
CREATE TABLE `tb_dept_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `user_id` int(11) NULL DEFAULT NULL COMMENT '用户id',
  `dept_id` int(11) NULL DEFAULT NULL COMMENT '部门id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

//职位表
CREATE TABLE `tb_position`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `position_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '职位名',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

//员工职位关联表
CREATE TABLE `tb_position_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `user_id` int(11) NULL DEFAULT NULL COMMENT '用户id',
  `position_id` int(11) NULL DEFAULT NULL COMMENT '职位id',
  `status` tinyint(1) NULL DEFAULT NULL COMMENT '状态,0离职1在职',
  `entry_time` date NULL DEFAULT NULL COMMENT '入职时间',
  `leave_time` date NULL DEFAULT NULL COMMENT '离职时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

 2.添加依赖

<!--spring-boot启动依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<!--spring-boot web依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql依赖-->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
    <version>8.0.27</version>
</dependency>
<!--lombok依赖-->
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>
<!--mybatis-plus启动依赖-->
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.5.1</version>
</dependency>
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-extension</artifactId>
	<version>3.5.1</version>
</dependency>

3. 创建相应的实体类

entity 包下,创建相应的实体类,这里只展示User 、Dept实体类。

@Getter
@Setter
@TableName("tb_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
     /**
    * id
    */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
      /**
     * 用户名
     */
    private String username;
      /**
     * 真实姓名
     */
    private String realname;
      /**
     * 密码
     */
    private String password;
      /**
     * 密码密钥
     */
    private String secretKey;
      /**
     * 联系方式
     */
    private String phone;
      /**
     * 性别,0男1女
     */
    private Integer gender;
      /**
     * 账号状态,0注销1正常2冻结
     */
    private Integer status;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 0已删除1未删除
     */
    private Integer delFlag;
}
@Getter
@Setter
@TableName("tb_dept")
public class Dept implements Serializable {
    private static final long serialVersionUID = 1L;
      /**
     * id
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 父节点id
     */
    private Integer parentId;
      /**
     * 部名门
     */
    private String deptName;
      /**
     * 0已删除1未删除
     */
    private Integer delFlag;
    /**
     * 子节点
     */
    @TableField(exist = false)
    private List<Dept> childNode;

    //是否有孩子节点
    @JsonIgnore
    @TableField(exist = false)
    private Boolean flag = false;

    // 添加结点到孩子结点集合
    public void addChildren(Dept dept) {
        this.childNode.add(dept);
    }

    // 设置有孩子结点
    public void hasChildren() {
        if (this.flag) {
            return;
        }
        this.flag = true;
        this.childNode = new ArrayList<>();
    }
}

4.创建VO类

创建Staff类

@Data
public class Staff {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @ApiModelProperty(value = "用户id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer userId;
    /**
     * 真实姓名
     */
    @ApiModelProperty(value = "真实姓名")
    private String realname;
    /**
     * 邮箱
     */
    @ApiModelProperty(value = "邮箱")
    private String email;
    /**
     * 联系方式
     */
    @ApiModelProperty(value = "手机号")
    private String phone;
    /**
     * 部名id
     */
    @ApiModelProperty(value = "部门id")
    private Integer deptId;
    /**
     * 部名门
     */
    @ApiModelProperty(value = "部门名")
    private String deptName;
    /**
     * 职位id
     */
    @ApiModelProperty(value = "职位id")
    private Integer positionId;
    /**
     * 职位名
     */
    @ApiModelProperty(value = "职位名")
    private String positionName;
    /**
     * 性别,0男1女
     */
    @ApiModelProperty(value = "性别")
    private Integer gender;
    /**
     * 状态,0离职1在职
     */
    @ApiModelProperty(value = "就职状态")
    private Integer status;
    /**
     * 账号状态,0注销1正常2冻结
     */
    @ApiModelProperty(value = "账号状态")
    private Integer accountStatus;
    /**
     * 入职时间
     */
    @ApiModelProperty(dataType = "java.sql.Date",example = "2020/01/01",value = "入职时间")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone="GMT+8")
    private Date entryTime;
    /**
     * 离职时间
     */
    @ApiModelProperty(dataType = "java.sql.Date",example = "2020/01/01",value = "离职时间")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone="GMT+8")
    private Date leaveTime;

}

创建Result统一结果返回类

@Data
@AllArgsConstructor
public class Result<T> {
    //代码
    private Integer code;
    //消息
    private String msg;
    //数据
    private Map<String,T> data = new HashMap<>();

    private Result() {}

    // 成功
    public static Result success() {
        Result result = new Result();
        result.setCode(200);
        result.setMsg("成功");
        return result;
    }

    public static Result success(int code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(message);
        return result;
    }

    // 失败
    public static Result error() {
        Result result = new Result();
        result.setCode(400);
        result.setMsg("失败");
        return result;
    }

    // 失败
    public static Result error(String message) {
        Result result = new Result();
        result.setCode(400);
        result.setMsg(message);
        return result;
    }

    public static Result error(int code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(message);
        return result;
    }

    public Result data(String key, T value){
        this.data.put(key, value);
        return this;
    }

    public Result data(Map<String, T> map){
        this.setData(map);
        return this;
    }
}

5.Mapper类

 UserMapper 数据访问接口,mapper 包下,继承MyBatisPlus的 BaseMapper,内部封装了单表的大部分操作。此处不展示其他mapper类。

@Mapper
public interface UserMapper extends BaseMapper<User> {
    IPage<Staff> selectStaffPage(IPage<Staff> page, @Param("id")Integer id);
}

6.mapper.xml配置文件

<select id="selectStaffPage" resultType="com.example.bugtrackingsystem.vo.staff.Staff">
        select
            *,u.id as userId,u.status as accountStatus,pu.status as status,d.id as deptId,pu.id as position_id
        from tb_user u
                 join tb_dept_user du on u.id=du.user_id
                 join tb_dept d on d.id=du.dept_id
                 join tb_position_user pu on u.id=pu.user_id
                 join tb_position p on pu.position_id=p.id
        where  u.del_flag=1
</select>

7.Service接口

public interface IUserService extends IService<User> {
    
    //根据部门id分页查询员工信息
    IPage<Staff> selectStaffPage(IPage<Staff> page, Integer id);
    
}
public interface IDeptService extends IService<Dept> {
    //查询所有部门信息
    List<Dept> getDeptList();
}

 8.Service实现类

DeptServiceImpl类中构造出部门的树形结构。

@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {
    @Autowired
    private DeptMapper deptMapper;
    public List<Dept> getDeptList(){
        //条件构造器
        QueryWrapper<Dept> wrapper = new QueryWrapper<Dept>();
        wrapper.eq("del_flag",1);
        //一次性查询所有数据
        List<Dept> depts = deptMapper.selectList(wrapper);
        //存储Dept->返回树形结构
        List<Dept> result = new ArrayList<>();
        // 构造树形结构
        for (int i = 0; i < depts.size(); i++) {
            Dept parent = depts.get(i);
            // 如果是根节点,则添加至树形结果列表
            if (parent.getParentId() == 0 || StringUtils.equals(Integer.toString(parent.getId()), Integer.toString(parent.getParentId()))) {
                result.add(parent);
            }
            for (int j = 0; j < depts.size(); j++) {
                Dept children = depts.get(j);
                // 判断children是否是parent的孩子节点
                if (children.getParentId()!=null && StringUtils.equals(Integer.toString(parent.getId()), Integer.toString(children.getParentId()))) {
                    parent.hasChildren();
                    parent.addChildren(children);
                }
            }
        }
        return result;
    }
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;  

    //根据部门id分页查询员工信息
    public IPage<Staff> selectStaffPage(IPage<Staff> page, @Param("id")Integer id){
        return userMapper.selectStaffPage(page,id);
    }
}

 9.Controller类

@RestController
@RequestMapping("/dept")
public class DeptController {
    @Autowired
    private IDeptService deptService;
    @ApiOperation("组织架构-获取部门信息接口")
    @GetMapping("/getDeptList")
    public Result getDeptList(){
        List<Dept> deptList = deptService.getDeptList();
        Map<String,Object> map = new HashMap<>();
        map.put("data",deptList);
        // 返回给前端的Result
        Result result = new Result(Code.SUCCESS,"查询成功",map);
        return result;
    }
}
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;

    @ApiOperation("组织架构-根据部门分页获取员工信息接口")
    @PostMapping("/selectStaffPage")
    public Result selectStaffPage(@RequestParam("page") Integer page,@RequestParam("size") Integer size,@RequestParam("deptId") Integer deptId) {
        Page<Staff> iPage = new Page<>(page, size);
        IPage<Staff> staffPage = userService.selectStaffPage(iPage, deptId);
        Map<String, Object> map = new HashMap<>();
        map.put("records", staffPage.getRecords());
        map.put("total", staffPage.getTotal());
        // 返回给前端的Result
        Result result = new Result(Code.SUCCESS, "查询成功", map);
        return result;
    }
}

前端实现

前端部分的代码实现可访问以下链接:  


总结 

感谢大家的观看,希望对大家有帮助,有问题可以指出 !