微人事项目学习之部门管理

学习SpringBoot+Vue前后端分离项目,原项目GitHub地址,项目作者江雨一点雨博客。

前端页面设计

DepMana.vue

<template>
    <div style="width: 500px;">
        <el-input
            placeholder="输入部门名称进行搜索"
            prefix-icon="el-icon-search"
            v-model="filterText">
        </el-input>

        <el-tree
                style="margin-top: 10px"
                :data="deps"
                :props="defaultProps"
                //是否在点击节点时展开或收缩节点,默认为true,false为只有点击箭头图标才有效。
                :expand-on-click-node="false"
                :filter-node-method="filterNode"
                ref="tree">
            <span class="custom-tree-node" style="display: flex;justify-content: space-between;width: 100%" slot-scope="{ node, data }">
        <span>{{ data.name }}</span>
        <span>
          <el-button
                  type="primary"
                  size="mini"
                  class="depBtn"
                  @click="() => showAddDepView(data)">
            添加部门
          </el-button>
          <el-button
                  type="danger"
                  size="mini"
                  class="depBtn"
                  @click="() => deleteDep(data)">
            删除部门
          </el-button>
        </span>
      </span>
        </el-tree>
        <el-dialog
                title="添加部门"
                :visible.sync="dialogVisible"
                width="30%">
            <div>
                <div>
                    <el-tag style="margin-bottom: 8px;margin-right: 8px">上级部门</el-tag>
                    <span>{{pname}}</span>
                </div>
                <div>
                    <el-tag style="margin-right: 8px">部门名称</el-tag>
                    <el-input v-model="dep.name" size="small" placeholder="请输入部门名称..." style="width: 70%"></el-input>
                </div>
            </div>
            <span slot="footer" class="dialog-footer">
    <el-button size="small" @click="dialogVisible = false">取 消</el-button>
    <el-button size="small" type="primary" @click="doAddDep">确 定</el-button>
  </span>
        </el-dialog>
    </div>
</template>

<script>
    export default {
        name: "DepMana",
        data(){
          return{
              filterText:'',
              deps:[],
              dialogVisible:false,
              dep:{
                name:'',
                parentId:-1,

              },
              pname:'',
              defaultProps: {
                  children: 'children',
                  label: 'name'
              }
          }
        },
        watch: {
            filterText(val) {
                this.$refs.tree.filter(val);
            }
        },
        mounted(){
          this.initDeps();
        },
        methods: {
            removeDep2Deps(deps,id){
                for (let i = 0; i <deps.length; i++) {
                    let d=deps[i];
                    if (d.id == id) {
                       deps.splice(i,1);
                        return;
                    }else {
                        this.removeDep2Deps(d.children,id);
                    }
                }
            },
            addDep2Deps(deps,dep){
                for (let i = 0; i <deps.length; i++) {
                        let d=deps[i];
                        if (d.id == dep.parentId) {
                            d.children=d.children.concat(dep);
                            return;
                        }else {
                            this.addDep2Deps(d.children,dep);
                        }
                }
            },
            initDep(){
                this.dep={
                    name:'',
                    parentId:-1,
                };
                this.pname=''
            },
            doAddDep(){
                this.postRequest("/system/basic/department/",this.dep).then(resp=>{
                    if (resp) {
                        this.addDep2Deps(this.deps,resp.obj);
                        this.initDep();
                        this.dialogVisible=false;
                    }
                })
            },
            deleteDep(data){
                if (data.parent) {
                    this.$message.error("父部门删除失败")
                }else {
                    this.$confirm('此操作将永久删除【' + data.name + '】部门, 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(() => {
                        this.deleteRequest("/system/basic/department/" + data.id).then(resp => {
                            if (resp) {
                                this.removeDep2Deps(this.deps,data.id);
                                this.initDep();
                                this.dialogVisible=false;
                            }
                        })
                    }).catch(() => {
                        this.$message({
                            type: 'info',
                            message: '已取消删除'
                        });
                    });
                }
            },
            showAddDepView(data){
                this.pname=data.name;
                this.dep.parentId=data.id;
                this.dialogVisible=true;
            },
            initDeps(){
                this.getRequest("/system/basic/department/").then(resp=>{
                    if (resp) {
                        this.deps=resp;
                    }
                })
            },
            filterNode(value, data) {
                if (!value) return true;
                return data.name.indexOf(value) !== -1;
            }
        },
    }
</script>

<style>
    .depBtn{
        padding: 2px;
    }

</style>

搜索功能详解

在部门管理页面有搜索功能可以快速定位到想要找的部门,filterText受到watch监控,当你在输入框打字时,就会调用watch里的filterText方法,val即你输入的字符。然后执行tree里面的filterNode方法,

filterNode(value, data) {
                if (!value) return true;
                return data.name.indexOf(value) !== -1;
            }

value指输入的字符,data则是传入的JSON数据。如果value不存在或者为空,当前data保留,即部门树全部展开。
如果value有值,查看data中的name包含value的下标是否等于-1,等于-1返回true,当前data保留,否则剔除。

后端端口设计

Department

model/Department 添加result和getter setter

private Integer result;

Controller

DepartmentController

@RestController
@RequestMapping("/system/basic/department")
public class DepartmentController {
    @Autowired
    DepartmentService departmentService;
    @GetMapping("/")
    public List<Department> getAllDepartments(){
        return departmentService.getAllDepartments();
    }
    @PostMapping("/")
    public RespBean addDep(@RequestBody Department dep){
        departmentService.addDep(dep);
        if (dep.getResult()==1){
            return RespBean.ok("添加成功",dep);
        }
        return RespBean.error("添加失败");
    }
    @DeleteMapping("/{id}")
    public RespBean deleteDepById(@PathVariable Integer id){
        Department dep=new Department();
        dep.setId(id);
        departmentService.deleteDepById(dep);
        //对应下面的deleteDep返回的result
        if (dep.getResult()==-2){
            return RespBean.error("该部门下有子部门,删除失败");
        }else if (dep.getResult()==-1){
            return RespBean.error("该部门下有员工,删除失败");
        }else if (dep.getResult()==1){
            return RespBean.ok("删除成功");
        }
        return RespBean.error("删除失败");
    }
}

Service

DepartmentService

@Service
public class DepartmentService {

    @Autowired
    DepartmentMapper departmentMapper;
    public List<Department> getAllDepartments() {
        return departmentMapper.getAllDepartmentsByParentId(-1);
    }

    public void addDep(Department dep) {
        dep.setEnabled(true);
        departmentMapper.addDep(dep);
    }

    public void deleteDepById(Department dep) {
        departmentMapper.deleteDepById(dep);
    }
}

Mapper

DepartmentMapper

void addDep(Department dep);

void deleteDepById(Department dep);

XML

DepartmentMapper.xml

<resultMap id="DepartmentWithChildren" type="org.javaboy.vhr.model.Department" extends="BaseResultMap" >
    <collection property="children" ofType="org.javaboy.vhr.model.Department"
                select="org.javaboy.vhr.mapper.DepartmentMapper.getAllDepartmentsByParentId" column="id"/>
</resultMap>
  
<select id="deleteDepById" statementType="CALLABLE">
	//调用存储过程deleteDep
    call deleteDep(#{id ,mode=IN,jdbcType=INTEGER},#{result,mode=OUT,jdbcType=INTEGER})
</select>
  
<select id="addDep" statementType="CALLABLE">
    call addDep(#{name,mode=IN,jdbcType=VARCHAR},#{parentId,mode=IN,jdbcType=INTEGER},
    #{enabled,mode=IN,jdbcType=BOOLEAN},#{result,mode=OUT,jdbcType=INTEGER},#{id,mode=OUT,jdbcType=INTEGER})
</select>

<select id="getAllDepartmentsByParentId" resultMap="DepartmentWithChildren">
    select * from department where parentId=#{pid}
</select>

存储过程解析

两个存储过程在我们当初导入SQL脚本的时候已经建好了,我们来分析一下。
addDep

//创建addDep存储过程,三个输入参数depName、parentId、enabled,两个输出参数result、result2
CREATE DEFINER=`root`@`localhost` PROCEDURE `addDep`(in depName varchar(32),in parentId int,in enabled boolean,out result int,out result2 int)
begin
  //声明两个参数
  declare did int;
  declare pDepPath varchar(64);
  //把三个输入参数插入到department表中
  insert into department set name=depName,parentId=parentId,enabled=enabled;
  //把刚才插入操作受影响的行数赋值给result,为1则表示插入成功,0表示失败
  select row_count() into result;
  //把department表中新添加的一行的id赋值给did
  select last_insert_id() into did;
  set result2=did;
  select depPath into pDepPath from department where id=parentId;
  //更新depPath为pDepPath.did
  update department set depPath=concat(pDepPath,'.',did) where id=did;
  //设置isParent为true
  update department set isParent=true where id=parentId;
end

deleteDep

CREATE DEFINER=`root`@`localhost` PROCEDURE `deleteDep`(in did int,out result int)
begin
  declare ecount int;
  declare pid int;
  declare pcount int;
  declare a int;
  //创建a表,从department表中选择行插入到a表中 条件:id等于did且没有子部门
  select count(*) into a from department where id=did and isParent=false;
  //没有行被选中  说明有子部门,删除失败
  if a=0 then set result=-2;
  else
  //a表中有数据,继续在employee表中查找员工并放入ecount中
  select count(*) into ecount from employee where departmentId=did;
  //大于零说明有员工,删除失败
  if ecount>0 then set result=-1;
  else
  // 把parentId传给pid
  select parentId into pid from department where id=did;
  delete from department where id=did and isParent=false;
  //删除的行数为1
  select row_count() into result;
  select count(*) into pcount from department where parentId=pid;
  //如果没有子部门,isParent设置为false
  if pcount=0 then update department set isParent=false where id=pid;
  end if;
  end if;
  end if;
end

你可能感兴趣的:(微人事项目学习)