部门树形结构
我们在添加或者编辑部门(用户)的时候,希望页面中部门这个字段呈现树形结构显示,让用户的体验效果更好点。效果图如下:
我们在做一个小的练习,完成树形结构的显示:
TreeViewPractice.java
package cn.xbmu.oa.test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import cn.xbmu.oa.domain.Department;
/**
* 说明:不能使用多层循环的方式,因为需要能支持任意层。
*/
public class TreeViewPractice {
/**
* 练习一:打印所有顶层部门及其子孙部门的信息(名称) 提示:假设有一个 打印部门树 的信息 的方法
*
* 要求打印如下效果:
*
* <pre>
* 市场部
* 宣传部
* 业务部
* 业务一部
* 业务二部
* 开发部
* 开发一部
* 开发二部
* </pre>
*/
@Test
public void printAllDepts_1() {
List<Department> topList = findTopLevelDepartmentList();
/**
* 方法一
for(Department top : topList){
showTree(top);
}
*/
//方法二
showTreeList(topList);
}
//显示一棵树的信息
private void showTree(Department top){
//顶点
System.out.println(top.getName());
//子树
for(Department child : top.getChildren()){
showTree(child);
}
}
//显示多颗树的信息
private void showTreeList(Collection<Department> topList){
for(Department top : topList){
//顶点
System.out.println(top.getName());
//子树
showTreeList(top.getChildren());
}
}
/**
* 练习二:打印所有顶层部门及其子孙部门的信息(名称),用不同的缩进表示层次(使用全角空格)。<br>
* 子部门的名称前比上级部门多一个空格,最顶层部门的名字前没有空格。 提示:假设有一个打印部门集合中所有部门信息的方法
*
* 要求打印如下效果:
*
* <pre>
* ┣市场部
* ┣宣传部
* ┣业务部
* ┣业务一部
* ┣业务二部
* ┣开发部
* ┣开发一部
* ┣开发二部
* </pre>
*/
@Test
public void printAllDepts_2() {
List<Department> topList = findTopLevelDepartmentList();
showTreeList_2(topList, "┣");
}
//显示多棵树的信息
private void showTreeList_2(Collection<Department> topList,String prefix){
for(Department top : topList){
//顶点
System.out.println(prefix + top.getName());
//子树
showTreeList_2(top.getChildren(), " "+prefix);
}
}
/**
* 结构如下:
*
* <pre>
* ┣市场部
* ┣宣传部
* ┣业务部
* ┣业务一部
* ┣业务二部
* ┣开发部
* ┣开发一部
* ┣开发二部
* </pre>
*
* @return 所有最顶层的部门的列表
*/
public static List<Department> findTopLevelDepartmentList() {
Department dept_1_1 = new Department();
dept_1_1.setId(new Long(11));
dept_1_1.setName("宣传部");
Department dept_1_2 = new Department();
dept_1_2.setId(new Long(12));
dept_1_2.setName("业务部");
Department dept_1_2_1 = new Department();
dept_1_2_1.setId(new Long(121));
dept_1_2_1.setName("业务一部");
Department dept_1_2_2 = new Department();
dept_1_2_2.setId(new Long(122));
dept_1_2_2.setName("业务二部");
dept_1_2_1.setParent(dept_1_2);
dept_1_2_2.setParent(dept_1_2);
Set<Department> children_0 = new LinkedHashSet<Department>();
children_0.add(dept_1_2_1);
children_0.add(dept_1_2_2);
dept_1_2.setChildren(children_0);
// ================================
Department dept_1 = new Department();
dept_1.setId(new Long(1));
dept_1.setName("市场部");
dept_1_1.setParent(dept_1);
dept_1_2.setParent(dept_1);
Set<Department> children_1 = new LinkedHashSet<Department>();
children_1.add(dept_1_1);
children_1.add(dept_1_2);
dept_1.setChildren(children_1);
// ---
Department dept_2_1 = new Department();
dept_2_1.setId(new Long(21));
dept_2_1.setName("开发一部");
Department dept_2_2 = new Department();
dept_2_2.setId((new Long(22)));
dept_2_2.setName("开发二部");
Department dept_2 = new Department();
dept_2.setId(new Long(2));
dept_2.setName("开发部");
dept_2_1.setParent(dept_2);
dept_2_2.setParent(dept_2);
Set<Department> children_2 = new LinkedHashSet<Department>();
children_2.add(dept_2_1);
children_2.add(dept_2_2);
dept_2.setChildren(children_2);
// ---
List<Department> depts = new ArrayList<Department>();
depts.add(dept_1);
depts.add(dept_2);
return depts;
}
}
将上面树形结构的方法,应用的项目中去,项目中将写一个部门的工具类实现:
DepartmentUtils:
DepartmentUtils.java
package cn.xbmu.oa.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import cn.xbmu.oa.domain.Department;
public class DepartmentUtils {
/**
* 遍历部门树,得到所有的部门列表,并修改了名称以表示层次
* @param topList
* @return
*/
public static List<Department> getAllDepartments(List<Department> topList){
List<Department> list = new ArrayList<Department>();
walkDepartmentTrees(topList,"┣",list);
return list;
}
/**
* 遍历部门树,把遍历出来的部门都放到指定的集合中
* @param topList
* @param string
* @param list
*/
private static void walkDepartmentTrees(Collection<Department> topList,
String prefix, List<Department> list) {
for(Department top : topList){
//顶点
Department copy = new Department();//
copy.setId(top.getId());
copy.setName(prefix+top.getName());
list.add(copy);
//子树
walkDepartmentTrees(top.getChildren()," "+prefix, list);
}
}
}
DepartmentAction.java
package cn.xbmu.oa.view.action;
import java.util.List;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import cn.xbmu.oa.base.BaseAction;
import cn.xbmu.oa.domain.Department;
import cn.xbmu.oa.utils.DepartmentUtils;
import com.opensymphony.xwork2.ActionContext;
@Controller
@Scope("prototype")
public class DepartmentAction extends BaseAction<Department> {
private Long parentId;
public String list() throws Exception {
List<Department> departmentList = departmentService.findAll();
ActionContext.getContext().put("departmentList", departmentList);
return "list";
}
public String delete() throws Exception {
departmentService.delete(model.getId());
return "toList";
}
public String editUI() throws Exception {
// 准备数据,departmentList,显示为树形结构
List<Department> topList = departmentService.findTopList();
List<Department> departmentList = DepartmentUtils
.getAllDepartments(topList);
ActionContext.getContext().put("departmentList", departmentList);
// 准备回显信息
Department department = departmentService.getById(model.getId());
ActionContext.getContext().getValueStack().push(department);
if (department.getParent() != null) {
parentId = department.getParent().getId();
}
return "saveUI";
}
public String edit() throws Exception {
// 1.从数据库中取出原对象
Department department = departmentService.getById(model.getId());
// 2.设置要修改的属性
department.setName(model.getName());
department.setDescription(model.getDescription());
department.setParent(departmentService.getById(parentId));// 上级部门
// 3.更新到数据库中
departmentService.update(department);
return "toList";
}
public String addUI() throws Exception {
// 准备数据,departmentList,显示为树形结构
List<Department> topList = departmentService.findTopList();
List<Department> departmentList = DepartmentUtils
.getAllDepartments(topList);
ActionContext.getContext().put("departmentList", departmentList);
return "saveUI";
}
public String add() throws Exception {
// 1.新建对象并封装属性,也可以使用model
if (parentId != null) {
model.setParent(departmentService.getById(parentId));
}
// 2.保存到数据库中
departmentService.save(model);
return "toList";
}
// ------------------------------------------------
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
}
UserAction.java
package cn.xbmu.oa.view.action;
import java.util.HashSet;
import java.util.List;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionContext;
import cn.xbmu.oa.base.BaseAction;
import cn.xbmu.oa.domain.Department;
import cn.xbmu.oa.domain.Role;
import cn.xbmu.oa.domain.User;
import cn.xbmu.oa.utils.DepartmentUtils;
@Controller
@Scope("prototype")
public class UserAction extends BaseAction<User> {
private Long departmentId;
private Long[] roleIds;
public String list() throws Exception {
List<User> userList = userSerivce.findAll();
ActionContext.getContext().put("userList", userList);
return "list";
}
public String delete() throws Exception {
userSerivce.delete(model.getId());
return "toList";
}
public String addUI() throws Exception {
// 准备数据,departmentList,显示为树形结构
List<Department> topList = departmentService.findTopList();
List<Department> departmentList = DepartmentUtils
.getAllDepartments(topList);
ActionContext.getContext().put("departmentList", departmentList);
// 准备数据,roleList
List<Role> roleList = roleService.findAll();
ActionContext.getContext().put("roleList", roleList);
return "saveUI";
}
public String add() throws Exception {
// 1.新建对象并设属性(也可以使用model)
Department department = departmentService.getById(departmentId);
model.setDepartment(department);
List<Role> roleList = roleService.getByIds(roleIds);
model.setRoles(new HashSet<Role>(roleList));
String passwdMD5 = DigestUtils.md5Hex("1234");
model.setPassword(passwdMD5);// 默认密码为1234,应使用MD5加密
// 2.保存到数据库
userSerivce.save(model);
return "toList";
}
public String editUI() throws Exception {
// 准备数据,departmentList,显示为树形结构
List<Department> topList = departmentService.findTopList();
List<Department> departmentList = DepartmentUtils
.getAllDepartments(topList);
ActionContext.getContext().put("departmentList", departmentList);
// 准备数据,roleList
List<Role> roleList = roleService.findAll();
ActionContext.getContext().put("roleList", roleList);
// 准备回显的数据
User user = userSerivce.getById(model.getId());
ActionContext.getContext().getValueStack().push(user);
if (user.getDepartment() != null) {
departmentId = user.getDepartment().getId();
}
if (user.getRoles().size() > 0) {
roleIds = new Long[user.getRoles().size()];
int index = 0;
for (Role role : user.getRoles()) {
roleIds[index++] = role.getId();
}
}
return "saveUI";
}
public String edit() throws Exception {
// 1,从数据库中取出原对象
User user = userSerivce.getById(model.getId());
// 2,设置要修改的属性
// >> 普通属性
user.setLoginName(model.getLoginName());
user.setName(model.getName());
user.setGender(model.getGender());
user.setPhoneNumber(model.getPhoneNumber());
user.setEmail(model.getEmail());
user.setDescription(model.getDescription());
// >> 所属部门
Department department = departmentService.getById(departmentId);
user.setDepartment(department);
// >> 关联的岗位
List<Role> roleList = roleService.getByIds(roleIds);
user.setRoles(new HashSet<Role>(roleList));
// 3,更新到数据库
userSerivce.update(user);
return "toList";
}
/** 初始化密码 */
public String initPassword() throws Exception {
// 1.从数据库中取出原对象
User user = userSerivce.getById(model.getId());
// 2.设置要修改的属性(要使用MD5摘要)
String passwdMD5 = DigestUtils.md5Hex("1234");
user.setPassword(passwdMD5);
// 3.更新到数据库
userSerivce.update(user);
return "toList";
}
// --------------------------------------
public Long getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Long departmentId) {
this.departmentId = departmentId;
}
public Long[] getRoleIds() {
return roleIds;
}
public void setRoleIds(Long[] roleIds) {
this.roleIds = roleIds;
}
}
DepartmentService.java
package cn.xbmu.oa.service;
import java.util.List;
import cn.xbmu.oa.base.BaseDao;
import cn.xbmu.oa.domain.Department;
public interface DepartmentService extends BaseDao<Department>{
/**
* 查询所有顶级部门的列表
* @return
*/
List<Department> findTopList();
}
DepartmentServiceImpl.java
package cn.xbmu.oa.service.impl;
import java.util.List;
import org.springframework.stereotype.Service;
import cn.xbmu.oa.base.BaseDaoImpl;
import cn.xbmu.oa.domain.Department;
import cn.xbmu.oa.service.DepartmentService;
@Service
@SuppressWarnings("unchecked")
public class DepartmentServiceImpl extends BaseDaoImpl<Department> implements
DepartmentService {
public List<Department> findTopList() {
return getSession().createQuery(//
"FROM Department d WHERE d.parent IS NULL")//
.list();
}
}
部门管理中的一些小功能:
- 从列表转到添加页面时,应默认选中原列表的上级部门。
- 增加“返回上一级”功能。
- 添加、修改、删除成功后还转到原列表页面,而不是顶级列表页面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>部门列表</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script>
<script language="javascript" src="${pageContext.request.contextPath}/script/pageCommon.js" charset="utf-8"></script>
<script language="javascript" src="${pageContext.request.contextPath}/script/PageUtils.js" charset="utf-8"></script>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/pageCommon.css" />
<script type="text/javascript">
</script>
</head>
<body>
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/> 部门管理
</div>
<div id="Title_End"></div>
</div>
</div>
<div id="MainArea">
<table cellspacing="0" cellpadding="0" class="TableStyle">
<!-- 表头-->
<thead>
<tr align=center valign=middle id=TableTitle>
<td width="150px">部门名称</td>
<td width="150px">上级部门名称</td>
<td width="200px">职能说明</td>
<td>相关操作</td>
</tr>
</thead>
<!--显示数据列表-->
<tbody id="TableData" class="dataContainer" datakey="departmentList">
<s:iterator value="#departmentList">
<tr class="TableDetail1 template">
<td><s:a action="departmentAction_list?parentId=%{id}">${name}</s:a> </td>
<td>${parent.name} </td>
<td>${description} </td>
<td>
<s:a onClick="return window.confirm('这将删除所有的下级部门,您确定要删除吗?')" action="departmentAction_delete?id=%{id}&parentId=%{parent.id}">删除</s:a>
<s:a action="departmentAction_editUI?id=%{id}">修改</s:a>
</td>
</tr>
</s:iterator>
</tbody>
</table>
<!-- 其他功能超链接 -->
<div id="TableTail">
<div id="TableTail_inside">
<s:a action="departmentAction_addUI?parentId=%{parentId}"><img src="${pageContext.request.contextPath}/style/images/createNew.png" /></s:a>
<s:if test="#parent != null">
<s:a action="departmentAction_list?parentId=%{#parent.parent.id}"><img src="${pageContext.request.contextPath}/style/images/ReturnToPrevLevel.png" /></s:a>
</s:if>
</div>
</div>
</div>
<!--说明-->
<div id="Description">
说明:<br />
1,列表页面只显示一层的(同级的)部门数据,默认显示最顶级的部门列表。<br />
2,点击部门名称,可以查看此部门相应的下级部门列表。<br />
3,删除部门时,同时删除此部门的所有下级部门。
</div>
</body>
</html>
Department.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.xbmu.oa.domain">
<class name="Department" table="xbmu_department">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="description" />
<!-- users属性,本类与User的一对多 -->
<set name="users">
<key column="departmentId"></key>
<one-to-many class="User" />
</set>
<!-- parent属性,本类与Department(上级)的多对一 -->
<many-to-one name="parent" class="Department" column="parentId"></many-to-one>
<!-- children属性,本类与Department(下级)的一对多 -->
<set name="children" cascade="delete" order-by="id">
<key column="parentId"></key>
<one-to-many class="Department" />
</set>
</class>
</hibernate-mapping>
源码下载:
http://download.csdn.net/detail/btt2013/9486968