大二暑假_SSM项目_筛选+动态配置

一、筛选功能

1)主要内容

在这里插入图片描述

要求:在图中画圈的位置加一个前端的时间筛选 按照开始日期筛选

2)部分代码

1、思路:
先实现一个搜索框,放在指定位置

在这里插入图片描述

然后写一个函数,当点击搜索按钮后,刷新下面的表格,使表格仅显示指定日期的数据

2、代码:
(1)搜索框(需要注意的是,筛选功能仅用来筛选下面那个表格,所以搜索框要放在两表中间,也就是说搜索框的代码要放在两个table中间,具体如下所示)

<table id="proessList" lay-filter="proessList" style="margin-top: -7px"></table>

	<blockquote class="layui-elem-quote">

		<form class="layui-form">
			<div class="layui-inline" style="height: 40px; width: 300px;">
				<div
					style="float: left; margin-left: 10px; height: 30px; text-align: center; margin-top: 0px">
					<input type="date" class="layui-input" id="selectdate"
						placeholder="yyyy-MM-dd"
						style="height: 25px; margin-top: 4px; float: left;">
				</div>
				<div
					style="float: left; margin-left: 10px; height: 30px; text-align: center; margin-top: 0px">
					<div id="btn" class="layui-btn"
						style="background-color: darkcyan; margin-top: 4px; float: right;">
						搜索</div>
				</div>
			</div>

		</form>
	</blockquote>

	<table id="startList" lay-filter="startList"></table>

表格(仅展示下面那个表格,也就是我们需要进行筛选操作的表格)

 startTableIns = table.render({
            elem: '#startList',
            url : '${pageContext.request.contextPath}/user/common/allStartProcess?selectdate='+encodeURI(selectdate),
            cellMinWidth : 95,
            //toolbar: '#startListBar',
            page : true,
            height : "full-320",
            limits : [10,15,20,25],
            defaultToolbar: ['filter'],
            limit : 10,
            id : "startListTable",
            cols : [[
                {type: "checkbox", fixed:"left", width:50},
                {field: 'id', title: '待办流程ID', minWidth:80, align:"center"},
                {field: 'name', title: '待办流程名称', minWidth:130, align:"center"},
                {field: 'time', title: '开始时间', minWidth:130, align:"center",templet: function(d) {
                    if(d.time==null||d.time==""||d.time=="undefined")
                    return "";
                    else
                     return util.toDateString(d.time);},edit: true},
                {field: 'state', title: '状态', minWidth:100, align:"center",templet:function(d){
                	var html="";
                	if(d.state==0){
                		html="<font color=red>未提交</font>"
                	}else if(d.state==1){
                		html="<font color=yellow>审批中</font>"
                	}else if(d.state==2){
                		html="<font color=blue>审批完成</font>"
                	}else if(d.state==3){
                		html="<font color=gray>已放弃</font>"
                	}else{
                		html="<font color=red>未知状态</font>"
                	}
                	return html;
                }},
                {title: '操作', minWidth:260, templet:'#startListBar',fixed:"right",align:"center"}

            ]]
        });

点击按钮后触发的函数(aa即上述表格所在的函数,调用aa函数就是在刷新表格,传入的selectdate参数就是搜索框中的日期)

  $("#btn").click(function(){
         var selectdate=$("#selectdate").val();//获取搜索框中的日期
           aa(selectdate);//刷新表格
         });
        

controller层

@RequestMapping(value="/user/common/allStartProcess",produces="application/json;charset=utf-8")
	@ResponseBody
	public Map<String, Object> allStartProcess(int page,int limit,HttpServletRequest request) {
		String date=request.getParameter("selectdate");
		
	User user=(User)request.getSession().getAttribute("user");
	int userId=user.getUser_id();
	List<Process> list =processService.getAllProcessByUserId(userId, page, limit);
	
	List<Process> selectlist=new ArrayList<>();
	
	System.out.println(list);
	Map<String, Object> map = new HashMap<String,Object>();
	map.put("code", 0);
	map.put("msg", "");
	int count=processService.getProcessCount(userId);
	map.put("count",count); 
	if(date.indexOf("-")!=-1)//判断搜索框中是否有日期,当未选择日期时
	//表格显示所有数据,当选择了日期时,表格仅显示所选日期的数据
	{
		for(int i=0;i<list.size();i++)
		{
			String Startdate=list.get(i).getStartdate().toString();
			if(Startdate.indexOf(date)!=-1)selectlist.add(list.get(i));
		}
		map.put("data",selectlist);
	}
	else map.put("data",list);
	return  map;
	}

需要注意的是我在判断搜索框中是否有日期时,用的是

if(date.indexOf("-")!=-1)

一开始我用的是

if(date!=null)

后来我发现程序会报错
于是我尝试着把前端传入的selectdate进行输出

在这里插入图片描述

发现结果如下

在这里插入图片描述

出现这个结果的原因可以参考如下博客:
[Object Object]

不过我们的重点不在于此,我们只需要能判断出是否选择了日期就行

由于选择了日期后,date一定是”2020-7-29“这样的样式,也就是说一定包含"-“这个字符,所以当date中没有”-“这个字符时,一定就是没选择日期,因此我把代码写成了上述的样子(用date.contains(”-")也可以)

3)遇到的困难

1、

困难:由于项目使用了layui前端框架,而我对它并不熟悉,所以我一开始毫无头绪,不知道怎么开始

解决方法:参考了博客
layui table数据渲染页面+筛选医生+在筛选日期一条龙

并研究了官网的说明:

table 数据表格文档 - layui.table

之后解决了困难

2、

困难:我在自己的电脑上运行成功后,便把代码发给了学长,但学长运行时出现了一个我运行时没出现的错误:

信息: 解析 HTTP 请求 header 错误注意:HTTP请求解析错误的进一步发生将记录在DEBUG级别。
java.lang.IllegalArgumentException: 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义

我去看了一下代码,发现是这一行出错了

在这里插入图片描述

虽然找到了错误,但我不知道为什么同样的代码在我的电脑上没错,在学长电脑上就出错

解决方法:看博客

通过以下博客我找到了出现该问题的原因:
tomcat 请求出现RFC 7230 and RFC3986的错误,解决办法

总结一下就是我和学长用的tomcat版本不同,学长用的是9.0,我用的是8.0,8.0可以解析上面图中的selcetdate变量,而9.0不行。

于是我把tomcat换成了9.0版本(由于我的Elipse版本太老,不支持tomcat9.0,我还特地去下了个最新版本的Elipse。。。。),并按照上面那个博客改了一下,发现还是没解决,于是我又找了另一篇博客:
IE上的The valid characters are defined in RFC 7230 and RFC 3986坑

按照这篇博客把selectdate变量encode了一下问题便解决了

在这里插入图片描述

3、
困难:上述困难解决后我遇到了一个很奇怪的BUG:
我在用tomcat8运行时,程序没有一点问题,但我换成tomcat9后,页面出现了如下乱码(代码完全一样的情况下)

在这里插入图片描述

解决方法:参考了两篇博客

我先是按照下面这篇博客改了Elipse的配置
eclipse 更改编码为UTF-8

发现还是有乱码

然后我又找了下面这篇博客
项目部署到Tomcat上,JS文件及后台数据显示都是乱码问题

我跳过了前三步,直接执行了第四步:清理浏览器缓存,然后再启动项目,乱码就不见了!

4)效果展示

当未选择日期时,表格显示所有数据

在这里插入图片描述

选择7月29日

在这里插入图片描述

点击搜索:

在这里插入图片描述

选择7月26日后点击搜索

在这里插入图片描述

随便选择一个没有数据的日期

在这里插入图片描述

把日期删掉后点击搜索

在这里插入图片描述

二、流程的动态配置

1)主要内容

在admin(系统管理员)的操作界面增加一个流程管理和角色流程管理的功能,给不同角色配置不同流程

2)部分代码

1、流程管理
(1)写个数据表,存放流程信息

在这里插入图片描述

(2)写实体类层和Dao层
这里需要注意的一点是,由于学长要求我把流程管理的界面做成如下样子

在这里插入图片描述

即树状结构的菜单,所以我需要额外建以下实体类:

流程菜单树

在这里插入图片描述

(这个实体类主要用于与前端对接,前端需要这些属性)

此外,我们的查询语句也会比较特殊

以下为查询语句代码

	<resultMap type="com.factory.pro.dto.WorkflowTree" id="menuTree">
		<id column="wmid" property="id" javaType="java.lang.String" />
		<result column="wmname" property="text" javaType="java.lang.String" />
		<collection column="wmid" property="children" select="selectChild" />
	</resultMap>

	<!-- 查找一级菜单 -->
	<!-- 先查询菜单根级目录 -->
	<!-- 这里的返回结果必须为resultMap,并且值为上面构建的resultMap的id的值 -->
	<select id="selectworkflow_MenuList" resultMap="menuTree">
		select * from workflow_menu where
		wmid='0'
	</select>
	
	<select id="selectChild" resultMap="menuTree">
		select * from workflow_menu where pid
		= #{wmid}
	</select>

通过上面这种方式,我们可以从wmid为0的根结点开始,递归地获取树中所有结点的信息。

而可以形成递归的原因,就是我们在resultmap中指定了children这一属性需要通过调用selectchild的SQL语句来获取。

具体递归流程如下:
(1)通过selectworkflow_MenuList查询出根节点的具体信息;
(2)调用selectchild,把根节点的所有子结点信息放入根节点的children属性中;
(3)这些子结点也有children属性,每一个子结点都会再次调用selectchild来把各自的子结点信息放入children属性中;
(4)重复步骤(3)直至所有结点均被遍历

增删改的代码比较简单,这里仅展示修改

<!-- 根据id修改数据 -->
	<update id="updateWorkflow_MenuById" parameterType="com.factory.pro.entity.Workflow_menu">
		update workflow_menu
		<trim prefix="set" suffixOverrides="," suffix="where wmid = #{wmid}">
          <if test='wmname != null and wmname != ""'>
		    	wmname = #{wmname},
		   </if>
		   <if test='wmname == null or wmname == ""'>
		    	wmname = null,
		   </if>
		   <if test='procedefname != null and procedefname != ""'>
			   procedefname = #{procedefname},
		    </if>
			<if test='icon != null and icon != ""'>
				icon = #{icon},
			</if>
			<if test='pid != null and pid != ""'>
				pid = #{pid},
			</if>
			<if test='is_parent != null'>
				is_parent = #{is_parent}
			</if>
		</trim>
	</update>

这里需要注意的是我用到了trim标签,这个标签的好处就是可以自动处理语句中的逗号。
比如当我仅传入了wname和wmid参数时,如果不使用标签,SQL语句会变成这样:

update workflow_menu set wmname = #{wmname},where wmid = #{wmid}

即会多一个逗号

而使用标签的话,它会自动帮我们处理掉多余的逗号

还有一个细节就是下图所示的地方

在这里插入图片描述

为什么在wmname为null时我要写一句 wmname=null呢?这看起来完全是个废话呀?

这是因为我们在传入参数时,有可能有多个参数都为空。

当除了wmid以外的所有参数都为空时,SQL语句会变成下面这样

update workflow_menu  ;

如果把set和where语句都放到标签外面的话,SQL语句就会变成这样

update workflow_menu set where wmid=? ;

总之,在这种情况下是形不成完整的SQL语句的,不论我们用不用标签、用什么标签、怎么用标签都是一样的结果。因此我加了一个wname=null这句看起来像废话的语句。

另外就是,当wmid为null时,程序会报另外一个错,即主键不能为空。
这个我们就无法通过更改SQL语句来改正这个错误了,我们应该在调用该update函数之前,先判断传入的wmid是否为空,如果为空直接告诉用户:“修改失败”即可。

(3)写Service层和controller层,
这两层其实就是在调用Dao层函数,唯一增加的东西就是在进行增删改操作时,把增删改的结果输出了一下,让用户能直观地看到增删改是否成功了。

那如何把增删改的结果从后端传到前端呢?

这就需要用到另一个实体类了(和上面的树一样,是个用来和前端对接的工具人)

package com.factory.pro.dto;

import java.io.Serializable;



public class GlobalResult implements Serializable{

    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;

    // 响应业务状态
    private Integer status;

    // 响应消息
    private String msg;

    // 响应中的数据
    private Object data;

    public static GlobalResult build(Integer status, String msg, Object data) {
        return new GlobalResult(status, msg, data);
    }

    public static GlobalResult ok(Object data) {
        return new GlobalResult(data);
    }

    public static GlobalResult ok() {
        return new GlobalResult(null);
    }

    public GlobalResult() {

    }

    public static GlobalResult build(Integer status, String msg) {
        return new GlobalResult(status, msg, null);
    }

    public GlobalResult(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public GlobalResult(Object data) {
        this.status = 200;
        this.msg = "OK";
        this.data = data;
    }

    public Boolean isOK() {
        return this.status == 200;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "ManagerResult [status=" + status + ", msg=" + msg + ", data=" + data + "]";
	}
    

}

这里用到Serializable接口也是前端的需要(涉及到了序列化、反序列化,不过对我来说这不是重点,毕竟前端不用我写。。。。后面有时间的话,我会去好好补习一下序列化的知识)

其中Serializable接口的作用及用法可参考下面的博客
Java 之 Serializable 序列化和反序列化的概念,作用的通俗易懂的解释

然后我们就可以通过这个类,实现与前端的对接。

以删除操作为例

	public GlobalResult deleteWorkflow_MenuById(String wmid) {
		Integer deleteCount = Workflow_menudao.deleteWorkflow_MenuById(wmid);
		if (deleteCount != null && deleteCount > 0) {
			
			return new GlobalResult(200, "数据删除成功", null);
		} else {
			return new GlobalResult(400, "数据删除失败", null);
		}
	}

2、角色流程管理
(1)建数据表,存储角色流程信息(即不同角色可以看到哪些流程)

在这里插入图片描述

(2)写实体类和Dao层

和刚才一样,学长要求我把流程按类别做成树状

在这里插入图片描述

那么首先我们要建一个工具类

package com.factory.pro.dto;
import java.util.ArrayList;
import java.util.List;
public class OptionalTreeNode {
	private String id;// 菜单id
	private String text;// 菜单名称
	private boolean checked;// 是否为选中
	private List<OptionalTreeNode> children = new ArrayList<OptionalTreeNode>();// 下级菜单
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}
	public boolean isChecked() {
		return checked;
	}
	public void setChecked(boolean checked) {
		this.checked = checked;
	}
	public List<OptionalTreeNode> getChildren() {
		return children;
	}
	public void setChildren(List<OptionalTreeNode> children) {
		this.children = children;
	}
	@Override
	public String toString() {
		return "EasyUIOptionalTreeNode [id=" + id + ", text=" + text + ", checked=" + checked + ", children=" + children
				+ "]";
	}
	
}

和刚才一样,这个类是用来和前端对接的。

接下来就是SQL语句(由于比较简单,这里仅展示一个)

	<!-- 查询该角色id(roleuuid)下的流程id(wmid) -->
	<select id="selectRoleFLowidByRoleid" resultType="string">
		select
		role_flow.wmid from role_flow WHERE
		role_flow.roleuuid=#{roleuuid}
	</select>
    

(3)Service层和controller层
我们刚才说了,界面需要做成下面这样

在这里插入图片描述

那我们首先就需要查询角色表,并显示在左侧

具体代码如下

	public DataGridResult findRolelistByPage(Integer page, Integer rows, Role role) {
		// 1.分页查询
		PageHelper.startPage(page, rows);//进行分页
		List<Role> list = roleDao.selectRolelistByPage(role);
		PageInfo<Role> pageInfo = new PageInfo<>(list);
		// 2.封装EasyUIDataGridResult
		DataGridResult result = new DataGridResult();
		result.setTotal((int) pageInfo.getTotal());//总数据量
		result.setRows(pageInfo.getList());//具体信息
		// 3.返回分页的结果
		return result;
	}

其中DataGridResult也是一个工具类,用来把数据和数据个数一起进行输出。

接着我们要查询角色流程信息,并显示在右侧。
由于需要做成树状,所以这块比较复杂。

话不多说,直接上代码

public List<OptionalTreeNode> findRoleFlowByRoleid(Integer roleuuid) {
		// 1.根据角色id获取角色对应的流程id
		List<String> flowIdList = roleDao.selectRoleFLowidByRoleid(roleuuid);
		// 2.获取一级菜单
		List<Workflow_menu> parentMenu = Workflow_menuDao.selectWorkflow_MenuIdName("0");//获取pid="0"的所有结点,即获取根节点的所有子结点
		// 3.当前角色对象对应的菜单权限
		List<OptionalTreeNode> treeList = new ArrayList<OptionalTreeNode>();
		// 暂存一级菜单
		OptionalTreeNode t1 = null;
		// 暂存二级菜单
		OptionalTreeNode t2 = null;
		// 一级菜单遍历
		for (Workflow_menu m1 : parentMenu) {
			t1 = new OptionalTreeNode();
			t1.setId(m1.getWmid());
			t1.setText(m1.getWmname());
			List<Workflow_menu> leafMenu = Workflow_menuDao.selectWorkflow_MenuIdName(m1.getWmid());//获取当前结点的所有子结点
			// 二级菜单遍历
			for (Workflow_menu m2 : leafMenu) {
				t2 = new OptionalTreeNode();
				t2.setId(m2.getWmid());
				t2.setText(m2.getWmname());
				// 如果角色下包含有这个权限菜单,让它勾选上
				for (String flowId : flowIdList) {
					if (m2.getWmid().equals(flowId)) {
						t2.setChecked(true);
					}
				}
				t1.getChildren().add(t2);
			}
			treeList.add(t1);
		}
		return treeList;
	}

接着就是当用户勾选完角色对应的流程后,我们应该让用户点击保存按钮后便可把数据库中的role_flow表进行更新

这块比较简单,直接上代码

@Override
	public GlobalResult updateRoleMenu(Integer roleuuid, String checkedIds) {
	
			roleDao.deleteMenuidByRoleid(roleuuid);
			// 权限角色id
			if (checkedIds != null) {//checkedIds保存了用户勾选的流程所对应的ID
				String[] ids = checkedIds.split(",");
				for (String menuUuid : ids) {
					roleDao.insertRolemenu(menuUuid, roleuuid);
				}
			}
			
			System.out.println("更新角色对应的对应的权限菜单 ,清除缓存");
		
		return GlobalResult.build(200, "权限设置成功");
	}

最后就是流程的显示部分了。思路很简单,我们只需在显示流程前,获取当前用户信息,并通过用户id获取其对应的角色。之后再根据角色id查询role_flow表,获取其所对应的流程,然后只显示这些流程即可。

代码如下

	public List<ActDeployment> queryProcessDeployWithAdmin(WorkFlow workFlow,int page,int limit,User user) {
	//user参数即当前用户
		if (workFlow.getDeploymentName() == null) {
			workFlow.setDeploymentName("");
		}
		String name = workFlow.getDeploymentName();
		// 查询总条数
		//long count = repositoryService.createDeploymentQuery().deploymentNameLike("%" + name + "%").count();
		// 查询
		int firstResult = (page - 1) * limit;
		int maxResults = limit;
		List<Deployment> delist = repositoryService.createDeploymentQuery().deploymentNameLike("%" + name + "%")
				.listPage(firstResult, maxResults);
		//获取当前用户对应的角色
		List<Integer> roleuuids=roleDao.getUserRole(user.getUser_id());
		//获取该角色对应的流程id
		List<String> flowIdList=new ArrayList<>();
		for (Integer roleuuid : roleuuids) {
			List<String> li=roleDao.selectRoleFLowidByRoleid(roleuuid);
			flowIdList.addAll(li);
		}
		//获取id对应的流程
		List<Workflow_menu> flowList=new ArrayList<>();
		for (String wmid : flowIdList) {
			List<Workflow_menu> flowli=workflow_menuDao.selectWorkflow_MenuById(wmid);
			flowList.addAll(flowli);
		}
		//让list中只包含角色对应的流程
		List<Deployment> list=new ArrayList<>();
		for (Deployment deployment : delist) {
			for (Workflow_menu flow : flowList) {
				if(flow.getWmname().contains(deployment.getName()))
				{
					list.add(deployment);
				}
			}
		}
		List<ActDeployment> data = new ArrayList<ActDeployment>();
		for (Deployment resultdeployment : list) {
			ActDeployment entity = new ActDeployment();
			// copy
			BeanUtils.copyProperties(resultdeployment, entity);
			data.add(entity);
		}
		return data;
	}

3)遇到的困难

1、
困难:一开始程序找不到我写的页面,一直报404

解决方法:问了学长后得知我忘了在controller层处理请求

在admincontroller.java中加入如下代码即可

在这里插入图片描述

所以说报404时一定要多检查前端和后端地url,很大可能时url的问题

2、

困难:不知道如何弄出树形菜单的效果

解决方法:问了学长,在学长的指导下解决了该困难(具体代码如上面所示)

3、

困难:不知道如何进行分页

解决方法:看了颜群老师的视频
Mybatis
其中第14集详细地讲解了如何用pageHelper和pageinfo进行分页

总结一下就是想实现分页,只需在查询函数之前加一句

PageHelper.startPage(page, rows);

即可。

当我们想要获取分页信息时,我们可以直接新建一个Page类

Page<Role> page=PageHelper.startPage(page, rows);

从page中获取分页信息,比如数据总量,页数,每页的数据量等。

也可以通过新建一个PageInfo对象来获取这些信息

PageInfo<Role> pageInfo = new PageInfo<>(list);

这两者的区别就是pageinfo更强大一些,它拥有更多的函数,可以查询更多的信息,比如开头那一页的信息、最后那一页的信息。

4、
困难:我在运行检测流程管理的增删改功能时,总是告诉我增加失败或删除失败

解决方法:
(1)首先我改了一下前端的代码

在这里插入图片描述

一开始的时候,data里面的id写成了menuid,然后程序就去获取menu数据表中的数据了(这个是学长做的另一个数据表,用来进行菜单管理和角色菜单管理),这样的话程序就会使用菜单管理功能所用到的数据和函数,导致程序运行失败。

也就是说,由于这个id写成了menuid,流程管理功能和菜单管理功能“串味”了,所以只需把这个id一改就可以解决了。

(2)上述操作之后,本来程序已经正常运行了。但没过多久,我又遇到了无法进行增删改操作的现象(代码一样的情况下)。

这次我改了好久,始终无法改正错误。

但当我给程序打了断点,准备通过debug模式一步步找出BUG原因时,程序居然运行成功了。。。

这件事告诉了我一个道理:在进行开发时一定要尽量用debug on server运行程序。这样不但能打断点一步步找BUG,而且还能避免一些用run on server运行程序时会出现的一些莫名其妙的BUG。。。。。

4)效果展示

(1)流程管理

界面

在这里插入图片描述

增加流程

在这里插入图片描述

如果id为空,则添加失败

在这里插入图片描述

如果不为空

在这里插入图片描述

成功添加

在这里插入图片描述

在这里插入图片描述

修改操作

在这里插入图片描述

点击确定后成功修改

在这里插入图片描述

在这里插入图片描述

右键重命名操作(右键菜单中的添加、删除、修改与操作栏中的一致,这里不再演示)

在这里插入图片描述

输入新名字

在这里插入图片描述

点击确定后成功修改

在这里插入图片描述

删除操作

在这里插入图片描述

点击确定后删除成功

在这里插入图片描述

在这里插入图片描述

(2)角色流程管理

界面(可在搜索栏中根据角色名搜索角色,这里不再演示此功能)

在这里插入图片描述

点击一个角色后,显示流程的树状菜单,打勾的即为该角色能看到的流程

在这里插入图片描述

我们修改一下后点击保存

在这里插入图片描述

查看数据表,发现确实多了一行数据

在这里插入图片描述

然后我们用该角色的账号密码登录系统,查看流程,发现确实能看到刚才我们勾选的那4类流程

在这里插入图片描述

接着我们再次用管理员身份登录,更改一下勾选的流程

在这里插入图片描述

发现确实只能看到我们勾选的那两个流程

在这里插入图片描述

至此演示完毕。

三、制度的动态配置

1)主要内容

在admin(系统管理员)的操作界面增加一个制度管理和角色制度管理的功能,给不同角色配置不同制度

这个任务与上面很类似,不同之处在于流程的名字很短,而制度一般都很长,一般都是一百字以上

2)部分代码

由于和上面的任务很类似,这里仅演示不同之处

1、制度管理
(1)写个数据表,存放制度信息

在这里插入图片描述

这里不同之处在于,content一栏的类别不再是vachar了,而是mysql中的text属性。

其次,由于我们与化工厂那边做对接时,他们会给我们四张表,分别是公司制度(companyruglation)、国家法律(law)、地方法规(localstatutes)、行业标准(standard)。因此我们就需要将这四张表,与我们写的这个zhidu表同步。

如何同步呢?

1)首先我们先说增删改,这个很简单,我们只要每次对zhidu表增删改时,都判断一下我们改的这个制度的类型,然后同步地修改对应数据表中地数据即可

比如我们修改了国家法律中的一个制度,那我们修改完zhidu表中的数据后,再把law表中的数据一并进行修改就好了。(具体代码之后展示)

2)然后就是初始数据的同步。
最简单的方法:把那四个表中的数据都复制到zhidu表对应的类别下。

如果数据很多,复制起来太麻烦。那我们就可以写个函数,先查询那四个表中的数据并用实体类存储,然后再分类别地插入到制度表中去。

这里由于我们是测试,数据量较小,就直接复制了。

(2)写实体类层和Dao层
这里和上面几乎一样,没什么好说的

(我一开始以为那个mysql中的text类别不能与java中的String进行一一对应,但后来才发现mybatis自动能帮我们把text转换为String ,我们什么都不用干,resultmap也不用写,不得不说这真是太方便了。)

关于Text类型可以看看下面这篇博客
MySQL数据类型之TEXT与BLOB

(3)写Service层和controller层,
上面说了,我们在对zhidu表进行增删改时,要对其他那四张表同步进行增删改。

以下为代码(以增加为例)

public GlobalResult addZhidu(Zhidu zhidu) {
		// 设置默认添加的菜单的状态为使用中
				if(zhidu.getZid()==null||zhidu.getZid().isEmpty())return new GlobalResult(400, "数据添加失败", null);
				
				Integer insertCount1 = zhidudao.insertZhidu(zhidu);
				Integer insertCount2=null;
				
				Zhidu parent=zhidudao.selectZhiduById(zhidu.getPid());
				int id=Integer.parseInt(zhidu.getZid())-Integer.parseInt(zhidu.getPid());//插入的id为zhidu表的id减去其父结点的id
				//比如101,它的父亲结点为100,这个id即为101-100=1
				//所以我们在管理制度时有个限制,即插入新的制度结点时,它的id不能乱取。
				//比如在100的下面添加子结点,那该子结点id应该为101-199之间
				if(id<=0)return new GlobalResult(400, "数据添加失败", null);
				
				Regulation regulation=new Regulation(id,zhidu.getContent());
				
				if(parent.getTitle().equals("公司制度"))
				{
					insertCount2=regulationdao.insertCompanyRegulation(regulation);
				}
				if(parent.getTitle().equals("国家法律"))
				{
					insertCount2=regulationdao.insertLaw(regulation);
				}
				if(parent.getTitle().equals("地方法规"))
				{
					insertCount2=regulationdao.insertLocalstatute(regulation);
				}
				if(parent.getTitle().equals("行业标准"))
				{
					insertCount2=regulationdao.insertStandard(regulation);
				}
				
				if (insertCount1 != null && insertCount1 > 0 &&insertCount2 != null && insertCount2 > 0) {
					return new GlobalResult(200, "数据添加成功", null);
				} else {
					return new GlobalResult(400, "数据添加失败", null);
				}
	}

(4)前端(没错,我这个后端仔也要负责改一下前端代码)
这里可以说是最大的不同了,由于制度的内容一般很长,如果还像之前那样用表格的一个单元格来显示制度内容会显示不下,或者把单元格撑得很大,导致看起来很丑,所以学长让我想一个方法来显示。

就这样,我这个前端小白写起了前端。

通过一通查资料,我弄出了下面这样的效果

在这里插入图片描述

这个拓展行的关键代码如下

view: detailview,
	    detailFormatter: function(rowIndex, rowData){
		return '<table><tr>' +
				'<td style="border:0">' +
				'<p>制度具体内容: ' + rowData.content + '</p>' +
				'</td>' +
				'</tr></table>';

需要注意的是,一定要在html文件加入下面一行(类似于导包,前端小白只能这样理解了)

<script type="text/javascript" src="http://www.w3cschool.cc/try/jeasyui/datagrid-detailview.js"></script>

还有就是增加或修改数据时,制度内容这部分肯定不能用普通文本框了。虽然文本框也能输入挺多信息的,但当内容很长时,我们只能看到一小部分。所以我们需要做成下面这样

在这里插入图片描述

也就是说需要用到textarea标签

<tr>
		<td align="right">制度内容:</td>
		<td align="left"><textarea  name="content" id="content"></textarea></td>
</tr>

2、角色制度管理
(1)建数据表,存储角色流程信息(即不同角色可以看到哪些流程)

与上面一样

(2)写实体类和Dao层

与上面一样

(3)Service层和controller层

这部分只是在用户的显示部分有些不同

代码如下(以公司制度为例)

	public List<Regulation> getAllCompanyRegulation(int page, int size) {
		if(page <= 0){
	         page = 1;
	      }
	      if (size <= 0){
	          size = 10;
	      }
	    Integer start = (page - 1) * size;
	    List<Regulation> rlist=regulationDao.getAllCompanyRegulation(start, size);
	    
	    User user = SessionUtils.getCurrentUser();
	    List<Integer> roleuuids=roleDao.getUserRole(user.getUser_id());
		//获取该角色对应的流程id
		List<String> zhiduIdList=new ArrayList<>();
		for (Integer roleuuid : roleuuids) {
			List<String> li=roleDao.selectRoleZhiduidByRoleid(roleuuid);
			zhiduIdList.addAll(li);
		}
		//获取id对应的制度
		List<Zhidu> zhiduList=new ArrayList<>();
		for (String zid : zhiduIdList) {
			Zhidu zhidu1=zhiduDao.selectZhiduById(zid);
			zhiduList.add(zhidu1);
		}
		//让list中只包含角色对应的流程
		List<Regulation> list=new ArrayList<>();
		for (Regulation regulation : rlist) {
			for (Zhidu zhidu : zhiduList) {
				Zhidu parent=zhiduDao.selectZhiduById(zhidu.getPid());
				if(parent.getTitle().equals("公司制度"))
				{
					if(Integer.parseInt(zhidu.getZid())-Integer.parseInt(zhidu.getPid())==regulation.getId())//101-100=1,通过id获取对应的制度
				    {
					    list.add(regulation);
				    }
				}
			}
		}
	    return list;
	}

(4)前端

和刚才一样,我们需要考虑制度内容的显示问题,这里直接上代码

// 加上双击函数和右键函数
var foo = 'bar';$('#tree').tree({    
	    	    url:'role/findRoleZhiduByRoleid?id=' + rowData.uuid,
	    	    animate:false,
	    	    checkbox:true,
                onDblClick: function(node){//双击
		           $.messager.alert("制度具体内容", node.attributes);  // alert node text property when clicked
	            },
            onContextMenu: function(e,node){//右键点击
			e.preventDefault();
			$(this).tree("select",node.target); //让右键点击的节点对象被选中
			$("#mm").menu("show",{
				left: e.pageX,
				top:e.pageY
			    });
		   }


	    	}); 

//当双击或右键时调用如下函数,
$("#showdetail").on("click",function(){
		//获取选中的节点对象
		var selectedNode = $("#tree").tree("getSelected");
		$.messager.alert("制度具体内容", selectedNode.attributes);//对话框输出信息
	}); 

效果如下

在这里插入图片描述

3)遇到的困难

1、
困难:出现了Column count doesn’t match value count at row 1 报错

解决方法:看了博客 Column count doesn’t match value count at row 1解决方法
发现是因为那四个表设置成了主键自增,而我插入时没有写主键值,也没在括号里注明,所以报错。

本来我是打算按照博客注明一下列名,但后来我一想,我之后进行增删改是要根据id进行zhidu表和那四张表的同步的,设置成id自增不利于同步,于是我就通过去掉自增设置解决了该困难

2、
困难:写制度管理时不知道如何对制度内容进行显示

解决方法:由于这块用到的框架为easyui,我就上它得官网看了下,发现下面这个拓展行行适合我
EasyUI 扩展行显示细节

但是这个又用到了php,我没学过php,就想着找找有没有简单点的写法,便找到了下面这个
EasyUI 数据网格视图

按照这个解决了困难

3、
困难:写完拓展行后我发现了一个问题,就是当单元格中内容很多时,内容会把单元格撑地很高,这样就很丑。

我尝试去设置行高后发现不行,只能对宽度进行设置,高度没办法设置。

解决方法:看博客
easyUi dataGrid 行高设置,解决错行问题
按照博客加了如下代码,解决了困难

		{
			field : 'content',
			title : '制度内容',
			width : 200,
			styler: function(value,row,index){
				return 'height:30px';
			}
		},

4、
困难:写角色制度管理时,不知道如何对制度内容进行显示
因为我发现树状结构不能像上面那样展开,官网也没有类似的教程

解决方法:参考学长代码,并自己思考了后想到了写双击函数。然后看了博客,了解了一下easyui中这个树组件如何写双击、右键函数
EasyUI Tree 树
之后解决了该困难

4)效果展示

这里仅展示与流程部分不同的地方

(1)制度管理

点击某一个制度

在这里插入图片描述

点击+号查看具体制度内容

在这里插入图片描述

修改制度

在这里插入图片描述

(2)角色制度管理

点击一个角色后,显示制度的树状菜单,打勾的即为该角色能看到的制度

在这里插入图片描述

双击父亲结点

在这里插入图片描述

双击叶子结点

在这里插入图片描述

右键点击叶子结点

在这里插入图片描述

点击显示具体信息

在这里插入图片描述

用该角色的账号密码登录系统,查看制度,发现确实能看到刚才勾选的那些制度

在这里插入图片描述

至此演示完毕。

由于该项目为商业项目,源代码就不传上来了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值