官网:http://www.ruoyi.vip
-
QQ群:满1389287 满1679294 满1529866 满1772718 满1366522 满1382251 满1145125 满86752435 满134072510 满210336300 满339522636 满130035985 满143151071 满158781320 满201531282 满101526938 满264355400 298522656
+
QQ群:满1389287 满1679294 满1529866 满1772718 满1366522 满1382251 满1145125 满86752435 满134072510 满210336300 满339522636 满130035985 满143151071 满158781320 满201531282 满101526938 满264355400 满298522656 139845794
微信:/ *若依
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
index e6dfa8baa..450c020e2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
@@ -2,6 +2,7 @@ package com.ruoyi.common.utils.file;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
@@ -111,8 +112,8 @@ public class FileUploadUtils
String fileName = extractFilename(file);
- File desc = getAbsoluteFile(baseDir, fileName);
- file.transferTo(desc);
+ String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+ file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index 00752a0be..d5329b2aa 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -316,7 +316,7 @@ public class ExcelUtil
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
if (StringUtils.isNotEmpty(dateFormat))
{
- val = parseDateToStr(dateFormat, (Date) val);
+ val = parseDateToStr(dateFormat, val);
}
else
{
@@ -328,7 +328,7 @@ public class ExcelUtil
{
val = Convert.toInt(val);
}
- else if (Long.TYPE == fieldType || Long.class == fieldType)
+ else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
{
val = Convert.toLong(val);
}
@@ -823,7 +823,7 @@ public class ExcelUtil
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
{
- cell.setCellValue(parseDateToStr(dateFormat, (Date) value));
+ cell.setCellValue(parseDateToStr(dateFormat, value));
}
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
{
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
index dac3b872e..e14a3b477 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
@@ -28,6 +28,7 @@ import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
+import com.ruoyi.framework.shiro.web.CustomShiroFilterFactoryBean;
import com.ruoyi.framework.shiro.web.filter.LogoutFilter;
import com.ruoyi.framework.shiro.web.filter.captcha.CaptchaValidateFilter;
import com.ruoyi.framework.shiro.web.filter.kickout.KickoutSessionFilter;
@@ -266,7 +267,7 @@ public class ShiroConfig
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
- ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+ CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
// Shiro的核心安全接口,这个属性是必须的
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 身份认证失败,则跳转到登录页面的配置
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java
new file mode 100644
index 000000000..1d42bdf75
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/CustomShiroFilterFactoryBean.java
@@ -0,0 +1,85 @@
+package com.ruoyi.framework.shiro.web;
+
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.filter.InvalidRequestFilter;
+import org.apache.shiro.web.filter.mgt.DefaultFilter;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.apache.shiro.mgt.SecurityManager;
+import org.springframework.beans.factory.BeanInitializationException;
+import javax.servlet.Filter;
+import java.util.Map;
+
+/**
+ * 自定义ShiroFilterFactoryBean解决资源中文路径问题
+ *
+ * @author ruoyi
+ */
+public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean
+{
+ @Override
+ public Class getObjectType()
+ {
+ return MySpringShiroFilter.class;
+ }
+
+ @Override
+ protected AbstractShiroFilter createInstance() throws Exception
+ {
+
+ SecurityManager securityManager = getSecurityManager();
+ if (securityManager == null)
+ {
+ String msg = "SecurityManager property must be set.";
+ throw new BeanInitializationException(msg);
+ }
+
+ if (!(securityManager instanceof WebSecurityManager))
+ {
+ String msg = "The security manager does not implement the WebSecurityManager interface.";
+ throw new BeanInitializationException(msg);
+ }
+
+ FilterChainManager manager = createFilterChainManager();
+ // Expose the constructed FilterChainManager by first wrapping it in a
+ // FilterChainResolver implementation. The AbstractShiroFilter implementations
+ // do not know about FilterChainManagers - only resolvers:
+ PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
+ chainResolver.setFilterChainManager(manager);
+
+ Map filterMap = manager.getFilters();
+ Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
+ if (invalidRequestFilter instanceof InvalidRequestFilter)
+ {
+ // 此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
+ ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
+ }
+ // Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
+ // FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
+ // here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
+ // injection of the SecurityManager and FilterChainResolver:
+ return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
+ }
+
+ private static final class MySpringShiroFilter extends AbstractShiroFilter
+ {
+ protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver)
+ {
+ if (webSecurityManager == null)
+ {
+ throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
+ }
+ else
+ {
+ this.setSecurityManager(webSecurityManager);
+ if (resolver != null)
+ {
+ this.setFilterChainResolver(resolver);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
From 191dba93ee009d28c1ee7465601b8971b14adb3a Mon Sep 17 00:00:00 2001
From: sf_zhengweigang <931069949@qq.com>
Date: Fri, 25 Mar 2022 16:24:16 +0800
Subject: [PATCH 3/4] 1
---
.../main/java/com/ruoyi/system/controller/AttribController.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/AttribController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/AttribController.java
index e5ad860dd..d72c505f8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/AttribController.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/AttribController.java
@@ -110,7 +110,7 @@ public class AttribController extends BaseController
}
/**
- * 删除属性
+ * 删除属性1
*/
@RequiresPermissions("system:attrib:remove")
@Log(title = "属性", businessType = BusinessType.DELETE)
From e872d462842aaf3a5fb93f3aa6a87a7be971674f Mon Sep 17 00:00:00 2001
From: zhuobaoji <931069949@qq.com>
Date: Thu, 7 Apr 2022 02:52:45 +0000
Subject: [PATCH 4/4] =?UTF-8?q?!2=201=20*=20=E4=BF=AE=E5=A4=8DExcel?=
=?UTF-8?q?=E6=B3=A8=E8=A7=A3prompt/combo=E5=90=8C=E6=97=B6=E4=BD=BF?=
=?UTF-8?q?=E7=94=A8=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98=20*=20?=
=?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BC=93=E5=AD=98=E4=BF=A1=E6=81=AF=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E9=83=A8=E9=97=A8ancestors=E7=A5=96=E7=BA=A7=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=20*=20=E4=BF=AE=E5=A4=8DURL=E7=B1=BB=E5=9E=8B?=
=?UTF-8?q?=E5=9B=9E=E9=80=80=E9=94=AE=E8=A2=AB=E7=A6=81=E6=AD=A2=E9=97=AE?=
=?UTF-8?q?=E9=A2=98=20*=20=E4=BC=98=E5=8C=96=E8=8F=9C=E5=8D=95=E4=BE=A7?=
=?UTF-8?q?=E8=BE=B9=E6=A0=8F=E6=BB=9A=E5=8A=A8=E6=9D=A1=E5=B0=BA=E5=AF=B8?=
=?UTF-8?q?=E5=8F=8A=E9=A2=9C=E8=89=B2=20*=20=E5=8D=87=E7=BA=A7spring-boot?=
=?UTF-8?q?=E5=88=B0=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC2.5.12=20=E9=98=B2?=
=?UTF-8?q?=E6=AD=A2RCE=E6=BC=8F=E6=B4=9E=20*=20=E6=96=B0=E5=A2=9E?=
=?UTF-8?q?=E6=B8=85=E7=90=86=E5=88=86=E9=A1=B5=E7=9A=84=E7=BA=BF=E7=A8=8B?=
=?UTF-8?q?=E5=8F=98=E9=87=8F=E6=96=B9=E6=B3=95=20*=20=E5=8D=87=E7=BA=A7sp?=
=?UTF-8?q?ring-boot=E5=88=B0=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC2.5.11=20?=
=?UTF-8?q?*=20=E5=8D=87=E7=BA=A7fastjson=E5=88=B0=E6=9C=80=E6=96=B0?=
=?UTF-8?q?=E7=89=881.2.80=20*=20=E4=BC=98=E5=8C=96IP=E5=9C=B0=E5=9D=80?=
=?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=88=B0=E5=A4=9A=E4=B8=AA=E7=9A=84=E9=97=AE?=
=?UTF-8?q?=E9=A2=98=20*=20=E4=BC=98=E5=8C=96=E5=AF=BC=E5=87=BAexcel?=
=?UTF-8?q?=E5=8D=95=E5=85=83=E6=A0=BC=E9=AA=8C=E8=AF=81,=E5=8C=85?=
=?UTF-8?q?=E5=90=AB=E5=8F=98=E6=9B=B4=E4=B8=BA=E5=BC=80=E5=A4=B4.?=
=?UTF-8?q?=E9=98=B2=E6=AD=A2=E6=AD=A3=E5=B8=B8=E5=86=85=E5=AE=B9=E8=A2=AB?=
=?UTF-8?q?=E6=9B=BF=E6=8D=A2=20*=20=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=BE=A4?=
=?UTF-8?q?=E5=8F=B7=EF=BC=9A139845794=20*=20=E4=BF=AE=E5=A4=8D=E5=88=9D?=
=?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=A4=9A=E8=A1=A8=E6=A0=BC=E5=A4=84=E7=90=86?=
=?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=87=BD=E6=95=B0=E6=97=B6=E8=8E=B7=E5=8F=96?=
=?UTF-8?q?=E7=9A=84=E8=A1=A8=E6=A0=BC=E9=85=8D=E7=BD=AE=E4=B8=8D=E4=B8=80?=
=?UTF-8?q?=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=20*=20=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89ShiroFilterFactoryBean=E9=98=B2=E6=AD=A2?=
=?UTF-8?q?=E4=B8=AD=E6=96=87=E8=AF=B7=E6=B1=82=E8=A2=AB=E6=8B=A6=E6=88=AA?=
=?UTF-8?q?=20*=20=E4=BC=98=E5=8C=96=E5=AF=BC=E5=87=BA=E6=95=B0=E6=8D=AELo?=
=?UTF-8?q?calDateTime=E7=B1=BB=E5=9E=8B=E6=97=A0=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=20*=20=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E5=85=BC=E5=AE=B9Weblogic=E7=8E=AF=E5=A2=83=20*=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E5=AF=BC=E5=85=A5Excel=E6=97=B6=E5=AD=97=E5=85=B8?=
=?UTF-8?q?=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=B8=BALong=E8=BD=AC?=
=?UTF-8?q?=E4=B9=89=E4=B8=BA=E7=A9=BA=E9=97=AE=E9=A2=98=20*=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E8=A1=A8=E6=A0=BC=E6=89=93=E5=8D=B0=E7=BB=84=E4=BB=B6?=
=?UTF-8?q?=E4=B8=8D=E8=AF=86=E5=88=AB=E5=A4=9A=E5=B1=82=E5=AF=B9=E8=B1=A1?=
=?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=80=BC=E9=97=AE=E9=A2=98(I4V7YV)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 4 +-
.../slimscroll/jquery.slimscroll.min.js | 2 +-
.../main/resources/static/ruoyi/js/common.js | 2 +-
.../core/controller/BaseController.java | 8 ++
.../java/com/ruoyi/common/utils/IpUtils.java | 83 +++++++++++++++++--
.../com/ruoyi/common/utils/PageUtils.java | 8 ++
.../com/ruoyi/common/utils/poi/ExcelUtil.java | 60 ++++----------
.../resources/mapper/system/SysUserMapper.xml | 15 ++--
8 files changed, 122 insertions(+), 60 deletions(-)
diff --git a/pom.xml b/pom.xml
index e5c5df597..64fcd257b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
3.0.0
2.2.2
1.4.1
- 1.2.79
+ 1.2.80
6.1.2
5.10.0
2.11.0
@@ -44,7 +44,7 @@
org.springframework.boot
spring-boot-dependencies
- 2.5.10
+ 2.5.12
pom
import
diff --git a/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js b/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js
index 374e76982..1e684fbd8 100644
--- a/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js
+++ b/ruoyi-admin/src/main/resources/static/js/plugins/slimscroll/jquery.slimscroll.min.js
@@ -5,4 +5,4 @@
* Version: 1.3.8
*
*/
-(function($){$.fn.extend({slimScroll:function(options){var defaults={width:"auto",height:"250px",size:"2px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:false,disableFadeOut:false,railVisible:false,railColor:"#333",railOpacity:0.2,railDraggable:true,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:false,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"};var o=$.extend(defaults,options);this.each(function(){var isOverPanel,isOverBar,isDragg,queueHide,touchDif,barHeight,percentScroll,lastScroll,divS="",minBarHeight=30,releaseScroll=false;var me=$(this);if(me.parent().hasClass(o.wrapperClass)){var offset=me.scrollTop();bar=me.siblings("."+o.barClass);rail=me.siblings("."+o.railClass);getBarHeight();if($.isPlainObject(options)){if("height" in options&&options.height=="auto"){me.parent().css("height","auto");me.css("height","auto");var height=me.parent().parent().height();me.parent().css("height",height);me.css("height",height)}else{if("height" in options){var h=options.height;me.parent().css("height",h);me.css("height",h)}}if("scrollTo" in options){offset=parseInt(o.scrollTo)}else{if("scrollBy" in options){offset+=parseInt(o.scrollBy)}else{if("destroy" in options){bar.remove();rail.remove();me.unwrap();return}}}scrollContent(offset,false,true)}return}else{if($.isPlainObject(options)){if("destroy" in options){return}}}o.height=(o.height=="auto")?me.parent().height():o.height;var wrapper=$(divS).addClass(o.wrapperClass).css({position:"relative",width:o.width,height:o.height});me.css({width:o.width,height:o.height});var rail=$(divS).addClass(o.railClass).css({width:o.size,height:"100%",position:"absolute",top:0,display:(o.alwaysVisible&&o.railVisible)?"block":"none","border-radius":o.railBorderRadius,background:o.railColor,opacity:o.railOpacity,zIndex:90});var bar=$(divS).addClass(o.barClass).css({background:o.color,width:o.size,position:"absolute",top:0,opacity:o.opacity,display:o.alwaysVisible?"block":"none","border-radius":o.borderRadius,BorderRadius:o.borderRadius,MozBorderRadius:o.borderRadius,WebkitBorderRadius:o.borderRadius,zIndex:99});var posCss=(o.position=="right")?{right:o.distance}:{left:o.distance};rail.css(posCss);bar.css(posCss);me.wrap(wrapper);me.parent().append(bar);me.parent().append(rail);if(o.railDraggable){bar.bind("mousedown",function(e){var $doc=$(document);isDragg=true;t=parseFloat(bar.css("top"));pageY=e.pageY;$doc.bind("mousemove.slimscroll",function(e){currTop=t+e.pageY-pageY;bar.css("top",currTop);scrollContent(0,bar.position().top,false)});$doc.bind("mouseup.slimscroll",function(e){isDragg=false;hideBar();$doc.unbind(".slimscroll")});return false}).bind("selectstart.slimscroll",function(e){e.stopPropagation();e.preventDefault();return false})}rail.hover(function(){showBar()},function(){hideBar()});bar.hover(function(){isOverBar=true},function(){isOverBar=false});me.hover(function(){isOverPanel=true;showBar();hideBar()},function(){isOverPanel=false;hideBar()});me.bind("touchstart",function(e,b){if(e.originalEvent.touches.length){touchDif=e.originalEvent.touches[0].pageY}});me.bind("touchmove",function(e){if(!releaseScroll){e.originalEvent.preventDefault()}if(e.originalEvent.touches.length){var diff=(touchDif-e.originalEvent.touches[0].pageY)/o.touchScrollStep;scrollContent(diff,true);touchDif=e.originalEvent.touches[0].pageY}});getBarHeight();if(o.start==="bottom"){bar.css({top:me.outerHeight()-bar.outerHeight()});scrollContent(0,true)}else{if(o.start!=="top"){scrollContent($(o.start).position().top,null,true);if(!o.alwaysVisible){bar.hide()}}}attachWheel(this);function _onWheel(e){if(!isOverPanel){return}var e=e||window.event;var delta=0;if(e.wheelDelta){delta=-e.wheelDelta/120}if(e.detail){delta=e.detail/3}var target=e.target||e.srcTarget||e.srcElement;if($(target).closest("."+o.wrapperClass).is(me.parent())){scrollContent(delta,true)}if(e.preventDefault&&!releaseScroll){e.preventDefault()}if(!releaseScroll){e.returnValue=false}}function scrollContent(y,isWheel,isJump){releaseScroll=false;var delta=y;var maxTop=me.outerHeight()-bar.outerHeight();if(isWheel){delta=parseInt(bar.css("top"))+y*parseInt(o.wheelStep)/100*bar.outerHeight();delta=Math.min(Math.max(delta,0),maxTop);delta=(y>0)?Math.ceil(delta):Math.floor(delta);bar.css({top:delta+"px"})}percentScroll=parseInt(bar.css("top"))/(me.outerHeight()-bar.outerHeight());delta=percentScroll*(me[0].scrollHeight-me.outerHeight());if(isJump){delta=y;var offsetTop=delta/me[0].scrollHeight*me.outerHeight();offsetTop=Math.min(Math.max(offsetTop,0),maxTop);bar.css({top:offsetTop+"px"})}me.scrollTop(delta);me.trigger("slimscrolling",~~delta);showBar();hideBar()}function attachWheel(target){if(window.addEventListener){target.addEventListener("DOMMouseScroll",_onWheel,{capture:false,passive:false});target.addEventListener("mousewheel",_onWheel,{capture:false,passive:false})}else{document.attachEvent("onmousewheel",_onWheel)}}function getBarHeight(){barHeight=Math.max((me.outerHeight()/me[0].scrollHeight)*me.outerHeight(),minBarHeight);bar.css({height:barHeight+"px"});var display=barHeight==me.outerHeight()?"none":"block";bar.css({display:display})}function showBar(){getBarHeight();clearTimeout(queueHide);if(percentScroll==~~percentScroll){releaseScroll=o.allowPageScroll;if(lastScroll!=percentScroll){var msg=(~~percentScroll==0)?"top":"bottom";me.trigger("slimscroll",msg)}}else{releaseScroll=false}lastScroll=percentScroll;if(barHeight>=me.outerHeight()){releaseScroll=true;return}bar.stop(true,true).fadeIn("fast");if(o.railVisible){rail.stop(true,true).fadeIn("fast")}}function hideBar(){if(!o.alwaysVisible){queueHide=setTimeout(function(){if(!(o.disableFadeOut&&isOverPanel)&&!isOverBar&&!isDragg){bar.fadeOut("slow");rail.fadeOut("slow")}},1000)}}});return this}});$.fn.extend({slimscroll:$.fn.slimScroll})})(jQuery);
\ No newline at end of file
+(function($){$.fn.extend({slimScroll:function(options){var defaults={width:"auto",height:"250px",size:"5px",color:"#99a9bf",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:false,disableFadeOut:false,railVisible:false,railColor:"#333",railOpacity:0.2,railDraggable:true,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:false,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"};var o=$.extend(defaults,options);this.each(function(){var isOverPanel,isOverBar,isDragg,queueHide,touchDif,barHeight,percentScroll,lastScroll,divS="",minBarHeight=30,releaseScroll=false;var me=$(this);if(me.parent().hasClass(o.wrapperClass)){var offset=me.scrollTop();bar=me.siblings("."+o.barClass);rail=me.siblings("."+o.railClass);getBarHeight();if($.isPlainObject(options)){if("height" in options&&options.height=="auto"){me.parent().css("height","auto");me.css("height","auto");var height=me.parent().parent().height();me.parent().css("height",height);me.css("height",height)}else{if("height" in options){var h=options.height;me.parent().css("height",h);me.css("height",h)}}if("scrollTo" in options){offset=parseInt(o.scrollTo)}else{if("scrollBy" in options){offset+=parseInt(o.scrollBy)}else{if("destroy" in options){bar.remove();rail.remove();me.unwrap();return}}}scrollContent(offset,false,true)}return}else{if($.isPlainObject(options)){if("destroy" in options){return}}}o.height=(o.height=="auto")?me.parent().height():o.height;var wrapper=$(divS).addClass(o.wrapperClass).css({position:"relative",width:o.width,height:o.height});me.css({width:o.width,height:o.height});var rail=$(divS).addClass(o.railClass).css({width:o.size,height:"100%",position:"absolute",top:0,display:(o.alwaysVisible&&o.railVisible)?"block":"none","border-radius":o.railBorderRadius,background:o.railColor,opacity:o.railOpacity,zIndex:90});var bar=$(divS).addClass(o.barClass).css({background:o.color,width:o.size,position:"absolute",top:0,opacity:o.opacity,display:o.alwaysVisible?"block":"none","border-radius":o.borderRadius,BorderRadius:o.borderRadius,MozBorderRadius:o.borderRadius,WebkitBorderRadius:o.borderRadius,zIndex:99});var posCss=(o.position=="right")?{right:o.distance}:{left:o.distance};rail.css(posCss);bar.css(posCss);me.wrap(wrapper);me.parent().append(bar);me.parent().append(rail);if(o.railDraggable){bar.bind("mousedown",function(e){var $doc=$(document);isDragg=true;t=parseFloat(bar.css("top"));pageY=e.pageY;$doc.bind("mousemove.slimscroll",function(e){currTop=t+e.pageY-pageY;bar.css("top",currTop);scrollContent(0,bar.position().top,false)});$doc.bind("mouseup.slimscroll",function(e){isDragg=false;hideBar();$doc.unbind(".slimscroll")});return false}).bind("selectstart.slimscroll",function(e){e.stopPropagation();e.preventDefault();return false})}rail.hover(function(){showBar()},function(){hideBar()});bar.hover(function(){isOverBar=true},function(){isOverBar=false});me.hover(function(){isOverPanel=true;showBar();hideBar()},function(){isOverPanel=false;hideBar()});me.bind("touchstart",function(e,b){if(e.originalEvent.touches.length){touchDif=e.originalEvent.touches[0].pageY}});me.bind("touchmove",function(e){if(!releaseScroll){e.originalEvent.preventDefault()}if(e.originalEvent.touches.length){var diff=(touchDif-e.originalEvent.touches[0].pageY)/o.touchScrollStep;scrollContent(diff,true);touchDif=e.originalEvent.touches[0].pageY}});getBarHeight();if(o.start==="bottom"){bar.css({top:me.outerHeight()-bar.outerHeight()});scrollContent(0,true)}else{if(o.start!=="top"){scrollContent($(o.start).position().top,null,true);if(!o.alwaysVisible){bar.hide()}}}attachWheel(this);function _onWheel(e){if(!isOverPanel){return}var e=e||window.event;var delta=0;if(e.wheelDelta){delta=-e.wheelDelta/120}if(e.detail){delta=e.detail/3}var target=e.target||e.srcTarget||e.srcElement;if($(target).closest("."+o.wrapperClass).is(me.parent())){scrollContent(delta,true)}if(e.preventDefault&&!releaseScroll){e.preventDefault()}if(!releaseScroll){e.returnValue=false}}function scrollContent(y,isWheel,isJump){releaseScroll=false;var delta=y;var maxTop=me.outerHeight()-bar.outerHeight();if(isWheel){delta=parseInt(bar.css("top"))+y*parseInt(o.wheelStep)/100*bar.outerHeight();delta=Math.min(Math.max(delta,0),maxTop);delta=(y>0)?Math.ceil(delta):Math.floor(delta);bar.css({top:delta+"px"})}percentScroll=parseInt(bar.css("top"))/(me.outerHeight()-bar.outerHeight());delta=percentScroll*(me[0].scrollHeight-me.outerHeight());if(isJump){delta=y;var offsetTop=delta/me[0].scrollHeight*me.outerHeight();offsetTop=Math.min(Math.max(offsetTop,0),maxTop);bar.css({top:offsetTop+"px"})}me.scrollTop(delta);me.trigger("slimscrolling",~~delta);showBar();hideBar()}function attachWheel(target){if(window.addEventListener){target.addEventListener("DOMMouseScroll",_onWheel,{capture:false,passive:false});target.addEventListener("mousewheel",_onWheel,{capture:false,passive:false})}else{document.attachEvent("onmousewheel",_onWheel)}}function getBarHeight(){barHeight=Math.max((me.outerHeight()/me[0].scrollHeight)*me.outerHeight(),minBarHeight);bar.css({height:barHeight+"px"});var display=barHeight==me.outerHeight()?"none":"block";bar.css({display:display})}function showBar(){getBarHeight();clearTimeout(queueHide);if(percentScroll==~~percentScroll){releaseScroll=o.allowPageScroll;if(lastScroll!=percentScroll){var msg=(~~percentScroll==0)?"top":"bottom";me.trigger("slimscroll",msg)}}else{releaseScroll=false}lastScroll=percentScroll;if(barHeight>=me.outerHeight()){releaseScroll=true;return}bar.stop(true,true).fadeIn("fast");if(o.railVisible){rail.stop(true,true).fadeIn("fast")}}function hideBar(){if(!o.alwaysVisible){queueHide=setTimeout(function(){if(!(o.disableFadeOut&&isOverPanel)&&!isOverBar&&!isDragg){bar.fadeOut("slow");rail.fadeOut("slow")}},1000)}}});return this}});$.fn.extend({slimscroll:$.fn.slimScroll})})(jQuery);
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js b/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js
index 068084724..ada827974 100644
--- a/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js
+++ b/ruoyi-admin/src/main/resources/static/ruoyi/js/common.js
@@ -511,7 +511,7 @@ window.onload = function() {
return _stopIt(event);
}
var type_e = elem.type.toUpperCase();
- if (name == 'INPUT' && (type_e != 'TEXT' && type_e != 'TEXTAREA' && type_e != 'PASSWORD' && type_e != 'FILE' && type_e != 'SEARCH' && type_e != 'NUMBER' && type_e != 'EMAIL')) {
+ if (name == 'INPUT' && (type_e != 'TEXT' && type_e != 'TEXTAREA' && type_e != 'PASSWORD' && type_e != 'FILE' && type_e != 'SEARCH' && type_e != 'NUMBER' && type_e != 'EMAIL' && type_e != 'URL')) {
return _stopIt(event);
}
if (name == 'INPUT' && (elem.readOnly == true || elem.disabled == true)) {
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
index aa08bd2e9..c2985040a 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
@@ -72,6 +72,14 @@ public class BaseController
}
}
+ /**
+ * 清理分页的线程变量
+ */
+ protected void clearPage()
+ {
+ PageUtils.clearPage();
+ }
+
/**
* 获取request
*/
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java
index d699215a2..5b3baa002 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/IpUtils.java
@@ -11,6 +11,12 @@ import javax.servlet.http.HttpServletRequest;
*/
public class IpUtils
{
+ /**
+ * 获取客户端IP
+ *
+ * @param request 请求对象
+ * @return IP地址
+ */
public static String getIpAddr(HttpServletRequest request)
{
if (request == null)
@@ -40,15 +46,27 @@ public class IpUtils
ip = request.getRemoteAddr();
}
- return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+ return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
}
+ /**
+ * 检查是否为内部IP地址
+ *
+ * @param ip IP地址
+ * @return 结果
+ */
public static boolean internalIp(String ip)
{
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
+ /**
+ * 检查是否为内部IP地址
+ *
+ * @param addr byte地址
+ * @return 结果
+ */
private static boolean internalIp(byte[] addr)
{
if (StringUtils.isNull(addr) || addr.length < 2)
@@ -109,7 +127,8 @@ public class IpUtils
{
case 1:
l = Long.parseLong(elements[0]);
- if ((l < 0L) || (l > 4294967295L)) {
+ if ((l < 0L) || (l > 4294967295L))
+ {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
@@ -119,12 +138,14 @@ public class IpUtils
break;
case 2:
l = Integer.parseInt(elements[0]);
- if ((l < 0L) || (l > 255L)) {
+ if ((l < 0L) || (l > 255L))
+ {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
- if ((l < 0L) || (l > 16777215L)) {
+ if ((l < 0L) || (l > 16777215L))
+ {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
@@ -135,13 +156,15 @@ public class IpUtils
for (i = 0; i < 2; ++i)
{
l = Integer.parseInt(elements[i]);
- if ((l < 0L) || (l > 255L)) {
+ if ((l < 0L) || (l > 255L))
+ {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
- if ((l < 0L) || (l > 65535L)) {
+ if ((l < 0L) || (l > 65535L))
+ {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
@@ -151,7 +174,8 @@ public class IpUtils
for (i = 0; i < 4; ++i)
{
l = Integer.parseInt(elements[i]);
- if ((l < 0L) || (l > 255L)) {
+ if ((l < 0L) || (l > 255L))
+ {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
@@ -168,6 +192,11 @@ public class IpUtils
return bytes;
}
+ /**
+ * 获取IP地址
+ *
+ * @return 本地IP地址
+ */
public static String getHostIp()
{
try
@@ -180,6 +209,11 @@ public class IpUtils
return "127.0.0.1";
}
+ /**
+ * 获取主机名
+ *
+ * @return 本地主机名
+ */
public static String getHostName()
{
try
@@ -191,4 +225,39 @@ public class IpUtils
}
return "未知";
}
+
+ /**
+ * 从多级反向代理中获得第一个非unknown IP地址
+ *
+ * @param ip 获得的IP地址
+ * @return 第一个非unknown IP地址
+ */
+ public static String getMultistageReverseProxyIp(String ip)
+ {
+ // 多级反向代理检测
+ if (ip != null && ip.indexOf(",") > 0)
+ {
+ final String[] ips = ip.trim().split(",");
+ for (String subIp : ips)
+ {
+ if (false == isUnknown(subIp))
+ {
+ ip = subIp;
+ break;
+ }
+ }
+ }
+ return ip;
+ }
+
+ /**
+ * 检测给定字符串是否为未知,多用于检测HTTP请求相关
+ *
+ * @param checkString 被检测的字符串
+ * @return 是否未知
+ */
+ public static boolean isUnknown(String checkString)
+ {
+ return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
+ }
}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
index 7db37a2fe..0585396c9 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
@@ -27,4 +27,12 @@ public class PageUtils extends PageHelper
PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
}
}
+
+ /**
+ * 清理分页的线程变量
+ */
+ public static void clearPage()
+ {
+ PageHelper.clearPage();
+ }
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index d5329b2aa..c6669fb7f 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -22,6 +22,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.RegExUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
@@ -88,6 +89,8 @@ public class ExcelUtil
{
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+ public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
+
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
/**
@@ -714,9 +717,9 @@ public class ExcelUtil
{
String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
- if (StringUtils.containsAny(cellValue, FORMULA_STR))
+ if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
{
- cellValue = StringUtils.replaceEach(cellValue, FORMULA_STR, new String[] { "\t=", "\t-", "\t+", "\t@" });
+ cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
}
cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
}
@@ -783,17 +786,10 @@ public class ExcelUtil
// 设置列宽
sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
}
- // 如果设置了提示信息则鼠标放上去提示.
- if (StringUtils.isNotEmpty(attr.prompt()))
+ if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0)
{
- // 这里默认设了2-101列提示.
- setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
- }
- // 如果设置了combo属性则本列只能选择不能输入
- if (attr.combo().length > 0)
- {
- // 这里默认设了2-101列只能选择不能输入.
- setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
+ // 提示信息或只能选择不能输入的列内容.
+ setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column);
}
}
@@ -857,48 +853,29 @@ public class ExcelUtil
}
/**
- * 设置 POI XSSFSheet 单元格提示
+ * 设置 POI XSSFSheet 单元格提示或选择框
*
* @param sheet 表单
- * @param promptTitle 提示标题
+ * @param textlist 下拉框显示的内容
* @param promptContent 提示内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
*/
- public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
+ public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
int firstCol, int endCol)
{
DataValidationHelper helper = sheet.getDataValidationHelper();
- DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
+ DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
DataValidation dataValidation = helper.createValidation(constraint, regions);
- dataValidation.createPromptBox(promptTitle, promptContent);
- dataValidation.setShowPromptBox(true);
- sheet.addValidationData(dataValidation);
- }
-
- /**
- * 设置某些列的值只能输入预制的数据,显示下拉框.
- *
- * @param sheet 要设置的sheet.
- * @param textlist 下拉框显示的内容
- * @param firstRow 开始行
- * @param endRow 结束行
- * @param firstCol 开始列
- * @param endCol 结束列
- * @return 设置好的sheet.
- */
- public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol)
- {
- DataValidationHelper helper = sheet.getDataValidationHelper();
- // 加载下拉列表内容
- DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
- // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
- CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
- // 数据有效性对象
- DataValidation dataValidation = helper.createValidation(constraint, regions);
+ if (StringUtils.isNotEmpty(promptContent))
+ {
+ // 如果设置了提示信息则鼠标放上去提示
+ dataValidation.createPromptBox("", promptContent);
+ dataValidation.setShowPromptBox(true);
+ }
// 处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation)
{
@@ -909,7 +886,6 @@ public class ExcelUtil
{
dataValidation.setSuppressDropDownArrow(false);
}
-
sheet.addValidationData(dataValidation);
}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 3df50dd86..e322bd66c 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -31,12 +31,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -50,7 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select u.user_id, u.dept_id, u.login_name, u.user_name, u.user_type, u.email, u.avatar, u.phonenumber, u.sex, u.password, u.salt, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_time, u.remark,
- d.dept_id, d.parent_id, d.dept_name, d.order_num, d.leader, d.status as dept_status,
+ d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id