diff --git a/common/src/main/java/com/jeesite/common/lang/TimeUtils.java b/common/src/main/java/com/jeesite/common/lang/TimeUtils.java index 06d3ea6e..e93addbe 100644 --- a/common/src/main/java/com/jeesite/common/lang/TimeUtils.java +++ b/common/src/main/java/com/jeesite/common/lang/TimeUtils.java @@ -26,7 +26,7 @@ public class TimeUtils { long minute = (ms - day * dd - hour * hh) / mi; long second = (ms - day * dd - hour * hh - minute * mi) / ss; StringBuilder sb = new StringBuilder(); - if (ms < 1000) { + if (ms >= 0 && ms < 1000) { sb.append(ms).append("毫秒"); } else { if (day > 0) { diff --git a/common/src/main/java/com/jeesite/common/mapper/JsonMapper.java b/common/src/main/java/com/jeesite/common/mapper/JsonMapper.java index 39862987..af9b035e 100644 --- a/common/src/main/java/com/jeesite/common/mapper/JsonMapper.java +++ b/common/src/main/java/com/jeesite/common/mapper/JsonMapper.java @@ -164,7 +164,7 @@ public class JsonMapper extends ObjectMapper { /** * 当JSON里只含有Bean的部分属性時,更新一个已存在Bean,只覆盖该部分的属性. */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "hiding" }) public T update(String jsonString, T object) { try { return (T) this.readerForUpdating(object).readValue(jsonString); diff --git a/common/src/main/resources/static/adminlte/css/skins/skin-blue-light2.css b/common/src/main/resources/static/adminlte/css/skins/skin-blue-light2.css index 67e0909e..79449677 100644 --- a/common/src/main/resources/static/adminlte/css/skins/skin-blue-light2.css +++ b/common/src/main/resources/static/adminlte/css/skins/skin-blue-light2.css @@ -193,4 +193,10 @@ th[aria-selected=true] .ui-jqgrid-sortable {color:#1890ff;} .box-main>.box-header .box-title .fa {color:#1890ff;} .form-control:focus,.select2-container--default.select2-container--focus .select2-selection--multiple, .select2-container--default .select2-search--dropdown .select2-search__field {border-color:#66afe9!important;} +.table thead tr, .ui-jqgrid-htable thead tr, .ui-jqgrid-hdiv, .ui-jqgrid-hbox {background-color:#f6f6f6;} +.ui-jqgrid .ui-jqgrid-labels th, .ui-jqgrid tr.ui-row-ltr td, .ui-jqgrid tr.ui-row-rtl td {border-color: #eaeaea;} +.ui-state-hover td, .ui-widget-content .ui-state-hover td, .ui-widget-header .ui-state-hover td, +.ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {background:#f5f5f5;} +.ui-jqgrid tr.ui-state-highlight.ui-row-ltr td {background-color:#e5f3ff;} .ui-jqgrid tr.ui-row-ltr td {border-right:0!important;} +.ui-jqgrid tr.ui-row-ltr td:last-child {border-right:1px solid #eaeaea!important;} diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java b/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java index c92e00f4..cbc07bc2 100644 --- a/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java +++ b/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java @@ -114,6 +114,7 @@ public class CasAuthorizingRealm extends BaseAuthorizingRealm { // 获取CAS传递过来的用户属性信息 user = new User(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("userCode")))); user.setLoginCode(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("loginCode")))); + user.setCorpCode_(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("corpCode")))); user.setPassword(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("password")))); user.setUserName(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("userName")))); user.setEmail(EncodeUtils.decodeUrl(ObjectUtils.toString(attrs.get("email")))); @@ -145,7 +146,7 @@ public class CasAuthorizingRealm extends BaseAuthorizingRealm { } // 重新获取用户登录 - user = UserUtils.getByLoginCode(token.getUsername()/*, corpCode*/); + user = UserUtils.getByLoginCode(token.getUsername(), user.getCorpCode_()); if (user != null) { return user; } diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/db/InitCoreData.xlsx b/modules/core/src/main/java/com/jeesite/modules/sys/db/InitCoreData.xlsx index 63a7c1e8..77d60978 100644 Binary files a/modules/core/src/main/java/com/jeesite/modules/sys/db/InitCoreData.xlsx and b/modules/core/src/main/java/com/jeesite/modules/sys/db/InitCoreData.xlsx differ diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/interceptor/LogInterceptor.java b/modules/core/src/main/java/com/jeesite/modules/sys/interceptor/LogInterceptor.java index 93734af7..43b46fd1 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/interceptor/LogInterceptor.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/interceptor/LogInterceptor.java @@ -15,6 +15,7 @@ import org.springframework.web.servlet.ModelAndView; import com.jeesite.common.lang.ByteUtils; import com.jeesite.common.lang.DateUtils; import com.jeesite.common.lang.TimeUtils; +import com.jeesite.common.network.IpUtils; import com.jeesite.common.service.BaseService; import com.jeesite.modules.sys.utils.LogUtils; import com.jeesite.modules.sys.utils.UserUtils; @@ -35,8 +36,8 @@ public class LogInterceptor extends BaseService implements HandlerInterceptor { long beginTime = System.currentTimeMillis();// 1、开始时间 startTimeThreadLocal.set(beginTime); // 线程绑定变量(该数据只有当前请求的线程可见) if (logger.isDebugEnabled()){ - logger.debug("开始计时: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS") - .format(beginTime), request.getRequestURI()); + logger.debug("开始计时: {} URI: {} IP: {}", new SimpleDateFormat("hh:mm:ss.SSS") + .format(beginTime), request.getRequestURI(), IpUtils.getRemoteAddr(request)); } return true; } diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java index 672ea993..6b4c5374 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java @@ -161,7 +161,8 @@ public class LoginController extends BaseController{ // 非授权异常,登录失败,验证码加1。 if (!UnauthorizedException.class.getName().equals(exception)){ - model.addAttribute("isValidCodeLogin", BaseAuthorizingRealm.isValidCodeLogin(username, (String)paramMap.get("deviceType"), "failed")); + model.addAttribute("isValidCodeLogin", BaseAuthorizingRealm.isValidCodeLogin(username, + (String)paramMap.get("corpCode"), (String)paramMap.get("deviceType"), "failed")); } //获取当前会话对象 diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java index 4b1d7053..5a5c6cca 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java @@ -112,21 +112,25 @@ public class OnlineController extends BaseController{ list.add(map); } // 本地排序 - if (StringUtils.isNotBlank(orderBy)){ - final String[] ss = orderBy.trim().split(" "); - if (ss != null && ss.length == 2){ - Collections.sort(list, new Comparator>() { - @Override - public int compare(Map o1, Map o2) { - String s1 = (String)o1.get(ss[0]); - String s2 = (String)o2.get(ss[0]); - if ("asc".equals(ss[1])){ - return s1.compareTo(s2); - }else{ - return s2.compareTo(s1); - } - }}); - } + if (StringUtils.isBlank(orderBy)){ + orderBy = "lastAccessTime desc"; + } + final String[] ss = orderBy.trim().split(" "); + if (ss != null && ss.length == 2){ + Collections.sort(list, new Comparator>() { + @Override + public int compare(Map o1, Map o2) { + String s1 = (String)o1.get(ss[0]); + String s2 = (String)o2.get(ss[0]); + if (s1 == null || s2 == null){ + return -1; + } + if ("asc".equals(ss[1])){ + return s1.compareTo(s2); + }else{ + return s2.compareTo(s1); + } + }}); } return list; } diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/CorpAdminController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/CorpAdminController.java index fe963e52..095f833c 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/CorpAdminController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/CorpAdminController.java @@ -114,7 +114,7 @@ public class CorpAdminController extends BaseController { if (StringUtils.isBlank(user.getCorpCode_())){ return renderResult(Global.FALSE, "租户代码不能为空!"); } - if (!Global.TRUE.equals(userService.checkLoginCode(oldLoginCode, user.getLoginCode()/*, user.getCorpCode_()*/))) { + if (!Global.TRUE.equals(userService.checkLoginCode(oldLoginCode, user.getLoginCode()))) { return renderResult(Global.FALSE, "保存用户'" + user.getLoginCode() + "'失败,登录账号已存在"); } if (user.getIsNewRecord()){ @@ -237,7 +237,7 @@ public class CorpAdminController extends BaseController { * @param isShowCode 是否显示编码(true or 1:显示在左侧;2:显示在右侧;false or null:不显示) * @return */ - @RequiresPermissions("user") + //@RequiresPermissions("user") // 注释掉,允许配置URI控制权限 @RequestMapping(value = "treeData") @ResponseBody public List> treeData(String pId, String isShowCode) { diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java index 90229993..a0d262f7 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/user/EmpUserController.java @@ -155,7 +155,7 @@ public class EmpUserController extends BaseController { if (!EmpUser.USER_TYPE_EMPLOYEE.equals(empUser.getUserType())){ return renderResult(Global.FALSE, "非法操作,不能够操作此用户!"); } - if (!Global.TRUE.equals(userService.checkLoginCode(oldLoginCode, empUser.getLoginCode()/*, null*/))) { + if (!Global.TRUE.equals(userService.checkLoginCode(oldLoginCode, empUser.getLoginCode()))) { return renderResult(Global.FALSE, text("保存用户失败,登录账号''{0}''已存在", empUser.getLoginCode())); } if (StringUtils.inString(op, Global.OP_ADD, Global.OP_EDIT) diff --git a/modules/core/src/main/resources/config/jeesite-core.yml b/modules/core/src/main/resources/config/jeesite-core.yml index e5aa7134..7e80bd03 100644 --- a/modules/core/src/main/resources/config/jeesite-core.yml +++ b/modules/core/src/main/resources/config/jeesite-core.yml @@ -162,6 +162,9 @@ user: # 多租户模式(SAAS模式)(专业版) useCorpModel: false + # 登录账号是否租户内唯一,否则全局唯一 + loginCodeCorpUnique: false + # 自助账号服务 account: # 注册用户 @@ -176,7 +179,7 @@ role: { 3: { Office: { - #控制类型的类名 : "用来获取控制表名和主键,如果为 NONE,则代表是不控制该类型权限;", + #控制类型的类名 : "用来获取控制表名和主键字段名,如果为 NONE,则代表是不控制该类型权限", ctrlTypeClass: "com.jeesite.modules.sys.entity.Office", #控制数据的类名: "指定一个静态类名,方便 ctrlDataAttrName 得到权限数据,如:当前部门编码、公司编码", ctrlDataClass: "com.jeesite.modules.sys.utils.EmpUtils", @@ -276,6 +279,9 @@ job: # 代码生成 gen: enabled: true + + # 表名字段名是否强制小写 + forceLowerCase: true # 系统监控 state: @@ -375,6 +381,7 @@ shiro: # ${adminPath}/cms/category/* = anon # ${adminPath}/cms/article/* = anon # ${adminPath}/cms/link/* = anon +# ${adminPath}/sys/corpAdmin/treeData = anon # ${adminPath}/** = user filterChainDefinitions: | /ReportServer/** = user @@ -415,6 +422,7 @@ session: # 会话唯一标识SessionId在Cookie中的名称。 sessionIdCookieName: jeesite.session.id + #sessionIdCookiePath: ${server.servlet.context-path} # 共享的SessionId的Cookie名称,保存到跟路径下,第三方应用获取。同一域名下多个项目时需设置共享Cookie的名称。 #shareSessionIdCookieName: ${session.sessionIdCookieName} @@ -560,7 +568,7 @@ video: # 消息提醒中心(专业版) msg: - enabled: true + enabled: false # 是否开启实时发送消息(保存消息后立即检查未读消息并发送),分布式部署下请单独配置消息发送服务,不建议开启此选项。 realtime: diff --git a/modules/core/src/main/resources/templates/modules/gen/crud/entity.xml b/modules/core/src/main/resources/templates/modules/gen/crud/entity.xml index ba1476f9..129b60e7 100644 --- a/modules/core/src/main/resources/templates/modules/gen/crud/entity.xml +++ b/modules/core/src/main/resources/templates/modules/gen/crud/entity.xml @@ -173,7 +173,7 @@ public class ${ClassName} extends ${table.isTreeEntity?'Tree':'Data'}Entity<${Cl } } // 如果不是基类属性 - else if(c.columnName != 'id' && !c.isSuperColumn){ + else if(!@StringUtils.equalsIgnoreCase(c.columnName, 'id') && !c.isSuperColumn){ // 父类对象 if(table.parentExists && table.parentTableFkName == c.columnName){ %> @@ -268,7 +268,7 @@ public class ${ClassName} extends ${table.isTreeEntity?'Tree':'Data'}Entity<${Cl <% } // 如果不是基类属性 - }else if(c.columnName != 'id' && !c.isSuperColumn){ + }else if(!@StringUtils.equalsIgnoreCase(c.columnName, 'id') && !c.isSuperColumn){ %> <% diff --git a/modules/core/src/main/resources/templates/modules/gen/crud/viewForm.xml b/modules/core/src/main/resources/templates/modules/gen/crud/viewForm.xml index cc91d32c..e6d59afd 100644 --- a/modules/core/src/main/resources/templates/modules/gen/crud/viewForm.xml +++ b/modules/core/src/main/resources/templates/modules/gen/crud/viewForm.xml @@ -19,7 +19,7 @@
- \${text(${className}.isNewRecord ? '新增${functionNameSimple}' : '编辑${functionNameSimple}')} + \${text(${className}.isNewRecord ? '新增${functionNameSimple}' : '编辑${functionNameSimple}')}
diff --git a/modules/core/src/main/resources/templates/modules/gen/crud/viewList.xml b/modules/core/src/main/resources/templates/modules/gen/crud/viewList.xml index 8eff60ab..f3d969ee 100644 --- a/modules/core/src/main/resources/templates/modules/gen/crud/viewList.xml +++ b/modules/core/src/main/resources/templates/modules/gen/crud/viewList.xml @@ -10,7 +10,7 @@
- \${text('${functionNameSimple}管理')} + \${text('${functionNameSimple}管理')}
\${text('查询')} diff --git a/modules/core/src/main/resources/templates/modules/gen/include/formControl.html b/modules/core/src/main/resources/templates/modules/gen/include/formControl.html index 6afbe842..9562b037 100644 --- a/modules/core/src/main/resources/templates/modules/gen/include/formControl.html +++ b/modules/core/src/main/resources/templates/modules/gen/include/formControl.html @@ -3,7 +3,7 @@ for (c in table.columnList){ if (c.isEdit == '1'){ // 如果是树结构的字段,则自动忽略 - if(table.isTreeEntity && @StringUtils.inString(c.columnName, 'parent_code', + if(table.isTreeEntity && @StringUtils.inStringIgnoreCase(c.columnName, 'parent_code', 'parent_codes', 'tree_sorts', 'tree_leaf', 'tree_level', 'tree_names')){ } // 如果是隐藏域 @@ -41,7 +41,7 @@ isNewLine = true; } // 如果是扩展字段,则输出子标题,并且强制换行 - if (c.columnName == 'extend_s1'){ + if (@StringUtils.equalsIgnoreCase(c.columnName, 'extend_s1')){ isNewLine = true; } // 如果是第一个控件 @@ -57,7 +57,7 @@ <% } // 如果是扩展字段,则输出子标题,并且强制换行 - if (c.columnName == 'extend_s1'){ + if (@StringUtils.equalsIgnoreCase(c.columnName, 'extend_s1')){ %>
\${text('扩展字段')}
<% diff --git a/modules/core/src/main/resources/templates/modules/gen/query/viewForm.xml b/modules/core/src/main/resources/templates/modules/gen/query/viewForm.xml index 1837fb07..f986a9a9 100644 --- a/modules/core/src/main/resources/templates/modules/gen/query/viewForm.xml +++ b/modules/core/src/main/resources/templates/modules/gen/query/viewForm.xml @@ -19,7 +19,7 @@
- \${text(${className}.isNewRecord ? '新增${functionNameSimple}' : '详情${functionNameSimple}')} + \${text(${className}.isNewRecord ? '新增${functionNameSimple}' : '详情${functionNameSimple}')}
diff --git a/modules/core/src/main/resources/templates/modules/gen/query/viewList.xml b/modules/core/src/main/resources/templates/modules/gen/query/viewList.xml index 6a59092e..0bee5603 100644 --- a/modules/core/src/main/resources/templates/modules/gen/query/viewList.xml +++ b/modules/core/src/main/resources/templates/modules/gen/query/viewList.xml @@ -10,7 +10,7 @@
- \${text('${functionNameSimple}查询')} + \${text('${functionNameSimple}查询')}
\${text('查询')} diff --git a/modules/core/src/main/resources/views/modules/sys/onlineList.html b/modules/core/src/main/resources/views/modules/sys/onlineList.html index 570cce7b..472fdfd3 100644 --- a/modules/core/src/main/resources/views/modules/sys/onlineList.html +++ b/modules/core/src/main/resources/views/modules/sys/onlineList.html @@ -28,7 +28,7 @@
- <#form:checkbox name="isVisitor" value="false" label="查询游客用户" + <#form:checkbox name="isVisitor" value="false" label="包含游客用户" class="form-control"/>
@@ -50,8 +50,8 @@ $('#dataGrid').dataGrid({ {header:'用户名称', name:'userName', index:'a.create_by_name', width:100, align:"center", formatter: function(val, obj, row, act){ return ''+(val||'游客'); }}, - {header:'创建时间', name:'startTimestamp', width:100, align:'center'}, - {header:'最后访问', name:'lastAccessTime', width:100, align:'center'}, + {header:'创建时间', name:'startTimestamp', firstsortorder:'desc', width:100, align:'center'}, + {header:'最后访问', name:'lastAccessTime', firstsortorder:'desc', width:100, align:'center'}, {header:'超时时间', name:'timeout', width:100, align:'center'}, {header:'客户主机', name:'host', width:70, align:'center'}, {header:'用户类型', name:'userType', width:50, align:'center', formatter: function(val, obj, row, act){ diff --git a/modules/core/src/main/resources/views/modules/sys/sysDesktop.html b/modules/core/src/main/resources/views/modules/sys/sysDesktop.html index 8f64fd27..0170cf90 100644 --- a/modules/core/src/main/resources/views/modules/sys/sysDesktop.html +++ b/modules/core/src/main/resources/views/modules/sys/sysDesktop.html @@ -254,9 +254,7 @@ 2:15 ThinkGem - I would like to meet you to discuss the latest news about - the arrival of the new theme. They say it is going to be one the - best themes on the market + JeeSite 自发布以来被用到了企业、政府、医疗、金融、互联网等各个领域中, JeeSite 的设计思想和开发模式已深入开发者的内心, 当前版本 JeeSite 团队结合了以往的经验和总结各方面的应用案例, 对架构做一次全部重构,也纳入非常多的新思想。

@@ -269,9 +267,7 @@ 5:15 ThinkGem - I would like to meet you to discuss the latest news about - the arrival of the new theme. They say it is going to be one the - best themes on the market + JeeSite 基于最主流的 Spring Boot 2 + MyBatis + Shiro + J2Cache/Redis + Beetl 的稳定架构。 前端采用了目前极为流行的扁平化响应式的设计风格,可以完美兼容电脑,平板,手机等多个平台。 基于 jQuery + Bootstrap + AdminLTE 实现。

@@ -283,9 +279,7 @@ 5:30 ThinkGem - I would like to meet you to discuss the latest news about - the arrival of the new theme. They say it is going to be one the - best themes on the market + JeeSite 严格遵循了 Web 安全的规范,前后台双重验证,参数编码传输,密码安全策略,密码散列加密存储, 精细的权限验证,数据验证,SQL 编码过滤,从根本上避免了SQL注入,防止 XSS 攻击, CSRF 攻击等常见的 Web 攻击手段。

@@ -297,23 +291,7 @@ 5:30 ThinkGem - I would like to meet you to discuss the latest news about - the arrival of the new theme. They say it is going to be one the - best themes on the market -

-
- - -
- user image -

- - 5:30 - ThinkGem - - I would like to meet you to discuss the latest news about - the arrival of the new theme. They say it is going to be one the - best themes on the market + 经典架构会的人多,提供一个强大的 在线代码生成 工具,此工具提供常用的单表、一对多、树结构及列表查询等功能的生成, 如果对外观要求不是很高,生成的功能就可以用了。如果你使用了本平台,就可以很简单很高效的快速开发出优秀的产品。

@@ -321,9 +299,9 @@ @@ -358,9 +336,9 @@ - Design a nice theme + 模块及插件分项目,尽量松耦合,方便模块升级、增减模块 - 2 mins + 2 分钟
@@ -373,8 +351,8 @@ - Make the theme responsive - 4 hours + 模块化数据库自动升级程序,自动对应版本执行 SQL 更新 + 4 小时
@@ -386,8 +364,8 @@ - Let theme shine like a star - 1 day + 持久层 @Table 注解配置,节省 85% 的重复 SQL 编写 + 1 天
@@ -399,8 +377,8 @@ - Let theme shine like a star - 3 days + 完善的安全体系,身份认证、密码策略、安全审计、日志收集 + 2 天
@@ -412,8 +390,8 @@ - Check your messages and notifications - 1 week + 平面化界面设计,更加美观、高端、大气、上档次 + 3 天
@@ -425,8 +403,8 @@ - Let theme shine like a star - 1 month + 基于 Spring Cloud 安全稳定、支持分布式、支持微服务 + 1 周
@@ -459,7 +437,7 @@

访问

-
+
+
+
- -
«July 2019»
SuMoTuWeThFrSa
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
+ +
«2019 年 7 月»
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910