分享一个基于easyui前端框架开发的后台管理系统模板

这篇具有很好参考价值的文章主要介绍了分享一个基于easyui前端框架开发的后台管理系统模板。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这是博主自己在使用的一套easyui前端框架的后台管理系统模版,包含了后端的Java代码,已经实现了菜单控制、权限控制功能,可以直接拿来使用。

springboot + mybatis + mybatis-plus实现的增删查改完整项目,前端使用了easyui前端框架。https://gitee.com/he-yunlin/easyui-crud.git

目录

功能介绍

一、菜单管理

菜单列表

角色-菜单列表

二、权限管理

权限列表

角色-权限列表

三、用户管理

用户列表

用户-角色列表

四、歌曲管理

歌曲列表

五、系统功能

系统设置

初始化权限

代码介绍

响应状态码

统一响应实体类

全局异常处理类

统一数据格式处理类

datagrid数据格式对象

获取用户登录信息的工具类

基于easyui的表格过滤插件功能实现

基础的分页器

基础的排序器


功能介绍

这是对本系统的一些简单的功能介绍。

一、菜单管理

菜单列表

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

点击表格头部工具栏的【添加】按钮,会添加一条模板数据

/**
 * 添加
 */
function insert() {
	requestUrl = "/menu/insert";

	ajaxPost(requestUrl, {
		type: 1,
		name: "xxx",
		url: "/html/xxx_list.html",
		icon: "icon-script"
	}, function (response) {
		showMsg(response.message);

		$("#menu_list").datagrid("reload");
	}, error);
}

修改功能是基于easyui的表格行内编辑完成的,鼠标选择一行数据,点击头部工具栏的【修改】按钮,会开启该行的编辑。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

点击保存会向后台控制器提交修改后的数据,点击取消则只会取消行内编辑。

通过给表格添加结束编辑事件,当表格行结束编辑,也就是调用了endEdit方法时触发事件,会把data修改为修改后的行数据。

let data = {};

/**
 * 保存
 */
function save() {
	if (editingId != null) {
		let datagrid = $("#menu_list");

		// 只有结束编辑才能获取到最新的值
		datagrid.datagrid("endEdit", editingId);

		ajaxPost(requestUrl, data, function () {
			editingId = null;

			datagrid.datagrid("reload");
		}, error);
	}
}

$(document).ready(function() {    
    $("#menu_list").datagrid({
		url: "/menu/selectByPage",
		method: "get",
		height: 680,
		fitColumns: true,
		pagination: true,
		onAfterEdit: function (index, row, changes) {
			data = {
				id: row.id,
				type: row.type,
				parentId: row.parentId,
				url: changes.url ? changes.url : row.url,
				name: changes.name ? changes.name : row.name,
				icon: changes.icon ? changes.icon : row.icon
			};
		},
        .....
    };

};

删除功能比较简单,就不介绍了~

角色-菜单列表

就是对角色的菜单进行管理,目前只是基于父级菜单实现,只需要给角色添加对应的父类菜单即可让该角色获得该菜单下的所有子菜单的权限。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

二、权限管理

权限列表

对系统资源权限(也就是控制器接口权限)进行管理

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

父级权限的编号格式为为服务名_控制器名,子级权限的编号为服务名_控制器名_方法名。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

权限初始化功能:一键自动完成权限的初始化功能,会先删除原来的权限,然后扫描控制器类的包,获取所有控制器接口信息,并保存到数据库。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

涉及的后端代码

    @Override
    public void resources() throws ClassNotFoundException {
        // 删除原来的权限
        permissionMapper.delete(null);

        // 扫描路径
        String basePackage = "cn.edu.sgu.www.controller";
        // 获取扫描结果
        List<Permission> permissions = resourceScanner.scan(basePackage);

        for (Permission permission : permissions) {
            permissionMapper.insert(permission);
        }
    }

扫描工具类的代码

package cn.edu.sgu.www.util;

import cn.edu.sgu.www.EasyuiCrud;
import cn.edu.sgu.www.annotation.AnonymityAccess;
import cn.edu.sgu.www.entity.Permission;
import cn.edu.sgu.www.enums.RequestMethod;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 接口资源扫描工具类
 * @author heyunlin
 * @version 1.0
 */
@Component
public class ResourceScanner {

    /**
     * 服务名
     */
    @Value("${spring.application.name}")
    private String SERVICE_NAME;

    private static List<String> classPaths = new ArrayList<>();
    private static final List<Permission> resources = new ArrayList<>();

    /**
     * 扫描controller包下的目录,生成权限
     * @param basePackage controller包
     * @return List<Permission>
     * @throws ClassNotFoundException 类找不到时抛出异常
     */
    public List<Permission> scan(String basePackage) throws ClassNotFoundException {
        // 删除掉上一次的数据
        if (!resources.isEmpty()) {
            resources.clear();
        }
        if (!classPaths.isEmpty()) {
            classPaths.clear();
        }

        String classpath = EasyuiCrud.class.getResource("/").getPath();
        String searchPath = classpath + basePackage.replace(".", "/");

        classpath = classpath.replaceFirst("/", "");
        classPaths = getClassPaths(new File(searchPath));

        for(String classPath : classPaths) {
            // 得到类的全限定名
            classPath = classPath.replace(classpath.replace("/", "\\")
                    .replaceFirst("\\\\", ""), "")
                    .replace("\\", ".")
                    .replace(".class", "");
            classpath = classPath.substring(classPath.indexOf(basePackage));

            // 通过反射获取类的信息
            Class<?> cls = Class.forName(classpath);

            // 获取标注在类上的@RequestMapping注解
            RequestMapping requestMapping = cls.getAnnotation(RequestMapping.class);

            // 构建父权限
            Permission parent = new Permission();
            // 控制器类上的路径
            String prefix = "";

            if(requestMapping != null) {
                // path或者value
                prefix = requestMapping.value().length > 0 ? requestMapping.value()[0] : requestMapping.path()[0];

                parent.setType(0);
                parent.setUrl(prefix);
                parent.setId(SERVICE_NAME + "_" + cls.getSimpleName());

                // 设置name
                if (cls.isAnnotationPresent(Api.class)) {
                    Api api = cls.getAnnotation(Api.class);

                    if (api != null) {
                        // 类的接口文档@Api注解的tags属性值
                        String name = api.tags()[0];

                        parent.setName(name);
                    }
                }

                resources.add(parent);
            }

            Method[] methods = cls.getDeclaredMethods();

            for (Method method : methods) {
                getClassAnnotation(method, prefix, cls.getSimpleName(), parent.getId());
            }
        }

        return resources;
    }

    /**
     * 得到类上面的注解信息
     * @param method Method
     * @param prefix String 控制器类上@RequestMapping注解指定的路径
     * @param controllerName 控制器名称
     * @param parentId String 父级权限ID
     */
    public void getClassAnnotation(Method method, String prefix, String controllerName, String parentId) {
        // 构建子权限
        Permission permission = new Permission();
        String url = null;

        // 获取url
        if (method.isAnnotationPresent(RequestMapping.class)) {
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            url = prefix + (requestMapping.value().length > 0 ? requestMapping.value()[0] : requestMapping.path()[0]);
            String requestMethod = requestMapping.method().length > 0 ? requestMapping.method()[0].name() : "get";

            permission.setMethod(RequestMethod.getValueByName(requestMethod));
        } else if (method.isAnnotationPresent(GetMapping.class)) {
            GetMapping getMapping = method.getAnnotation(GetMapping.class);
            url = prefix + getMapping.value()[0];

            permission.setMethod(RequestMethod.GET.getValue());
        } else if (method.isAnnotationPresent(PostMapping.class)) {
            PostMapping postMapping = method.getAnnotation(PostMapping.class);
            url = prefix + postMapping.value()[0];

            permission.setMethod(RequestMethod.POST.getValue());
        }

        // 处理URL
        if(url != null && url.endsWith("/")) {
            url = url.substring(0, url.length() - 1);
        }
        permission.setUrl(url);

        // 设置value
        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation operation = method.getAnnotation(ApiOperation.class);

            if (operation != null) {
                String name = operation.value();

                permission.setName(name);
            }
        }
        // 默认值0
        permission.setAnonymity(0);

        if (method.isAnnotationPresent(AnonymityAccess.class)) {
            AnonymityAccess annotation = method.getAnnotation(AnonymityAccess.class);

            if (annotation != null) {
                permission.setAnonymity(annotation.value() ? 1 : 0);
            }
        }

        permission.setType(1);
        permission.setParentId(parentId);
        permission.setId(SERVICE_NAME + "_" + controllerName + "_" + method.getName());

        resources.add(permission);
    }

    private List<String> getClassPaths(File path) {
        if (path.isDirectory()) {
            File[] files = path.listFiles();

            if (files != null) {
                for (File file : files) {
                    getClassPaths(file);
                }
            }
        } else {
            if (path.getName().endsWith(".class")) {
                classPaths.add(path.getPath());
            }
        }

        return classPaths;
    }

}

角色-权限列表

角色权限的维护,包括简单的增删改和基于easyui树实现的授权功能,以及超管账户的权限初始化功能。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

授权功能:通过简单的复选框勾选/取消勾选来给角色分配权限

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

权限初始化功能:其实非常简单,就是查询所有的资源权限,然后分配给超管用户。

    @Override
    public void init(String userId) {
        // 删除用当前户所有角色的权限
        rolePermissionMapper.deleteByUserId(userId);

        // 查询全部子权限
        List<Permission> list = permissionMapper.selectByType(PermissionType.ZQX.getValue());

        list.forEach(permission -> {
            RolePermission rolePermission = new RolePermission();

            rolePermission.setId(null);
            rolePermission.setRoleId(1);
            rolePermission.setPermissionId(permission.getId());

            rolePermissionMapper.insert(rolePermission);
        });
    }

三、用户管理

因为这个部分的功能很简单,只有简单的crud,不做过多介绍。

用户列表

用户-角色列表

四、歌曲管理

歌曲列表

歌曲的维护、歌单导入/导出功能。

五、系统功能

系统设置

鼠标移动到右上方的下拉菜单,点击【系统设置】打开系统设置窗口。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

修改密码功能

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

 对密码进行加密存储

    @Override
	public void updatePassword(UserPassUpdateDTO userPassUpdateDTO) {
		// 用户名
		String username = userPassUpdateDTO.getUsername();
		// 旧密码
		String oldPass = userPassUpdateDTO.getOldPass();
		// 新密码
		String password = userPassUpdateDTO.getPassword();

		// 验证两次输入的密码是否相等
		if (password.equals(userPassUpdateDTO.getRePass())) {
			// 查询用户信息
			String encodedPassword = selectByUsername(username).getPassword();

			// 验证输入的旧密码是否正确
			if (PasswordEncoder.matches(oldPass, encodedPassword)) {
				UpdateWrapper<User> wrapper = new UpdateWrapper<>();

				wrapper.eq("username", username);
				wrapper.set("password", PasswordEncoder.encode(password));

				userMapper.update(wrapper.getEntity(), wrapper);
			} else {
				throw new GlobalException(ResponseCode.FORBIDDEN, "输入的密码不正确");
			}
		} else {
			throw new GlobalException(ResponseCode.FORBIDDEN, "两次输入的密码不一样");
		}
	}

菜单控制功能:就是控制左侧菜单的显示,勾选/取消勾选对应的菜单,然后点击窗口右下角的【确定】按钮提交修改。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

初始化权限

这个按钮的功能和权限列表的【初始化】按钮是一样的。

分享一个基于easyui前端框架开发的后台管理系统模板,前端框架,easyui,前端

代码介绍

前面已经对这个系统做了一些简单的介绍,接下来介绍一下博主经过多次实践产出的一部分公共的Java代码,可以直接使用。

响应状态码

在枚举中自定义了几种响应状态码

package cn.edu.sgu.www.restful;

/**
 * 响应状态码
 * @author heyunlin
 * @version 1.0
 */
public enum ResponseCode {

    /**
     * 请求成功
     */
    OK(200),
    /**
     * 失败的请求
     */
    BAD_REQUEST(400),
    /**
     * 未授权
     */
    UNAUTHORIZED(401),
    /**
     * 禁止访问
     */
    FORBIDDEN(403),
    /**
     * 找不到
     */
    NOT_FOUND(404),
    /**
     * 不可访问
     */
    NOT_ACCEPTABLE(406),
    /**
     * 冲突
     */
    CONFLICT(409),
    /**
     * 服务器发生异常
     */
    ERROR(500);

    private final Integer value;

    ResponseCode(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

}

统一响应实体类

包含提示信息、响应数据和响应状态码的web响应实体类。

package cn.edu.sgu.www.restful;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;

import java.io.Serializable;

/**
 * 响应实体类
 * @param <T>
 * @author heyunlin
 * @version 1.0
 */
@Data
public class JsonResult<T> implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 响应数据
     */
    private T data;

    /**
     * 响应状态码
     */
    private Integer code;

    /**
     * 响应提示信息
     */
    private String message;

    /**
     * 成功提示
     */
    private static final String successMessage = "请求成功";

    public static JsonResult<Void> success() {
        return success(successMessage);
    }

    public static JsonResult<Void> success(String message) {
        return success(message, null);
    }

    public static <T> JsonResult<T> success(String message, T data) {
        JsonResult<T> jsonResult = new JsonResult<>();

        jsonResult.setCode(ResponseCode.OK.getValue());
        jsonResult.setMessage(message);
        jsonResult.setData(data);

        return jsonResult;
    }

    public static JsonResult<Void> error(String message) {
        JsonResult<Void> jsonResult = new JsonResult<>();

        jsonResult.setCode(ResponseCode.ERROR.getValue());
        jsonResult.setMessage(message);

        return jsonResult;
    }

    public static JsonResult<Void> error(ResponseCode responseCode, Throwable e) {
        return error(responseCode, e.getMessage() != null ? e.getMessage() : "系统发生异常,请联系管理员!");
    }

    public static JsonResult<Void> error(ResponseCode responseCode, String message) {
        JsonResult<Void> jsonResult = new JsonResult<>();

        jsonResult.setCode(responseCode.getValue());
        jsonResult.setMessage(message);

        return jsonResult;
    }

    public static <T> JsonResult<JsonPage<T>> restPage(Page<T> page) {
        JsonPage<T> jsonPage = JsonPage.restPage(page);

        return success(successMessage, jsonPage);
    }

}

全局异常处理类

package cn.edu.sgu.www.restful.handler;

import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.JsonResult;
import cn.edu.sgu.www.restful.ResponseCode;
import cn.edu.sgu.www.util.UserUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 全局异常处理类
 * @author heyunlin
 * @version 1.0
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理GlobalException
     * @param e GlobalException
     * @return JsonResult<Void>
     */
    @ExceptionHandler
    public JsonResult<Void> handleGlobalException(GlobalException e) {
        printMessage(e);

        HttpServletResponse response = UserUtils.getResponse();
        response.setStatus(e.getResponseCode().getValue());

        return JsonResult.error(e.getResponseCode(), e);
    }

    /**
     * 处理BindException
     * @param e BindException
     * @return JsonResult<Void>
     */
    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public JsonResult<Void> handleBindException(BindException e) {
        printMessage(e);

        BindingResult bindingResult = e.getBindingResult();
        FieldError fieldError = bindingResult.getFieldError();
        String defaultMessage = Objects.requireNonNull(fieldError).getDefaultMessage();

        return JsonResult.error(ResponseCode.BAD_REQUEST, defaultMessage);
    }

    /**
     * 处理Exception
     * @param e Exception
     * @return JsonResult<Void>
     */
    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public JsonResult<Void> handleException(Exception e) {
        printMessage(e);

        return JsonResult.error(ResponseCode.ERROR, e);
    }

    private void printMessage(Exception e) {
        e.printStackTrace();
    }

}

统一数据格式处理类

这个类需要注意的是,knife4j的接口路径不能被处理,否则接口文档的页面内容不能正常显示。

# 配置统一数据格式返回处理类忽略的路径
response:
  ignore:
    - /error
    - /v2/api-docs
    - /swagger-resources
package cn.edu.sgu.www.restful.handler;

import cn.edu.sgu.www.config.property.ResponseProperties;
import cn.edu.sgu.www.restful.JsonResult;
import cn.edu.sgu.www.util.UserUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.List;

/**
 * 统一数据格式返回处理类
 * @author heyunlin
 * @version 1.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice {

    private final List<String> ignore;

    @Autowired
    public GlobalResponseHandler(ResponseProperties responseProperties) {
        ignore = responseProperties.getIgnore();
    }

    @Override
    public boolean supports(MethodParameter parameter, Class type) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter parameter, MediaType mediaType, Class type
            , ServerHttpRequest request, ServerHttpResponse response) {
        // 返回值类型为JsonResult,则直接返回
        if (body instanceof JsonResult) {
            return body;
        }

        // 忽略的请求地址
        String requestURI = UserUtils.getRequest().getRequestURI();

        if (ignore.contains(requestURI)) {
            return body;
        }

        log.debug("接口{}的返回值为:{}", requestURI, body.toString());

        // 将返回值类型修改为JsonResult
        JsonResult<Object> jsonResult = JsonResult.success(null, body);

        if (body instanceof String) {
            return JSON.toJSONString(jsonResult);
        }

        return jsonResult;
    }

}

datagrid数据格式对象

基于easyui的datagrid组件要求返回的数据格式,封装成的对象。

package cn.edu.sgu.www.restful;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * easyui datagrid数据格式对象
 * @param <T>
 * @author heyunlin
 * @version 1.0
 */
@Data
public class JsonPage<T> implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 总记录数
     */
    private Long total;

    /**
     * 查询结果
     */
    private List<T> rows;

    /**
     * 页脚数据
     */
    private T footer;

    public static <T> JsonPage<T> restPage(Page<T> page) {
        JsonPage<T> jsonPage = new JsonPage<>();

        jsonPage.setTotal(page.getTotal());
        jsonPage.setRows(page.getRecords());

        return jsonPage;
    }

}

获取用户登录信息的工具类

基于shiro的获取用户登录信息的工具类

package cn.edu.sgu.www.util;

import cn.edu.sgu.www.entity.User;
import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.ResponseCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 获取用户信息的工具类
 * @author heyunlin
 * @version 1.0
 */
public class UserUtils {

    /**
     * 得到Subject对象
     * @return Subject
     */
    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }

    /**
     * 获取登录的用户信息
     * @return User
     */
    public static User getUserInfo() {
        Object object =  getSubject().getPrincipal();

        if (object == null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "获取登录信息失败,当前没有用户登录。");
        }

        return (User) object;
    }

    /**
     * 获取登录用户的ID
     * @return String
     */
    public static String getUserId() {
        return getUserInfo().getId();
    }

    /**
     * 获取登录的用户名
     * @return String
     */
    public static String getLoginUsername() {
        return getUserInfo().getUsername();
    }

    public static HttpServletRequest getRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();

        if (attributes != null ) {
            return ((ServletRequestAttributes) attributes).getRequest();
        }

        throw new GlobalException(ResponseCode.ERROR, "获取request对象失败");
    }

    public static HttpServletResponse getResponse() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();

        if (attributes != null ) {
            return ((ServletRequestAttributes) attributes).getResponse();
        }

        throw new GlobalException(ResponseCode.ERROR, "获取response对象失败");
    }

}

基于easyui的表格过滤插件功能实现

package cn.edu.sgu.www.base;

import lombok.Data;

import java.io.Serializable;

/**
 * 过滤规则
 * @author heyunlin
 * @version 1.0
 */
@Data
public class FilterRule implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 字段名
     */
    private String field;

    /**
     * 比较符
     */
    private Operator op;

    /**
     * 字段值
     */
    private String value;
}
package cn.edu.sgu.www.base;

/**
 * 比较符
 * @author heyunlin
 * @version 1.0
 */
public enum Operator {
    /**
     * 包含
     */
    contains,
    /**
     * 等于
     */
    equal,
    /**
     * 不等于
     */
    notequal,
    /**
     * 以...开始
     */
    beginwith,
    /**
     * 以...结尾
     */
    endwith,
    /**
     * 小于
     */
    less,
    /**
     * 小于或等于
     */
    lessorequal,
    /**
     * 大于
     */
    greater,
    /**
     * 大于或等于
     */
    greaterorequal
}

基础的分页器

提供了分页的功能,需要分页功能的接口的参数类型只需要集成该类即可,将自动获得分页功能。

package cn.edu.sgu.www.base;

import cn.edu.sgu.www.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;
import java.util.List;

/**
 * 基础分页参数对象,包含页数和每页的记录数
 * @author heyunlin
 * @version 1.0
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class Pager<T> extends Sorter implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 页数
     */
    private Integer page = 1;

    /**
     * 每页记录数
     */
    private Integer rows = 10;

    /**
     * 过滤规则
     */
    private List<FilterRule> filterRules;

    /**
     * 根据Pager创建Page对象
     * @param pager Pager
     * @return Page
     */
    public static <T> Page<T> ofPage(Pager<T> pager) {
        return new Page<>(pager.getPage(), pager.getRows());
    }

    /**
     * 根据Pager创建QueryWrapper对象
     * @param pager Pager
     * @return QueryWrapper<T>
     */
    public static <T> QueryWrapper<T> getQueryWrapper(Pager<T> pager, boolean enableSort) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();

        List<FilterRule> filterRules = pager.getFilterRules();

        if (filterRules != null && !filterRules.isEmpty()) {
            for (FilterRule filterRule : filterRules) {
                // 字段名:转为小写字母+下划线的格式
                String field = StringUtils.toLower(filterRule.getField());
                // 字段值
                String value = filterRule.getValue();

                if (StringUtils.isNotEmpty(value)) {
                    switch (filterRule.getOp()) {
                        case less:
                            wrapper.lt(field, value);
                            break;
                        case equal:
                            wrapper.eq(field, value);
                            break;
                        case greater:
                            wrapper.gt(field, value);
                            break;
                        case notequal:
                            wrapper.ne(field, value);
                            break;
                        case lessorequal:
                            wrapper.le(field, value);
                            break;
                        case greaterorequal:
                            wrapper.ge(field, value);
                            break;
                        case beginwith:
                            wrapper.likeLeft(field, value);
                            break;
                        case endwith:
                            wrapper.likeRight(field, value);
                            break;
                        case contains:
                            wrapper.like(field, value);
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        if (enableSort) {
            // 得到order by语句
            String statement = getOrderByStatement(pager);

            if (StringUtils.isNotEmpty(statement)) {
                wrapper.last(statement);
            }
        }

        return wrapper;
    }

}

基础的排序器

因为前端的基础分页器Pager已经继承了Sorter,所以开启了分页功能后自动获得排序功能。

package cn.edu.sgu.www.base;

import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.ResponseCode;
import cn.edu.sgu.www.util.StringUtils;
import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 基础排序对象,包含排序字段和排序方式
 * @author heyunlin
 * @version 1.0
 */
@Data
public class Sorter implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 空字符串
     */
    private static final String EMPTY_STR = "";

    /**
     * 分割符
     */
    private static final String SEPARATOR = ",";

    /**
     * 排序方式
     */
    private static final List<String> ORDER_STYLES = new ArrayList<>(2);

    static {
        ORDER_STYLES.add("asc");
        ORDER_STYLES.add("desc");
    }

    /**
     * 排序字段
     */
    private String sort;

    /**
     * 排序方式:asc/desc
     */
    private String order;

    /**
     * 根据查询条件拼接得到order by语句
     * @param sorter 分页查询条件
     * @return String
     */
    public static String getStatement(Sorter sorter) {
        String sort;
        String sortColumn = sorter.getSort();

        // 处理排序字段
        String[] sortArray = {};

        if (StringUtils.isNotEmpty(sortColumn)) {
            // 驼峰命名转为下划线
            sort = StringUtils.toLower(sortColumn);

            if (sort.contains(SEPARATOR)) {
                sortArray = sort.split(SEPARATOR);
            }
        } else {
            return EMPTY_STR;
        }

        // 处理排序方式
        String[] orderArray = {};
        String order = sorter.getOrder();

        if (StringUtils.isNotEmpty(order)) {
            if (order.contains(SEPARATOR)) {
                orderArray = order.split(SEPARATOR);
            }
        } else {
            return EMPTY_STR;
        }

        StringBuilder statement = new StringBuilder();

        if (sortArray.length > 0 && orderArray.length > 0) {
            int length = sortArray.length;

            for (int i = 0; i < length; i++) {
                String pagerSort = sortArray[i];
                String pagerOrder = orderArray[i];

                boolean result = validate(pagerSort, pagerOrder);

                if (result) {
                    statement.append(pagerSort);
                    statement.append(" ");
                    statement.append(pagerOrder);

                    if (i < length - 1 ) {
                        statement.append(", ");
                    }
                }
            }
        } else {
            // " #{sort} #{order}“
            statement.append(sort);
            statement.append(" ");
            statement.append(order);
        }

        return statement.toString();
    }

    /**
     * 根据查询条件拼接得到order by语句
     * @param sorter 分页查询条件
     * @return String
     */
    public static String getOrderByStatement(Sorter sorter) {
        String statement = getStatement(sorter);

        if (StringUtils.isNotEmpty(statement)) {
            return " order by " + statement;
        } else {
            return EMPTY_STR;
        }
    }

    /**
     * 往Pager的排序字段中添加排序
     * @param pager Pager Pager对象
     * @param sort String 排序字段
     * @param order String 排序方式
     * @return Pager<?> 返回重新设置排序字段和排序方式后的Pager对象
     */
    public static Pager<?> append(Pager<?> pager, String sort, String order) {
        boolean result = validatePager(pager);

        if (result) {
            String pagerSort = pager.getSort();
            String pagerOrder = pager.getOrder();

            pager.setSort(pagerSort.concat(SEPARATOR).concat(sort));
            pager.setOrder(pagerOrder.concat(SEPARATOR).concat(order));

            return pager;
        }

        return null;
    }

    /**
     * 验证Pager对象的sort和order的值是否合法
     * @param pager Pager<?>
     * @return boolean
     */
    private static boolean validatePager(Pager<?> pager) {
        String sort = pager.getSort();
        String order = pager.getOrder();

        return validate(sort, order);
    }

    /**
     * 验证sort和order的值是否合法
     * @param sort 排序字段
     * @param order 排序方式
     * @return boolean
     */
    private static boolean validate(String sort, String order) {
        if (StringUtils.isEmpty(sort)) {
            throw new GlobalException(ResponseCode.FORBIDDEN, "排序字段不允许为空!");
        } else if (StringUtils.isEmpty(order)) {
            throw new GlobalException(ResponseCode.FORBIDDEN, "排序方式不允许为空!");
        } else if(!ORDER_STYLES.contains(order.toLowerCase())) {
            throw new GlobalException(ResponseCode.FORBIDDEN, "排序方式不合法!");
        }

        return true;
    }

}

好了,文章就分享到这里了,自己的一个小成果,分享给大家,希望对大家有所帮助~文章来源地址https://www.toymoban.com/news/detail-804962.html

到了这里,关于分享一个基于easyui前端框架开发的后台管理系统模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vite-Admin后台管理系统|vite4+vue3+pinia前端后台框架实例

    基于 vite4.x+vue3+pinia 前端后台管理系统解决方案 ViteAdmin 。 前段时间分享了一篇vue3自研pc端UI组件库VEPlus。这次带来最新开发的基于 vite4+vue3+pinia 技术栈搭配ve-plus组件库构建的中后台权限管理系统框架。 支持vue-i18n国际化多语言、动态路由鉴权、4种布局模板及tab页面缓存 等功

    2023年04月13日
    浏览(81)
  • Vue3 + Element-UI 搭建一个后台管理系统框架模板

    本文将介绍如何基于Vue3和element-ui搭建一个后台管理系统框架模板。我们将详细讲解代码流程,并提供详细的说明。 Vue3 Element-ui Axios 本文假设读者已经熟悉Vue3和Element-ui的基本使用方法,并且对Axios有一定的了解。 步骤1:创建Vue3项目 我们可以使用Vue CLI来创建一个Vue3项目,

    2023年04月26日
    浏览(118)
  • 前端使用elementui开发后台管理系统的常用功能(持续更新)

    前言:本次的文章完全是自己开发中遇到的一些问题,经过不断的修改终于完成的一些功能,当个快捷的查看手册吧~ 功能描述:数据使用的若依的字典,或者是自定义数据,可以点击每个选项进行选择,取消选择,也可以在已选择进行清除和单个删除 使用: @selection-change

    2024年02月09日
    浏览(45)
  • 超详细!10分钟开发一个Vue3的后台管理系统

    有很多人说 vue2 早就过时了,都 23年了竟然还有人在用 vue2?简直就是个土老帽! “你有说话的权利,但我不认同你的观点。”任何公司的技术架构不是一蹴而就的,而是随着业务的增长不断升级变化的。技术越新,用的人不一定会很多。 其实我敢说现在国内跟多公司还在用

    2024年02月16日
    浏览(34)
  • 从零开发一个自己的Shiro+Vue通用后台管理系统(附源码)

    分享一个基于Shiro和Vue构建的通用后台管理系统项目,该项目实现了jwt无状态登录、redis缓存、token续期和可控权限管理。

    2024年02月06日
    浏览(49)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)七:工作台界面实现

      本章实现工作台界面相关内容,包括echart框架引入,mock框架引入等,实现工作台界面框架搭建,数据加载。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载 基于VUE3+Layui从头搭建通用后台管理系统合集-工作台界面布局实现 echart官网:https

    2024年02月14日
    浏览(62)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十一:通用表单组件封装实现

      本章实现通用表单组件,根据实体配置识别实体属性,并自动生成编辑组件,实现对应数据填充、校验及保存等逻辑。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载

    2024年02月10日
    浏览(51)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)八:自定义组件封装上

      本章实现一些自定义组件的封装,包括数据字典组件的封装、下拉列表组件封装、复选框单选框组件封装、单选框组件封装、文件上传组件封装、级联选择组件封装、富文本组件封装等。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载

    2024年02月12日
    浏览(48)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)一:项目规划及初始化

      使用vue3+Layui实现通用管理系统前端,使用vue3+layui搭建系统UI界面,使用nodejs搭建模拟web服务器,使用echarts实现系统可视化模块,可以此项目为基础进行扩展开发,快速搭建管理系统,具体内容如下:    1. 常见功能实现: 实现用户登录(用户名密码登录、手机验证码

    2024年02月13日
    浏览(55)
  • 基于VUE3+Layui从头搭建通用后台管理系统(前端篇)二:登录界面及对应功能实现

      本章介绍系统登录界面、登录流程、登录接口等相关内容的开发,实现包括账号密码登录、短信验证登录等不同的登录方式,使用svg-capter生成图形验证码,使用expressjwt实现登录token的生成及验证。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击

    2024年02月11日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包