# easyui-admin **Repository Path**: muyu-chengfeng/easyui-admin ## Basic Information - **Project Name**: easyui-admin - **Description**: Spring Boot + JQuery版EasyUI前端框架实现的管理系统项目 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 12 - **Forks**: 5 - **Created**: 2024-06-20 - **Last Updated**: 2025-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # easyui-admin ## 一、项目介绍 Spring Boot + JQuery版EasyUI前端框架实现的管理系统项目。 ## 二、技术介绍 ### 1、后端技术 | 技术 | 说明 | 官网 | | ------------ | ---------------- | ------------------------------------------- | | Spring Boot | 容器+MVC框架 | https://spring.io/projects/spring-boot | | Apache Shiro | 认证和授权框架 | https://shiro.apache.org/ | | MyBatis | ORM框架 | https://blog.mybatis.org/ | | MyBatis-Plus | MyBatis增强工具 | https://www.baomidou.com/ | | Knife4j | 接口文档生成工具 | https://doc.xiaominfo.com/docs/quick-start/ | | Redis | 分布式缓存数据库 | https://redis.io/ | | Fastjson | 序列化工具 | https://github.com/alibaba/fastjson | | Easy Excel | 操作excel的工具 | https://easyexcel.opensource.alibaba.com/ | ### 2、前端技术 | 技术 | 说明 | 官网 | | -------------- | ------------ | ----------------------------- | | JQuery版Easyui | 前端UI框架 | https://www.jeasyui.cn/ | | JQuery | Javascript库 | https://jquery.com/ | | HTML | 网页编程语言 | https://html.com/ | | CSS | 网页样式语言 | https://www.w3.org/Style/CSS/ | ## 三、功能介绍 ### 1、数据过滤 基于easyui的js插件实现的表格数据过滤功能。 #### 第一步 在页面引入easyui目录下的datagrid-filter.js ```html ``` #### 第二步 在渲染数据网格datagrid(easyui表格)时指定两个选项,通过enableFilter方法设置哪些列需要开启过滤功能。 ```js const datagrid = $(selector).datagrid({ // 其他选项... remoteFilter: true, // 开启远程过滤 clientPaging: false, // 关闭客户端分页 }); datagrid.datagrid("enableFilter", [{ field: "name", // 表格字段名 type: "textbox", // 组件类型名称 operator: ["equal", "contains"] // 展示的过滤选项 }]); ``` #### 实现原理 easyui datagrid组件的remoteFilter选项设置为true时,当使用过滤功能时,请求的URL会携带名为filterRules参数。 filterRules参数的格式是一个json数组的字符串,后端通过Spring的转换器将其转为List类型。 然后通过Pager类的getQueryWrapper()方法统一处理过滤的请求参数,并设置到QueryWrapper中。 ```java /** * 根据Pager创建QueryWrapper对象 * @param pager Pager * @return QueryWrapper */ public static QueryWrapper getQueryWrapper(Pager pager, boolean enableSort) { QueryWrapper queryWrapper = new QueryWrapper<>(); List filterRules = pager.getFilterRules(); if (CollectionUtils.isNotEmpty(filterRules)) { for (FilterRule filterRule : filterRules) { // 字段名:转为小写字母+下划线的格式 String field = StringUtils.toLower(filterRule.getField()); // 字段值 String value = filterRule.getValue(); if (StringUtils.isNotEmpty(value)) { switch (filterRule.getOperator()) { case less: queryWrapper.lt(field, value); break; case equal: queryWrapper.eq(field, value); break; case greater: queryWrapper.gt(field, value); break; case notequal: queryWrapper.ne(field, value); break; case lessorequal: queryWrapper.le(field, value); break; case greaterorequal: queryWrapper.ge(field, value); break; case beginwith: queryWrapper.likeLeft(field, value); break; case endwith: queryWrapper.likeRight(field, value); break; case contains: queryWrapper.like(field, value); break; default: break; } } } } if (enableSort) { // 得到order by语句 String statement = getOrderByStatement(pager); if (StringUtils.isNotEmpty(statement)) { queryWrapper.last(statement); } } return queryWrapper; } ``` 详情参考文件/js/menu_list.js和MenuServiceImpl类的selectByPage()方法。 ``` cn.edu.sgu.www.easyui.service.impl.MenuServiceImpl#selectByPage() ``` ##### FilterRule.java ```java package cn.edu.sgu.www.easyui.support; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; /** * 过滤规则 * @author 沐雨橙风ιε * @version 1.0 */ @Data @ApiModel public class FilterRule implements Serializable { private static final long serialVersionUID = 18L; /** * 字段名 */ @ApiModelProperty(value = "字段名") private String field; /** * 字段值 */ @ApiModelProperty(value = "字段值") private String value; /** * 比较符 */ @ApiModelProperty(value = "比较符") private Operator operator; } ``` ##### Operator.java ```java package cn.edu.sgu.www.easyui.support; /** * 比较符 * @author 沐雨橙风ιε * @version 1.0 */ public enum Operator { /** * 包含 */ contains, /** * 等于 */ equal, /** * 不等于 */ notequal, /** * 以...开始 */ beginwith, /** * 以...结尾 */ endwith, /** * 小于 */ less, /** * 小于或等于 */ lessorequal, /** * 大于 */ greater, /** * 大于或等于 */ greaterorequal } ``` ##### StringToListOfFilterRuleConverter.java ```java package cn.edu.sgu.www.easyui.converter; import cn.edu.sgu.www.easyui.support.FilterRule; import com.alibaba.fastjson.JSON; import org.springframework.core.convert.converter.Converter; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import java.util.List; /** * String ==> List的转换器 * @author 沐雨橙风ιε * @version 1.0 */ @Component public class StringToListOfFilterRuleConverter implements Converter> { @Override public List convert(@NonNull String source) { return JSON.parseArray(source, FilterRule.class); } } ``` ### 2、权限控制 基于RBAC模型实现的访问控制功能,通过一个过滤器PermsFilter完成鉴权。 ```java package cn.edu.sgu.www.easyui.shiro.filter; import cn.edu.sgu.www.easyui.consts.ContentTypes; import cn.edu.sgu.www.easyui.restful.JsonResult; import cn.edu.sgu.www.easyui.restful.ResponseCode; import cn.edu.sgu.www.easyui.util.HttpUtils; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * 定义PermsFilter过滤器(覆盖shiro的perms过滤器) * @author 沐雨橙风ιε * @version 1.0 */ @Slf4j @WebFilter public class PermsFilter extends PermissionsAuthorizationFilter { @Override public boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws IOException { boolean accessAllowed = super.isAccessAllowed(req, resp, mappedValue); // 未授权的处理 if (!accessAllowed) { // 获取HttpServletRequest对象 HttpServletRequest request = (HttpServletRequest) req; // 定义错误消息 String errorMessage = "正在访问未授权的资源:" + request.getRequestURI(); log.error(errorMessage); ResponseCode responseCode = ResponseCode.UNAUTHORIZED; // 获取HttpServletResponse对象 HttpServletResponse response = HttpUtils.getResponse(); response.setStatus(responseCode.getValue()); response.setContentType(ContentTypes.APPLICATION_JSON_CHARSET_UTF_8); // 构建返回对象 JsonResult jsonResult = JsonResult.error(responseCode, errorMessage); try (PrintWriter writer = response.getWriter()) { writer.write(JSON.toJSONString(jsonResult)); } catch (Exception e) { e.printStackTrace(); } } return true; // 返回true,防止shiro重复处理未授权的访问 } } ``` ### 3、菜单管理 通过role_menu表实现:基于角色的菜单管理功能,菜单直接分配给角色; 通过user_menu表实现:用户可以自定义展示哪些菜单,勾选则代表显示,取消勾选则隐藏(在用户的角色菜单的基础上自定义)。 ![](doc/文档图片/用户菜单控制.png) ### 4、隐藏表格列 支持隐藏列的记忆功能,下次打开页面,之前操作设置隐藏的列不会显示在表格中。 在需要使用隐藏列功能的页面中引入classpath下的/js/columnMenu.js ```html ``` 通过给表格增加一个onLoadSuccess事件来实现,在使用时,修改选择器的值为对应表格的ID选择器。 ```js // 给表格头部添加鼠标右键点击事件 onHeaderContextMenu: function(e){ e.preventDefault(); if (!columnMenu){ createColumnMenu("#permission_list"); } columnMenu.menu("show", { left: e.pageX, top: e.pageY }); }, onLoadSuccess: function () { let selector = "#permission_list"; let fields = getFields(selector); if (fields.length > 0) { let datagrid = $(selector); for (let i = 0; i < fields.length; i++) { let field = fields[i]; // 隐藏未选中的字段 if (!field.selected) { datagrid.datagrid("hideColumn", field.name); } } datagrid.datagrid("fitColumns"); } }, ``` 更多代码详情,参考src/main/resources/static/js/permission_list.js ## 四、常见问题 ### 问题1 不小心把用户对应角色的权限管理相关的权限取消了,导致访问权限管理相关接口失败,无法重新为角色分配权限管理功能的权限。 把system.settings.enable-authorization设置为false,然后重启项目,为角色分配完权限之后,再恢复成true ```yaml system: settings: enable-authorization: true # 是否开启鉴权 ``` ### 问题2 pom.xml文件报错,父依赖找不到 ```xml 20250901 cn.edu.sgu.www springcloud-parent ``` 在Intellij IDEA中,通过Git拉取这个项目到本地 ``` https://gitee.com/muyu-chengfeng/springcloud-parent.git ``` 使用maven插件将项目到本地仓库,然后刷新当前项目的maven依赖。 ![](doc/文档图片/安装父项目到本地.png)