bootatrap-treeview实现下拉树及其模糊查询

bootstrap-table-tree.js的引入

tip:bootstrap-table-tree.js必须在bootstrap-table.js后引入,因为bootstrap-table-tree.js对bootstrap-table.js中的initData等方法进行了重写。

bootstrap-table.js中添加属性

 			treeView: options.treeView,
            treeId: options.treeId,
            parentIdField: options.parentIdField,
            treeField: options.treeField,
            treeRootLevel:options.treeRootLevel,
            treeCollapseAll:options.treeCollapseAll,//默认全部展开

自定义所添加的属性

    	$(function () {
    //初始化日历
    $("#datePicker").createDateRangePicker(function (startTime, endTime) {
        $("#startTime").val(startTime);
        $("#endTime").val(endTime);
    });


    var options = {
        //ajax url 和类型
        tableAjax: {
            url: '/sysDeptList/findSysDeptList',
            type: "GET"
        },
        //table的html id
        uniqueId: 'deptId',
        pagination: false,
        queryParams: queryParams,
        rowStyle: rowStyle,

        treeView: true,
        treeId: "deptId",
        parentIdField: "parentId",
        treeField: "deptName",
        treeCollapseAll: false,
        //table的列
        tableColumn: [{
            checkbox: true,
            align: 'center'
        }, {
            title: 'deptId',
            field: 'deptId',
            visible: false,
        }, {
            field: 'deptName',
            title: '部门名称',
        }, {
            field: 'orderNum',
            title: '排序',
        }, {
            field: 'status',
            title: '状态',
            formatter: function (value, row, index) {
                return changeStatusVal(value, row['deptId'], row['status']);
            }
        }, {
            field: 'createTime',
            title: '创建时间',
        }, {
            field: "operate",
            title: "操作",
            formatter: function (value, row, index) {
                return '<a class="option" onclick="toAddSysDept(' + row["deptId"] + ')">新增</a><a class="option" onclick="toUpdateDeptById(' + row['deptId'] + ')">编辑</a><a class="option" onclick="deleteSysDeptByDeptIds(' + row['deptId'] + ')" >删除</a>';
            }
        }],
    };
    //初始化Table
    $("#sys_dept").createTable(options);
	function queryParams(params) {
	        //查询参数,以对象传参
	        var sysDept = {
	            deptName: $("#deptName").val(),
	            status: $("#status").val(),
	            startTime: $("#startTime").val(),
	            endTime: $("#endTime").val()
	        };
	        return $.extend(params, sysDept);
	    }


效果图
在这里插入图片描述模糊查询
tip:网上很多关于ztree的查询,都是关于js的模糊查询,这里我做了一个后端的treeview的模糊查询
step:

  • 添加查询按钮
 <div class="panel-body">
        <div class="panel-body">
            <div class="panel panel-primary">
                    <div class="panel-heading" ><lable class="lable-default">查询条件</lable></div>
                    <div class="panel-body">
                        <form class="form-horizontal" >
                            <div class="form-group">
                                <label class="control-label col-sm-1">部门名称 :</label>
                                <div class="col-sm-2">
                                    <input type="text" class="form-control" id="deptName"
                                           placeholder="请输入部门名称">
                                </div>
                                <label class="control-label col-sm-1">部门状态 :</label>
                                <div class="col-sm-2">
                                    <select id="status" class="form-control">
                                        <option value="">全部</option>
                                        <option value="0">正常</option>
                                        <option value="1">停用</option>
                                    </select>
                                </div>
                                <label class="control-label col-sm-1">创建时间 :</label>
                                <div class="col-sm-3">
                                    <input type="text" class="form-control" id="datePicker"
                                           placeholder="请选择创建时间" readonly>
                                    <i class="glyphicon glyphicon-calendar far fa-calendar-alt"></i>
                                    <input type="hidden" id="startTime" name="startTime">
                                    <input type="hidden" id="endTime" name="endTime">
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="col-sm-12 text-center">
                                    <button type="button" id="btn_query" class="btn btn-primary"
                                            onclick="search()"><span class="glyphicon glyphicon-search" aria-hidden="true"></span> 查询</button>
                                    <button type="button" class="btn btn-default col-xs-offset-1"
                                            onclick="resetForm()"> <span class="glyphicon glyphicon-refresh" aria-hidden="true" ></span> 重置</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>

查询的方法(即bootstraptable中的刷新)
tip:在上面进行初始化table时添加查询参数queryParams,具体看上面初始化table的queryparam的方法。
查询的结果进行高亮

  • 在bootstrap-table.js中添加rowStyle:
    在这里插入图片描述

  • 自定义rowStyle方法:
    在这里插入图片描述


    function rowStyle(row, index) {
        //高亮行
        var data = $("#sys_dept").bootstrapTable("getData");
        var jsonData = JSON.stringify(data);
        var result = $.parseJSON(jsonData);
        for (var i = 0; i < result.length; i++) {
            if (result[i].forHighLightFlag == true) {
                if (row['deptId'] == result[i].deptId) {
                    //对一行进行设置高亮
                    var style = {};
                    style = {css: {'color': '#ed5565'}};
                    return style;
                }
            }
        }
        return {};
    }
/**
 * 查询
 */
function search() {
    $("#sys_dept").refreshTable();
}

后台查询实现类impl

  • 映射类
@Data
@EqualsAndHashCode(callSuper = false)
public class SysDept extends BaseVO {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long deptId;

    private Long parentId;

    private String deptName;

    private Integer orderNum;

    private String leader;

    private String phone;

    private String email;

    private String status;

    @Transient
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date startTime;

    @Transient
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;

    private List<TreeView> treeViews;

    private boolean forHighLightFlag;
}
@Service
public class SysDeptServiceImpl implements SysDeptService {
    private static int rootId = -1;
    private static String statusOfAll = "3";
    private static String statusOfStop = "1";
    private static String statusOfStart = "0";
    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Override
    public List<SysDept> findDeptList(SysDept sysDeptVO) throws Exception {
        Example example = new Example(SysDept.class);
        Example.Criteria criteria = example.createCriteria();
        //只有进行模糊查询的时候才查询子树的所有上级节点
        boolean flag = false;
        if (StringUtils.isNotEmpty(sysDeptVO.getDeptName())) {
        //当查询中设计中文字符,需要添加上“%”
            criteria.andLike("deptName", "%" + sysDeptVO.getDeptName() + "%");
            flag = true;
        }
        if (StringUtils.isNotEmpty(sysDeptVO.getStatus()) && !(statusOfAll.equals(sysDeptVO.getStatus()))) {
            criteria.andEqualTo("status", sysDeptVO.getStatus());
            flag = true;
        }
        if (Objects.nonNull(sysDeptVO.getStartTime())) {
            criteria.andGreaterThanOrEqualTo("createTime", sysDeptVO.getStartTime());
            flag = true;
        }
        if (Objects.nonNull(sysDeptVO.getEndTime())) {
            criteria.andLessThanOrEqualTo("createTime", sysDeptVO.getEndTime());
            flag = true;
        }
        example.setOrderByClause("order_num asc");
        List<SysDept> childSysDeptList = sysDeptMapper.selectByExample(example);
        //查询出符合条件的所有上级部门
        if (flag) {
        //其中childSysDeptList是模糊查询的结果,将其暂时保存在forHighLightList中
            List<SysDept> forHighLightList = childSysDeptList;
            //查询模糊查询的结果childSysDeptList中每一条数据的上级部门(为了生成树)
            childSysDeptList = getAllParentDept(childSysDeptList);
     //对生成树的所有结果进行遍历,将模糊查询的结果进行高亮
            childSysDeptList.forEach(sysDept -> {
                forHighLightList.forEach(sysDept2 -> {
                    if (sysDept.getDeptId().equals(sysDept2.getDeptId())){
                         //高亮数据置true(为了前台js遍历)
                        sysDept.setForHighLightFlag(true);
                    }
                });
            });
        }
        return childSysDeptList;
    }

    /**查询父亲级别的部门**/
    private List<SysDept> getAllParentDept(List<SysDept> childSysDeptList) {
        Set<SysDept> childSysDeptSet = new HashSet<>(childSysDeptList);
        Set<SysDept> parentSet = new HashSet<>();
        childSysDeptSet.forEach(sysDept -> {
            if (sysDept.getParentId() != rootId) {
                Example example1 = new Example(SysDept.class);
                example1.createCriteria().andEqualTo("deptId", sysDept.getParentId());
                SysDept parentSysDept = sysDeptMapper.selectOneByExample(example1);
                parentSet.add(parentSysDept);
            }
        });
        //追加上父级部门
        childSysDeptSet.addAll(parentSet);
        parentSet.forEach(parentSysDept -> {
            getAllGrandParentSysDeptList(parentSet, childSysDeptSet);
        });
        return new ArrayList<>(childSysDeptSet);
    }

    /**查询祖先级别的部门**/
    private void getAllGrandParentSysDeptList(Set<SysDept> parentSet, Set<SysDept> allSysDeptSet) {
        Set<SysDept> parentSet1 = new HashSet<>();
        if (parentSet != null) {
            parentSet.forEach(sysDept1 -> {
                if (sysDept1.getParentId() != rootId) {
                    Example example1 = new Example(SysDept.class);
                    example1.createCriteria().andEqualTo("deptId", sysDept1.getParentId());
                    SysDept parentSysDept = sysDeptMapper.selectOneByExample(example1);
                    parentSet1.add(parentSysDept);
                }
            });
        }
        //追加上祖先部门
        allSysDeptSet.addAll(parentSet1);
        parentSet1.forEach(parentSysDept -> {
            getAllGrandParentSysDeptList(parentSet1, allSysDeptSet);
        });
    }

效果图
在这里插入图片描述
修改时树的回显
tip:点击编辑时,弹出模态框,回显数据,表中的编辑操作回显出上级部门且不可改变其上级部门。

  • 表格中的编辑
, {
            field: "operate",
            title: "操作",
            formatter: function (value, row, index) {
                return '<a class="option" onclick="toUpdateDeptById(' + row['deptId'] + ')">编辑</a>';
            }
  • js中实现方法
/*
 *修改
 */
function toUpdateDeptById(deptId) {
    if (typeof (deptId) == "undefined") {
        var rows = $("#sys_dept").bootstrapTable("getSelections");
        if (rows.length < 1) {
            toastr.warning("请至少选择一条记录");
            return;
        } else if (rows.length > 1) {
            toastr.warning("只能选择一条记录");
            return;
        }
        Dialog.modal({
            url: "/tpl/sys_dept/sys_dept_update.html",
            //enableToChange 等于 0时表示表格中的编辑,回显出上级部门且不能更改,等于1时则反之。
            data: {deptId: rows[0]['deptId'], enableToChange: 0},
        });
    } else {
        Dialog.modal({
            url: "/tpl/sys_dept/sys_dept_update.html",
            data: {deptId: deptId, enableToChange: 1},
        });
    }
}
  • 模态框
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<form name="updateForm" id="updateForm" class="form-horizontal">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal"
                aria-hidden="true">&times;</button>
        <h4 class="modal-title">更新部门</h4>
    </div>
    <div class="modal-body row">
        <div class="panel-body wrapper-sm">
            <div class="form-group">
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">状态</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <select class="form-control" id="status" name="status">
                        <option value="0">正常</option>
                        <option value="1">停用</option>
                    </select>
                </div>
                <input id="deptId" type="hidden" name="deptId" class="form-control">
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">部门名称</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <input type="text" id="deptName" name="deptName" class="form-control">
                </div>
            </div>

            <div class="form-group">
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">显示顺序</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <input type="text" id="orderNum" name="orderNum" class="form-control">
                </div>
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">负责人</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <input type="text" id="leader" name="leader" class="form-control">
                </div>
            </div>

            <div class="form-group">
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">联系电话</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <input type="text" id="phone" name="phone" class="form-control">
                </div>
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">邮箱</b><b class="form-error">*</b>:</label>
                <div class="col-sm-3">
                    <input type="text" id="email" name="email" class="form-control">
                </div>
            </div>

            <div class="form-group">
                <label class="col-sm-2 control-label text-right"><b
                        class="form-text-black">上级部门</b><b class="form-error">*</b>:</label>
                <div class="col-sm-8">
                    <input type="hidden" name="parentId" id="parentId">
                    <input type="text" class="form-control" name="parentName" id="parentName" readonly onclick="$('#treeView').show()" placeholder="上级部门">
                </div>
            </div>
        </div>
    </div>
    <div class="modal-footer">
        <div class="col-sm-25 m-b text-center">
            <button type="button" class="btn btn-primary" onclick="updateSysDept()">
                <span class="glyphicon glyphicon-save" aria-hidden="true"></span>保存
            </button>
            <button class="btn btn-default" data-dismiss="modal">
                <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭
            </button>
        </div>
    </div>
</form>
</html>
<div id="treeView" style="display: none;position: absolute; width: 63.66%;top: 165px;left: 25%;margin-left:12px;overflow: auto;height: 300px"></div>
<script type="text/javascript" src="/tpl/sys_dept/sys_dept_tree.js"></script>
<script type="text/javascript" src="/tpl/sys_dept/sys_dept_update.js"></script>
  • 进入sys_dept_tree.js发送请求,然后渲染树
$(function () {
    $.ajax({
        type : "get",
        url : '/sysDept/findSysDeptListByTreeView',
        success : function(data) {
            $('#treeView').treeview({
                data: data.data,
                showIcon: false,
                onhoverColor: "white",
                selectedColor: "#333",
                selectedBackColor: "white",
                expandIcon: 'glyphicon glyphicon-chevron-right',
                collapseIcon: 'glyphicon glyphicon-chevron-down',
                showCheckbox: false,
                onNodeSelected: function(event, node) {
                    $("#parentId").val(node.id);
                    $("#parentName").val(node.text);
                    $("#treeView").hide();
                },
            });
        }
    })
});
  • 查询树的controller
    /**
     * treeView的查询
     */
    @RequestMapping(value = "/sysDept/findSysDeptListByTreeView", method = RequestMethod.GET)
    public ResponseEntity<RestResponse> findSysDeptListByTreeView() {
        return new ResponseEntity<>(RestResponseGenerator.genSuccessResponse(sysDeptService.findSysDeptListByTreeView()), HttpStatus.OK);
    }
  • 查询树的实现类impl
  @Override
    public List<TreeView> findSysDeptListByTreeView() {
        //查询所有顶级节点
        List<TreeView> topNodesList = new ArrayList<>();
        List<SysDept> sysDeptList = sysDeptMapper.selectAll();
        sysDeptList.forEach(sysDept -> {
            if (sysDept.getParentId() == rootId) {
                TreeView topTreeViewVO = new TreeView();
                topTreeViewVO.setId(sysDept.getDeptId());
                topTreeViewVO.setText(sysDept.getDeptName());
                topNodesList.add(topTreeViewVO);
            }
        });
        //查询所有父节点下的子节点
        topNodesList.forEach(topNode -> findSubNodes(topNode, sysDeptList));
        return topNodesList;
    }

    private void findSubNodes(TreeView topTreeViewVO, List<SysDept> sysDeptList) {
        List<TreeView> subNodesList = new ArrayList<>();
        sysDeptList.forEach(sysDept -> {
            if (sysDept.getParentId().equals(topTreeViewVO.getId())) {
                TreeView subTreeViewVO = new TreeView();
                subTreeViewVO.setId(sysDept.getDeptId());
                subTreeViewVO.setText(sysDept.getDeptName());
                subNodesList.add(subTreeViewVO);
            }
        });
        topTreeViewVO.setNodes(subNodesList.size() > 0 ? subNodesList : null);
        if (topTreeViewVO.getNodes() != null) {
            topTreeViewVO.getNodes().forEach(secondTop -> findSubNodes(secondTop, sysDeptList));
        }
    }
  • treeview映射类
@Data
@EqualsAndHashCode(callSuper = false)
public class TreeView {

    private String text;

    private Long id;

    private List<TreeView> nodes;
}
  • 此时树已经在模态框中渲染好,接下来在sys_dept_add.js中发送请求回显数据
$(function () {
    var sysDept = Dialog.loadData();

    /**
     * 选中图标 (常用于更新时默认选中图标)
     * @param filter lay-filter
     * @param iconName 图标名称,自动识别fontClass/unicode
     */
    $(".icon-picker").iconpicker({icon: "fas fa-align-left"});

    //bootstrap icon初始化
    $('.icon-picker').on('change', function (e) {
        $("#icon").val(e.icon);
    });

    $.ajax({
        type: "get",
        url: "/sysDept/sysDeptUpdateById",
        data: {deptId: sysDept.deptId},
        success: function (result) {
            getParentName(result.data.parentId);
             $("#parentName").val(parentName);
            sysDept = result.data;
            $("#updateForm").loadForm(sysDept);
        }
    });
   //更新时回显父级部门的名称(表格里更新不能更改父级部门名称)
    function getParentName(parentId) {
        var obj = {parentId: parentId};
        $.ajax({
            type: "post",
            url: "/sysDept/findSysDeptParentName",
            data: JSON.stringify(obj),
            async: false,//这里异步查询上级部门名称
            success: function (result) {
                parentName = result.data.deptName;
            }
        });
    }
    }
  • 效果图

在这里插入图片描述
tip:这样回显的效果就是表格外的修改的效果,表格里的编辑则需要对上级部门进行“禁言”的效果,具体看下面的步骤:
将上面的回显改成下面红框里面的模样,这样,上面模态框发送数据enableToChange也有了解释。
,在这里插入图片描述
tip:modal框有了禁言的效果在提交之前应该将其禁言效果失效,即:
在这里插入图片描述

over,如有不对或者更加简单的方法,欢迎批评指摘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值