diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/LoggingMapper.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/LoggingMapper.java index 38fd7444ee92fba6fe45025ae3d47f80f43e3764..76cff5eb478cb9b68f4de13586c6bedc3faed1bc 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/LoggingMapper.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/LoggingMapper.java @@ -26,4 +26,13 @@ public interface LoggingMapper { * Return: 日志信息列表 * */ List selectList(LoggingType loggingType); + + + /** + * 根据id查询日志 + * + * @param id + * @return + */ + Logging getById(String id); } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/xml/LoggingMapper.xml b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/xml/LoggingMapper.xml index 5ae0090548f3b19a25951cb9dce3c7760e656e3b..9503ba6069521de8ef52d60f6668ab0db39645fd 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/xml/LoggingMapper.xml +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/mapper/xml/LoggingMapper.xml @@ -28,7 +28,7 @@ - insert into sys_logging + insert into sys_logging id, @@ -143,4 +143,32 @@ + + \ No newline at end of file diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/LoggingService.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/LoggingService.java index 9134661586b9ae90f6106727e648a6543c12c7c1..501c1bc7453a72a68c547b1c681dbc087a1fbf37 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/LoggingService.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/LoggingService.java @@ -2,26 +2,37 @@ package com.pearadmin.common.plugins.logging.service; import com.pearadmin.common.plugins.logging.domain.Logging; import com.pearadmin.common.plugins.logging.enums.LoggingType; + import java.util.List; /** * Describe: 日 志 服 务 接 口 * Author: 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public interface LoggingService { /** * 执 行 插 入 操 作 + * * @param logging 日志实体 * @return 执行结果 - * */ + */ boolean save(Logging logging); /** * 执 行 查 询 操 作 + * * @param loggingType 日志类型 * @return 执行结果 - * */ + */ List data(LoggingType loggingType); + + /** + * 根据id查询日志 + * + * @param id + * @return + */ + Logging getById(String id); } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/impl/LoggingServiceImpl.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/impl/LoggingServiceImpl.java index 608bad34dbb9b3cf2d86259fb556657a09b87b78..773cac4fc66dc186a5581df1e0d9d4f6f51e1c25 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/impl/LoggingServiceImpl.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/service/impl/LoggingServiceImpl.java @@ -46,4 +46,9 @@ public class LoggingServiceImpl implements LoggingService { public List data(LoggingType loggingType) { return loggingMapper.selectList(loggingType); } + + @Override + public Logging getById(String id) { + return loggingMapper.getById(id); + } } diff --git a/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.css b/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.css new file mode 100644 index 0000000000000000000000000000000000000000..57aa4501e372f85b3e855bf1e4b0129ac9630e2a --- /dev/null +++ b/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.css @@ -0,0 +1,57 @@ +/* Root element */ +.json-document { + padding: 1em 2em; +} + +/* Syntax highlighting for JSON objects */ +ul.json-dict, ol.json-array { + list-style-type: none; + margin: 0 0 0 1px; + border-left: 1px dotted #ccc; + padding-left: 2em; +} +.json-string { + color: #0B7500; +} +.json-literal { + color: #1A01CC; + font-weight: bold; +} + +/* Toggle button */ +a.json-toggle { + position: relative; + color: inherit; + text-decoration: none; +} +a.json-toggle:focus { + outline: none; +} +a.json-toggle:before { + font-size: 1.1em; + color: #c0c0c0; + content: "\25BC"; /* down arrow */ + position: absolute; + display: inline-block; + width: 1em; + text-align: center; + line-height: 1em; + left: -1.2em; +} +a.json-toggle:hover:before { + color: #aaa; +} +a.json-toggle.collapsed:before { + /* Use rotated down arrow, prevents right arrow appearing smaller than down arrow in some browsers */ + transform: rotate(-90deg); +} + +/* Collapsable placeholder links */ +a.json-placeholder { + color: #aaa; + padding: 0 1em; + text-decoration: none; +} +a.json-placeholder:hover { + text-decoration: underline; +} diff --git a/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.js b/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.js new file mode 100644 index 0000000000000000000000000000000000000000..611411bc76362f3be5fb73a11fbcd6f3ad73406a --- /dev/null +++ b/pear-entrance/src/main/resources/static/component/json-viewer/jquery.json-viewer.js @@ -0,0 +1,158 @@ +/** + * jQuery json-viewer + * @author: Alexandre Bodelot + * @link: https://github.com/abodelot/jquery.json-viewer + */ +(function($) { + + /** + * Check if arg is either an array with at least 1 element, or a dict with at least 1 key + * @return boolean + */ + function isCollapsable(arg) { + return arg instanceof Object && Object.keys(arg).length > 0; + } + + /** + * Check if a string represents a valid url + * @return boolean + */ + function isUrl(string) { + var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i; + return urlRegexp.test(string); + } + + /** + * Transform a json object into html representation + * @return string + */ + function json2html(json, options) { + var html = ''; + if (typeof json === 'string') { + // Escape tags and quotes + json = json + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"'); + + if (options.withLinks && isUrl(json)) { + html += '' + json + ''; + } else { + // Escape double quotes in the rendered non-URL string. + json = json.replace(/"/g, '\\"'); + html += '"' + json + '"'; + } + } else if (typeof json === 'number') { + html += '' + json + ''; + } else if (typeof json === 'boolean') { + html += '' + json + ''; + } else if (json === null) { + html += 'null'; + } else if (json instanceof Array) { + if (json.length > 0) { + html += '[
    '; + for (var i = 0; i < json.length; ++i) { + html += '
  1. '; + // Add toggle button if item is collapsable + if (isCollapsable(json[i])) { + html += ''; + } + html += json2html(json[i], options); + // Add comma if item is not last + if (i < json.length - 1) { + html += ','; + } + html += '
  2. '; + } + html += '
]'; + } else { + html += '[]'; + } + } else if (typeof json === 'object') { + var keyCount = Object.keys(json).length; + if (keyCount > 0) { + html += '{
    '; + for (var key in json) { + if (Object.prototype.hasOwnProperty.call(json, key)) { + html += '
  • '; + var keyRepr = options.withQuotes ? + '"' + key + '"' : key; + // Add toggle button if item is collapsable + if (isCollapsable(json[key])) { + html += '' + keyRepr + ''; + } else { + html += keyRepr; + } + html += ': ' + json2html(json[key], options); + // Add comma if item is not last + if (--keyCount > 0) { + html += ','; + } + html += '
  • '; + } + } + html += '
}'; + } else { + html += '{}'; + } + } + return html; + } + + /** + * jQuery plugin method + * @param json: a javascript object + * @param options: an optional options hash + */ + $.fn.jsonViewer = function(json, options) { + // Merge user options with default options + options = Object.assign({}, { + collapsed: false, + rootCollapsable: true, + withQuotes: false, + withLinks: true + }, options); + + // jQuery chaining + return this.each(function() { + + // Transform to HTML + var html = json2html(json, options); + if (options.rootCollapsable && isCollapsable(json)) { + html = '' + html; + } + + // Insert HTML in target DOM element + $(this).html(html); + $(this).addClass('json-document'); + + // Bind click on toggle buttons + $(this).off('click'); + $(this).on('click', 'a.json-toggle', function() { + var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array'); + target.toggle(); + if (target.is(':visible')) { + target.siblings('.json-placeholder').remove(); + } else { + var count = target.children('li').length; + var placeholder = count + (count > 1 ? ' items' : ' item'); + target.after('' + placeholder + ''); + } + return false; + }); + + // Simulate click on toggle button when placeholder is clicked + $(this).on('click', 'a.json-placeholder', function() { + $(this).siblings('a.json-toggle').click(); + return false; + }); + + if (options.collapsed == true) { + // Trigger click to collapse all nodes + $(this).find('a.json-toggle').click(); + } + }); + }; +})(jQuery); diff --git a/pear-entrance/src/main/resources/templates/system/logging/logging-details.html b/pear-entrance/src/main/resources/templates/system/logging/logging-details.html new file mode 100644 index 0000000000000000000000000000000000000000..20ba327eefdd6b77186b474ce8f490b9aad03f0d --- /dev/null +++ b/pear-entrance/src/main/resources/templates/system/logging/logging-details.html @@ -0,0 +1,29 @@ + + + + + 日志详情 + + + +
+
+ +
+

+        
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/pear-entrance/src/main/resources/templates/system/logging/main.html b/pear-entrance/src/main/resources/templates/system/logging/main.html index 9e12c60a0446c560edb9daaccd91b5e0332b6f81..6c483d31c38b2dcf3b908635c1d2a9a7fcf229e8 100644 --- a/pear-entrance/src/main/resources/templates/system/logging/main.html +++ b/pear-entrance/src/main/resources/templates/system/logging/main.html @@ -14,10 +14,10 @@
-
+
-
+
@@ -100,13 +100,13 @@ }); } - table.on('toolbar(log-operate-table)', function (obj) { + table.on('tool(log-operate-table)', function (obj) { if (obj.event === 'details') { window.details(obj); } }); - table.on('toolbar(log-login-table)', function (obj) { + table.on('tool(log-login-table)', function (obj) { if (obj.event === 'details') { window.details(obj); } @@ -117,7 +117,7 @@ type: 2, title: '详细信息', shade: 0, - area: ['450px', '550px'], + area: ['400px', '400px'], content: MODULE_PATH + "details?id="+obj.data['id'] }); } diff --git a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java index 626878a6149de142ad593595b87f0c82824a3ef7..b16be0cd19e54227237e9398ab0a899371c0b577 100644 --- a/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java +++ b/pear-modules/pear-system/src/main/java/com/pearadmin/system/controller/SysLoggingController.java @@ -1,5 +1,6 @@ package com.pearadmin.system.controller; +import com.alibaba.fastjson.JSON; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.pearadmin.common.plugins.logging.domain.Logging; @@ -15,19 +16,21 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; /** * Describe: 日 志 控 制 器 * Author: 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @RestController @RequestMapping("system/logging") public class SysLoggingController extends BaseController { /** * 引 入 日 志 组 件 的 日 志 服 务 - * */ + */ @Resource private LoggingService loggingService; @@ -35,10 +38,10 @@ public class SysLoggingController extends BaseController { * Describe: 行为日志视图 * Param: null * Return: ModelAndView - * */ + */ @GetMapping("main") @PreAuthorize("hasPermission('/system/logging/main','sys:logging:main')") - public ModelAndView main(){ + public ModelAndView main() { return JumpPage("system/logging/main"); } @@ -46,27 +49,32 @@ public class SysLoggingController extends BaseController { * Describe: 操作日志数据 * Param: null * Return: ResultTable - * */ + */ @GetMapping("operateLog") @PreAuthorize("hasPermission('/system/logging/operateLog','sys:logging:operateLog')") - public ResultTable operateLog(PageDomain pageDomain) - { - PageHelper.startPage(pageDomain.getPage(),pageDomain.getLimit()); + public ResultTable operateLog(PageDomain pageDomain) { + PageHelper.startPage(pageDomain.getPage(), pageDomain.getLimit()); PageInfo pageInfo = new PageInfo<>(loggingService.data(LoggingType.OPERATE)); - return pageTable(pageInfo.getList(),pageInfo.getTotal()); + return pageTable(pageInfo.getList(), pageInfo.getTotal()); } /** * Describe: 登录日志数据 * Param: null * Return: ModelAndView - * */ + */ @GetMapping("loginLog") @PreAuthorize("hasPermission('/system/logging/loginLog','sys:logging:loginLog')") - public ResultTable loginLog(PageDomain pageDomain) - { - PageHelper.startPage(pageDomain.getPage(),pageDomain.getLimit()); + public ResultTable loginLog(PageDomain pageDomain) { + PageHelper.startPage(pageDomain.getPage(), pageDomain.getLimit()); PageInfo pageInfo = new PageInfo<>(loggingService.data(LoggingType.LOGIN)); - return pageTable(pageInfo.getList(),pageInfo.getTotal()); + return pageTable(pageInfo.getList(), pageInfo.getTotal()); + } + + @GetMapping("/details") + public ModelAndView details(String id) { + Map params = new HashMap<>(); + params.put("loggingDetails", JSON.toJSONString(loggingService.getById(id))); + return JumpPage("system/logging/logging-details", params); } }