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">×</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,如有不对或者更加简单的方法,欢迎批评指摘。