diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
index 61c98d29..d57abddf 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -6,10 +6,17 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.base.AjaxResult;
import com.ruoyi.common.config.Global;
import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.framework.config.ServerConfig;
+import com.ruoyi.framework.util.FileUploadUtils;
/**
* 通用请求处理
@@ -21,7 +28,21 @@ public class CommonController
{
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
- @RequestMapping("common/download")
+ /**
+ * 文件上传路径
+ */
+ public static final String UPLOAD_PATH = "/profile/upload/";
+
+ @Autowired
+ private ServerConfig serverConfig;
+
+ /**
+ * 通用下载请求
+ *
+ * @param fileName 文件名称
+ * @param delete 是否删除
+ */
+ @GetMapping("common/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
@@ -31,7 +52,8 @@ public class CommonController
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
- response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
+ response.setHeader("Content-Disposition",
+ "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
@@ -44,6 +66,31 @@ public class CommonController
}
}
+ /**
+ * 通用上传请求
+ */
+ @PostMapping("/common/upload")
+ @ResponseBody
+ public AjaxResult uploadFile(MultipartFile file) throws Exception
+ {
+ try
+ {
+ // 上传文件路径
+ String filePath = Global.getUploadPath();
+ // 上传并返回新文件名称
+ String fileName = FileUploadUtils.upload(filePath, file);
+ String url = serverConfig.getUrl() + UPLOAD_PATH + fileName;
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("fileName", fileName);
+ ajax.put("url", url);
+ return ajax;
+ }
+ catch (Exception e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+ }
+
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
{
final String agent = request.getHeader("USER-AGENT");
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
index bb1e7ab7..bae77734 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -181,4 +181,16 @@ public class SysRoleController extends BaseController
{
return prefix + "/tree";
}
+
+ /**
+ * 角色状态修改
+ */
+ @Log(title = "角色管理", businessType = BusinessType.UPDATE)
+ @RequiresPermissions("system:role:edit")
+ @PostMapping("/changeStatus")
+ @ResponseBody
+ public AjaxResult changeStatus(SysRole role)
+ {
+ return toAjax(roleService.changeStatus(role));
+ }
}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index 9be5f248..a7e94e8c 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -45,7 +45,7 @@ public class SysUserController extends BaseController
@Autowired
private ISysPostService postService;
-
+
@Autowired
private SysPasswordService passwordService;
@@ -225,4 +225,16 @@ public class SysUserController extends BaseController
{
return userService.checkEmailUnique(user);
}
+
+ /**
+ * 用户状态修改
+ */
+ @Log(title = "用户管理", businessType = BusinessType.UPDATE)
+ @RequiresPermissions("system:user:edit")
+ @PostMapping("/changeStatus")
+ @ResponseBody
+ public AjaxResult changeStatus(SysUser user)
+ {
+ return toAjax(userService.changeStatus(user));
+ }
}
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
index 326d1c37..cf35a623 100644
--- a/ruoyi-admin/src/main/resources/application-druid.yml
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -17,32 +17,33 @@ spring:
username:
password:
# 初始连接数
- initial-size: 10
- # 最大连接池数量
- max-active: 100
+ initialSize: 5
# 最小连接池数量
- min-idle: 10
+ minIdle: 10
+ # 最大连接池数量
+ maxActive: 20
# 配置获取连接等待超时的时间
- max-wait: 60000
- # 打开PSCache,并且指定每个连接上PSCache的大小
- pool-prepared-statements: true
- max-pool-prepared-statement-per-connection-size: 20
+ maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
- min-evictable-idle-time-millis: 300000
- validation-query: SELECT 1 FROM DUAL
- test-while-idle: true
- test-on-borrow: false
- test-on-return: false
- stat-view-servlet:
+ minEvictableIdleTimeMillis: 300000
+ # 配置一个连接在池中最大生存的时间,单位是毫秒
+ maxEvictableIdleTimeMillis: 900000
+ # 配置检测连接是否有效
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ statViewServlet:
enabled: true
url-pattern: /monitor/druid/*
filter:
stat:
+ # 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
- merge-sql: false
+ merge-sql: true
wall:
config:
multi-statement-allow: true
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index d039e073..8ec2a1cc 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -3,9 +3,9 @@ ruoyi:
# 名称
name: RuoYi
# 版本
- version: 3.1.0
+ version: 3.2.0
# 版权年份
- copyrightYear: 2018
+ copyrightYear: 2019
# 文件上传路径
profile: D:/profile/
# 获取ip地址开关
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
index 38ecc35a..ebe7b7f6 100644
--- a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js
@@ -1,44 +1,35 @@
/**
- * @author: Dennis Hernández
- * @webSite: http://djhvscf.github.io/Blog
- * @version: v1.1.0
+ * 基于bootstrap-table-mobile修改
+ * 修正部分iPhone手机不显示卡片视图
+ * Copyright (c) 2019 ruoyi
*/
-
!function ($) {
-
+
'use strict';
-
- var showHideColumns = function (that, checked) {
- if (that.options.columnsHidden.length > 0 ) {
- $.each(that.columns, function (i, column) {
- if (that.options.columnsHidden.indexOf(column.field) !== -1) {
- if (column.visible !== checked) {
- that.toggleColumn($.fn.bootstrapTable.utils.getFieldIndex(that.columns, column.field), checked, true);
- }
- }
- });
- }
- };
-
+
var resetView = function (that) {
if (that.options.height || that.options.showFooter) {
- setTimeout(function(){
- that.resetView.call(that);
- }, 1);
+ setTimeout(that.resetView(), 1);
}
};
+
+ // 判断是否 iphone
+ var isIPhone = function () {
+ let browserName = navigator.userAgent.toLowerCase();
+ return /(iphone)/i.test(browserName);
+ };
var changeView = function (that, width, height) {
if (that.options.minHeight) {
- if ((width <= that.options.minWidth) && (height <= that.options.minHeight)) {
+ if (checkValuesLessEqual(width, that.options.minWidth) && checkValuesLessEqual(height, that.options.minHeight)) {
conditionCardView(that);
- } else if ((width > that.options.minWidth) && (height > that.options.minHeight)) {
+ } else if (checkValuesGreater(width, that.options.minWidth) && checkValuesGreater(height, that.options.minHeight)) {
conditionFullView(that);
}
} else {
- if (width <= that.options.minWidth) {
+ if (checkValuesLessEqual(width, that.options.minWidth) || isIPhone()) {
conditionCardView(that);
- } else if (width > that.options.minWidth) {
+ } else if (checkValuesGreater(width, that.options.minWidth)) {
conditionFullView(that);
}
}
@@ -46,14 +37,20 @@
resetView(that);
};
+ var checkValuesLessEqual = function (currentValue, targetValue) {
+ return currentValue <= targetValue;
+ };
+
+ var checkValuesGreater = function (currentValue, targetValue) {
+ return currentValue > targetValue;
+ };
+
var conditionCardView = function (that) {
changeTableView(that, false);
- showHideColumns(that, false);
};
var conditionFullView = function (that) {
changeTableView(that, true);
- showHideColumns(that, true);
};
var changeTableView = function (that, cardViewState) {
@@ -61,27 +58,12 @@
that.toggleView();
};
- var debounce = function(func,wait) {
- var timeout;
- return function() {
- var context = this,
- args = arguments;
- var later = function() {
- timeout = null;
- func.apply(context,args);
- };
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- };
- };
-
$.extend($.fn.bootstrapTable.defaults, {
mobileResponsive: false,
minWidth: 562,
minHeight: undefined,
- heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
checkOnInit: true,
- columnsHidden: []
+ toggled: false
});
var BootstrapTable = $.fn.bootstrapTable.Constructor,
@@ -98,39 +80,13 @@
return;
}
- if (this.options.minWidth < 100 && this.options.resizable) {
- console.log("The minWidth when the resizable extension is active should be greater or equal than 100");
- this.options.minWidth = 100;
- }
-
- var that = this,
- old = {
- width: $(window).width(),
- height: $(window).height()
- };
-
- $(window).on('resize orientationchange',debounce(function (evt) {
- // reset view if height has only changed by at least the threshold.
- var height = $(this).height(),
- width = $(this).width();
-
- if (Math.abs(old.height - height) > that.options.heightThreshold || old.width != width) {
- changeView(that, width, height);
- old = {
- width: width,
- height: height
- };
- }
- },200));
+ var that = this;
+ $(window).resize(function () {
+ changeView(that, $(this).width(), $(this).height())
+ });
if (this.options.checkOnInit) {
- var height = $(window).height(),
- width = $(window).width();
- changeView(this, width, height);
- old = {
- width: width,
- height: height
- };
+ changeView(this, $(window).width(), $(window).height());
}
};
}(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js b/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js
deleted file mode 100644
index 2d074bc3..00000000
--- a/ruoyi-admin/src/main/resources/static/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
-* bootstrap-table - v1.11.0 - 2016-07-02
-* https://github.com/wenzhixin/bootstrap-table
-* Copyright (c) 2016 zhixin wen
-* Licensed MIT License
-*/
-!function(a){"use strict";var b=function(b,c){b.options.columnsHidden.length>0&&a.each(b.columns,function(d,e){-1!==b.options.columnsHidden.indexOf(e.field)&&e.visible!==c&&b.toggleColumn(a.fn.bootstrapTable.utils.getFieldIndex(b.columns,e.field),c,!0)})},c=function(a){(a.options.height||a.options.showFooter)&&setTimeout(function(){a.resetView.call(a)},1)},d=function(a,b,d){a.options.minHeight?b<=a.options.minWidth&&d<=a.options.minHeight?e(a):b>a.options.minWidth&&d>a.options.minHeight&&f(a):b<=a.options.minWidth?e(a):b>a.options.minWidth&&f(a),c(a)},e=function(a){g(a,!1),b(a,!1)},f=function(a){g(a,!0),b(a,!0)},g=function(a,b){a.options.cardView=b,a.toggleView()},h=function(a,b){var c;return function(){var d=this,e=arguments,f=function(){c=null,a.apply(d,e)};clearTimeout(c),c=setTimeout(f,b)}};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,heightThreshold:100,checkOnInit:!0,columnsHidden:[]});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){this.options.minWidth<100&&this.options.resizable&&(console.log("The minWidth when the resizable extension is active should be greater or equal than 100"),this.options.minWidth=100);var b=this,c={width:a(window).width(),height:a(window).height()};if(a(window).on("resize orientationchange",h(function(){var e=a(this).height(),f=a(this).width();(Math.abs(c.height-e)>b.options.heightThreshold||c.width!=f)&&(d(b,f,e),c={width:f,height:e})},200)),this.options.checkOnInit){var e=a(window).height(),f=a(window).width();d(this,f,e),c={width:f,height:e}}}}}(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js
index 9e3e7290..a4373ae8 100644
--- a/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js
+++ b/ruoyi-admin/src/main/resources/static/ajax/libs/jquery-layout/jquery.layout-latest.js
@@ -1,6091 +1,18 @@
-/**
- * @preserve
- * jquery.layout 1.4.4
- * $Date: 2014-11-29 08:00:00 (Sat, 29 November 2014) $
- * $Rev: 1.0404 $
- *
- * Copyright (c) 2014 Kevin Dalman (http://jquery-dev.com)
- * Based on work by Fabrizio Balliano (http://www.fabrizioballiano.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * SEE: http://layout.jquery-dev.com/LICENSE.txt
- *
- * Changelog: http://layout.jquery-dev.com/changelog.cfm
- *
- * Docs: http://layout.jquery-dev.com/documentation.html
- * Tips: http://layout.jquery-dev.com/tips.html
- * Help: http://groups.google.com/group/jquery-ui-layout
- */
-
-//
东
-//南
-//西
-//北
-//中
-//
-
-/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html
- * {!Object} non-nullable type (never NULL)
- * {?string} nullable type (sometimes NULL) - default for {Object}
- * {number=} optional parameter
- * {*} ALL types
- */
-/* TODO for jQ 2.x
- * check $.fn.disableSelection - this is in jQuery UI 1.9.x
- */
-
-// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars
-
-;(function ($) {
-
-// alias Math methods - used a lot!
-var min = Math.min
-, max = Math.max
-, round = Math.floor
-
-, isStr = function (v) { return $.type(v) === "string"; }
-
- /**
- * @param {!Object} Instance
- * @param {Array.} a_fn
- */
-, runPluginCallbacks = function (Instance, a_fn) {
- if ($.isArray(a_fn))
- for (var i=0, c=a_fn.length; i').appendTo("body")
- , d = { width: $c.outerWidth - $c[0].clientWidth, height: 100 - $c[0].clientHeight };
- $c.remove();
- window.scrollbarWidth = d.width;
- window.scrollbarHeight = d.height;
- return dim.match(/^(width|height)$/) ? d[dim] : d;
- }
-
-
-, disableTextSelection: function () {
- var $d = $(document)
- , s = 'textSelectionDisabled'
- , x = 'textSelectionInitialized'
- ;
- if ($.fn.disableSelection) {
- if (!$d.data(x)) // document hasn't been initialized yet
- $d.on('mouseup', $.layout.enableTextSelection ).data(x, true);
- if (!$d.data(s))
- $d.disableSelection().data(s, true);
- }
- }
-, enableTextSelection: function () {
- var $d = $(document)
- , s = 'textSelectionDisabled';
- if ($.fn.enableSelection && $d.data(s))
- $d.enableSelection().data(s, false);
- }
-
-
- /**
- * Returns hash container 'display' and 'visibility'
- *
- * @see $.swap() - swaps CSS, runs callback, resets CSS
- * @param {!Object} $E jQuery element
- * @param {boolean=} [force=false] Run even if display != none
- * @return {!Object} Returns current style props, if applicable
- */
-, showInvisibly: function ($E, force) {
- if ($E && $E.length && (force || $E.css("display") === "none")) { // only if not *already hidden*
- var s = $E[0].style
- // save ONLY the 'style' props because that is what we must restore
- , CSS = { display: s.display || '', visibility: s.visibility || '' };
- // show element 'invisibly' so can be measured
- $E.css({ display: "block", visibility: "hidden" });
- return CSS;
- }
- return {};
- }
-
- /**
- * Returns data for setting size of an element (container or a pane).
- *
- * @see _create(), onWindowResize() for container, plus others for pane
- * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
- */
-, getElementDimensions: function ($E, inset) {
- var
- // dimensions hash - start with current data IF passed
- d = { css: {}, inset: {} }
- , x = d.css // CSS hash
- , i = { bottom: 0 } // TEMP insets (bottom = complier hack)
- , N = $.layout.cssNum
- , R = Math.round
- , off = $E.offset()
- , b, p, ei // TEMP border, padding
- ;
- d.offsetLeft = off.left;
- d.offsetTop = off.top;
-
- if (!inset) inset = {}; // simplify logic below
-
- $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge
- b = x["border" + e] = $.layout.borderWidth($E, e);
- p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e);
- ei = e.toLowerCase();
- d.inset[ei] = inset[ei] >= 0 ? inset[ei] : p; // any missing insetX value = paddingX
- i[ei] = d.inset[ei] + b; // total offset of content from outer side
- });
-
- x.width = R($E.width());
- x.height = R($E.height());
- x.top = N($E,"top",true);
- x.bottom = N($E,"bottom",true);
- x.left = N($E,"left",true);
- x.right = N($E,"right",true);
-
- d.outerWidth = R($E.outerWidth());
- d.outerHeight = R($E.outerHeight());
- // calc the TRUE inner-dimensions, even in quirks-mode!
- d.innerWidth = max(0, d.outerWidth - i.left - i.right);
- d.innerHeight = max(0, d.outerHeight - i.top - i.bottom);
- // layoutWidth/Height is used in calcs for manual resizing
- // layoutW/H only differs from innerW/H when in quirks-mode - then is like outerW/H
- d.layoutWidth = R($E.innerWidth());
- d.layoutHeight = R($E.innerHeight());
-
- //if ($E.prop('tagName') === 'BODY') { debugData( d, $E.prop('tagName') ); } // DEBUG
-
- //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0;
-
- return d;
- }
-
-, getElementStyles: function ($E, list) {
- var
- CSS = {}
- , style = $E[0].style
- , props = list.split(",")
- , sides = "Top,Bottom,Left,Right".split(",")
- , attrs = "Color,Style,Width".split(",")
- , p, s, a, i, j, k
- ;
- for (i=0; i < props.length; i++) {
- p = props[i];
- if (p.match(/(border|padding|margin)$/))
- for (j=0; j < 4; j++) {
- s = sides[j];
- if (p === "border")
- for (k=0; k < 3; k++) {
- a = attrs[k];
- CSS[p+s+a] = style[p+s+a];
- }
- else
- CSS[p+s] = style[p+s];
- }
- else
- CSS[p] = style[p];
- };
- return CSS
- }
-
- /**
- * Return the innerWidth for the current browser/doctype
- *
- * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
- * @param {Array.