getActiveSessions()
+ {
+ throw new UnsupportedOperationException("getActiveSessions method not supported");
+ }
+}
diff --git a/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java b/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
new file mode 100644
index 000000000..dd0375289
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
@@ -0,0 +1,141 @@
+package com.ruoyi.framework.shiro.web.session;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionValidationScheduler;
+import org.apache.shiro.session.mgt.ValidatingSessionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 自定义任务调度器完成
+ *
+ * @author ruoyi
+ */
+public class SpringSessionValidationScheduler implements SessionValidationScheduler
+{
+ private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
+
+ public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
+
+ /**
+ * 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。
+ */
+ private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
+
+ private volatile boolean enabled = false;
+
+ /**
+ * The session manager used to validate sessions.
+ */
+ private ValidatingSessionManager sessionManager;
+
+ /**
+ * The session validation interval in milliseconds.
+ */
+ private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;
+
+ /**
+ * Default constructor.
+ */
+ public SpringSessionValidationScheduler()
+ {
+ }
+
+ /**
+ * Constructor that specifies the session manager that should be used for validating sessions.
+ *
+ * @param sessionManager the SessionManager that should be used to validate sessions.
+ */
+ public SpringSessionValidationScheduler(ValidatingSessionManager sessionManager)
+ {
+ this.sessionManager = sessionManager;
+ }
+
+ public void setSessionManager(ValidatingSessionManager sessionManager)
+ {
+ this.sessionManager = sessionManager;
+ }
+
+ @Override
+ public boolean isEnabled()
+ {
+ return this.enabled;
+ }
+
+ /**
+ * Specifies how frequently (in milliseconds) this Scheduler will call the
+ * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
+ * ValidatingSessionManager#validateSessions()} method.
+ *
+ *
+ * Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
+ *
+ * @param sessionValidationInterval
+ */
+ public void setSessionValidationInterval(long sessionValidationInterval)
+ {
+ this.sessionValidationInterval = sessionValidationInterval;
+ }
+
+ /**
+ * Starts session validation by creating a spring PeriodicTrigger.
+ */
+ @Override
+ public void enableSessionValidation()
+ {
+
+ enabled = true;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Scheduling session validation job using Spring Scheduler with "
+ + "session validation interval of [" + sessionValidationInterval + "]ms...");
+ }
+
+ try
+ {
+ executorService.scheduleAtFixedRate(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if (enabled)
+ {
+ sessionManager.validateSessions();
+ }
+ }
+ }, 1000, sessionValidationInterval, TimeUnit.MILLISECONDS);
+
+ this.enabled = true;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Session validation job successfully scheduled with Spring Scheduler.");
+ }
+
+ }
+ catch (Exception e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error(
+ "Error starting the Spring Scheduler session validation job. Session validation may not occur.",
+ e);
+ }
+ }
+ }
+
+ @Override
+ public void disableSessionValidation()
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Stopping Spring Scheduler session validation job...");
+ }
+
+ this.enabled = false;
+ }
+}
diff --git a/src/main/java/com/ruoyi/framework/web/controller/BaseController.java b/src/main/java/com/ruoyi/framework/web/controller/BaseController.java
new file mode 100644
index 000000000..36e6b65ee
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/controller/BaseController.java
@@ -0,0 +1,131 @@
+package com.ruoyi.framework.web.controller;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.security.ShiroUtils;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.PageDomain;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.framework.web.page.TableSupport;
+import com.ruoyi.project.system.user.domain.User;
+
+/**
+ * web层通用数据处理
+ *
+ * @author ruoyi
+ */
+public class BaseController
+{
+ /**
+ * 将前台传递过来的日期格式的字符串,自动转化为Date类型
+ */
+ @InitBinder
+ public void initBinder(WebDataBinder binder)
+ {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ dateFormat.setLenient(false);
+ binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
+ }
+
+ /**
+ * 设置请求分页数据
+ */
+ protected void startPage()
+ {
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ Integer pageNum = pageDomain.getPageNum();
+ Integer pageSize = pageDomain.getPageSize();
+ if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
+ {
+ String orderBy = pageDomain.getOrderBy();
+ PageHelper.startPage(pageNum, pageSize, orderBy);
+ }
+ }
+
+ /**
+ * 响应请求分页数据
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected TableDataInfo getDataTable(List> list)
+ {
+ TableDataInfo rspData = new TableDataInfo();
+ rspData.setRows(list);
+ rspData.setTotal(new PageInfo(list).getTotal());
+ return rspData;
+ }
+
+ /**
+ * 返回成功
+ */
+ public AjaxResult success()
+ {
+ return AjaxResult.success();
+ }
+
+ /**
+ * 返回失败消息
+ */
+ public AjaxResult error()
+ {
+ return AjaxResult.error();
+ }
+
+ /**
+ * 返回成功消息
+ */
+ public AjaxResult success(String message)
+ {
+ return AjaxResult.success(message);
+ }
+
+ /**
+ * 返回失败消息
+ */
+ public AjaxResult error(String message)
+ {
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 返回错误码消息
+ */
+ public AjaxResult error(int code, String message)
+ {
+ return AjaxResult.error(code, message);
+ }
+
+ /**
+ * 页面跳转
+ */
+ public String redirect(String url)
+ {
+ return StringUtils.format("redirect:{}", url);
+ }
+
+ public User getUser()
+ {
+ return ShiroUtils.getUser();
+ }
+
+ public void setUser(User user)
+ {
+ ShiroUtils.setUser(user);
+ }
+
+ public Long getUserId()
+ {
+ return getUser().getUserId();
+ }
+
+ public String getLoginName()
+ {
+ return getUser().getLoginName();
+ }
+}
diff --git a/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java b/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java
new file mode 100644
index 000000000..4fbc9fa13
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java
@@ -0,0 +1,94 @@
+package com.ruoyi.framework.web.domain;
+
+import java.util.HashMap;
+
+/**
+ * 操作消息提醒
+ *
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 初始化一个新创建的 Message 对象
+ */
+ public AjaxResult()
+ {
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @return 错误消息
+ */
+ public static AjaxResult error()
+ {
+ return error(1, "操作失败");
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @param msg 内容
+ * @return 错误消息
+ */
+ public static AjaxResult error(String msg)
+ {
+ return error(500, msg);
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @param code 错误码
+ * @param msg 内容
+ * @return 错误消息
+ */
+ public static AjaxResult error(int code, String msg)
+ {
+ AjaxResult json = new AjaxResult();
+ json.put("code", code);
+ json.put("msg", msg);
+ return json;
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @param msg 内容
+ * @return 成功消息
+ */
+ public static AjaxResult success(String msg)
+ {
+ AjaxResult json = new AjaxResult();
+ json.put("msg", msg);
+ json.put("code", 0);
+ return json;
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @return 成功消息
+ */
+ public static AjaxResult success()
+ {
+ return AjaxResult.success("操作成功");
+ }
+
+ /**
+ * 返回成功消息
+ *
+ * @param key 键值
+ * @param value 内容
+ * @return 成功消息
+ */
+ @Override
+ public AjaxResult put(String key, Object value)
+ {
+ super.put(key, value);
+ return this;
+ }
+}
diff --git a/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java b/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java
new file mode 100644
index 000000000..06a947b0b
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java
@@ -0,0 +1,98 @@
+package com.ruoyi.framework.web.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * Entity基类
+ *
+ * @author ruoyi
+ */
+public class BaseEntity implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+ /** 搜索值 */
+ private String searchValue;
+ /** 创建者 */
+ private String createBy;
+ /** 创建时间 */
+ private Date createTime;
+ /** 更新者 */
+ private String updateBy;
+ /** 更新时间 */
+ private Date updateTime;
+ /** 备注 */
+ private String remark;
+
+ public String getSearchValue()
+ {
+ return searchValue;
+ }
+
+ public void setSearchValue(String searchValue)
+ {
+ this.searchValue = searchValue;
+ }
+
+ public String getCreateBy()
+ {
+ return createBy;
+ }
+
+ public void setCreateBy(String createBy)
+ {
+ this.createBy = createBy;
+ }
+
+ public String getCreateTimeStr()
+ {
+ return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, createTime) : "";
+ }
+
+ public String getCreateDateTimeStr()
+ {
+ return createTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, createTime) : "";
+ }
+
+ public void setCreateTime(Date createTime)
+ {
+ this.createTime = createTime;
+ }
+
+ public String getUpdateBy()
+ {
+ return updateBy;
+ }
+
+ public void setUpdateBy(String updateBy)
+ {
+ this.updateBy = updateBy;
+ }
+
+ public String getUpdateTimeStr()
+ {
+ return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, updateTime) : "";
+ }
+
+ public String getUpdateDateTimeStr()
+ {
+ return updateTime != null ? DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, updateTime) : "";
+ }
+
+ public void setUpdateTime(Date updateTime)
+ {
+ this.updateTime = updateTime;
+ }
+
+ public String getRemark()
+ {
+ return remark;
+ }
+
+ public void setRemark(String remark)
+ {
+ this.remark = remark;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/exception/DefaultExceptionHandler.java b/src/main/java/com/ruoyi/framework/web/exception/DefaultExceptionHandler.java
new file mode 100644
index 000000000..1570b05e7
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/exception/DefaultExceptionHandler.java
@@ -0,0 +1,72 @@
+package com.ruoyi.framework.web.exception;
+
+import org.apache.shiro.authz.AuthorizationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import com.ruoyi.common.exception.DemoModeException;
+import com.ruoyi.framework.web.domain.AjaxResult;
+
+/**
+ * 自定义异常处理器
+ *
+ * @author ruoyi
+ */
+@RestControllerAdvice
+public class DefaultExceptionHandler
+{
+ private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
+
+ /**
+ * 权限校验失败
+ */
+ @ExceptionHandler(AuthorizationException.class)
+ public AjaxResult handleAuthorizationException(AuthorizationException e)
+ {
+ log.error(e.getMessage(), e);
+ return AjaxResult.error("您没有数据的权限,请联系管理员添加");
+ }
+
+ /**
+ * 请求方式不支持
+ */
+ @ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
+ public AjaxResult handleException(HttpRequestMethodNotSupportedException e)
+ {
+ log.error(e.getMessage(), e);
+ return AjaxResult.error("不支持' " + e.getMethod() + "'请求");
+ }
+
+ /**
+ * 拦截未知的运行时异常
+ */
+ @ExceptionHandler(RuntimeException.class)
+ public AjaxResult notFount(RuntimeException e)
+ {
+ log.error("运行时异常:", e);
+ return AjaxResult.error("运行时异常:" + e.getMessage());
+ }
+
+ /**
+ * 系统异常
+ */
+ @ExceptionHandler(Exception.class)
+ public AjaxResult handleException(Exception e)
+ {
+ log.error(e.getMessage(), e);
+ return AjaxResult.error("服务器错误,请联系管理员");
+ }
+
+ /**
+ * 演示模式异常
+ */
+ @ExceptionHandler(DemoModeException.class)
+ public AjaxResult demoModeException(DemoModeException e)
+ {
+ return AjaxResult.error("演示模式,不允许操作");
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/page/PageDomain.java b/src/main/java/com/ruoyi/framework/web/page/PageDomain.java
new file mode 100644
index 000000000..3ea659b50
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/page/PageDomain.java
@@ -0,0 +1,70 @@
+package com.ruoyi.framework.web.page;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 分页数据
+ *
+ * @author ruoyi
+ */
+public class PageDomain
+{
+ /** 当前记录起始索引 */
+ private Integer pageNum;
+ /** 每页显示记录数 */
+ private Integer pageSize;
+ /** 排序列 */
+ private String orderByColumn;
+ /** 排序的方向 "desc" 或者 "asc". */
+ private String isAsc;
+
+ public String getOrderBy()
+ {
+ if (StringUtils.isEmpty(orderByColumn))
+ {
+ return "";
+ }
+ return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
+ }
+
+ public Integer getPageNum()
+ {
+ return pageNum;
+ }
+
+ public void setPageNum(Integer pageNum)
+ {
+ this.pageNum = pageNum;
+ }
+
+ public Integer getPageSize()
+ {
+ return pageSize;
+ }
+
+ public void setPageSize(Integer pageSize)
+ {
+ this.pageSize = pageSize;
+ }
+
+ public String getOrderByColumn()
+ {
+ return orderByColumn;
+ }
+
+ public void setOrderByColumn(String orderByColumn)
+ {
+ this.orderByColumn = orderByColumn;
+ }
+
+ public String getIsAsc()
+ {
+ return isAsc;
+ }
+
+ public void setIsAsc(String isAsc)
+ {
+ this.isAsc = isAsc;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java b/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java
new file mode 100644
index 000000000..bb122134e
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java
@@ -0,0 +1,58 @@
+package com.ruoyi.framework.web.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 表格分页数据对象
+ *
+ * @author ruoyi
+ */
+public class TableDataInfo implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+ /** 总记录数 */
+ private long total;
+ /** 列表数据 */
+ private List> rows;
+
+ /**
+ * 表格数据对象
+ */
+ public TableDataInfo()
+ {
+ }
+
+ /**
+ * 分页
+ *
+ * @param list 列表数据
+ * @param total 总记录数
+ */
+ public TableDataInfo(List> list, int total)
+ {
+ this.rows = list;
+ this.total = total;
+ }
+
+ public long getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(long total)
+ {
+ this.total = total;
+ }
+
+ public List> getRows()
+ {
+ return rows;
+ }
+
+ public void setRows(List> rows)
+ {
+ this.rows = rows;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/page/TableSupport.java b/src/main/java/com/ruoyi/framework/web/page/TableSupport.java
new file mode 100644
index 000000000..61b5e0523
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/page/TableSupport.java
@@ -0,0 +1,31 @@
+package com.ruoyi.framework.web.page;
+
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 表格数据处理
+ *
+ * @author ruoyi
+ */
+public class TableSupport
+{
+ /**
+ * 封装分页对象
+ */
+ public static PageDomain getPageDomain()
+ {
+ PageDomain pageDomain = new PageDomain();
+ pageDomain.setPageNum(ServletUtils.getParameterToInt(Constants.PAGENUM));
+ pageDomain.setPageSize(ServletUtils.getParameterToInt(Constants.PAGESIZE));
+ pageDomain.setOrderByColumn(ServletUtils.getParameter(Constants.ORDERBYCOLUMN));
+ pageDomain.setIsAsc(ServletUtils.getParameter(Constants.ISASC));
+ return pageDomain;
+ }
+
+ public static PageDomain buildPageRequest()
+ {
+ return getPageDomain();
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/service/ConfigService.java b/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
new file mode 100644
index 000000000..f0cfefaf9
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.framework.web.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.project.system.config.service.IConfigService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现参数管理
+ *
+ * @author ruoyi
+ */
+@Component
+public class ConfigService
+{
+ @Autowired
+ private IConfigService configService;
+
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configName 参数名称
+ * @return 参数键值
+ */
+ public String selectConfigByKey(String configKey)
+ {
+ return configService.selectConfigByKey(configKey);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/framework/web/service/DictService.java b/src/main/java/com/ruoyi/framework/web/service/DictService.java
new file mode 100644
index 000000000..0b207164f
--- /dev/null
+++ b/src/main/java/com/ruoyi/framework/web/service/DictService.java
@@ -0,0 +1,30 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.project.system.dict.domain.DictData;
+import com.ruoyi.project.system.dict.service.IDictDataService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现字典读取
+ *
+ * @author ruoyi
+ */
+@Component
+public class DictService
+{
+ @Autowired
+ private IDictDataService dictDataService;
+
+ /**
+ * 根据字典类型查询字典数据信息
+ *
+ * @param dictType 字典类型
+ * @return 参数键值
+ */
+ public List selectDictData(String dictType)
+ {
+ return dictDataService.selectDictDataByType(dictType);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/common/CommonController.java b/src/main/java/com/ruoyi/project/common/CommonController.java
new file mode 100644
index 000000000..59c23f3a9
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/common/CommonController.java
@@ -0,0 +1,84 @@
+package com.ruoyi.project.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * 下载
+ *
+ * @author ruoyi
+ */
+@Controller
+public class CommonController
+{
+ @RequestMapping("common/download")
+ public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
+ {
+ String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
+ try
+ {
+ String filePath = ResourceUtils.getURL("classpath:").getPath() + "static/file/" + fileName;
+
+ response.setCharacterEncoding("utf-8");
+ response.setContentType("multipart/form-data");
+ response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
+ File file = new File(filePath);
+ InputStream inputStream = new FileInputStream(file);
+ OutputStream os = response.getOutputStream();
+ byte[] b = new byte[1024];
+ int length;
+ while ((length = inputStream.read(b)) > 0)
+ {
+ os.write(b, 0, length);
+ }
+ os.close();
+ inputStream.close();
+ if (delete && file.exists())
+ {
+ file.delete();
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+ {
+ final String agent = request.getHeader("USER-AGENT");
+ String filename = fileName;
+ if (agent.contains("MSIE"))
+ {
+ // IE浏览器
+ filename = URLEncoder.encode(filename, "utf-8");
+ filename = filename.replace("+", " ");
+ }
+ else if (agent.contains("Firefox"))
+ {
+ // 火狐浏览器
+ filename = new String(fileName.getBytes(), "ISO8859-1");
+ }
+ else if (agent.contains("Chrome"))
+ {
+ // google浏览器
+ filename = URLEncoder.encode(filename, "utf-8");
+ }
+ else
+ {
+ // 其它浏览器
+ filename = URLEncoder.encode(filename, "utf-8");
+ }
+ return filename;
+
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/druid/DruidController.java b/src/main/java/com/ruoyi/project/monitor/druid/DruidController.java
new file mode 100644
index 000000000..dbbc6dece
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/druid/DruidController.java
@@ -0,0 +1,26 @@
+package com.ruoyi.project.monitor.druid;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.framework.web.controller.BaseController;
+
+/**
+ * druid 监控
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/data")
+public class DruidController extends BaseController
+{
+ private String prefix = "/monitor/druid";
+
+ @RequiresPermissions("monitor:data:view")
+ @GetMapping()
+ public String index()
+ {
+ return redirect(prefix + "/index");
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/controller/JobController.java b/src/main/java/com/ruoyi/project/monitor/job/controller/JobController.java
new file mode 100644
index 000000000..b0606e2d1
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/controller/JobController.java
@@ -0,0 +1,143 @@
+package com.ruoyi.project.monitor.job.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.job.domain.Job;
+import com.ruoyi.project.monitor.job.service.IJobService;
+
+/**
+ * 调度任务信息操作处理
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/job")
+public class JobController extends BaseController
+{
+ private String prefix = "monitor/job";
+
+ @Autowired
+ private IJobService jobService;
+
+ @RequiresPermissions("monitor:job:view")
+ @GetMapping()
+ public String job()
+ {
+ return prefix + "/job";
+ }
+
+ @RequiresPermissions("monitor:job:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(Job job)
+ {
+ startPage();
+ List list = jobService.selectJobList(job);
+ return getDataTable(list);
+ }
+
+ @Log(title = "定时任务", action = BusinessType.EXPORT)
+ @PostMapping("/export")
+ @ResponseBody
+ public AjaxResult export(Job job) throws Exception
+ {
+ try
+ {
+ List list = jobService.selectJobList(job);
+ ExcelUtil util = new ExcelUtil(Job.class);
+ return util.exportExcel(list, "job");
+ }
+ catch (Exception e)
+ {
+ return error("导出Excel失败,请联系网站管理员!");
+ }
+ }
+
+ @Log(title = "定时任务", action = BusinessType.DELETE)
+ @RequiresPermissions("monitor:job:remove")
+ @PostMapping("/remove")
+ @ResponseBody
+ public AjaxResult remove(String ids)
+ {
+ try
+ {
+ jobService.deleteJobByIds(ids);
+ return success();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return error(e.getMessage());
+ }
+ }
+
+ /**
+ * 任务调度状态修改
+ */
+ @Log(title = "定时任务", action = BusinessType.UPDATE)
+ @RequiresPermissions("monitor:job:changeStatus")
+ @PostMapping("/changeStatus")
+ @ResponseBody
+ public AjaxResult changeStatus(Job job)
+ {
+ if (jobService.changeStatus(job) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ /**
+ * 新增调度
+ */
+ @Log(title = "定时任务", action = BusinessType.INSERT)
+ @RequiresPermissions("monitor:job:add")
+ @GetMapping("/add")
+ public String add(Model model)
+ {
+ return prefix + "/add";
+ }
+
+ /**
+ * 修改调度
+ */
+ @Log(title = "定时任务", action = BusinessType.UPDATE)
+ @RequiresPermissions("monitor:job:edit")
+ @GetMapping("/edit/{jobId}")
+ public String edit(@PathVariable("jobId") Long jobId, Model model)
+ {
+ Job job = jobService.selectJobById(jobId);
+ model.addAttribute("job", job);
+ return prefix + "/edit";
+ }
+
+ /**
+ * 保存调度
+ */
+ @Log(title = "定时任务", action = BusinessType.SAVE)
+ @RequiresPermissions("monitor:job:save")
+ @PostMapping("/save")
+ @ResponseBody
+ public AjaxResult save(Job job)
+ {
+ if (jobService.saveJobCron(job) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/controller/JobLogController.java b/src/main/java/com/ruoyi/project/monitor/job/controller/JobLogController.java
new file mode 100644
index 000000000..4f27e3f84
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/controller/JobLogController.java
@@ -0,0 +1,85 @@
+package com.ruoyi.project.monitor.job.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.job.domain.JobLog;
+import com.ruoyi.project.monitor.job.service.IJobLogService;
+
+/**
+ * 调度日志操作处理
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/jobLog")
+public class JobLogController extends BaseController
+{
+ private String prefix = "monitor/job";
+
+ @Autowired
+ private IJobLogService jobLogService;
+
+ @RequiresPermissions("monitor:job:view")
+ @GetMapping()
+ public String jobLog()
+ {
+ return prefix + "/jobLog";
+ }
+
+ @RequiresPermissions("monitor:job:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(JobLog jobLog)
+ {
+ startPage();
+ List list = jobLogService.selectJobLogList(jobLog);
+ return getDataTable(list);
+ }
+
+ @Log(title = "调度日志", action = BusinessType.EXPORT)
+ @PostMapping("/export")
+ @ResponseBody
+ public AjaxResult export(JobLog jobLog) throws Exception
+ {
+ try
+ {
+ List list = jobLogService.selectJobLogList(jobLog);
+ ExcelUtil util = new ExcelUtil(JobLog.class);
+ return util.exportExcel(list, "jobLog");
+ }
+ catch (Exception e)
+ {
+ return error("导出Excel失败,请联系网站管理员!");
+ }
+ }
+
+ @Log(title = "调度日志", action = BusinessType.DELETE)
+ @RequiresPermissions("monitor:job:remove")
+ @PostMapping("/remove")
+ @ResponseBody
+ public AjaxResult remove(String ids)
+ {
+ try
+ {
+ jobLogService.deleteJobLogByIds(ids);
+ return success();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return error(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/domain/Job.java b/src/main/java/com/ruoyi/project/monitor/job/domain/Job.java
new file mode 100644
index 000000000..92ff24e37
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/domain/Job.java
@@ -0,0 +1,122 @@
+package com.ruoyi.project.monitor.job.domain;
+
+import java.io.Serializable;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+
+/**
+ * 定时任务调度信息 sys_job
+ *
+ * @author ruoyi
+ */
+public class Job extends BaseEntity implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 任务ID */
+ @Excel(name = "任务序号", column = "A")
+ private Long jobId;
+
+ /** 任务名称 */
+ @Excel(name = "任务名称", column = "B")
+ private String jobName;
+
+ /** 任务组名 */
+ @Excel(name = "任务组名", column = "C")
+ private String jobGroup;
+
+ /** 任务方法 */
+ @Excel(name = "任务方法", column = "D")
+ private String methodName;
+
+ /** 方法参数 */
+ @Excel(name = "方法参数", column = "E")
+ private String params;
+
+ /** cron执行表达式 */
+ @Excel(name = "执行表达式 ", column = "F")
+ private String cronExpression;
+
+ /** 任务状态(0正常 1暂停) */
+ @Excel(name = "任务状态", column = "G")
+ private String status;
+
+ public Long getJobId()
+ {
+ return jobId;
+ }
+
+ public void setJobId(Long jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getMethodName()
+ {
+ return methodName;
+ }
+
+ public void setMethodName(String methodName)
+ {
+ this.methodName = methodName;
+ }
+
+ public String getParams()
+ {
+ return params;
+ }
+
+ public void setParams(String params)
+ {
+ this.params = params;
+ }
+
+ public String getCronExpression()
+ {
+ return cronExpression;
+ }
+
+ public void setCronExpression(String cronExpression)
+ {
+ this.cronExpression = cronExpression;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Job [jobId=" + jobId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName=" + methodName
+ + ", params=" + params + ", cronExpression=" + cronExpression + ", status=" + status + "]";
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/domain/JobLog.java b/src/main/java/com/ruoyi/project/monitor/job/domain/JobLog.java
new file mode 100644
index 000000000..2c5adbdf1
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/domain/JobLog.java
@@ -0,0 +1,135 @@
+package com.ruoyi.project.monitor.job.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+
+/**
+ * 定时任务调度日志信息 sys_job_log
+ *
+ * @author ruoyi
+ */
+public class JobLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** ID */
+ @Excel(name = "日志序号", column = "A")
+ private Long jobLogId;
+
+ /** 任务名称 */
+ @Excel(name = "任务名称", column = "B")
+ private String jobName;
+
+ /** 任务组名 */
+ @Excel(name = "任务组名", column = "C")
+ private String jobGroup;
+
+ /** 任务方法 */
+ @Excel(name = "任务方法", column = "D")
+ private String methodName;
+
+ /** 方法参数 */
+ @Excel(name = "方法参数", column = "E")
+ private String params;
+
+ /** 日志信息 */
+ @Excel(name = "日志信息", column = "F")
+ private String jobMessage;
+
+ /** 执行状态(0正常 1失败) */
+ @Excel(name = "执行状态", column = "G")
+ private String status;
+
+ /** 异常信息 */
+ @Excel(name = "异常信息", column = "H")
+ private String exceptionInfo;
+
+ public Long getJobLogId()
+ {
+ return jobLogId;
+ }
+
+ public void setJobLogId(Long jobLogId)
+ {
+ this.jobLogId = jobLogId;
+ }
+
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getMethodName()
+ {
+ return methodName;
+ }
+
+ public void setMethodName(String methodName)
+ {
+ this.methodName = methodName;
+ }
+
+ public String getParams()
+ {
+ return params;
+ }
+
+ public void setParams(String params)
+ {
+ this.params = params;
+ }
+
+ public String getJobMessage()
+ {
+ return jobMessage;
+ }
+
+ public void setJobMessage(String jobMessage)
+ {
+ this.jobMessage = jobMessage;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getExceptionInfo()
+ {
+ return exceptionInfo;
+ }
+
+ public void setExceptionInfo(String exceptionInfo)
+ {
+ this.exceptionInfo = exceptionInfo;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "JobLog [jobLogId=" + jobLogId + ", jobName=" + jobName + ", jobGroup=" + jobGroup + ", methodName="
+ + methodName + ", params=" + params + ", jobMessage=" + jobMessage + ", status=" + status
+ + ", exceptionInfo=" + exceptionInfo + "]";
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/mapper/JobLogMapper.java b/src/main/java/com/ruoyi/project/monitor/job/mapper/JobLogMapper.java
new file mode 100644
index 000000000..cdb32b859
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/mapper/JobLogMapper.java
@@ -0,0 +1,54 @@
+package com.ruoyi.project.monitor.job.mapper;
+
+import java.util.List;
+import com.ruoyi.project.monitor.job.domain.JobLog;
+
+/**
+ * 调度任务日志信息 数据层
+ *
+ * @author ruoyi
+ */
+public interface JobLogMapper
+{
+
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List selectJobLogList(JobLog jobLog);
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobLogId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ public JobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ * @return 结果
+ */
+ public int insertJobLog(JobLog jobLog);
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteJobLogByIds(Long[] ids);
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ * @return 结果
+ */
+ public int deleteJobLogById(Long jobId);
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/mapper/JobMapper.java b/src/main/java/com/ruoyi/project/monitor/job/mapper/JobMapper.java
new file mode 100644
index 000000000..250c2df1e
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/mapper/JobMapper.java
@@ -0,0 +1,69 @@
+package com.ruoyi.project.monitor.job.mapper;
+
+import java.util.List;
+import com.ruoyi.project.monitor.job.domain.Job;
+
+/**
+ * 调度任务信息 数据层
+ *
+ * @author ruoyi
+ */
+public interface JobMapper
+{
+
+ /**
+ * 查询调度任务日志集合
+ *
+ * @param job 调度信息
+ * @return 操作日志集合
+ */
+ public List selectJobList(Job job);
+
+ /**
+ * 查询所有调度任务
+ *
+ * @return 调度任务列表
+ */
+ public List selectJobAll();
+
+ /**
+ * 通过调度ID查询调度任务信息
+ *
+ * @param jobId 调度ID
+ * @return 角色对象信息
+ */
+ public Job selectJobById(Long jobId);
+
+ /**
+ * 通过调度ID删除调度任务信息
+ *
+ * @param jobId 调度ID
+ * @return 结果
+ */
+ public int deleteJobById(Job job);
+
+ /**
+ * 批量删除调度任务信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteJobLogByIds(Long[] ids);
+
+ /**
+ * 修改调度任务信息
+ *
+ * @param job 调度任务信息
+ * @return 结果
+ */
+ public int updateJob(Job job);
+
+ /**
+ * 新增调度任务信息
+ *
+ * @param job 调度任务信息
+ * @return 结果
+ */
+ public int insertJob(Job job);
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/service/IJobLogService.java b/src/main/java/com/ruoyi/project/monitor/job/service/IJobLogService.java
new file mode 100644
index 000000000..ce38bb465
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/service/IJobLogService.java
@@ -0,0 +1,53 @@
+package com.ruoyi.project.monitor.job.service;
+
+import java.util.List;
+import com.ruoyi.project.monitor.job.domain.JobLog;
+
+/**
+ * 定时任务调度日志信息信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface IJobLogService
+{
+
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ public List selectJobLogList(JobLog jobLog);
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobLogId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ public JobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ */
+ public void addJobLog(JobLog jobLog);
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteJobLogByIds(String ids);
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ * @return 结果
+ */
+ public int deleteJobLogById(Long jobId);
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/service/IJobService.java b/src/main/java/com/ruoyi/project/monitor/job/service/IJobService.java
new file mode 100644
index 000000000..3322953cc
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/service/IJobService.java
@@ -0,0 +1,101 @@
+package com.ruoyi.project.monitor.job.service;
+
+import java.util.List;
+import com.ruoyi.project.monitor.job.domain.Job;
+
+/**
+ * 定时任务调度信息信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface IJobService
+{
+
+ /**
+ * 获取quartz调度器的计划任务
+ *
+ * @param job 调度信息
+ * @return 调度任务集合
+ */
+ public List selectJobList(Job job);
+
+ /**
+ * 通过调度任务ID查询调度信息
+ *
+ * @param jobId 调度任务ID
+ * @return 调度任务对象信息
+ */
+ public Job selectJobById(Long jobId);
+
+ /**
+ * 暂停任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int pauseJob(Job job);
+
+ /**
+ * 恢复任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int resumeJob(Job job);
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int deleteJob(Job job);
+
+ /**
+ * 批量删除调度信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public void deleteJobByIds(String ids);
+
+ /**
+ * 任务调度状态修改
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int changeStatus(Job job);
+
+ /**
+ * 立即运行任务
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int triggerJob(Job job);
+
+ /**
+ * 新增任务表达式
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int addJobCron(Job job);
+
+ /**
+ * 更新任务的时间表达式
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int updateJobCron(Job job);
+
+ /**
+ * 保存任务的时间表达式
+ *
+ * @param job 调度信息
+ * @return 结果
+ */
+ public int saveJobCron(Job job);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/service/JobLogServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/job/service/JobLogServiceImpl.java
new file mode 100644
index 000000000..3089337eb
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/service/JobLogServiceImpl.java
@@ -0,0 +1,80 @@
+package com.ruoyi.project.monitor.job.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.support.Convert;
+import com.ruoyi.project.monitor.job.domain.JobLog;
+import com.ruoyi.project.monitor.job.mapper.JobLogMapper;
+
+/**
+ * 定时任务调度日志信息 服务层
+ *
+ * @author ruoyi
+ */
+@Service("jobLogService")
+public class JobLogServiceImpl implements IJobLogService
+{
+
+ @Autowired
+ private JobLogMapper jobLogMapper;
+
+ /**
+ * 获取quartz调度器日志的计划任务
+ *
+ * @param jobLog 调度日志信息
+ * @return 调度任务日志集合
+ */
+ @Override
+ public List selectJobLogList(JobLog jobLog)
+ {
+ return jobLogMapper.selectJobLogList(jobLog);
+ }
+
+ /**
+ * 通过调度任务日志ID查询调度信息
+ *
+ * @param jobId 调度任务日志ID
+ * @return 调度任务日志对象信息
+ */
+ @Override
+ public JobLog selectJobLogById(Long jobLogId)
+ {
+ return jobLogMapper.selectJobLogById(jobLogId);
+ }
+
+ /**
+ * 新增任务日志
+ *
+ * @param jobLog 调度日志信息
+ */
+ @Override
+ public void addJobLog(JobLog jobLog)
+ {
+ jobLogMapper.insertJobLog(jobLog);
+ }
+
+ /**
+ * 批量删除调度日志信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ @Override
+ public int deleteJobLogByIds(String ids)
+ {
+ return jobLogMapper.deleteJobLogByIds(Convert.toLongArray(ids));
+ }
+
+ /**
+ * 删除任务日志
+ *
+ * @param jobId 调度日志ID
+ */
+ @Override
+ public int deleteJobLogById(Long jobId)
+ {
+ return jobLogMapper.deleteJobLogById(jobId);
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/service/JobServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/job/service/JobServiceImpl.java
new file mode 100644
index 000000000..232223e83
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/service/JobServiceImpl.java
@@ -0,0 +1,241 @@
+package com.ruoyi.project.monitor.job.service;
+
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.quartz.CronTrigger;
+import org.quartz.Scheduler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.support.Convert;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.security.ShiroUtils;
+import com.ruoyi.project.monitor.job.domain.Job;
+import com.ruoyi.project.monitor.job.mapper.JobMapper;
+import com.ruoyi.project.monitor.job.util.ScheduleUtils;
+
+/**
+ * 定时任务调度信息 服务层
+ *
+ * @author ruoyi
+ */
+@Service("jobService")
+public class JobServiceImpl implements IJobService
+{
+ @Autowired
+ private Scheduler scheduler;
+
+ @Autowired
+ private JobMapper jobMapper;
+
+ /**
+ * 项目启动时,初始化定时器
+ */
+ @PostConstruct
+ public void init()
+ {
+ List jobList = jobMapper.selectJobAll();
+ for (Job job : jobList)
+ {
+ CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, job.getJobId());
+ // 如果不存在,则创建
+ if (cronTrigger == null)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ else
+ {
+ ScheduleUtils.updateScheduleJob(scheduler, job);
+ }
+ }
+ }
+
+ /**
+ * 获取quartz调度器的计划任务列表
+ *
+ * @param job 调度信息
+ * @return
+ */
+ @Override
+ public List selectJobList(Job job)
+ {
+ return jobMapper.selectJobList(job);
+ }
+
+ /**
+ * 通过调度任务ID查询调度信息
+ *
+ * @param jobId 调度任务ID
+ * @return 调度任务对象信息
+ */
+ @Override
+ public Job selectJobById(Long jobId)
+ {
+ return jobMapper.selectJobById(jobId);
+ }
+
+ /**
+ * 暂停任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int pauseJob(Job job)
+ {
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ job.setUpdateBy(ShiroUtils.getLoginName());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.pauseJob(scheduler, job.getJobId());
+ }
+ return rows;
+ }
+
+ /**
+ * 恢复任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int resumeJob(Job job)
+ {
+ job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
+ job.setUpdateBy(ShiroUtils.getLoginName());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.resumeJob(scheduler, job.getJobId());
+ }
+ return rows;
+ }
+
+ /**
+ * 删除任务后,所对应的trigger也将被删除
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int deleteJob(Job job)
+ {
+ int rows = jobMapper.deleteJobById(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.deleteScheduleJob(scheduler, job.getJobId());
+ }
+ return rows;
+ }
+
+ /**
+ * 批量删除调度信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ @Override
+ public void deleteJobByIds(String ids)
+ {
+ Long[] jobIds = Convert.toLongArray(ids);
+ for (Long jobId : jobIds)
+ {
+ Job job = jobMapper.selectJobById(jobId);
+ deleteJob(job);
+ }
+ }
+
+ /**
+ * 任务调度状态修改
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int changeStatus(Job job)
+ {
+ int rows = 0;
+ String status = job.getStatus();
+ if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
+ {
+ rows = resumeJob(job);
+ }
+ else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
+ {
+ rows = pauseJob(job);
+ }
+ return rows;
+ }
+
+ /**
+ * 立即运行任务
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int triggerJob(Job job)
+ {
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.run(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 新增任务
+ *
+ * @param job 调度信息 调度信息
+ */
+ @Override
+ public int addJobCron(Job job)
+ {
+ job.setCreateBy(ShiroUtils.getLoginName());
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.insertJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 更新任务的时间表达式
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int updateJobCron(Job job)
+ {
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.updateScheduleJob(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 保存任务的时间表达式
+ *
+ * @param job 调度信息
+ */
+ @Override
+ public int saveJobCron(Job job)
+ {
+ Long jobId = job.getJobId();
+ int rows = 0;
+ if (StringUtils.isNotNull(jobId))
+ {
+ rows = updateJobCron(job);
+ }
+ else
+ {
+ rows = addJobCron(job);
+ }
+ return rows;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/task/RyTask.java b/src/main/java/com/ruoyi/project/monitor/job/task/RyTask.java
new file mode 100644
index 000000000..20cf58b60
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/task/RyTask.java
@@ -0,0 +1,24 @@
+package com.ruoyi.project.monitor.job.task;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * 定时任务调度测试
+ *
+ * @author ruoyi
+ */
+@Component("ryTask")
+public class RyTask
+{
+
+ public void ryParams(String params)
+ {
+ System.out.println("执行有参方法:" + params);
+ }
+
+ public void ryNoParams()
+ {
+ System.out.println("执行无参方法");
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleJob.java b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleJob.java
new file mode 100644
index 000000000..b1e090692
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleJob.java
@@ -0,0 +1,77 @@
+package com.ruoyi.project.monitor.job.util;
+
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.project.monitor.job.domain.Job;
+import com.ruoyi.project.monitor.job.domain.JobLog;
+import com.ruoyi.project.monitor.job.service.IJobLogService;
+
+/**
+ * 定时任务
+ *
+ * @author ruoyi
+ *
+ */
+public class ScheduleJob extends QuartzJobBean
+{
+ private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class);
+
+ private ExecutorService service = Executors.newSingleThreadExecutor();
+
+ @Override
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException
+ {
+ Job job = (Job) context.getMergedJobDataMap().get(ScheduleConstants.JOB_PARAM_KEY);
+
+ IJobLogService jobLogService = (IJobLogService) SpringUtils.getBean(IJobLogService.class);
+
+ JobLog jobLog = new JobLog();
+ jobLog.setJobName(job.getJobName());
+ jobLog.setJobGroup(job.getJobGroup());
+ jobLog.setMethodName(job.getMethodName());
+ jobLog.setParams(job.getParams());
+ jobLog.setCreateTime(new Date());
+
+ long startTime = System.currentTimeMillis();
+
+ try
+ {
+ // 执行任务
+ log.info("任务开始执行 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
+ ScheduleRunnable task = new ScheduleRunnable(job.getJobName(), job.getMethodName(), job.getParams());
+ Future> future = service.submit(task);
+ future.get();
+ long times = System.currentTimeMillis() - startTime;
+ // 任务状态 0:成功 1:失败
+ jobLog.setStatus(Constants.SUCCESS);
+ jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
+
+ log.info("任务执行结束 - 名称:{} 耗时:{} 毫秒", job.getJobName(), times);
+ }
+ catch (Exception e)
+ {
+ log.info("任务执行失败 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
+ log.error("任务执行异常 - :", e);
+ long times = System.currentTimeMillis() - startTime;
+ jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
+ // 任务状态 0:成功 1:失败
+ jobLog.setStatus(Constants.FAIL);
+ jobLog.setExceptionInfo(e.toString());
+ }
+ finally
+ {
+ jobLogService.addJobLog(jobLog);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleRunnable.java b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleRunnable.java
new file mode 100644
index 000000000..6066f4940
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleRunnable.java
@@ -0,0 +1,59 @@
+package com.ruoyi.project.monitor.job.util;
+
+import java.lang.reflect.Method;
+
+import org.springframework.util.ReflectionUtils;
+
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 执行定时任务
+ *
+ * @author ruoyi
+ *
+ */
+public class ScheduleRunnable implements Runnable
+{
+ private Object target;
+ private Method method;
+ private String params;
+
+ public ScheduleRunnable(String beanName, String methodName, String params)
+ throws NoSuchMethodException, SecurityException
+ {
+ this.target = SpringUtils.getBean(beanName);
+ this.params = params;
+
+ if (StringUtils.isNotEmpty(params))
+ {
+ this.method = target.getClass().getDeclaredMethod(methodName, String.class);
+ }
+ else
+ {
+ this.method = target.getClass().getDeclaredMethod(methodName);
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ ReflectionUtils.makeAccessible(method);
+ if (StringUtils.isNotEmpty(params))
+ {
+ method.invoke(target, params);
+ }
+ else
+ {
+ method.invoke(target);
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleUtils.java b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleUtils.java
new file mode 100644
index 000000000..0c5072e0f
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/job/util/ScheduleUtils.java
@@ -0,0 +1,193 @@
+package com.ruoyi.project.monitor.job.util;
+
+import org.quartz.CronScheduleBuilder;
+import org.quartz.CronTrigger;
+import org.quartz.JobBuilder;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.TriggerBuilder;
+import org.quartz.TriggerKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.project.monitor.job.domain.Job;
+
+/**
+ * 定时任务工具类
+ *
+ * @author ruoyi
+ *
+ */
+public class ScheduleUtils
+{
+ private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class);
+
+ private final static String JOB_NAME = "TASK_";
+
+ /**
+ * 获取触发器key
+ */
+ public static TriggerKey getTriggerKey(Long jobId)
+ {
+ return TriggerKey.triggerKey(JOB_NAME + jobId);
+ }
+
+ /**
+ * 获取jobKey
+ */
+ public static JobKey getJobKey(Long jobId)
+ {
+ return JobKey.jobKey(JOB_NAME + jobId);
+ }
+
+ /**
+ * 获取表达式触发器
+ */
+ public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId)
+ {
+ try
+ {
+ return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ return null;
+ }
+
+ /**
+ * 创建定时任务
+ */
+ public static void createScheduleJob(Scheduler scheduler, Job job)
+ {
+ try
+ {
+ // 构建job信息
+ JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build();
+
+ // 表达式调度构建器
+ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+
+ // 按新的cronExpression表达式构建一个新的trigger
+ CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId())).withSchedule(scheduleBuilder).build();
+
+ // 放入参数,运行时的方法可以获取
+ jobDetail.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
+
+ scheduler.scheduleJob(jobDetail, trigger);
+
+ // 暂停任务
+ if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+ {
+ pauseJob(scheduler, job.getJobId());
+ }
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 更新定时任务
+ */
+ public static void updateScheduleJob(Scheduler scheduler, Job job)
+ {
+ try
+ {
+ TriggerKey triggerKey = getTriggerKey(job.getJobId());
+
+ // 表达式调度构建器
+ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+
+ CronTrigger trigger = getCronTrigger(scheduler, job.getJobId());
+
+ // 按新的cronExpression表达式重新构建trigger
+ trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
+
+ // 参数
+ trigger.getJobDataMap().put(ScheduleConstants.JOB_PARAM_KEY, job);
+
+ scheduler.rescheduleJob(triggerKey, trigger);
+
+ // 暂停任务
+ if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+ {
+ pauseJob(scheduler, job.getJobId());
+ }
+
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 立即执行任务
+ */
+ public static void run(Scheduler scheduler, Job job)
+ {
+ try
+ {
+ // 参数
+ JobDataMap dataMap = new JobDataMap();
+ dataMap.put(ScheduleConstants.JOB_PARAM_KEY, job);
+
+ scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 暂停任务
+ */
+ public static void pauseJob(Scheduler scheduler, Long jobId)
+ {
+ try
+ {
+ scheduler.pauseJob(getJobKey(jobId));
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 恢复任务
+ */
+ public static void resumeJob(Scheduler scheduler, Long jobId)
+ {
+ try
+ {
+ scheduler.resumeJob(getJobKey(jobId));
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 删除定时任务
+ */
+ public static void deleteScheduleJob(Scheduler scheduler, Long jobId)
+ {
+ try
+ {
+ scheduler.deleteJob(getJobKey(jobId));
+ }
+ catch (SchedulerException e)
+ {
+ log.error(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/logininfor/controller/LogininforController.java b/src/main/java/com/ruoyi/project/monitor/logininfor/controller/LogininforController.java
new file mode 100644
index 000000000..ec1e8e6b5
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/logininfor/controller/LogininforController.java
@@ -0,0 +1,81 @@
+package com.ruoyi.project.monitor.logininfor.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
+import com.ruoyi.project.monitor.logininfor.service.ILogininforService;
+
+/**
+ * 系统访问记录
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/logininfor")
+public class LogininforController extends BaseController
+{
+ private String prefix = "monitor/logininfor";
+
+ @Autowired
+ private ILogininforService logininforService;
+
+ @RequiresPermissions("monitor:logininfor:view")
+ @GetMapping()
+ public String logininfor()
+ {
+ return prefix + "/logininfor";
+ }
+
+ @RequiresPermissions("monitor:logininfor:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(Logininfor logininfor)
+ {
+ startPage();
+ List list = logininforService.selectLogininforList(logininfor);
+ return getDataTable(list);
+ }
+
+ @Log(title = "登陆日志", action = BusinessType.EXPORT)
+ @PostMapping("/export")
+ @ResponseBody
+ public AjaxResult export(Logininfor logininfor) throws Exception
+ {
+ try
+ {
+ List list = logininforService.selectLogininforList(logininfor);
+ ExcelUtil util = new ExcelUtil(Logininfor.class);
+ return util.exportExcel(list, "logininfor");
+ }
+ catch (Exception e)
+ {
+ return error("导出Excel失败,请联系网站管理员!");
+ }
+ }
+
+ @RequiresPermissions("monitor:logininfor:remove")
+ @Log(title = "登陆日志", action = BusinessType.DELETE)
+ @PostMapping("/remove")
+ @ResponseBody
+ public AjaxResult remove(String ids)
+ {
+ int rows = logininforService.deleteLogininforByIds(ids);
+ if (rows > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/logininfor/domain/Logininfor.java b/src/main/java/com/ruoyi/project/monitor/logininfor/domain/Logininfor.java
new file mode 100644
index 000000000..301d35569
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/logininfor/domain/Logininfor.java
@@ -0,0 +1,141 @@
+package com.ruoyi.project.monitor.logininfor.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import java.util.Date;
+
+/**
+ * 系统访问日志情况信息 sys_logininfor
+ *
+ * @author ruoyi
+ */
+public class Logininfor extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+ /** ID */
+ @Excel(name = "序号", column = "A")
+ private Integer infoId;
+ /** 用户账号 */
+ @Excel(name = "用户账号", column = "B")
+ private String loginName;
+ /** 登录状态 0成功 1失败 */
+ @Excel(name = "登录状态", column = "C")
+ private String status;
+ /** 登录IP地址 */
+ @Excel(name = "登录地址", column = "D")
+ private String ipaddr;
+ /** 登录地点 */
+ @Excel(name = "登录地点", column = "E")
+ private String loginLocation;
+ /** 浏览器类型 */
+ @Excel(name = "浏览器", column = "F")
+ private String browser;
+ /** 操作系统 */
+ @Excel(name = "操作系统 ", column = "G")
+ private String os;
+ /** 提示消息 */
+ @Excel(name = "提示消息", column = "H")
+ private String msg;
+ /** 访问时间 */
+ @Excel(name = "访问时间", column = "I")
+ private Date loginTime;
+
+ public Integer getInfoId()
+ {
+ return infoId;
+ }
+
+ public void setInfoId(Integer infoId)
+ {
+ this.infoId = infoId;
+ }
+
+ public String getLoginName()
+ {
+ return loginName;
+ }
+
+ public void setLoginName(String loginName)
+ {
+ this.loginName = loginName;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public String getMsg()
+ {
+ return msg;
+ }
+
+ public void setMsg(String msg)
+ {
+ this.msg = msg;
+ }
+
+ public Date getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Date loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Logininfor [infoId=" + infoId + ", loginName=" + loginName + ", status=" + status + ", ipaddr=" + ipaddr
+ + ",loginLocation=" + loginLocation + ", browser=" + browser + ", os=" + os + ", msg=" + msg
+ + ", loginTime=" + loginTime + "]";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/project/monitor/logininfor/mapper/LogininforMapper.java b/src/main/java/com/ruoyi/project/monitor/logininfor/mapper/LogininforMapper.java
new file mode 100644
index 000000000..297bde9be
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/logininfor/mapper/LogininforMapper.java
@@ -0,0 +1,35 @@
+package com.ruoyi.project.monitor.logininfor.mapper;
+
+import java.util.List;
+import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
+
+/**
+ * 系统访问日志情况信息 数据层
+ *
+ * @author ruoyi
+ */
+public interface LogininforMapper
+{
+ /**
+ * 新增系统登录日志
+ *
+ * @param logininfor 访问日志对象
+ */
+ public void insertLogininfor(Logininfor logininfor);
+
+ /**
+ * 查询系统登录日志集合
+ *
+ * @param logininfor 访问日志对象
+ * @return 登录记录集合
+ */
+ public List selectLogininforList(Logininfor logininfor);
+
+ /**
+ * 批量删除系统登录日志
+ *
+ * @param ids 需要删除的数据
+ * @return
+ */
+ public int deleteLogininforByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/logininfor/service/ILogininforService.java b/src/main/java/com/ruoyi/project/monitor/logininfor/service/ILogininforService.java
new file mode 100644
index 000000000..3ec08cfc5
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/logininfor/service/ILogininforService.java
@@ -0,0 +1,36 @@
+package com.ruoyi.project.monitor.logininfor.service;
+
+import java.util.List;
+import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
+
+/**
+ * 系统访问日志情况信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface ILogininforService
+{
+
+ /**
+ * 新增系统登录日志
+ *
+ * @param logininfor 访问日志对象
+ */
+ public void insertLogininfor(Logininfor logininfor);
+
+ /**
+ * 查询系统登录日志集合
+ *
+ * @param logininfor 访问日志对象
+ * @return 登录记录集合
+ */
+ public List selectLogininforList(Logininfor logininfor);
+
+ /**
+ * 批量删除系统登录日志
+ *
+ * @param ids 需要删除的数据
+ * @return
+ */
+ public int deleteLogininforByIds(String ids);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/logininfor/service/LogininforServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/logininfor/service/LogininforServiceImpl.java
new file mode 100644
index 000000000..a5e16deac
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/logininfor/service/LogininforServiceImpl.java
@@ -0,0 +1,56 @@
+package com.ruoyi.project.monitor.logininfor.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.support.Convert;
+import com.ruoyi.project.monitor.logininfor.domain.Logininfor;
+import com.ruoyi.project.monitor.logininfor.mapper.LogininforMapper;
+
+/**
+ * 系统访问日志情况信息 服务层处理
+ *
+ * @author ruoyi
+ */
+@Service("logininforService")
+public class LogininforServiceImpl implements ILogininforService
+{
+
+ @Autowired
+ private LogininforMapper logininforMapper;
+
+ /**
+ * 新增系统登录日志
+ *
+ * @param logininfor 访问日志对象
+ */
+ @Override
+ public void insertLogininfor(Logininfor logininfor)
+ {
+ logininforMapper.insertLogininfor(logininfor);
+ }
+
+ /**
+ * 查询系统登录日志集合
+ *
+ * @param logininfor 访问日志对象
+ * @return 登录记录集合
+ */
+ @Override
+ public List selectLogininforList(Logininfor logininfor)
+ {
+ return logininforMapper.selectLogininforList(logininfor);
+ }
+
+ /**
+ * 批量删除系统登录日志
+ *
+ * @param ids 需要删除的数据
+ * @return
+ */
+ @Override
+ public int deleteLogininforByIds(String ids)
+ {
+ return logininforMapper.deleteLogininforByIds(Convert.toLongArray(ids));
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/controller/UserOnlineController.java b/src/main/java/com/ruoyi/project/monitor/online/controller/UserOnlineController.java
new file mode 100644
index 000000000..8aa4e7a43
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/controller/UserOnlineController.java
@@ -0,0 +1,113 @@
+package com.ruoyi.project.monitor.online.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.ruoyi.common.utils.security.ShiroUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.online.domain.OnlineSession;
+import com.ruoyi.project.monitor.online.domain.UserOnline;
+import com.ruoyi.project.monitor.online.service.IUserOnlineService;
+
+/**
+ * 在线用户监控
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/online")
+public class UserOnlineController extends BaseController
+{
+ private String prefix = "monitor/online";
+
+ @Autowired
+ private IUserOnlineService userOnlineService;
+
+ @Autowired
+ private OnlineSessionDAO onlineSessionDAO;
+
+ @RequiresPermissions("monitor:online:view")
+ @GetMapping()
+ public String online()
+ {
+ return prefix + "/online";
+ }
+
+ @RequiresPermissions("monitor:online:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(UserOnline userOnline)
+ {
+ startPage();
+ List list = userOnlineService.selectUserOnlineList(userOnline);
+ return getDataTable(list);
+ }
+
+ @RequiresPermissions("monitor:online:batchForceLogout")
+ @Log(title = "在线用户", action = BusinessType.FORCE)
+ @PostMapping("/batchForceLogout")
+ @ResponseBody
+ public AjaxResult batchForceLogout(@RequestParam("ids[]") String[] ids)
+ {
+ for (String sessionId : ids)
+ {
+ UserOnline online = userOnlineService.selectOnlineById(sessionId);
+ if (online == null)
+ {
+ return error("用户已下线");
+ }
+ OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
+ if (onlineSession == null)
+ {
+ return error("用户已下线");
+ }
+ if (sessionId.equals(ShiroUtils.getSessionId()))
+ {
+ return error("当前登陆用户无法强退");
+ }
+ onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
+ online.setStatus(OnlineSession.OnlineStatus.off_line);
+ userOnlineService.saveOnline(online);
+ }
+ return success();
+ }
+
+ @RequiresPermissions("monitor:online:forceLogout")
+ @Log(title = "在线用户", action = BusinessType.FORCE)
+ @PostMapping("/forceLogout")
+ @ResponseBody
+ public AjaxResult forceLogout(String sessionId)
+ {
+ UserOnline online = userOnlineService.selectOnlineById(sessionId);
+ if (sessionId.equals(ShiroUtils.getSessionId()))
+ {
+ return error("当前登陆用户无法强退");
+ }
+ if (online == null)
+ {
+ return error("用户已下线");
+ }
+ OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
+ if (onlineSession == null)
+ {
+ return error("用户已下线");
+ }
+ onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
+ online.setStatus(OnlineSession.OnlineStatus.off_line);
+ userOnlineService.saveOnline(online);
+ return success();
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/domain/OnlineSession.java b/src/main/java/com/ruoyi/project/monitor/online/domain/OnlineSession.java
new file mode 100644
index 000000000..02a144eff
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/domain/OnlineSession.java
@@ -0,0 +1,155 @@
+package com.ruoyi.project.monitor.online.domain;
+
+import org.apache.shiro.session.mgt.SimpleSession;
+
+/**
+ * 在线用户会话属性
+ *
+ * @author ruoyi
+ */
+public class OnlineSession extends SimpleSession
+{
+
+ private static final long serialVersionUID = 1L;
+
+ /** 用户ID */
+ private Long userId;
+
+ /** 用户名称 */
+ private String loginName;
+
+ /** 部门名称 */
+ private String deptName;
+
+ /** 登录IP地址 */
+ private String host;
+
+ /** 浏览器类型 */
+ private String browser;
+
+ /** 操作系统 */
+ private String os;
+
+ /** 在线状态 */
+ private OnlineStatus status = OnlineStatus.on_line;
+
+ /** 属性是否改变 优化session数据同步 */
+ private transient boolean attributeChanged = false;
+
+ @Override
+ public String getHost()
+ {
+ return host;
+ }
+
+ @Override
+ public void setHost(String host)
+ {
+ this.host = host;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public String getLoginName()
+ {
+ return loginName;
+ }
+
+ public void setLoginName(String loginName)
+ {
+ this.loginName = loginName;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public OnlineStatus getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(OnlineStatus status)
+ {
+ this.status = status;
+ }
+
+ public void markAttributeChanged()
+ {
+ this.attributeChanged = true;
+ }
+
+ public void resetAttributeChanged()
+ {
+ this.attributeChanged = false;
+ }
+
+ public boolean isAttributeChanged()
+ {
+ return attributeChanged;
+ }
+
+ @Override
+ public void setAttribute(Object key, Object value)
+ {
+ super.setAttribute(key, value);
+ }
+
+ @Override
+ public Object removeAttribute(Object key)
+ {
+ return super.removeAttribute(key);
+ }
+
+ public static enum OnlineStatus
+ {
+ /** 用户状态 */
+ on_line("在线"), off_line("离线");
+ private final String info;
+
+ private OnlineStatus(String info)
+ {
+ this.info = info;
+ }
+
+ public String getInfo()
+ {
+ return info;
+ }
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/domain/UserOnline.java b/src/main/java/com/ruoyi/project/monitor/online/domain/UserOnline.java
new file mode 100644
index 000000000..b3dad54ea
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/domain/UserOnline.java
@@ -0,0 +1,202 @@
+package com.ruoyi.project.monitor.online.domain;
+
+import com.ruoyi.common.utils.AddressUtils;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import com.ruoyi.project.monitor.online.domain.OnlineSession.OnlineStatus;
+import java.util.Date;
+
+/**
+ * 当前在线会话 sys_user_online
+ *
+ * @author ruoyi
+ */
+public class UserOnline extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+ /** 用户会话id */
+ private String sessionId;
+
+ /** 部门名称 */
+ private String deptName;
+
+ /** 登录名称 */
+ private String loginName;
+
+ /** 登录IP地址 */
+ private String ipaddr;
+
+ /** 登录地址 */
+ private String longinLocation;
+
+ /** 浏览器类型 */
+ private String browser;
+
+ /** 操作系统 */
+ private String os;
+
+ /** session创建时间 */
+ private Date startTimestamp;
+
+ /** session最后访问时间 */
+ private Date lastAccessTime;
+
+ /** 超时时间,单位为分钟 */
+ private Long expireTime;
+
+ /** 在线状态 */
+ private OnlineStatus status = OnlineStatus.on_line;
+
+ /** 备份的当前用户会话 */
+ private OnlineSession session;
+
+ /**
+ * 设置session对象
+ */
+ public static final UserOnline fromOnlineSession(OnlineSession session)
+ {
+ UserOnline online = new UserOnline();
+ online.setSessionId(String.valueOf(session.getId()));
+ online.setDeptName(session.getDeptName());
+ online.setLoginName(session.getLoginName());
+ online.setStartTimestamp(session.getStartTimestamp());
+ online.setLastAccessTime(session.getLastAccessTime());
+ online.setExpireTime(session.getTimeout());
+ online.setIpaddr(session.getHost());
+ online.setLonginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
+ online.setBrowser(session.getBrowser());
+ online.setOs(session.getOs());
+ online.setStatus(session.getStatus());
+ online.setSession(session);
+ return online;
+ }
+
+ public String getSessionId()
+ {
+ return sessionId;
+ }
+
+ public void setSessionId(String sessionId)
+ {
+ this.sessionId = sessionId;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public String getLoginName()
+ {
+ return loginName;
+ }
+
+ public void setLoginName(String loginName)
+ {
+ this.loginName = loginName;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLonginLocation()
+ {
+ return longinLocation;
+ }
+
+ public void setLonginLocation(String longinLocation)
+ {
+ this.longinLocation = longinLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Date getStartTimestamp()
+ {
+ return startTimestamp;
+ }
+
+ public void setStartTimestamp(Date startTimestamp)
+ {
+ this.startTimestamp = startTimestamp;
+ }
+
+ public Date getLastAccessTime()
+ {
+ return lastAccessTime;
+ }
+
+ public void setLastAccessTime(Date lastAccessTime)
+ {
+ this.lastAccessTime = lastAccessTime;
+ }
+
+ public Long getExpireTime()
+ {
+ return expireTime;
+ }
+
+ public void setExpireTime(Long expireTime)
+ {
+ this.expireTime = expireTime;
+ }
+
+ public OnlineStatus getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(OnlineStatus status)
+ {
+ this.status = status;
+ }
+
+ public OnlineSession getSession()
+ {
+ return session;
+ }
+
+ public void setSession(OnlineSession session)
+ {
+ this.session = session;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "UserOnline [sessionId=" + sessionId + ", deptName=" + deptName + ", loginName=" + loginName
+ + ", ipaddr=" + ipaddr + ", browser=" + browser + ", os=" + os + ", startTimestamp=" + startTimestamp
+ + ", lastAccessTime=" + lastAccessTime + ", expireTime=" + expireTime + ", status=" + status
+ + ", session=" + session + "]";
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/mapper/UserOnlineMapper.java b/src/main/java/com/ruoyi/project/monitor/online/mapper/UserOnlineMapper.java
new file mode 100644
index 000000000..32f4caa42
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/mapper/UserOnlineMapper.java
@@ -0,0 +1,52 @@
+package com.ruoyi.project.monitor.online.mapper;
+
+import java.util.List;
+import com.ruoyi.project.monitor.online.domain.UserOnline;
+
+/**
+ * 在线用户 数据层
+ *
+ * @author ruoyi
+ */
+public interface UserOnlineMapper
+{
+ /**
+ * 通过会话序号查询信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ public UserOnline selectOnlineById(String sessionId);
+
+ /**
+ * 通过会话序号删除信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ public int deleteOnlineById(String sessionId);
+
+ /**
+ * 保存会话信息
+ *
+ * @param online 会话信息
+ * @return 结果
+ */
+ public int saveOnline(UserOnline online);
+
+ /**
+ * 查询会话集合
+ *
+ * @param userOnline 会话参数
+ * @return 会话集合
+ */
+ public List selectUserOnlineList(UserOnline userOnline);
+
+ /**
+ * 查询过期会话集合
+ *
+ * @param lastAccessTime 过期时间
+ * @return 会话集合
+ */
+ public List selectOnlineByExpired(String lastAccessTime);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/service/IUserOnlineService.java b/src/main/java/com/ruoyi/project/monitor/online/service/IUserOnlineService.java
new file mode 100644
index 000000000..dd2ffea96
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/service/IUserOnlineService.java
@@ -0,0 +1,67 @@
+package com.ruoyi.project.monitor.online.service;
+
+import java.util.Date;
+import java.util.List;
+import com.ruoyi.project.monitor.online.domain.UserOnline;
+
+/**
+ * 在线用户 服务层
+ *
+ * @author ruoyi
+ */
+public interface IUserOnlineService
+{
+ /**
+ * 通过会话序号查询信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ public UserOnline selectOnlineById(String sessionId);
+
+ /**
+ * 通过会话序号删除信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ public void deleteOnlineById(String sessionId);
+
+ /**
+ * 通过会话序号删除信息
+ *
+ * @param sessions 会话ID集合
+ * @return 在线用户信息
+ */
+ public void batchDeleteOnline(List sessions);
+
+ /**
+ * 保存会话信息
+ *
+ * @param online 会话信息
+ */
+ public void saveOnline(UserOnline online);
+
+ /**
+ * 查询会话集合
+ *
+ * @param userOnline 分页参数
+ * @return 会话集合
+ */
+ public List selectUserOnlineList(UserOnline userOnline);
+
+ /**
+ * 强退用户
+ *
+ * @param sessionId 会话ID
+ */
+ public void forceLogout(String sessionId);
+
+ /**
+ * 查询会话集合
+ *
+ * @param expiredDate 有效期
+ * @return 会话集合
+ */
+ public List selectOnlineByExpired(Date expiredDate);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/online/service/UserOnlineServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/online/service/UserOnlineServiceImpl.java
new file mode 100644
index 000000000..be584773c
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/online/service/UserOnlineServiceImpl.java
@@ -0,0 +1,124 @@
+package com.ruoyi.project.monitor.online.service;
+
+import java.util.Date;
+import java.util.List;
+import org.apache.shiro.session.Session;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
+import com.ruoyi.project.monitor.online.domain.UserOnline;
+import com.ruoyi.project.monitor.online.mapper.UserOnlineMapper;
+
+/**
+ * 在线用户 服务层处理
+ *
+ * @author ruoyi
+ */
+@Service("userOnlineService")
+public class UserOnlineServiceImpl implements IUserOnlineService
+{
+ @Autowired
+ private UserOnlineMapper userOnlineDao;
+
+ @Autowired
+ private OnlineSessionDAO onlineSessionDAO;
+
+ /**
+ * 通过会话序号查询信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ @Override
+ public UserOnline selectOnlineById(String sessionId)
+ {
+ return userOnlineDao.selectOnlineById(sessionId);
+ }
+
+ /**
+ * 通过会话序号删除信息
+ *
+ * @param sessionId 会话ID
+ * @return 在线用户信息
+ */
+ @Override
+ public void deleteOnlineById(String sessionId)
+ {
+ UserOnline userOnline = selectOnlineById(sessionId);
+ if (userOnline != null)
+ {
+ userOnlineDao.deleteOnlineById(sessionId);
+ }
+ }
+
+ /**
+ * 通过会话序号删除信息
+ *
+ * @param sessions 会话ID集合
+ * @return 在线用户信息
+ */
+ @Override
+ public void batchDeleteOnline(List sessions)
+ {
+ for (String sessionId : sessions)
+ {
+ UserOnline userOnline = selectOnlineById(sessionId);
+ if (userOnline != null)
+ {
+ userOnlineDao.deleteOnlineById(sessionId);
+ }
+ }
+ }
+
+ /**
+ * 保存会话信息
+ *
+ * @param online 会话信息
+ */
+ @Override
+ public void saveOnline(UserOnline online)
+ {
+ userOnlineDao.saveOnline(online);
+ }
+
+ /**
+ * 查询会话集合
+ *
+ * @param pageUtilEntity 分页参数
+ */
+ @Override
+ public List selectUserOnlineList(UserOnline userOnline)
+ {
+ return userOnlineDao.selectUserOnlineList(userOnline);
+ }
+
+ /**
+ * 强退用户
+ *
+ * @param sessionId 会话ID
+ */
+ @Override
+ public void forceLogout(String sessionId)
+ {
+ Session session = onlineSessionDAO.readSession(sessionId);
+ if (session == null)
+ {
+ return;
+ }
+ session.setTimeout(1000);
+ userOnlineDao.deleteOnlineById(sessionId);
+ }
+
+ /**
+ * 查询会话集合
+ *
+ * @param online 会话信息
+ */
+ @Override
+ public List selectOnlineByExpired(Date expiredDate)
+ {
+ String lastAccessTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, expiredDate);
+ return userOnlineDao.selectOnlineByExpired(lastAccessTime);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/operlog/controller/OperlogController.java b/src/main/java/com/ruoyi/project/monitor/operlog/controller/OperlogController.java
new file mode 100644
index 000000000..cd308722c
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/operlog/controller/OperlogController.java
@@ -0,0 +1,91 @@
+package com.ruoyi.project.monitor.operlog.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.monitor.operlog.domain.OperLog;
+import com.ruoyi.project.monitor.operlog.service.IOperLogService;
+
+/**
+ * 操作日志记录
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/monitor/operlog")
+public class OperlogController extends BaseController
+{
+ private String prefix = "monitor/operlog";
+
+ @Autowired
+ private IOperLogService operLogService;
+
+ @RequiresPermissions("monitor:operlog:view")
+ @GetMapping()
+ public String operlog()
+ {
+ return prefix + "/operlog";
+ }
+
+ @RequiresPermissions("monitor:operlog:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(OperLog operLog)
+ {
+ startPage();
+ List list = operLogService.selectOperLogList(operLog);
+ return getDataTable(list);
+ }
+
+ @Log(title = "操作日志", action = BusinessType.EXPORT)
+ @PostMapping("/export")
+ @ResponseBody
+ public AjaxResult export(OperLog operLog) throws Exception
+ {
+ try
+ {
+ List list = operLogService.selectOperLogList(operLog);
+ ExcelUtil util = new ExcelUtil(OperLog.class);
+ return util.exportExcel(list, "operLog");
+ }
+ catch (Exception e)
+ {
+ return error("导出Excel失败,请联系网站管理员!");
+ }
+ }
+
+ @RequiresPermissions("monitor:operlog:remove")
+ @PostMapping("/remove")
+ @ResponseBody
+ public AjaxResult remove(String ids)
+ {
+ int rows = operLogService.deleteOperLogByIds(ids);
+ if (rows > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ @RequiresPermissions("monitor:operlog:detail")
+ @GetMapping("/detail/{operId}")
+ public String detail(@PathVariable("operId") Long deptId, Model model)
+ {
+ OperLog operLog = operLogService.selectOperLogById(deptId);
+ model.addAttribute("operLog", operLog);
+ return prefix + "/detail";
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/operlog/domain/OperLog.java b/src/main/java/com/ruoyi/project/monitor/operlog/domain/OperLog.java
new file mode 100644
index 000000000..15e08bc0d
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/operlog/domain/OperLog.java
@@ -0,0 +1,222 @@
+package com.ruoyi.project.monitor.operlog.domain;
+
+import java.util.Date;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+
+/**
+ * 操作日志记录 oper_log
+ *
+ * @author ruoyi
+ */
+public class OperLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 日志主键 */
+ @Excel(name = "操作序号", column = "A")
+ private Integer operId;
+
+ /** 操作模块 */
+ @Excel(name = "操作模块", column = "B")
+ private String title;
+
+ /** 操作类型 */
+ @Excel(name = "操作类型", column = "C")
+ private String action;
+
+ /** 请求方法 */
+ @Excel(name = "请求方法", column = "D")
+ private String method;
+
+ /** 来源渠道 */
+ @Excel(name = "来源渠道", column = "E")
+ private String channel;
+
+ /** 操作人员 */
+ @Excel(name = "操作人员", column = "F")
+ private String operName;
+
+ /** 部门名称 */
+ @Excel(name = "部门名称", column = "G")
+ private String deptName;
+
+ /** 请求url */
+ @Excel(name = "请求地址", column = "H")
+ private String operUrl;
+
+ /** 操作地址 */
+ @Excel(name = "操作地址", column = "I")
+ private String operIp;
+
+ /** 操作地点 */
+ @Excel(name = "操作地点", column = "J")
+ private String operLocation;
+
+ /** 请求参数 */
+ @Excel(name = "请求参数", column = "K")
+ private String operParam;
+
+ /** 状态0正常 1异常 */
+ @Excel(name = "状态", column = "L")
+ private String status;
+
+ /** 错误消息 */
+ @Excel(name = "错误消息", column = "N")
+ private String errorMsg;
+
+ /** 操作时间 */
+ @Excel(name = "操作时间", column = "M")
+ private Date operTime;
+
+ public Integer getOperId()
+ {
+ return operId;
+ }
+
+ public void setOperId(Integer operId)
+ {
+ this.operId = operId;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public String getAction()
+ {
+ return action;
+ }
+
+ public void setAction(String action)
+ {
+ this.action = action;
+ }
+
+ public String getMethod()
+ {
+ return method;
+ }
+
+ public void setMethod(String method)
+ {
+ this.method = method;
+ }
+
+ public String getChannel()
+ {
+ return channel;
+ }
+
+ public void setChannel(String channel)
+ {
+ this.channel = channel;
+ }
+
+ public String getOperName()
+ {
+ return operName;
+ }
+
+ public void setOperName(String operName)
+ {
+ this.operName = operName;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public String getOperUrl()
+ {
+ return operUrl;
+ }
+
+ public void setOperUrl(String operUrl)
+ {
+ this.operUrl = operUrl;
+ }
+
+ public String getOperIp()
+ {
+ return operIp;
+ }
+
+ public void setOperIp(String operIp)
+ {
+ this.operIp = operIp;
+ }
+
+ public String getOperLocation()
+ {
+ return operLocation;
+ }
+
+ public void setOperLocation(String operLocation)
+ {
+ this.operLocation = operLocation;
+ }
+
+ public String getOperParam()
+ {
+ return operParam;
+ }
+
+ public void setOperParam(String operParam)
+ {
+ this.operParam = operParam;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getErrorMsg()
+ {
+ return errorMsg;
+ }
+
+ public void setErrorMsg(String errorMsg)
+ {
+ this.errorMsg = errorMsg;
+ }
+
+ public Date getOperTime()
+ {
+ return operTime;
+ }
+
+ public void setOperTime(Date operTime)
+ {
+ this.operTime = operTime;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "OperLog [operId=" + operId + ", title=" + title + ", action=" + action + ", method=" + method
+ + ", channel=" + channel + ", operName=" + operName + ", deptName=" + deptName + ", operUrl=" + operUrl
+ + ", operIp=" + operIp + ", operLocation=" + operLocation + ", operParam=" + operParam + ", status="
+ + status + ", errorMsg=" + errorMsg + ", operTime=" + operTime + "]";
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/operlog/mapper/OperLogMapper.java b/src/main/java/com/ruoyi/project/monitor/operlog/mapper/OperLogMapper.java
new file mode 100644
index 000000000..6418b1bb9
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/operlog/mapper/OperLogMapper.java
@@ -0,0 +1,43 @@
+package com.ruoyi.project.monitor.operlog.mapper;
+
+import java.util.List;
+import com.ruoyi.project.monitor.operlog.domain.OperLog;
+
+/**
+ * 操作日志 数据层
+ *
+ * @author ruoyi
+ */
+public interface OperLogMapper
+{
+ /**
+ * 新增操作日志
+ *
+ * @param operLog 操作日志对象
+ */
+ public void insertOperlog(OperLog operLog);
+
+ /**
+ * 查询系统操作日志集合
+ *
+ * @param operLog 操作日志对象
+ * @return 操作日志集合
+ */
+ public List selectOperLogList(OperLog operLog);
+
+ /**
+ * 批量删除系统操作日志
+ *
+ * @param ids 需要删除的数据
+ * @return 结果
+ */
+ public int deleteOperLogByIds(Long[] ids);
+
+ /**
+ * 查询操作日志详细
+ *
+ * @param operId 操作ID
+ * @return 操作日志对象
+ */
+ public OperLog selectOperLogById(Long operId);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/operlog/service/IOperLogService.java b/src/main/java/com/ruoyi/project/monitor/operlog/service/IOperLogService.java
new file mode 100644
index 000000000..4725e1dbb
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/operlog/service/IOperLogService.java
@@ -0,0 +1,43 @@
+package com.ruoyi.project.monitor.operlog.service;
+
+import java.util.List;
+import com.ruoyi.project.monitor.operlog.domain.OperLog;
+
+/**
+ * 操作日志 服务层
+ *
+ * @author ruoyi
+ */
+public interface IOperLogService
+{
+ /**
+ * 新增操作日志
+ *
+ * @param operLog 操作日志对象
+ */
+ public void insertOperlog(OperLog operLog);
+
+ /**
+ * 查询系统操作日志集合
+ *
+ * @param operLog 操作日志对象
+ * @return 操作日志集合
+ */
+ public List selectOperLogList(OperLog operLog);
+
+ /**
+ * 批量删除系统操作日志
+ *
+ * @param ids 需要删除的数据
+ * @return 结果
+ */
+ public int deleteOperLogByIds(String ids);
+
+ /**
+ * 查询操作日志详细
+ *
+ * @param operId 操作ID
+ * @return 操作日志对象
+ */
+ public OperLog selectOperLogById(Long operId);
+}
diff --git a/src/main/java/com/ruoyi/project/monitor/operlog/service/OperLogServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/operlog/service/OperLogServiceImpl.java
new file mode 100644
index 000000000..819a85b4b
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/monitor/operlog/service/OperLogServiceImpl.java
@@ -0,0 +1,67 @@
+package com.ruoyi.project.monitor.operlog.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.support.Convert;
+import com.ruoyi.project.monitor.operlog.domain.OperLog;
+import com.ruoyi.project.monitor.operlog.mapper.OperLogMapper;
+
+/**
+ * 操作日志 服务层处理
+ *
+ * @author ruoyi
+ */
+@Service("operLogService")
+public class OperLogServiceImpl implements IOperLogService
+{
+ @Autowired
+ private OperLogMapper operLogMapper;
+
+ /**
+ * 新增操作日志
+ *
+ * @param operLog 操作日志对象
+ */
+ @Override
+ public void insertOperlog(OperLog operLog)
+ {
+ operLogMapper.insertOperlog(operLog);
+ }
+
+ /**
+ * 查询系统操作日志集合
+ *
+ * @param operLog 操作日志对象
+ * @return 操作日志集合
+ */
+ @Override
+ public List selectOperLogList(OperLog operLog)
+ {
+ return operLogMapper.selectOperLogList(operLog);
+ }
+
+ /**
+ * 批量删除系统操作日志
+ *
+ * @param ids 需要删除的数据
+ * @return
+ */
+ @Override
+ public int deleteOperLogByIds(String ids)
+ {
+ return operLogMapper.deleteOperLogByIds(Convert.toLongArray(ids));
+ }
+
+ /**
+ * 查询操作日志详细
+ *
+ * @param operId 操作ID
+ * @return 操作日志对象
+ */
+ @Override
+ public OperLog selectOperLogById(Long operId)
+ {
+ return operLogMapper.selectOperLogById(operId);
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/config/controller/ConfigController.java b/src/main/java/com/ruoyi/project/system/config/controller/ConfigController.java
new file mode 100644
index 000000000..612869b19
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/config/controller/ConfigController.java
@@ -0,0 +1,145 @@
+package com.ruoyi.project.system.config.controller;
+
+import java.util.List;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.project.system.config.domain.Config;
+import com.ruoyi.project.system.config.service.IConfigService;
+
+/**
+ * 参数配置 信息操作处理
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/config")
+public class ConfigController extends BaseController
+{
+ private String prefix = "system/config";
+
+ @Autowired
+ private IConfigService configService;
+
+ @RequiresPermissions("system:config:view")
+ @GetMapping()
+ public String index()
+ {
+ return prefix + "/config";
+ }
+
+ /**
+ * 查询参数配置列表
+ */
+ @RequiresPermissions("system:config:list")
+ @PostMapping("/list")
+ @ResponseBody
+ public TableDataInfo list(Config config)
+ {
+ startPage();
+ List list = configService.selectConfigList(config);
+ return getDataTable(list);
+ }
+
+
+ @Log(title = "参数管理", action = BusinessType.EXPORT)
+ @PostMapping("/export")
+ @ResponseBody
+ public AjaxResult export(Config config) throws Exception
+ {
+ try
+ {
+ List list = configService.selectConfigList(config);
+ ExcelUtil util = new ExcelUtil(Config.class);
+ return util.exportExcel(list, "config");
+ }
+ catch (Exception e)
+ {
+ return error("导出Excel失败,请联系网站管理员!");
+ }
+ }
+
+ /**
+ * 新增参数配置
+ */
+ @RequiresPermissions("system:config:add")
+ @Log(title = "参数管理", action = BusinessType.INSERT)
+ @GetMapping("/add")
+ public String add()
+ {
+ return prefix + "/add";
+ }
+
+ /**
+ * 修改参数配置
+ */
+ @RequiresPermissions("system:config:edit")
+ @Log(title = "参数管理", action = BusinessType.UPDATE)
+ @GetMapping("/edit/{configId}")
+ public String edit(@PathVariable("configId") Integer configId, Model model)
+ {
+ Config config = configService.selectConfigById(configId);
+ model.addAttribute("config", config);
+ return prefix + "/edit";
+ }
+
+ /**
+ * 保存参数配置
+ */
+ @RequiresPermissions("system:config:save")
+ @Log(title = "参数管理", action = BusinessType.SAVE)
+ @PostMapping("/save")
+ @ResponseBody
+ public AjaxResult save(Config config)
+ {
+ if (configService.saveConfig(config) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ /**
+ * 删除参数配置
+ */
+ @RequiresPermissions("system:config:remove")
+ @Log(title = "参数管理", action = BusinessType.DELETE)
+ @PostMapping("/remove")
+ @ResponseBody
+ public AjaxResult remove(String ids)
+ {
+ if (configService.deleteConfigByIds(ids) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ /**
+ * 校验参数键名
+ */
+ @PostMapping("/checkConfigKeyUnique")
+ @ResponseBody
+ public String checkConfigKeyUnique(Config config)
+ {
+ String uniqueFlag = "0";
+ if (config != null)
+ {
+ uniqueFlag = configService.checkConfigKeyUnique(config);
+ }
+ return uniqueFlag;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/system/config/domain/Config.java b/src/main/java/com/ruoyi/project/system/config/domain/Config.java
new file mode 100644
index 000000000..910ad3621
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/config/domain/Config.java
@@ -0,0 +1,86 @@
+package com.ruoyi.project.system.config.domain;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.framework.web.domain.BaseEntity;
+
+/**
+ * 参数配置表 sys_config
+ *
+ * @author ruoyi
+ */
+public class Config extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 参数主键 */
+ @Excel(name = "参数主键", column = "A")
+ private Integer configId;
+
+ /** 参数名称 */
+ @Excel(name = "参数名称", column = "B")
+ private String configName;
+
+ /** 参数键名 */
+ @Excel(name = "参数键名", column = "C")
+ private String configKey;
+
+ /** 参数键值 */
+ @Excel(name = "参数键值", column = "D")
+ private String configValue;
+
+ /** 系统内置(Y是 N否) */
+ @Excel(name = "系统内置", column = "E")
+ private String configType;
+
+
+ public Integer getConfigId()
+ {
+ return configId;
+ }
+
+ public void setConfigId(Integer configId)
+ {
+ this.configId = configId;
+ }
+
+ public String getConfigName()
+ {
+ return configName;
+ }
+
+ public void setConfigName(String configName)
+ {
+ this.configName = configName;
+ }
+
+ public String getConfigKey()
+ {
+ return configKey;
+ }
+
+ public void setConfigKey(String configKey)
+ {
+ this.configKey = configKey;
+ }
+
+ public String getConfigValue()
+ {
+ return configValue;
+ }
+
+ public void setConfigValue(String configValue)
+ {
+ this.configValue = configValue;
+ }
+
+ public String getConfigType()
+ {
+ return configType;
+ }
+
+ public void setConfigType(String configType)
+ {
+ this.configType = configType;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/system/config/mapper/ConfigMapper.java b/src/main/java/com/ruoyi/project/system/config/mapper/ConfigMapper.java
new file mode 100644
index 000000000..4f88f508d
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/config/mapper/ConfigMapper.java
@@ -0,0 +1,70 @@
+package com.ruoyi.project.system.config.mapper;
+
+import com.ruoyi.project.system.config.domain.Config;
+import java.util.List;
+
+/**
+ * 参数配置 数据层
+ *
+ * @author ruoyi
+ */
+public interface ConfigMapper
+{
+
+ /**
+ * 查询参数配置信息
+ *
+ * @param configId 参数配置ID
+ * @return 参数配置信息
+ */
+ public Config selectConfigById(Integer configId);
+
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configKey 参数键名
+ * @return 参数配置信息
+ */
+ public Config selectConfigByKey(String configKey);
+
+ /**
+ * 查询参数配置列表
+ *
+ * @param config 参数配置信息
+ * @return 参数配置集合
+ */
+ public List selectConfigList(Config config);
+
+ /**
+ * 新增参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ public int insertConfig(Config config);
+
+ /**
+ * 修改参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ public int updateConfig(Config config);
+
+ /**
+ * 删除参数配置
+ *
+ * @param configId 参数配置ID
+ * @return 结果
+ */
+ public int deleteConfigById(Integer configId);
+
+ /**
+ * 批量删除参数配置
+ *
+ * @param configIds 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteConfigByIds(Integer[] configIds);
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/project/system/config/service/ConfigServiceImpl.java b/src/main/java/com/ruoyi/project/system/config/service/ConfigServiceImpl.java
new file mode 100644
index 000000000..4b704cbbe
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/config/service/ConfigServiceImpl.java
@@ -0,0 +1,153 @@
+package com.ruoyi.project.system.config.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.support.Convert;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.project.system.config.domain.Config;
+import com.ruoyi.project.system.config.mapper.ConfigMapper;
+
+/**
+ * 参数配置 服务层实现
+ *
+ * @author ruoyi
+ */
+@Service
+public class ConfigServiceImpl implements IConfigService
+{
+ @Autowired
+ private ConfigMapper configMapper;
+
+ /**
+ * 查询参数配置信息
+ *
+ * @param configId 参数配置ID
+ * @return 参数配置信息
+ */
+ @Override
+ public Config selectConfigById(Integer configId)
+ {
+ return configMapper.selectConfigById(configId);
+ }
+
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configName 参数名称
+ * @return 参数键值
+ */
+ @Override
+ public String selectConfigByKey(String configKey)
+ {
+ Config config = configMapper.selectConfigByKey(configKey);
+ return StringUtils.isNotNull(config) ? config.getConfigValue() : "";
+ }
+
+ /**
+ * 查询参数配置列表
+ *
+ * @param config 参数配置信息
+ * @return 参数配置集合
+ */
+ @Override
+ public List selectConfigList(Config config)
+ {
+ return configMapper.selectConfigList(config);
+ }
+
+ /**
+ * 新增参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ @Override
+ public int insertConfig(Config config)
+ {
+ return configMapper.insertConfig(config);
+ }
+
+ /**
+ * 修改参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ @Override
+ public int updateConfig(Config config)
+ {
+ return configMapper.updateConfig(config);
+ }
+
+ /**
+ * 保存参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ @Override
+ public int saveConfig(Config config)
+ {
+ Integer configId = config.getConfigId();
+ int rows = 0;
+ if (StringUtils.isNotNull(configId))
+ {
+ rows = configMapper.updateConfig(config);
+ }
+ else
+ {
+ rows = configMapper.insertConfig(config);
+ }
+ return rows;
+ }
+
+ /**
+ * 删除参数配置信息
+ *
+ * @param configId 参数配置ID
+ * @return 结果
+ */
+ @Override
+ public int deleteConfigById(Integer configId)
+ {
+ return configMapper.deleteConfigById(configId);
+ }
+
+ /**
+ * 批量删除参数配置对象
+ *
+ * @param configIds 需要删除的数据ID
+ * @return 结果
+ */
+ @Override
+ public int deleteConfigByIds(String ids)
+ {
+ return configMapper.deleteConfigByIds(Convert.toIntArray(ids));
+ }
+
+ /**
+ * 校验参数键名是否唯一
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ @Override
+ public String checkConfigKeyUnique(Config config)
+ {
+ if (config.getConfigId() == null)
+ {
+ config.setConfigId(-1);
+ }
+ Integer configId = config.getConfigId();
+ Config info = configMapper.selectConfigByKey(config.getConfigKey());
+ if (StringUtils.isNotNull(info) && StringUtils.isNotNull(info.getConfigId())
+ && info.getConfigId().intValue() != configId.intValue())
+ {
+ return UserConstants.CONFIG_KEY_NOT_UNIQUE;
+ }
+ return UserConstants.CONFIG_KEY_UNIQUE;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/project/system/config/service/IConfigService.java b/src/main/java/com/ruoyi/project/system/config/service/IConfigService.java
new file mode 100644
index 000000000..f05bd2c48
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/config/service/IConfigService.java
@@ -0,0 +1,86 @@
+package com.ruoyi.project.system.config.service;
+
+import com.ruoyi.project.system.config.domain.Config;
+import java.util.List;
+
+/**
+ * 参数配置 服务层
+ *
+ * @author ruoyi
+ */
+public interface IConfigService
+{
+
+ /**
+ * 查询参数配置信息
+ *
+ * @param configId 参数配置ID
+ * @return 参数配置信息
+ */
+ public Config selectConfigById(Integer configId);
+
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configKey 参数键名
+ * @return 参数键值
+ */
+ public String selectConfigByKey(String configKey);
+
+ /**
+ * 查询参数配置列表
+ *
+ * @param config 参数配置信息
+ * @return 参数配置集合
+ */
+ public List selectConfigList(Config config);
+
+ /**
+ * 新增参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ public int insertConfig(Config config);
+
+ /**
+ * 修改参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ public int updateConfig(Config config);
+
+ /**
+ * 保存参数配置
+ *
+ * @param config 参数配置信息
+ * @return 结果
+ */
+ public int saveConfig(Config config);
+
+ /**
+ * 删除参数配置信息
+ *
+ * @param configId 参数配置ID
+ * @return 结果
+ */
+ public int deleteConfigById(Integer configId);
+
+ /**
+ * 批量删除参数配置信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ public int deleteConfigByIds(String ids);
+
+ /**
+ * 校验参数键名是否唯一
+ *
+ * @param config 参数信息
+ * @return 结果
+ */
+ public String checkConfigKeyUnique(Config config);
+
+}
diff --git a/src/main/java/com/ruoyi/project/system/dept/controller/DeptController.java b/src/main/java/com/ruoyi/project/system/dept/controller/DeptController.java
new file mode 100644
index 000000000..ddd5931e2
--- /dev/null
+++ b/src/main/java/com/ruoyi/project/system/dept/controller/DeptController.java
@@ -0,0 +1,152 @@
+package com.ruoyi.project.system.dept.controller;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.constant.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.dept.domain.Dept;
+import com.ruoyi.project.system.dept.service.IDeptService;
+
+/**
+ * 部门信息
+ *
+ * @author ruoyi
+ */
+@Controller
+@RequestMapping("/system/dept")
+public class DeptController extends BaseController
+{
+ private String prefix = "system/dept";
+
+ @Autowired
+ private IDeptService deptService;
+
+ @RequiresPermissions("system:dept:view")
+ @GetMapping()
+ public String dept()
+ {
+ return prefix + "/dept";
+ }
+
+ @RequiresPermissions("system:dept:list")
+ @GetMapping("/list")
+ @ResponseBody
+ public List list()
+ {
+ List deptList = deptService.selectDeptAll();
+ return deptList;
+ }
+
+ /**
+ * 修改
+ */
+ @Log(title = "部门管理", action = BusinessType.UPDATE)
+ @RequiresPermissions("system:dept:edit")
+ @GetMapping("/edit/{deptId}")
+ public String edit(@PathVariable("deptId") Long deptId, Model model)
+ {
+ Dept dept = deptService.selectDeptById(deptId);
+ model.addAttribute("dept", dept);
+ return prefix + "/edit";
+ }
+
+ /**
+ * 新增
+ */
+ @Log(title = "部门管理", action = BusinessType.INSERT)
+ @RequiresPermissions("system:dept:add")
+ @GetMapping("/add/{parentId}")
+ public String add(@PathVariable("parentId") Long parentId, Model model)
+ {
+ Dept dept = deptService.selectDeptById(parentId);
+ model.addAttribute("dept", dept);
+ return prefix + "/add";
+ }
+
+ /**
+ * 保存
+ */
+ @Log(title = "部门管理", action = BusinessType.SAVE)
+ @RequiresPermissions("system:dept:save")
+ @PostMapping("/save")
+ @ResponseBody
+ public AjaxResult save(Dept dept)
+ {
+ if (deptService.saveDept(dept) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ /**
+ * 删除
+ */
+ @Log(title = "部门管理", action = BusinessType.DELETE)
+ @RequiresPermissions("system:dept:remove")
+ @PostMapping("/remove/{deptId}")
+ @ResponseBody
+ public AjaxResult remove(@PathVariable("deptId") Long deptId)
+ {
+ if (deptService.selectDeptCount(deptId) > 0)
+ {
+ return error(1, "存在下级部门,不允许删除");
+ }
+ if (deptService.checkDeptExistUser(deptId))
+ {
+ return error(1, "部门存在用户,不允许删除");
+ }
+ if (deptService.deleteDeptById(deptId) > 0)
+ {
+ return success();
+ }
+ return error();
+ }
+
+ /**
+ * 校验部门名称
+ */
+ @PostMapping("/checkDeptNameUnique")
+ @ResponseBody
+ public String checkDeptNameUnique(Dept dept)
+ {
+ String uniqueFlag = "0";
+ if (dept != null)
+ {
+ uniqueFlag = deptService.checkDeptNameUnique(dept);
+ }
+ return uniqueFlag;
+ }
+
+ /**
+ * 选择部门树
+ */
+ @GetMapping("/selectDeptTree/{deptId}")
+ public String selectDeptTree(@PathVariable("deptId") Long deptId, Model model)
+ {
+ model.addAttribute("treeName", deptService.selectDeptById(deptId).getDeptName());
+ return prefix + "/tree";
+ }
+
+ /**
+ * 加载部门列表树
+ */
+ @GetMapping("/treeData")
+ @ResponseBody
+ public List