部门列表树
1
<div class="col-sm-3">
<div class="table-header">
部门列表
<a class="green" href="#">
<!--新增部门按钮-->
<i class="ace-icon fa fa-plus-circle orange bigger-130 dept-add"></i>
</a>
</div>
<div id="deptList">
<!--展示部门列表-->
</div>
</div>
2
<!--mustache模板-->
<script id="deptListTemplate" type="x-tmpl-mustache">
<ol class="dd-list">
<!--模板中使用循环,循环 deptList 的元素-->
{{#deptList}}
<li class="dd-item dd2-item dept-name" id="dept_{{id}}" href="javascript:void(0)" data-id="{{id}}">
<!--部门名称-->
<div class="dd2-content" style="cursor:pointer;">
{{name}}
<!--编辑、删除按钮-->
<span style="float:right;">
<a class="green dept-edit" href="#" data-id="{{id}}" >
<i class="ace-icon fa fa-pencil bigger-100"></i>
</a>
<a class="red dept-delete" href="#" data-id="{{id}}" data-name="{{name}}">
<i class="ace-icon fa fa-trash-o bigger-100"></i>
</a>
</span>
</div>
</li>
{{/deptList}}
</ol>
</script>
3
<script type="text/javascript">
$(function(){
var deptList; // 存储树形部门列表
var deptMap = {}; // 存储 map 格式的所有部门信息
var optionStr = ""; // 下拉框的选项
var deptListTemplate = $('#deptListTemplate').html();
Mustache.parse(deptListTemplate);
loadDeptTree(); // 初始化并显示部门树
// 渲染第一层部门树
function loadDeptTree() {
$.ajax({
url: "/sys/dept/tree",
success : function (result) {
if (result.ret) {
deptList = result.data; // deptList存到全局变量
var rendered = Mustache.render(deptListTemplate, {deptList: result.data}); // 把数据deptList(来源:后台返回的json数据)渲染到 deptListTemplate 模板用作循环
$("#deptList").html(rendered); // 把渲染结果插入空的<div id="deptList"></div>下显示
recursiveRenderDept(result.data);
bindDeptClick(); // 绑定修改、删除、加载当前部门的用户列表点击事件
} else {
showMessage("加载部门列表", result.msg, false);
}
}
})
}
// 递归渲染部门树
function recursiveRenderDept(deptList) {
if(deptList && deptList.length > 0) {
$(deptList).each(function (i, dept) {
deptMap[dept.id] = dept; // 所有的部门信息存到全局变量
// 如果存在子部门递归处理
if (dept.deptList.length > 0) {
var rendered = Mustache.render(deptListTemplate, {deptList: dept.deptList});
$("#dept_" + dept.id).append(rendered);
recursiveRenderDept(dept.deptList);
}
})
}
}
})
</script>
新增部门
1
<div class="table-header">
部门列表
<a class="green" href="#">
<!--新增部门按钮-->
<i class="ace-icon fa fa-plus-circle orange bigger-130 dept-add"></i>
</a>
</div>
<!--新增部门对话框-->
<div id="dialog-dept-form" style="display: none;">
<form id="deptForm">
<table class="table table-striped table-bordered table-hover dataTable no-footer" role="grid">
<tr>
<td style="width: 80px;"><label for="parentId">上级部门</label></td>
<td>
<select id="parentId" name="parentId" data-placeholder="选择部门" style="width: 200px;"></select>
<input type="hidden" name="id" id="deptId"/>
</td>
</tr>
<tr>
<td><label for="deptName">名称</label></td>
<td><input type="text" name="name" id="deptName" value="" class="text ui-widget-content ui-corner-all"></td>
</tr>
<tr>
<td><label for="deptSeq">顺序</label></td>
<td><input type="text" name="seq" id="deptSeq" value="1" class="text ui-widget-content ui-corner-all"></td>
</tr>
<tr>
<td><label for="deptRemark">备注</label></td>
<td><textarea name="remark" id="deptRemark" class="text ui-widget-content ui-corner-all" rows="3" cols="25"></textarea></td>
</tr>
</table>
</form>
</div>
2
// 点击增加按钮弹出增加部门模态对话框
$(".dept-add").click(function(){
$("#dialog-dept-form").dialog({
model: true, // 是否为模态对话框
title: "新增部门",
// 对话框打开时数据等初始化
open: function(event, ui){
$(".ui-dialog-titlebar-close", $(this).parent()).hide(); // 取消所有默认的功能(关闭)按钮,原因是关闭时可以处理相关操作并不是单纯的关闭
optionStr = "<option value=\"0\">请选择</option>";
recursiveRenderDeptSelect(deptList, 1);
$("#deptForm")[0].reset(); //重置表格,清空表格数据
$("#parentId").html(optionStr); // 渲染到<select id="parentId"></select>中
},
// 属性名将会被作为按钮的提示文字,属性值为一个函数,即按钮的处理函数
buttons:{
"添加":function(e){
e.preventDefault(); // 拦截默认的点击事件
// true为新增,false为修改。操作成功关闭模态框。
updateDept(true,
function (data) {
$("#dialog-dept-form").dialog("close");
},
function (data) {
showMessage("新增部门", data.msg, false);
})
},
"取消":function(){ $("#dialog-dept-form").dialog("close");}
}
})
})
2.1 初始化下拉框
// 下拉框初始化部门列表函数
function recursiveRenderDeptSelect(deptList, level){
level = level | 0; // level 没有则为置为 0
if (deptList && deptList.length > 0){
$(deptList).each(function (i, dept) {
deptMap[dept.id] = dept;
var blank = "";
// 如果 level 不是第一层
if(level > 1){
for(var j = 3; j <= level; j++) {
blank += "..";
}
blank += "∟";
}
optionStr += Mustache.render("<option value='{{id}}'>{{name}}</option>", {id: dept.id, name: blank + dept.name}); // 渲染数据
// 递归渲染
if (dept.deptList && dept.deptList.length > 0) {
recursiveRenderDeptSelect(dept.deptList, level + 1);
}
})
}
}
2.2 保存更新函数
// 部门保存更新函数
function updateDept(isCreate, successCallback, failCallback) {
$.ajax({
url: isCreate ? "/sys/dept/save" : "/sys/dept/update",
data: $("#deptForm").serializeArray(),
type: 'POST',
success: function(result) {
if (result.ret) {
loadDeptTree();
if (successCallback) {
successCallback(result);
}
} else {
if (failCallback) {
failCallback(result);
}
}
}
})
}
编辑部门
1
<!--mustache模板-->
<script id="deptListTemplate" type="x-tmpl-mustache">
<ol class="dd-list">
<!--模板中使用循环,循环 deptList 的元素-->
{{#deptList}}
<li class="dd-item dd2-item dept-name" id="dept_{{id}}" href="javascript:void(0)" data-id="{{id}}">
<!--部门名称-->
<div class="dd2-content" style="cursor:pointer;">
{{name}}
<!--编辑、删除按钮-->
<span style="float:right;">
<a class="green dept-edit" href="#" data-id="{{id}}" >
<i class="ace-icon fa fa-pencil bigger-100"></i>
</a>
<a class="red dept-delete" href="#" data-id="{{id}}" data-name="{{name}}">
<i class="ace-icon fa fa-trash-o bigger-100"></i>
</a>
</span>
</div>
</li>
{{/deptList}}
</ol>
</script>
2
// 点击修改按钮弹出修改模态对话框
$(".dept-edit").click(function(e){
e.preventDefault(); // 拦截默认的点击事件
e.stopPropagation(); // 阻止冒泡事件
var deptId = $(this).attr("data-id"); // 取出当前元素的 data-id的值
$("#dialog-dept-form").dialog({
model: true, // 是否为模态对话框
title: "编辑部门",
// 对话框打开时数据等初始化
open: function(event, ui){
$(".ui-dialog-titlebar-close", $(this).parent()).hide(); // 取消所有默认的功能按钮,原因是关闭时可以处理相关操作并不是单纯的关闭
optionStr = "<option value=\"0\">请选择</option>";
recursiveRenderDeptSelect(deptList, 1);
$("#deptForm")[0].reset(); // 重置表格,清空表格数据
$("#parentId").html(optionStr); // 渲染到<select id="parentId"></select>中
$("#deptId").val(deptId); // 获取当前部门的deptId信息填入输入框
var targetDept = deptMap[deptId]; // 根据 deptId 从存储所有部门信息的 deptMap 取出
if (targetDept) {
$("#parentId").val(targetDept.parentId);
$("#deptName").val(targetDept.name);
$("#deptSeq").val(targetDept.seq);
$("#deptRemark").val(targetDept.remark);
}
},
// buttons:属性名将会被作为按钮的提示文字,属性值为一个函数,即按钮的处理函数
buttons:{
"更新":function(e){
e.preventDefault(); // 拦截默认的点击事件
// true为新增,false为修改。操作成功关闭模态框。
updateDept(false,
function (data) {
$("#dialog-dept-form").dialog("close");
},
function (data) {
showMessage("更新部门", data.msg, false);
})
},
"取消":function(){ $("#dialog-dept-form").dialog("close");}
}
})
})
删除部门
1
<!--mustache模板-->
<script id="deptListTemplate" type="x-tmpl-mustache">
<ol class="dd-list">
<!--模板中使用循环,循环 deptList 的元素-->
{{#deptList}}
<li class="dd-item dd2-item dept-name" id="dept_{{id}}" href="javascript:void(0)" data-id="{{id}}">
<!--部门名称-->
<div class="dd2-content" style="cursor:pointer;">
{{name}}
<!--编辑、删除按钮-->
<span style="float:right;">
<a class="green dept-edit" href="#" data-id="{{id}}" >
<i class="ace-icon fa fa-pencil bigger-100"></i>
</a>
<a class="red dept-delete" href="#" data-id="{{id}}" data-name="{{name}}">
<i class="ace-icon fa fa-trash-o bigger-100"></i>
</a>
</span>
</div>
</li>
{{/deptList}}
</ol>
</script>
2
// 点击删除按钮删除数据
$(".dept-delete").click(function (e) {
e.preventDefault(); // 拦截默认的点击事件
e.stopPropagation(); // 阻止冒泡事件
var deptId = $(this).attr("data-id"); // 取出当前元素的 data-id的值
var deptName = $(this).attr("data-name"); // 取出当前元素的 data-name的值
if (confirm("确定要删除部门[" + deptName + "]吗?")) {
// TODO
alert("删除中...");
}
});
加载部门信息
1
<!--mustache模板-->
<script id="deptListTemplate" type="x-tmpl-mustache">
<ol class="dd-list">
<!--模板中使用循环,循环 deptList 的元素-->
{{#deptList}}
<li class="dd-item dd2-item dept-name" id="dept_{{id}}" href="javascript:void(0)" data-id="{{id}}">
<!--部门名称-->
<div class="dd2-content" style="cursor:pointer;">
{{name}}
<!--编辑、删除按钮-->
<span style="float:right;">
<a class="green dept-edit" href="#" data-id="{{id}}" >
<i class="ace-icon fa fa-pencil bigger-100"></i>
</a>
<a class="red dept-delete" href="#" data-id="{{id}}" data-name="{{name}}">
<i class="ace-icon fa fa-trash-o bigger-100"></i>
</a>
</span>
</div>
</li>
{{/deptList}}
</ol>
</script>
2
// 加载当前部门的用户列表
$(".dept-name").click(function(e) {
e.preventDefault(); // 拦截默认的点击事件
e.stopPropagation(); // 阻止冒泡事件
var deptId = $(this).attr("data-id"); // 取出当前元素的 data-id的值
handleDeptSelected(deptId);
});
2.1
// 根据当前 deptId 加载用户部门用户列表函数
function handleDeptSelected(deptId) {
if (lastClickDeptId != -1) {
var lastDept = $("#dept_" + lastClickDeptId + " .dd2-content:first"); // 获取上次点击的部门的 <li> 下显示部门名称的 <div> 节点
lastDept.removeClass("btn-yellow"); // 去除高亮样式
lastDept.removeClass("no-hover");
}
var currentDept = $("#dept_" + deptId + " .dd2-content:first"); // 获取当前点击的部门的 <li> 下显示部门名称的 <div> 节点
currentDept.addClass("btn-yellow"); // 添加高亮样式
currentDept.addClass("no-hover");
lastClickDeptId = deptId; // 把当前点击的 deptId 设置为上次点击的 deptId
loadUserList(deptId); // 加载用户部门用户列表函数
}
2.1.1
<select id="pageSize" name="dynamic-table_length" aria-controls="dynamic-table" class="form-control input-sm">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select> 条记录 </label>
// 带分页参数的 ajax 请求
function loadUserList(deptId) {
var pageSize = $("#pageSize").val();
var url = "/sys/user/list?deptId=" + deptId;
var pageNo = $("#userPage .pageNo").val() || 1; // 第一次请求时 pageNo 数值为1
$.ajax({
url : url,
data: {
pageSize: pageSize, // 分页参数
pageNo: pageNo // 分页参数
},
success: function (result) {
renderUserListAndPage(result, url);
}
})
}
ajax 请求路径
@RequestMapping("/list")
@ResponseBody
public JsonData page(int deptId, PageQuery pageQuery) {
PageResult result = sysUserService.getPageByDeptId(deptId, pageQuery);
return JsonData.success(result);
}
传入分页实体类 PageQuery、返回分页实体类结果PageResult
public class PageQuery {
@Getter
@Setter
@Min(value = 1, message = "当前页码不合法")
private int pageNo = 1;
@Getter
@Setter
@Min(value = 1, message = "每页展示数量不合法")
private int pageSize = 10;
@Setter
private int offset;
public int getOffset() {
return (pageNo - 1) * pageSize;
}
}
@Getter
@Setter
@ToString
@Builder
public class PageResult<T> {
private List<T> data = Lists.newArrayList();
private int total = 0;
public PageResult(List<T> data, int total) {
super();
this.data = data;
this.total = total;
}
public PageResult() {
super();
}
}
service
public PageResult<SysUser> getPageByDeptId(int deptId, PageQuery page){
int count = sysUserMapper.countByDeptId(deptId);
if(count >0) {
List<SysUser> list = sysUserMapper.getPageByDeptId(deptId, page);
PageResult<SysUser> pageResult = new PageResult<>(list, count);
return pageResult;
}
return new PageResult<>();
}
mapper
<select id="getPageByDeptId" parameterType="map" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys_user
WHERE dept_id = #{deptId}
ORDER BY username ASC
LIMIT #{page.offset}, #{page.pageSize}
</select>
2.1.1.1
<table id="dynamic-table" class="table table-striped table-bordered table-hover dataTable no-footer" role="grid" aria-describedby="dynamic-table_info" style="font-size:14px">
<thead>
<tr role="row">
<th tabindex="0" aria-controls="dynamic-table" rowspan="1" colspan="1">
姓名
</th>
<th tabindex="0" aria-controls="dynamic-table" rowspan="1" colspan="1">
所属部门
</th>
<th tabindex="0" aria-controls="dynamic-table" rowspan="1" colspan="1">
邮箱
</th>
<th tabindex="0" aria-controls="dynamic-table" rowspan="1" colspan="1">
电话
</th>
<th tabindex="0" aria-controls="dynamic-table" rowspan="1" colspan="1">
状态
</th>
<th class="sorting_disabled" rowspan="1" colspan="1" aria-label="">操作</th>
</tr>
</thead>
<tbody id="userList">
<!--展示用户列表-->
</tbody>
</table>
// 渲染用户分页列表
function renderUserListAndPage(result, url){
if(result.ret){
if(result.data.total >0){
// 渲染用户模板
var rendered = Mustache.render(userListTemplate,{
userList: result.data.data,
"showDeptName": function() {
return deptMap[this.deptId].name;
},
"showStasus": function() {
return this.stasus == 1 ? '有效' : (this.stasus == 0 ? '无效' : '删除');
},
"bold": function() {
return function(text, render) {
var stasus = render(text);
if (stasus == '有效') {
return "<span class='label label-sm label-success'>有效</span>";
} else if(stasus == '无效') {
return "<span class='label label-sm label-warning'>无效</span>";
} else {
return "<span class='label'>删除</span>";
}
}
}
});
$("#userList").html(rendered); // 把渲染结果插入空的 <tbody id="userList"></tbody>下显示
bindUserClick(); // 绑定用户信息列表的点击事件
$.each(result.data.data, function(i, user) {
userMap[user.id] = user; // 存到全局的 userMap 里面
})
}else {
$("#userList").html(''); // result.data.total = 0 即result没有返回数据
}
// 下面渲染分页信息栏
var pageSize = $("#pageSize").val();
var pageNo = $("#userPage .pageNo").val() || 1;
renderPage(url, result.data.total, pageNo, pageSize, result.data.total > 0 ? result.data.data.length : 0, "userPage", renderUserListAndPage); // 调用 page.ftl 文件的 renderPage方法
} else {
showMessage("获取部门下用户列表", result.msg, false);
}
}
注:分页模板详见 4-3