Micro-Personnel Department Management Module (15)

Tree display and search for department management

The data display page is a tree. We can load the data at one time, and we can also query the sub-departments by clicking the id load once. We get the json data once and load it. If there is not much data, we can use
recursion. If there is a lot of data, we can use lazy loading. The way

Since the sub-department is relatively deep, it is not suitable, as shown in the menu between permission group roles
insert image description here

insert image description here

Write the backend interface

DepartmentController

@RestController
@RequestMapping("/system/basic/department")
public class DepartmentController {
    
    

    @Autowired
    DepartmentService departmentService;

    @GetMapping("/")
    public List<Department>  getAllDepartments(){
    
    
        return departmentService.getAllDepartments();
    }
}

DepartmentService

@Service
public class DepartmentService {
    
    


    @Autowired
    DepartmentMapper departmentMapper;

    public List<Department> getAllDepartments() {
    
    
        //传递-1直接查询最顶级的股东会然后根据mybatis语句进行递归
        return departmentMapper.getAllDepartmentsByParentId(-1);
    }
}

DepartmentMapper

insert image description here

  <resultMap id="DepartmentWithChildren" type="com.xyg.pojo.Department" extends="BaseResultMap"> <!--当查询的时候会以children属性会调用select把当前id传进去,然后新查询的同会继续调用,形成一个递归-->
    <collection property="children" ofType="com.xyg.pojo.Department" select="com.xyg.mapper.DepartmentMapper.getAllDepartmentsByParentId" column="id" ></collection>
  </resultMap>


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

Entity class adds a children field one-to-many

insert image description here

test
insert image description here

front-end writing

Add elementui component
insert image description hereDemMarna.vue

<div  style="width: 500px">
    <el-input
            prefix-icon="el-icon-search"

            placeholder="输入部门名称进行搜索"
            v-model="filterText">         
    </el-input>

    <el-tree
            :data="deps"
            :props="defaultProps"
            default-expand-all
            :filter-node-method="filterNode"     //过滤的方法
            ref="tree">
    </el-tree>
</div>

insert image description here

 data(){
    
    
            return{
    
    
                filterText:"",
                deps:[],
                defaultProps: {
    
    
                    children: 'children',
                    label: 'name'
                }
            }
        },

insert image description here

 mounted(){
    
    
            this.getDeps()
        },

        methods: {
    
    

            getDeps(){
    
    
                this.getRequest("/system/basic/department/").then(resp=>{
    
    
                    if(resp){
    
    
                        this.deps=resp
                    }
                })
            },

Data display effect
insert image description here

Front-end query filtering

insert image description here
insert image description here


            filterNode(value, data) {
    
    //过滤的方法,value传过来的最新值,data的Json数组得出每一项,
                if (!value) return true;  //进行比较,如果value不存在的话直接返回true,表示当前的data留着,否则剔除掉
                return data.name.indexOf(value) !== -1;//ata.name是否包含这个值,如果不等于-1就返回值这个值
            }

        watch: {
    
     //监控filterText值发生变化
            filterText(val) {
    
    
                this.$refs.tree.filter(val);//会触发这个方法
            }
        },

In short, it is to monitor the variables bound to the input box to monitor whether there is any change, trigger the filter method, and
realize the front-end query through the method
insert image description here

Department tree shows adding and deleting

Use this
insert image description here
to paste into the tree component
insert image description here
insert image description here
and use this method to solve it : expand-on-click-node="false" Whether to expand or shrink the node when the node is clicked, the default value is true, if it is false, there is only an arrow icon Only when the node is expanded or contracted.

  <!--  :expand-on-click-node="false" 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。-->
    <el-tree

            :data="deps"
            node-key="id"
            :props="defaultProps"
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            ref="tree">
        <!--slot-scope="{ node, data }   node指当前的元素( :props="defaultProps"),data值得到就是服务端返回的json对象-->
        <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
                  class="depBtn"
                  type="primary"
                  size="mini"
                  @click="() => showAddDep(data)">
            添加部门
          </el-button>
          <el-button
                  class="depBtn"
                  type="danger"
                  size="mini"
                  @click="() => delDeps(node, data)">
            删除部门
          </el-button>
        </span>
      </span>
    </el-tree>
</div>

Effect
insert image description here

Addition of backend department tree

If you add a department on the board of directors, it is a sub-department of the board of directors, so the parameters to be passed are the id of the parent department and the name of the added department

insert image description here
The first step is to add the name, and partentid fields, and the id will be automatically generated. The
second step is to query the partentid according to the generated id to generate its own depPath. The third step isParent has no sub-departments for flash. true if it has its own subdepartment

This is not difficult, write service plus transaction in three steps

DepartmentController

 @PostMapping("/")
    public RespBean AddDep(@RequestBody Department department) {
    
    
        if(department.getName()!=""){
    
    
            Department department1 = departmentService.AddDep(department);
            if (department1 != null) {
    
    
                return RespBean.ok("添加成功",department1);
            }
        }
        return RespBean.err("添加失败");
    }

DepartmentService

@Transactional
    public Department AddDep(Department department) {
    
    

        //第一步做添加操作把name,和partentid字段加进来,id会自动生成,数据库返回新增的id
        departmentMapper.insertDep(department);

        //第二步就要去根据生成的id,查询到他partentid生成组成自己的depPath,
        //根据id查询出自己的对象
        Department dep = departmentMapper.selectByPrimaryKey(department.getId());
        //获取当前对象父id的对象
        Department parDep = departmentMapper.selectParentDepath(dep.getParentid());

        //获取父id的deppath加自己的id,生成自己Deppath
        String Deppath=parDep.getDeppath()+'.'+department.getId();

        if (Deppath.toString().startsWith("null")){
    
    
            throw new RuntimeException("操作错误");
        }
        //设置自己Deppath
        department.setDeppath(Deppath);
        //设自己是可启用
        department.setEnabled(true);
        //设置自己刚添加是没有子部门
        department.setIsparent(false);
        //进行更新操作
        departmentMapper.updateByPrimaryKey(department);
        //如果有新数据进行添加如果有父部门,都把父部门的Isparent 更新为 true
        Department department1 = departmentMapper.selectByPrimaryKey(department.getParentid());
        department1.setIsparent(true);
        departmentMapper.updateByPrimaryKey(department1);

        return departmentMapper.selectByPrimaryKey(department.getId());

    }

DepartmentMapper

The mapper only writes this interface, and the others exist

int insertDep(Department record);
<!--useGeneratedKeys="true" keyProperty="id"   实现id回调,获取插入数据库的id-->
  <insert id="insertDep" parameterType="com.xyg.pojo.Department" useGeneratedKeys="true" keyProperty="id" >
    insert into department (id, name, parentId,
                            depPath, enabled, isParent)
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{parentid,jdbcType=INTEGER},
            #{deppath,jdbcType=VARCHAR}, #{enabled,jdbcType=BIT}, #{isparent,jdbcType=BIT})
  </insert>

Front-end docking

When clicking add, the input box should pop up

<el-dialog
            title="添加部门"
            :visible.sync="dialogVisible"
            width="30%">
        <div>
            <el-tag size="small">上级部门</el-tag>
            <span >{
    
    {
    
    this.parDep.name}}</span>
        </div>
        <div  style="margin-top: 8px">
            <el-tag size="small">部门名称</el-tag>
            <el-input  size="mini" v-model="chalDep.name"   placeholder="请输入部门名称" style="width: 200px"></el-input>
        </div>
        <span slot="footer" class="dialog-footer">
    <el-button @click="cannelChal">取 消</el-button>
    <el-button type="primary" @click="chalAdd">确 定</el-button>
  </span>
    </el-dialog>
   

insert image description here

   showAddDep(data){
    
    
                console.log(data)
                this.dialogVisible=true
                this.parDep=data
                this.chalDep.parentid=data.id
            },

insert image description here

insert image description here
#Interface docking
insert image description here

insert image description here


            cannelChal(){
    
    
              this.dialogVisible=false;
              this.chalDep.name=""
            },

            chalAdd(){
    
    
              this.postRequest("/system/basic/department/",this.chalDep).then(resp=>{
    
    
                  if (resp){
    
    
                      this.getDeps()
                      this.chalDep.name=""
                      this.dialogVisible=false
                  }
              })
            },

Deletion of the backend department

DepartmentController

    @DeleteMapping("/{id}")
    public RespBean delDep(@PathVariable Integer id){
    
    
        if(departmentService.delDep(id)==1){
    
    
            return RespBean.ok("删除成功");
        }
        return RespBean.err("删除失败");
    }

DepartmentService

    public Integer delDep(Integer id) {
    
    
        return departmentMapper.delDep(id);
    }

DepartmentMapper

Integer delDep(Integer id) ;
  <delete id="delDep" >
    delete from  department where id=#{id}
  </delete>

Front-end docking

insert image description here

 delDeps(node,data){
    
    
                this.$confirm('此操作将永久删除, 是否继续?', '提示', {
    
    
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
    
    
                    this.deleteRequest("/system/basic/department/"+data.id).then(resp=>{
    
    
                        if(resp){
    
    
                            this.getDeps()
                        }
                    })

                }).catch(() => {
    
    
                    this.$message({
    
    
                        type: 'info',
                        message: '已取消删除'
                    });
                });
            },
            getDeps(){
    
    
                this.getRequest("/system/basic/department/").then(resp=>{
    
    
                    if(resp){
    
    
                        this.deps=resp
                    }
                })
            },
            filterNode(value, data) {
    
    //过滤的方法,value传过来的最新值,data的Json数组得出每一项,
                if (!value) return true;  //进行比较,如果value不存在的话直接返回true,表示当前的data留着,否则剔除掉
                return data.name.indexOf(value) !== -1;//ata.name是否包含这个值,如果不等于-1就返回值这个值
            }
        },
        watch: {
    
     //监控filterText值发生变化
            filterText(val) {
    
    
                this.$refs.tree.filter(val);//会触发这个方法
            }
        },

Fix tree component addition and removal shrinkage issues

After the el-tree in element-ui adds or deletes child nodes, that is, the tree will be closed every time the data is refreshed, but if we still need to perform follow-up operations under the current node, and there are many layers of nodes , it is very troublesome, and the user experience is very poor, so how to solve it?

Solution: Define an array, and then when you click on a tree node, save it and store it in the data. After refreshing, the nodes that were expanded before the tree can still be expanded.
insert image description here
insert image description here

 handleNodeClick(data) {
    
    
                this.defaultExpandKeys.push(data.id) ;//记录当前点击节点,并赋值给默认展开的节点的 key 的数组
            },

Guess you like

Origin blog.csdn.net/qq_45709416/article/details/132390478