Compare commits

...

41 Commits

Author SHA1 Message Date
thinkgem
b212013db1 upgrade fastjson v1.2.67 2020-03-27 12:05:29 +08:00
thinkgem
f3fa1e2ee4 点击右上角【Star】收藏本软件 ^_^ 2020-03-25 22:42:57 +08:00
thinkgem
35c293d7fc 更新行政区划全国数据 2020-03-10 20:39:35 +08:00
thinkgem
c030985bb0 一些微调优化 2020-03-05 21:44:22 +08:00
thinkgem
8d7f5e9f33 文字修正 2020-03-01 16:24:38 +08:00
thinkgem
12ea728671 脚本优化 2020-02-28 21:33:34 +08:00
thinkgem
d1b1479053 仅适用国内 Maven 服务器 2020-02-28 19:28:36 +08:00
thinkgem
4cd0666ce8 导入增加所属机构验证;修改密码长度200 2020-02-28 12:39:02 +08:00
thinkgem
f974d058d1 Excel工具优化BigDecimal类型 2020-02-24 12:23:58 +08:00
thinkgem
d5f63c480f 新增inputmask插件金额使用例子;增加editGrid列表选择组件的例子; 2020-02-24 12:22:53 +08:00
thinkgem
c5a3565cfe 新增微信模块 2020-02-22 01:11:45 +08:00
thinkgem
a34d0d162a upgrade tomcat 8.5.51 2020-02-21 15:08:28 +08:00
thinkgem
35023285dd 升级 jQuery 3.4 下个版本默认切换。 2020-02-20 14:35:26 +08:00
thinkgem
3c203d6615 升级 jQuery 3.4 下个版本默认切换。 2020-02-20 12:35:40 +08:00
thinkgem
044770e205 代码优化 2020-02-20 12:34:00 +08:00
thinkgem
e8aa8095ce POI 代码优化 2020-02-19 21:15:22 +08:00
thinkgem
5df57a9f49 部门数接口 isLoadUser 改进为(true: 一次性加载;lazy: 懒加载,点击再加载) 2020-02-19 19:56:24 +08:00
thinkgem
acf6ea7738 issues #I1546S 2020-02-19 19:23:48 +08:00
thinkgem
c15312083d 新增账号注册界面示例 2020-02-19 19:23:06 +08:00
thinkgem
57e77af09d 新增全空格的前端验证 isBlank 2020-02-19 11:55:17 +08:00
thinkgem
1f9c7e4a50 登录视图自定义优化,可以显示来源页面消息。 2020-02-18 12:47:52 +08:00
thinkgem
11d1b2ee09 beetl 添加 hasRole 函数 2020-02-18 12:45:49 +08:00
thinkgem
734af686af 新增多页签应用示例 2020-02-13 23:47:09 +08:00
thinkgem
7d5e0f28ff 点击右上角【Star】收藏本软件 ^_^ 2020-02-10 12:16:30 +08:00
thinkgem
aa50b5a696 代码生成工具超多字段的时候使用 2020-02-02 12:51:48 +08:00
thinkgem
bf6940ae92 PropertiesUtils提醒信息优化 2020-02-02 12:46:42 +08:00
thinkgem
055befdb79 新增多表格联动示例 2020-01-31 15:47:48 +08:00
thinkgem
3ab9e28188 update 2020-01-31 00:30:30 +08:00
thinkgem
d7e2784bac 点击右上角【Star】收藏本软件 ^_^ 2020-01-31 00:30:20 +08:00
thinkgem
d81d10f01a update 2020-01-22 18:12:37 +08:00
thinkgem
203a81f52e 点击右上角【Star】收藏本软件 ^_^ 2020-01-21 21:14:35 +08:00
thinkgem
e75fa7d6d0 兼容旧系统 2020-01-21 17:45:34 +08:00
thinkgem
47d3d5bd78 新增 scheme 强制替换为 https 的过滤器,用于当 nginx 配置了 ssl,而被代理的系统不采用 ssl 的时候使用。 2020-01-21 10:34:36 +08:00
thinkgem
62df63900d update 2020-01-15 17:59:02 +08:00
thinkgem
ed7b9d2922 增加一些默认包导入,该包默认导入适应于BPM流程脚本。 2020-01-14 18:24:21 +08:00
thinkgem
de77f34353 用户提醒异常消息优化 2020-01-14 18:02:37 +08:00
thinkgem
28aa05c24e update 2020-01-11 23:39:10 +08:00
thinkgem
d85ed438b0 更新属性文件值时包含环境的属性文件 2020-01-10 18:06:37 +08:00
thinkgem
5128a5ff3b update 2020-01-10 16:40:15 +08:00
thinkgem
7ff3a87d9c 点击右上角【Star】收藏本软件 ^_^ 2020-01-06 22:21:57 +08:00
thinkgem
208e04bd54 修正合并分支后漏掉的字段,导致工号验证问题。 2020-01-06 17:26:00 +08:00
61 changed files with 16491 additions and 4146 deletions

4
.gitignore vendored
View File

@@ -7,9 +7,7 @@
*.epoch
*.lic
**/.settings/**/*
!**/.settings/org.eclipse.core.resources.prefs
!**/.settings/org.eclipse.wst.common.project.facet.core.xml
.settings
.apt_generated
.factorypath
.classpath

View File

@@ -1,6 +1,6 @@
## 引言
JeeSite 是一个 Java EE 企业级快速开发平台基于经典技术组合Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE采用经典开发模式让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能包括核心模块如组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计界面无刷新一键换肤众多账号安全设置密码策略在线定时任务配置支持集群支持SAAS支持多数据源支持微服务。
JeeSite 是一个 Java EE 企业级快速开发平台基于经典技术组合Spring Boot、Spring MVC、Apache Shiro、MyBatis、Beetl、Bootstrap、AdminLTE采用经典开发模式让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能包括核心模块如组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、工作流等。采用松耦合设计界面无刷新一键换肤众多账号安全设置密码策略在线定时任务配置支持集群支持SAAS支持多数据源支持读写分离、分库分表;支持微服务。
JeeSite 快速开发平台的主要目的是能够让初级的研发人员快速的开发出复杂的业务功能(经典架构会的人多),让开发者注重专注业务,其余有平台来封装技术细节,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。
@@ -16,7 +16,8 @@ JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面
* 持久层Apache MyBatis 3.4、Hibernate Validation 6.0、Alibaba Druid 1.1
* 视图层Spring MVC 5.0、Beetl 3.0替换JSP、Bootstrap 3.3、AdminLTE 2.4
* 前端组件jQuery 1.12、jqGrid 4.7、layer 3.1、zTree 3.5、jquery-validation
* 工具组件Apache Commons、Jackson 2.10、POI 3.16、Quartz 2.3、Flowable 6.4
* 工具组件Apache Commons、Jackson 2.10、POI 3.16、Quartz 2.3
* 工作流引擎Flowable 6.5、符合 BPMN 规范、在线流程设计器、中国式工作流
* 技术选型详情:<http://jeesite.com/?t=273599>
## 内置功能
@@ -76,7 +77,7 @@ JeeSite 4.x 的升级,作者结合了多年总结和经验,以及各方面
# 技术交流方式
* QQ 群号:`127515876``209330483``223507718``709534275``730390092``183903863(外包)`
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>  [【新手必读】](http://www.dianbo.org/9238/stone/tiwendezhihui.htm)
* 问题反馈:<https://gitee.com/thinkgem/jeesite4/issues>  [【新手必读】](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
* 码云Gitee<https://gitee.com/thinkgem/jeesite4>
* GitHub<https://github.com/thinkgem/jeesite4>
* 作者博客:<https://my.oschina.net/thinkgem>

View File

@@ -1,5 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.8"/>
</faceted-project>

View File

@@ -301,6 +301,39 @@
<plugins>
</plugins>
<pluginManagement>
<plugins>
<!-- YUI Compressor (CSS/JS压缩) -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<encoding>UTF-8</encoding>
<jswarn>false</jswarn>
<nosuffix>true</nosuffix>
<linebreakpos>30000</linebreakpos>
<force>true</force>
<includes>
<include>**/*.js</include>
<include>**/*.css</include>
</includes>
<excludes>
<exclude>**/*.min.js</exclude>
<exclude>**/*.min.css</exclude>
<exclude>**/jquery-*.js</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<developers>

View File

@@ -105,18 +105,19 @@ public class PropertiesUtils {
*/
public PropertiesUtils(String... configFiles) {
for (String location : configFiles) {
try {
Resource resource = ResourceUtils.getResource(location);
if (resource.exists()){
if (location.endsWith(".properties")){
try (InputStreamReader is = new InputStreamReader(resource.getInputStream(), "UTF-8")){
properties.load(is);
configSet.add(location);
} catch (IOException ex) {
logger.error("Load " + location + " failure. ", ex);
}
Resource resource = ResourceUtils.getResource(location);
if (resource.exists()){
if (location.endsWith(".properties")){
try (InputStreamReader is = new InputStreamReader(resource.getInputStream(), "UTF-8")){
properties.load(is);
configSet.add(location);
} catch (IOException e) {
System.err.println("Load " + location + " failure.");
e.printStackTrace();
}
else if (location.endsWith(".yml")){
}
else if (location.endsWith(".yml")){
try {
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
bean.setResources(resource);
for (Map.Entry<Object,Object> entry : bean.getObject().entrySet()){
@@ -124,12 +125,14 @@ public class PropertiesUtils {
ObjectUtils.toString(entry.getValue()));
}
configSet.add(location);
}
}
} catch (Exception e) {
logger.error("Load " + location + " failure. ", e);
} catch (Exception e) {
System.err.println("Load " + location + " failure.");
e.printStackTrace();
}
}
}
}
properties.put("configFiles", StringUtils.join(configFiles, ","));
}
/**

View File

@@ -36,7 +36,7 @@ public class SmsUtils {
// conn.data("mobile", mobile);
// // 短信内容
// conn.data("content", prefix + content + suffix);
logger.warn("模拟发送短信成功!请实现 "+SmsUtils.class+" 的 send 方法。");
logger.warn("模拟发送短信成功!请实现 "+SmsUtils.class+" 的 send 方法。内容:"+content);
return "{result:0,message:\"模拟发送短信成功!\"}";
}

View File

@@ -10,6 +10,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@@ -21,13 +22,17 @@ import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
@@ -51,7 +56,7 @@ import com.jeesite.common.utils.excel.annotation.ExcelFields;
/**
* 导出Excel文件导出“XLSX”格式支持大数据量导出 @see org.apache.poi.ss.SpreadsheetVersion
* @author ThinkGem
* @version 2018-08-11
* @version 2020-2-19
*/
public class ExcelExport implements Closeable{
@@ -348,24 +353,24 @@ public class ExcelExport implements Closeable{
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
CellStyle style = wb.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font titleFont = wb.createFont();
titleFont.setFontName("Arial");
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
titleFont.setBold(true);
style.setFont(titleFont);
styles.put("title", style);
style = wb.createCellStyle();
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(CellStyle.BORDER_THIN);
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
@@ -375,29 +380,29 @@ public class ExcelExport implements Closeable{
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(CellStyle.ALIGN_LEFT);
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(CellStyle.ALIGN_RIGHT);
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
// style.setWrapText(true);
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
@@ -462,6 +467,8 @@ public class ExcelExport implements Closeable{
}else if(val instanceof Float) {
cell.setCellValue((Float) val);
defaultDataFormat = "0.00";
}else if(val instanceof BigDecimal) {
cell.setCellValue(((BigDecimal)val).doubleValue());
}else if(val instanceof Date) {
cell.setCellValue((Date) val);
defaultDataFormat = "yyyy-MM-dd HH:mm";
@@ -636,28 +643,28 @@ public class ExcelExport implements Closeable{
// }
//
// // 创建一个Sheet表并导入数据
// ExcelExport ee = new ExcelExport("表格1", "表格标题1", headerList, null);
// for (int i = 0; i < dataList.size(); i++) {
// Row row = ee.addRow();
// for (int j = 0; j < dataList.get(i).size(); j++) {
// ee.addCell(row, j, dataList.get(i).get(j));
// try(ExcelExport ee = new ExcelExport("表格1", "表格标题1", headerList, null)){
//
// for (int i = 0; i < dataList.size(); i++) {
// Row row = ee.addRow();
// for (int j = 0; j < dataList.get(i).size(); j++) {
// ee.addCell(row, j, dataList.get(i).get(j));
// }
// }
// }
//
// // 再创建一个Sheet表并导入数据
// ee.createSheet("表格2", "表格标题2", headerList, null);
// for (int i = 0; i < dataList.size(); i++) {
// Row row = ee.addRow();
// for (int j = 0; j < dataList.get(i).size(); j++) {
// ee.addCell(row, j, dataList.get(i).get(j)+"2");
//
// // 再创建一个Sheet表并导入数据
// ee.createSheet("表格2", "表格标题2", headerList, null);
// for (int i = 0; i < dataList.size(); i++) {
// Row row = ee.addRow();
// for (int j = 0; j < dataList.get(i).size(); j++) {
// ee.addCell(row, j, dataList.get(i).get(j)+"2");
// }
// }
// }
//
// // 输出到文件
// ee.writeFile("target/export.xlsx");
//
// // 输出到文件
// ee.writeFile("target/export.xlsx");
//
// // 清理销毁
// ee.dispose();
// }
//
// log.debug("Export success.");
//

View File

@@ -23,6 +23,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
@@ -48,7 +49,7 @@ import com.jeesite.common.utils.excel.annotation.ExcelFields;
/**
* 导入Excel文件支持“XLS”和“XLSX”格式
* @author ThinkGem
* @version 2018-08-11
* @version 2020-2-19
*/
public class ExcelImport implements Closeable {
@@ -262,7 +263,7 @@ public class ExcelImport implements Closeable {
try{
Cell cell = row.getCell(column);
if (cell != null){
if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
if (cell.getCellTypeEnum() == CellType.NUMERIC){
val = cell.getNumericCellValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
@@ -273,36 +274,36 @@ public class ExcelImport implements Closeable {
val = new DecimalFormat("0").format(val);
}
}
}else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
}else if (cell.getCellTypeEnum() == CellType.STRING) {
val = cell.getStringCellValue();
}else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA){
}else if (cell.getCellTypeEnum() == CellType.FORMULA){
try {
val = cell.getStringCellValue();
} catch (Exception e) {
FormulaEvaluator evaluator = cell.getSheet().getWorkbook()
.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateFormulaCell(cell);
evaluator.evaluateFormulaCellEnum(cell);
CellValue cellValue = evaluator.evaluate(cell);
switch (cellValue.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
switch (cellValue.getCellTypeEnum()) {
case NUMERIC:
val = cellValue.getNumberValue();
break;
case Cell.CELL_TYPE_STRING:
case STRING:
val = cellValue.getStringValue();
break;
case Cell.CELL_TYPE_BOOLEAN:
case BOOLEAN:
val = cellValue.getBooleanValue();
break;
case Cell.CELL_TYPE_ERROR:
case ERROR:
val = ErrorEval.getText(cellValue.getErrorValue());
break;
default:
val = cell.getCellFormula();
}
}
}else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN){
}else if (cell.getCellTypeEnum() == CellType.BOOLEAN){
val = cell.getBooleanCellValue();
}else if (cell.getCellType() == Cell.CELL_TYPE_ERROR){
}else if (cell.getCellTypeEnum() == CellType.ERROR){
val = cell.getErrorCellValue();
}
}

View File

@@ -82,7 +82,7 @@ public @interface ExcelField {
Class<?> fieldType() default Class.class;
/**
* 数值格式例如0.00yyyy-MM-dd
* 数值格式(例如:数值:0.00;日期:yyyy-MM-dd;金额:¥#,##0.00
*/
String dataFormat() default "@";

View File

@@ -23,6 +23,8 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.io.PropertiesUtils;
import com.jeesite.common.lang.ExceptionUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.mapper.XmlMapper;
@@ -184,7 +186,16 @@ public class ServletUtils {
resultMap.put("result", result);
resultMap.put("message", message);
if (data != null){
if (data instanceof Map){
if (data instanceof Throwable){
Throwable ex = (Throwable)data;
String exMsg = ExceptionUtils.getExceptionMessage(ex);
if (StringUtils.isNotBlank(exMsg)){
resultMap.put("message", message + "" + exMsg);
}else if (ObjectUtils.toBoolean(PropertiesUtils.getInstance()
.getProperty("error.page.printErrorInfo", "true"))){
resultMap.put("message", message + "" + ex.getMessage());
}
}else if (data instanceof Map){
resultMap.putAll((Map<String, Object>)data);
}else{
resultMap.put("data", data);

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,678 @@
/*!
* jQuery Migrate - v3.1.0 - 2019-06-08
* Copyright OpenJS Foundation and other contributors
*/
;( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [ "jquery" ], function ( jQuery ) {
return factory( jQuery, window );
} );
} else if ( typeof module === "object" && module.exports ) {
// Node/CommonJS
// eslint-disable-next-line no-undef
module.exports = factory( require( "jquery" ), window );
} else {
// Browser globals
factory( jQuery, window );
}
} )( function( jQuery, window ) {
"use strict";
jQuery.migrateVersion = "3.1.0";
/* exported jQueryVersionSince, compareVersions */
// Returns 0 if v1 == v2, -1 if v1 < v2, 1 if v1 > v2
function compareVersions( v1, v2 ) {
var rVersionParts = /^(\d+)\.(\d+)\.(\d+)/,
v1p = rVersionParts.exec( v1 ) || [ ],
v2p = rVersionParts.exec( v2 ) || [ ];
for ( var i = 1; i <= 3; i++ ) {
if ( +v1p[ i ] > +v2p[ i ] ) {
return 1;
}
if ( +v1p[ i ] < +v2p[ i ] ) {
return -1;
}
}
return 0;
}
function jQueryVersionSince( version ) {
return compareVersions( jQuery.fn.jquery, version ) >= 0;
}
/* exported migrateWarn, migrateWarnFunc, migrateWarnProp */
( function() {
// Support: IE9 only
// IE9 only creates console object when dev tools are first opened
// IE9 console is a host object, callable but doesn't have .apply()
if ( !window.console || !window.console.log ) {
return;
}
// Need jQuery 3.0.0+ and no older Migrate loaded
if ( !jQuery || !jQueryVersionSince( "3.0.0" ) ) {
window.console.log( "JQMIGRATE: jQuery 3.0.0+ REQUIRED" );
}
if ( jQuery.migrateWarnings ) {
window.console.log( "JQMIGRATE: Migrate plugin loaded multiple times" );
}
// Show a message on the console so devs know we're active
//window.console.log( "JQMIGRATE: Migrate is installed" +
// ( jQuery.migrateMute ? "" : " with logging active" ) +
// ", version " + jQuery.migrateVersion );
} )();
var warnedAbout = {};
// List of warnings already given; public read only
jQuery.migrateWarnings = [];
// Set to false to disable traces that appear with warnings
if ( jQuery.migrateTrace === undefined ) {
jQuery.migrateTrace = true;
}
// Forget any warnings we've already given; public
jQuery.migrateReset = function() {
warnedAbout = {};
jQuery.migrateWarnings.length = 0;
};
function migrateWarn( msg ) {
var console = window.console;
if ( !warnedAbout[ msg ] ) {
warnedAbout[ msg ] = true;
jQuery.migrateWarnings.push( msg );
if ( console && console.warn && !jQuery.migrateMute ) {
console.warn( "JQMIGRATE: " + msg );
if ( jQuery.migrateTrace && console.trace ) {
console.trace();
}
}
}
}
function migrateWarnProp( obj, prop, value, msg ) {
Object.defineProperty( obj, prop, {
configurable: true,
enumerable: true,
get: function() {
migrateWarn( msg );
return value;
},
set: function( newValue ) {
migrateWarn( msg );
value = newValue;
}
} );
}
function migrateWarnFunc( obj, prop, newFunc, msg ) {
obj[ prop ] = function() {
migrateWarn( msg );
return newFunc.apply( this, arguments );
};
}
if ( window.document.compatMode === "BackCompat" ) {
// JQuery has never supported or tested Quirks Mode
migrateWarn( "jQuery is not compatible with Quirks Mode" );
}
var oldInit = jQuery.fn.init,
oldIsNumeric = jQuery.isNumeric,
oldFind = jQuery.find,
rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,
rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
jQuery.fn.init = function( arg1 ) {
var args = Array.prototype.slice.call( arguments );
if ( typeof arg1 === "string" && arg1 === "#" ) {
// JQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0
migrateWarn( "jQuery( '#' ) is not a valid selector" );
args[ 0 ] = [];
}
return oldInit.apply( this, args );
};
jQuery.fn.init.prototype = jQuery.fn;
jQuery.find = function( selector ) {
var args = Array.prototype.slice.call( arguments );
// Support: PhantomJS 1.x
// String#match fails to match when used with a //g RegExp, only on some strings
if ( typeof selector === "string" && rattrHashTest.test( selector ) ) {
// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
// First see if qS thinks it's a valid selector, if so avoid a false positive
try {
window.document.querySelector( selector );
} catch ( err1 ) {
// Didn't *look* valid to qSA, warn and try quoting what we think is the value
selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {
return "[" + attr + op + "\"" + value + "\"]";
} );
// If the regexp *may* have created an invalid selector, don't update it
// Note that there may be false alarms if selector uses jQuery extensions
try {
window.document.querySelector( selector );
migrateWarn( "Attribute selector with '#' must be quoted: " + args[ 0 ] );
args[ 0 ] = selector;
} catch ( err2 ) {
migrateWarn( "Attribute selector with '#' was not fixed: " + args[ 0 ] );
}
}
}
return oldFind.apply( this, args );
};
// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)
var findProp;
for ( findProp in oldFind ) {
if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {
jQuery.find[ findProp ] = oldFind[ findProp ];
}
}
// The number of elements contained in the matched element set
jQuery.fn.size = function() {
migrateWarn( "jQuery.fn.size() is deprecated and removed; use the .length property" );
return this.length;
};
jQuery.parseJSON = function() {
migrateWarn( "jQuery.parseJSON is deprecated; use JSON.parse" );
return JSON.parse.apply( null, arguments );
};
jQuery.isNumeric = function( val ) {
// The jQuery 2.2.3 implementation of isNumeric
function isNumeric2( obj ) {
var realStringObj = obj && obj.toString();
return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
}
var newValue = oldIsNumeric( val ),
oldValue = isNumeric2( val );
if ( newValue !== oldValue ) {
migrateWarn( "jQuery.isNumeric() should not be called on constructed objects" );
}
return oldValue;
};
if ( jQueryVersionSince( "3.3.0" ) ) {
migrateWarnFunc( jQuery, "isWindow",
function( obj ) {
return obj != null && obj === obj.window;
},
"jQuery.isWindow() is deprecated"
);
}
migrateWarnFunc( jQuery, "holdReady", jQuery.holdReady,
"jQuery.holdReady is deprecated" );
migrateWarnFunc( jQuery, "unique", jQuery.uniqueSort,
"jQuery.unique is deprecated; use jQuery.uniqueSort" );
// Now jQuery.expr.pseudos is the standard incantation
migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos,
"jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" );
migrateWarnProp( jQuery.expr, ":", jQuery.expr.pseudos,
"jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos" );
// Prior to jQuery 3.2 there were internal refs so we don't warn there
if ( jQueryVersionSince( "3.2.0" ) ) {
migrateWarnFunc( jQuery, "nodeName", jQuery.nodeName,
"jQuery.nodeName is deprecated" );
}
var oldAjax = jQuery.ajax;
jQuery.ajax = function( ) {
var jQXHR = oldAjax.apply( this, arguments );
// Be sure we got a jQXHR (e.g., not sync)
if ( jQXHR.promise ) {
migrateWarnFunc( jQXHR, "success", jQXHR.done,
"jQXHR.success is deprecated and removed" );
migrateWarnFunc( jQXHR, "error", jQXHR.fail,
"jQXHR.error is deprecated and removed" );
migrateWarnFunc( jQXHR, "complete", jQXHR.always,
"jQXHR.complete is deprecated and removed" );
}
return jQXHR;
};
var oldRemoveAttr = jQuery.fn.removeAttr,
oldToggleClass = jQuery.fn.toggleClass,
rmatchNonSpace = /\S+/g;
jQuery.fn.removeAttr = function( name ) {
var self = this;
jQuery.each( name.match( rmatchNonSpace ), function( _i, attr ) {
if ( jQuery.expr.match.bool.test( attr ) ) {
migrateWarn( "jQuery.fn.removeAttr no longer sets boolean properties: " + attr );
self.prop( attr, false );
}
} );
return oldRemoveAttr.apply( this, arguments );
};
jQuery.fn.toggleClass = function( state ) {
// Only deprecating no-args or single boolean arg
if ( state !== undefined && typeof state !== "boolean" ) {
return oldToggleClass.apply( this, arguments );
}
migrateWarn( "jQuery.fn.toggleClass( boolean ) is deprecated" );
// Toggle entire class name of each element
return this.each( function() {
var className = this.getAttribute && this.getAttribute( "class" ) || "";
if ( className ) {
jQuery.data( this, "__className__", className );
}
// If the element has a class name or if we're passed `false`,
// then remove the whole classname (if there was one, the above saved it).
// Otherwise bring back whatever was previously saved (if anything),
// falling back to the empty string if nothing was stored.
if ( this.setAttribute ) {
this.setAttribute( "class",
className || state === false ?
"" :
jQuery.data( this, "__className__" ) || ""
);
}
} );
};
var internalSwapCall = false;
// If this version of jQuery has .swap(), don't false-alarm on internal uses
if ( jQuery.swap ) {
jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) {
var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;
if ( oldHook ) {
jQuery.cssHooks[ name ].get = function() {
var ret;
internalSwapCall = true;
ret = oldHook.apply( this, arguments );
internalSwapCall = false;
return ret;
};
}
} );
}
jQuery.swap = function( elem, options, callback, args ) {
var ret, name,
old = {};
if ( !internalSwapCall ) {
migrateWarn( "jQuery.swap() is undocumented and deprecated" );
}
// Remember the old values, and insert the new ones
for ( name in options ) {
old[ name ] = elem.style[ name ];
elem.style[ name ] = options[ name ];
}
ret = callback.apply( elem, args || [] );
// Revert the old values
for ( name in options ) {
elem.style[ name ] = old[ name ];
}
return ret;
};
var oldData = jQuery.data;
jQuery.data = function( elem, name, value ) {
var curData;
// Name can be an object, and each entry in the object is meant to be set as data
if ( name && typeof name === "object" && arguments.length === 2 ) {
curData = jQuery.hasData( elem ) && oldData.call( this, elem );
var sameKeys = {};
for ( var key in name ) {
if ( key !== jQuery.camelCase( key ) ) {
migrateWarn( "jQuery.data() always sets/gets camelCased names: " + key );
curData[ key ] = name[ key ];
} else {
sameKeys[ key ] = name[ key ];
}
}
oldData.call( this, elem, sameKeys );
return name;
}
// If the name is transformed, look for the un-transformed name in the data object
if ( name && typeof name === "string" && name !== jQuery.camelCase( name ) ) {
curData = jQuery.hasData( elem ) && oldData.call( this, elem );
if ( curData && name in curData ) {
migrateWarn( "jQuery.data() always sets/gets camelCased names: " + name );
if ( arguments.length > 2 ) {
curData[ name ] = value;
}
return curData[ name ];
}
}
return oldData.apply( this, arguments );
};
var oldTweenRun = jQuery.Tween.prototype.run;
var linearEasing = function( pct ) {
return pct;
};
jQuery.Tween.prototype.run = function( ) {
if ( jQuery.easing[ this.easing ].length > 1 ) {
migrateWarn(
"'jQuery.easing." + this.easing.toString() + "' should use only one argument"
);
jQuery.easing[ this.easing ] = linearEasing;
}
oldTweenRun.apply( this, arguments );
};
var intervalValue = jQuery.fx.interval || 13,
intervalMsg = "jQuery.fx.interval is deprecated";
// Support: IE9, Android <=4.4
// Avoid false positives on browsers that lack rAF
// Don't warn if document is hidden, jQuery uses setTimeout (#292)
if ( window.requestAnimationFrame ) {
Object.defineProperty( jQuery.fx, "interval", {
configurable: true,
enumerable: true,
get: function() {
if ( !window.document.hidden ) {
migrateWarn( intervalMsg );
}
return intervalValue;
},
set: function( newValue ) {
migrateWarn( intervalMsg );
intervalValue = newValue;
}
} );
}
var oldLoad = jQuery.fn.load,
oldEventAdd = jQuery.event.add,
originalFix = jQuery.event.fix;
jQuery.event.props = [];
jQuery.event.fixHooks = {};
migrateWarnProp( jQuery.event.props, "concat", jQuery.event.props.concat,
"jQuery.event.props.concat() is deprecated and removed" );
jQuery.event.fix = function( originalEvent ) {
var event,
type = originalEvent.type,
fixHook = this.fixHooks[ type ],
props = jQuery.event.props;
if ( props.length ) {
migrateWarn( "jQuery.event.props are deprecated and removed: " + props.join() );
while ( props.length ) {
jQuery.event.addProp( props.pop() );
}
}
if ( fixHook && !fixHook._migrated_ ) {
fixHook._migrated_ = true;
migrateWarn( "jQuery.event.fixHooks are deprecated and removed: " + type );
if ( ( props = fixHook.props ) && props.length ) {
while ( props.length ) {
jQuery.event.addProp( props.pop() );
}
}
}
event = originalFix.call( this, originalEvent );
return fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
};
jQuery.event.add = function( elem, types ) {
// This misses the multiple-types case but that seems awfully rare
if ( elem === window && types === "load" && window.document.readyState === "complete" ) {
migrateWarn( "jQuery(window).on('load'...) called after load event occurred" );
}
return oldEventAdd.apply( this, arguments );
};
jQuery.each( [ "load", "unload", "error" ], function( _, name ) {
jQuery.fn[ name ] = function() {
var args = Array.prototype.slice.call( arguments, 0 );
// If this is an ajax load() the first arg should be the string URL;
// technically this could also be the "Anything" arg of the event .load()
// which just goes to show why this dumb signature has been deprecated!
// jQuery custom builds that exclude the Ajax module justifiably die here.
if ( name === "load" && typeof args[ 0 ] === "string" ) {
return oldLoad.apply( this, args );
}
migrateWarn( "jQuery.fn." + name + "() is deprecated" );
args.splice( 0, 0, name );
if ( arguments.length ) {
return this.on.apply( this, args );
}
// Use .triggerHandler here because:
// - load and unload events don't need to bubble, only applied to window or image
// - error event should not bubble to window, although it does pre-1.7
// See http://bugs.jquery.com/ticket/11820
this.triggerHandler.apply( this, args );
return this;
};
} );
jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup contextmenu" ).split( " " ),
function( _i, name ) {
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) {
migrateWarn( "jQuery.fn." + name + "() event shorthand is deprecated" );
return arguments.length > 0 ?
this.on( name, null, data, fn ) :
this.trigger( name );
};
} );
// Trigger "ready" event only once, on document ready
jQuery( function() {
jQuery( window.document ).triggerHandler( "ready" );
} );
jQuery.event.special.ready = {
setup: function() {
if ( this === window.document ) {
migrateWarn( "'ready' event is deprecated" );
}
}
};
jQuery.fn.extend( {
bind: function( types, data, fn ) {
migrateWarn( "jQuery.fn.bind() is deprecated" );
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
migrateWarn( "jQuery.fn.unbind() is deprecated" );
return this.off( types, null, fn );
},
delegate: function( selector, types, data, fn ) {
migrateWarn( "jQuery.fn.delegate() is deprecated" );
return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
migrateWarn( "jQuery.fn.undelegate() is deprecated" );
return arguments.length === 1 ?
this.off( selector, "**" ) :
this.off( types, selector || "**", fn );
},
hover: function( fnOver, fnOut ) {
migrateWarn( "jQuery.fn.hover() is deprecated" );
return this.on( "mouseenter", fnOver ).on( "mouseleave", fnOut || fnOver );
}
} );
var oldOffset = jQuery.fn.offset;
jQuery.fn.offset = function() {
var docElem,
elem = this[ 0 ],
origin = { top: 0, left: 0 };
if ( !elem || !elem.nodeType ) {
migrateWarn( "jQuery.fn.offset() requires a valid DOM element" );
return origin;
}
docElem = ( elem.ownerDocument || window.document ).documentElement;
if ( !jQuery.contains( docElem, elem ) ) {
migrateWarn( "jQuery.fn.offset() requires an element connected to a document" );
return origin;
}
return oldOffset.apply( this, arguments );
};
var oldParam = jQuery.param;
jQuery.param = function( data, traditional ) {
var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
if ( traditional === undefined && ajaxTraditional ) {
migrateWarn( "jQuery.param() no longer uses jQuery.ajaxSettings.traditional" );
traditional = ajaxTraditional;
}
return oldParam.call( this, data, traditional );
};
var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
jQuery.fn.andSelf = function() {
migrateWarn( "jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()" );
return oldSelf.apply( this, arguments );
};
var oldDeferred = jQuery.Deferred,
tuples = [
// Action, add listener, callbacks, .then handlers, final state
[ "resolve", "done", jQuery.Callbacks( "once memory" ),
jQuery.Callbacks( "once memory" ), "resolved" ],
[ "reject", "fail", jQuery.Callbacks( "once memory" ),
jQuery.Callbacks( "once memory" ), "rejected" ],
[ "notify", "progress", jQuery.Callbacks( "memory" ),
jQuery.Callbacks( "memory" ) ]
];
jQuery.Deferred = function( func ) {
var deferred = oldDeferred(),
promise = deferred.promise();
deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
migrateWarn( "deferred.pipe() is deprecated" );
return jQuery.Deferred( function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
// Deferred.done(function() { bind to newDefer or newDefer.resolve })
// deferred.fail(function() { bind to newDefer or newDefer.reject })
// deferred.progress(function() { bind to newDefer or newDefer.notify })
deferred[ tuple[ 1 ] ]( function() {
var returned = fn && fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ tuple[ 0 ] + "With" ](
this === promise ? newDefer.promise() : this,
fn ? [ returned ] : arguments
);
}
} );
} );
fns = null;
} ).promise();
};
if ( func ) {
func.call( deferred, deferred );
}
return deferred;
};
// Preserve handler of uncaught exceptions in promise chains
jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook;
return jQuery;
} );

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.utility"/>
<fixed facet="java"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.8"/>
</faceted-project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.modules.config.web;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
/**
* 将请求协议转换为 https
* @author ThinkGem
* @version 2020年1月21日
*/
@Configuration
@ConditionalOnProperty(name="server.schemeHttps", havingValue="true", matchIfMissing=false)
public class SchemeHttpsConfig {
@Bean
public FilterRegistrationBean<Filter> schemeFilterRegistrationBean() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
bean.setFilter(new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) {
@Override
public String getScheme() {
return "https";
}
@Override
public StringBuffer getRequestURL() {
StringBuffer sb = super.getRequestURL();
if ("http:".equals(sb.substring(0, 5))){
return sb.replace(0, 5, "https:");
}else{
return sb;
}
}
}, response);
}
@Override
public void destroy() {}
});
bean.addUrlPatterns("/*");
return bean;
}
}

View File

@@ -7,6 +7,7 @@ import javax.validation.Valid;
import com.jeesite.common.entity.BaseEntity;
import com.jeesite.common.entity.DataEntity;
import com.jeesite.common.entity.TreeEntity;
import com.jeesite.common.mybatis.annotation.Column;
import com.jeesite.common.mybatis.annotation.JoinTable;
import com.jeesite.common.mybatis.annotation.JoinTable.Type;
@@ -32,14 +33,16 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@Column(includeEntity=BaseEntity.class),
@Column(includeEntity=DataEntity.class),
@Column(name="emp_code", attrName="empCode", label="员工编码", isPK=true),
@Column(name="emp_no", attrName="empNo", label="员工工号"),
@Column(name="emp_name", attrName="empName", label="员工姓名", queryType=QueryType.LIKE),
@Column(name="emp_name_en", attrName="empNameEn", label="英文名", queryType=QueryType.LIKE),
}),
@JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
on="o.office_code=e.office_code", attrName="employee.office",
columns={
@Column(includeEntity=DataEntity.class),
@Column(includeEntity=TreeEntity.class),
@Column(name="office_code", label="机构编码", isPK=true),
@Column(name="parent_codes",label="所有父级编码", queryType=QueryType.LIKE),
@Column(name="view_code", label="机构代码"),
@Column(name="office_name", label="机构名称", isQuery=false),
@Column(name="full_name", label="机构全称"),
@@ -53,12 +56,12 @@ import com.jeesite.common.utils.excel.fieldtype.OfficeType;
@JoinTable(type=Type.LEFT_JOIN, entity=Company.class, alias="c",
on="c.company_code=e.company_code", attrName="employee.company",
columns={
@Column(includeEntity=DataEntity.class),
@Column(includeEntity=TreeEntity.class),
@Column(name="company_code", label="公司编码", isPK=true),
@Column(name="parent_codes",label="所有父级编码", queryType=QueryType.LIKE),
@Column(name="view_code", label="公司代码"),
@Column(name="company_name", label="公司名称", isQuery=false),
@Column(name="full_name", label="公司全称"),
@Column(name="area_code", attrName="area.areaCode", label="区域编码"),
}),
@JoinTable(type=Type.LEFT_JOIN, entity=Area.class, alias="ar",
on="ar.area_code = c.area_code", attrName="employee.company.area",

View File

@@ -38,36 +38,13 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
}, joinTable={
@JoinTable(type=Type.LEFT_JOIN, entity=Office.class, alias="o",
on="o.office_code = a.office_code",
columns={
@Column(name="office_code", label="机构编码", isPK=true),
@Column(name="parent_codes",label="所有父级编码", queryType=QueryType.LIKE),
@Column(name="view_code", label="机构代码"),
@Column(name="office_name", label="机构名称", isQuery=false),
@Column(name="full_name", label="机构全称"),
@Column(name="office_type", label="机构类型"),
@Column(name="leader", label="负责人"),
@Column(name="phone", label="电话"),
@Column(name="address", label="联系地址"),
@Column(name="zip_code", label="邮政编码"),
@Column(name="email", label="邮箱"),
}),
columns={@Column(includeEntity=Office.class)}),
@JoinTable(type=Type.LEFT_JOIN, entity=Company.class, alias="c",
on="c.company_code = a.company_code",
columns={
@Column(name="company_code", label="公司编码", isPK=true),
@Column(name="parent_codes",label="所有父级编码", queryType=QueryType.LIKE),
@Column(name="view_code", label="公司代码"),
@Column(name="company_name", label="公司名称", isQuery=false),
@Column(name="full_name", label="公司全称"),
@Column(name="area_code", attrName="area.areaCode", label="区域编码"),
}),
columns={@Column(includeEntity=Company.class)}),
@JoinTable(type=Type.LEFT_JOIN, entity=Area.class, alias="ar",
on="ar.area_code = c.area_code", attrName="company.area",
columns={
@Column(name="area_code", label="区域代码", isPK=true),
@Column(name="area_name", label="区域名称", isQuery=false),
@Column(name="area_type", label="区域类型"),
}),
columns={@Column(includeEntity=Area.class)}),
}, orderBy="a.update_date DESC"
)
public class Employee extends DataEntity<Employee> {

View File

@@ -123,6 +123,14 @@ public class Office extends TreeEntity<Office> {
this.officeType = officeType;
}
public String[] getOfficeType_in(){
return sqlMap.getWhere().getValue("office_type", QueryType.IN);
}
public void setOfficeType_in(String[] officeTypes){
sqlMap.getWhere().and("office_type", QueryType.IN, officeTypes);
}
@Length(min=0, max=100, message="负责人长度不能超过 100 个字符")
public String getLeader() {
return leader;

View File

@@ -172,6 +172,13 @@ public class EmpUserServiceSupport extends CrudService<EmpUserDao, EmpUser>
try{
// 验证数据文件
ValidatorUtils.validateWithException(user);
// 部门为空验证
if (StringUtils.isBlank(user.getEmployee().getOffice().getOfficeCode())) {
failureNum++;
failureMsg.append("<br/>" + failureNum + "、账号 " + user.getLoginCode()
+ " 导入失败:归属机构不能为空");
continue;
}
// 验证是否存在这个用户
User u = UserUtils.getByLoginCode(user.getLoginCode());
if (u == null){

View File

@@ -3,7 +3,6 @@
*/
package com.jeesite.modules.sys.service.support;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.jeesite.common.entity.Page;
@@ -43,7 +42,7 @@ public class LogServiceSupport extends CrudService<LogDao, Log>
/**
* 不使用数据库事务,执行插入日志
*/
@Transactional(readOnly=false, propagation=Propagation.NOT_SUPPORTED)
@Transactional(readOnly=false)//, propagation=Propagation.NOT_SUPPORTED)
public void insertLog(Log entity) {
dao.insert(entity);
}

View File

@@ -105,11 +105,12 @@ public class LoginController extends BaseController{
// 返回指定用户类型的登录页视图
String userType = (String)paramMap.get("userType");
if (StringUtils.isNotBlank(userType)){
String view = UserUtils.getUserTypeValue(userType, "loginView");
if(StringUtils.isNotBlank(view)){
return view;
}
if (StringUtils.isBlank(userType)){
userType = User.USER_TYPE_EMPLOYEE;
}
String view = UserUtils.getUserTypeValue(userType, "loginView");
if(StringUtils.isNotBlank(view)){
return view;
}
return "modules/sys/sysLogin";
@@ -177,11 +178,12 @@ public class LoginController extends BaseController{
// 返回指定用户类型的登录页视图
String userType = (String)paramMap.get("userType");
if (StringUtils.isNotBlank(userType)){
String view = UserUtils.getUserTypeValue(userType, "loginView");
if(StringUtils.isNotBlank(view)){
return view;
}
if (StringUtils.isBlank(userType)){
userType = User.USER_TYPE_EMPLOYEE;
}
String view = UserUtils.getUserTypeValue(userType, "loginView");
if(StringUtils.isNotBlank(view)){
return view;
}
return "modules/sys/sysLogin";

View File

@@ -217,7 +217,7 @@ public class OfficeController extends BaseController {
* @param companyCode 仅查询公司下的机构
* @param isShowCode 是否显示编码true or 1显示在左侧2显示在右侧false or null不显示
* @param isShowFullName 是否显示全机构名称
* @param isLoadUser 是否加载机构下的用户
* @param isLoadUser 是否加载机构下的用户true 一次性加载lazy 懒加载,点击再加载)
* @param postCode 机构下的用户过滤岗位
* @param roleCode 机构下的用户过滤角色
* @return
@@ -227,7 +227,7 @@ public class OfficeController extends BaseController {
@ResponseBody
public List<Map<String, Object>> treeData(String excludeCode, String parentCode, Boolean isAll,
String officeTypes, String companyCode, String isShowCode, String isShowFullName,
Boolean isLoadUser, String postCode, String roleCode, String ctrlPermi) {
String isLoadUser, String postCode, String roleCode, String ctrlPermi) {
List<Map<String, Object>> mapList = ListUtils.newArrayList();
Office where = new Office();
where.setStatus(Office.STATUS_NORMAL);
@@ -235,6 +235,15 @@ public class OfficeController extends BaseController {
if (!(isAll != null && isAll) || Global.isStrictMode()){
officeService.addDataScopeFilter(where, ctrlPermi);
}
// 根据父节点过滤数据
if (StringUtils.isNotBlank(parentCode)){
where.setParentCode(parentCode);
where.setParentCodes(","+parentCode+",");
}
// 根据部门类型过滤数据
if (StringUtils.isNotBlank(officeTypes)){
where.setOfficeType_in(officeTypes.split(","));
}
List<Office> list = officeService.findList(where);
for (int i = 0; i < list.size(); i++) {
Office e = list.get(i);
@@ -251,21 +260,6 @@ public class OfficeController extends BaseController {
continue;
}
}
// 根据父节点过滤数据
if (StringUtils.isNotBlank(parentCode)){
if (!e.getOfficeCode().equals(parentCode)){
continue;
}
if (!e.getParentCodes().contains("," + parentCode + ",")){
continue;
}
}
// 根据部门类型过滤数据
if (StringUtils.isNotBlank(officeTypes)){
if (!StringUtils.inString(e.getOfficeType(), officeTypes.split(","))){
continue;
}
}
Map<String, Object> map = MapUtils.newHashMap();
map.put("id", e.getId());
map.put("pId", e.getParentCode());
@@ -275,16 +269,26 @@ public class OfficeController extends BaseController {
}
map.put("name", StringUtils.getTreeNodeName(isShowCode, e.getViewCode(), name));
map.put("title", e.getFullName());
// 一次性后台加载用户,提高性能(推荐方法)
if (isLoadUser != null && isLoadUser) {
// 如果需要加载用户,则处理用户数据
if (StringUtils.inString(isLoadUser, "true", "lazy")) {
map.put("isParent", true);
List<Map<String, Object>> userList;
userList = empUserController.treeData("u_", e.getOfficeCode(), e.getOfficeCode(),
companyCode, postCode, roleCode, isAll, isShowCode, ctrlPermi);
mapList.addAll(userList);
// 一次性后台加载用户,若数据量比较大,建议使用懒加载
if (StringUtils.equals(isLoadUser, "true")) {
List<Map<String, Object>> userList =
empUserController.treeData("u_", e.getOfficeCode(), e.getOfficeCode(),
companyCode, postCode, roleCode, isAll, isShowCode, ctrlPermi);
mapList.addAll(userList);
}
}
mapList.add(map);
}
// 懒加载用户,点击叶子节点的时候再去加载部门(懒加载无法回显,数据量大时,建议使用 listselect 实现列表选择用户)
if (StringUtils.inString(isLoadUser, "lazy") && StringUtils.isNotBlank(parentCode)) {
List<Map<String, Object>> userList =
empUserController.treeData("u_", parentCode, parentCode,
companyCode, postCode, roleCode, isAll, isShowCode, ctrlPermi);
mapList.addAll(userList);
}
return mapList;
}

View File

@@ -100,12 +100,10 @@ public class AccountController extends BaseController{
UserUtils.putCache("fpUserCode", u.getUserCode());
UserUtils.putCache("fpLoginCode", u.getLoginCode());
UserUtils.putCache("fpValidCode", fpValidCode);
// 发送短信消息。
// 发送邮箱或短信验证码
if("mobile".equals(validType)){
return sendSmsValidCode(u, fpValidCode, text("找回密码"));
}
// 发送邮件消息。
else if("email".equals(validType)){
}else if("email".equals(validType)){
return sendEmailValidCode(u, fpValidCode, text("找回密码"));
}
return null;
@@ -272,8 +270,8 @@ public class AccountController extends BaseController{
@ApiImplicitParam(name = "userName", value = "用户姓名", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "email", value = "电子邮箱", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "mobile", value = "手机号码", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "corpCode", value = "租户编号", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "corpName", value = "租户名称", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "corpCode_", value = "租户编号", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "corpName_", value = "租户名称", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "userType", value = "用户类型employee", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "validCode", value = "图片验证码,防止重复机器人", required = true),
@ApiImplicitParam(name = "validType", value = "验证方式mobile、email", required = true),
@@ -287,6 +285,9 @@ public class AccountController extends BaseController{
return renderResult(Global.FALSE, text("非法操作。"));
}
// 非空数据校验。
if (Global.isUseCorpModel() && StringUtils.isBlank(user.getCorpCode_())) {
return renderResult(Global.FALSE, text("请选择注册到的租户!"));
}
if (!(StringUtils.isNotBlank(user.getLoginCode()) && StringUtils.isNotBlank(user.getUserName()))){
return renderResult(Global.FALSE, text("登录账号和用户姓名不能为空!"));
}
@@ -305,30 +306,31 @@ public class AccountController extends BaseController{
UserUtils.putCache("regLastDate", new Date());
}
// 验证用户编码是否存在。
if (UserUtils.getByLoginCode(user.getLoginCode()) != null){
if (UserUtils.getByLoginCode(user.getLoginCode(), user.getCorpCode_()) != null){
return renderResult(Global.FALSE, text("登录账号已存在"));
}
// 生成验证码,并缓存。
String code = StringUtils.getRandomNum(6);
UserUtils.putCache("regCorpCode", user.getCorpCode());
UserUtils.putCache("regCorpName", user.getCorpName());
String regValidCode = StringUtils.getRandomNum(6);
UserUtils.putCache("regCorpCode", user.getCorpCode_());
UserUtils.putCache("regCorpName", user.getCorpName_());
UserUtils.putCache("regLoginCode", user.getLoginCode());
UserUtils.putCache("regUserName", user.getUserName());
// 账号注册类型
String[] userTypes = StringUtils.split(Global.getConfig(
"sys.account.registerUser.userTypes.userTypes", "-1"), ",");
"sys.account.registerUser.userTypes", "-1"), ",");
if (StringUtils.inString(user.getUserType(), userTypes)){
UserUtils.putCache("regUserType", user.getUserType());
}else{
return renderResult(Global.FALSE, text("非法的用户类型!"));
return renderResult(Global.FALSE, text("请在参数设置里设定允许自助注册的用户类型")+""+user.getUserType());
}
UserUtils.putCache("regEmail", user.getEmail());
UserUtils.putCache("regMobile", user.getMobile());
UserUtils.putCache("regValidCode", code);
UserUtils.putCache("regValidCode", regValidCode);
// 发送邮箱或短信验证码
if("send_email".equals(validType)){
return sendEmailValidCode(user, code, text("注册账号"));
}else if("send_mobile".equals(validType)){
return sendSmsValidCode(user, code, text("注册账号"));
if("email".equals(validType)){
return sendEmailValidCode(user, regValidCode, text("注册账号"));
}else if("mobile".equals(validType)){
return sendSmsValidCode(user, regValidCode, text("注册账号"));
}
return null;
}
@@ -343,7 +345,6 @@ public class AccountController extends BaseController{
@ApiOperation(value = "根据短信或邮件验证码注册用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "loginCode", value = "登录账号", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "userName", value = "用户姓名", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "password", value = "登录密码", required = true, paramType="query", type="String"),
@ApiImplicitParam(name = "regValidCode", value = "手机或邮箱接受的验证码", required = true),
})
@@ -355,6 +356,7 @@ public class AccountController extends BaseController{
String corpName = (String)UserUtils.getCache("regCorpName");
String userType = (String)UserUtils.getCache("regUserType");
String loginCode = (String)UserUtils.getCache("regLoginCode");
String userName = (String)UserUtils.getCache("regUserName");
String email = (String)UserUtils.getCache("regEmail");
String mobile = (String)UserUtils.getCache("regMobile");
String validCode = (String)UserUtils.getCache("regValidCode");
@@ -384,21 +386,25 @@ public class AccountController extends BaseController{
User u = new User();
u.setIsNewRecord(true);
if (StringUtils.isNotBlank(corpCode)){
u.setCorpCode(corpCode);
u.setCorpName(corpName);
u.setCorpCode_(corpCode);
u.setCorpName_(corpName);
}
u.setLoginCode(loginCode);
u.setUserName(user.getUserName());
u.setUserName(userName);
u.setPassword(user.getPassword());
u.setEmail(email);
u.setMobile(mobile);
u.setUserType(userType);
u.setMgrType(User.MGR_TYPE_NOT_ADMIN);
u.setStatus(User.STATUS_AUDIT); // 待审核状态
userService.save(u);
// 验证成功后清理验证码,验证码只允许使用一次。
UserUtils.removeCache("regCorpCode");
UserUtils.removeCache("regCorpName");
UserUtils.removeCache("regUserType");
UserUtils.removeCache("regLoginCode");
UserUtils.removeCache("regUserName");
UserUtils.removeCache("regValidCode");
UserUtils.removeCache("regLastDate");

View File

@@ -32,6 +32,9 @@ IMPORT_PACKAGE_core=\
com.jeesite.common.security.;\
com.jeesite.common.web.http.;\
com.jeesite.modules.sys.utils.;\
com.jeesite.common.entity.;\
com.jeesite.common.service.;\
com.jeesite.common.utils.;\
### 资源配置resource后的属性只限于特定ResourceLoader ####
#classpath 跟路径,与框架集成的时候,此配置会被框架代码覆盖而不能生效
@@ -98,6 +101,7 @@ FN.toInteger = com.jeesite.common.beetl.ext.fn.ToInteger
FN.toJson = com.jeesite.common.beetl.ext.fn.ToJson
FN.fromJson = com.jeesite.common.beetl.ext.fn.FromJson
FN.hasPermi = com.jeesite.common.beetl.ext.fn.HasPermi
FN.hasRole = com.jeesite.common.beetl.ext.fn.HasRole
FN.cookie = com.jeesite.common.beetl.ext.fn.Cookie
FN.lang = com.jeesite.common.beetl.ext.fn.Lang
FN.text = com.jeesite.common.beetl.ext.fn.Text

View File

@@ -173,13 +173,6 @@ user:
# 登录账号是否租户内唯一,否则全局唯一
loginCodeCorpUnique: false
# 自助账号服务
account:
# 注册用户
registerUser:
enabled: false
userTypes: 0, 1
# 角色管理
role:
# 扩展数据权限定义3本部门4本公司5本部门和本公司
@@ -229,7 +222,7 @@ role:
# 菜单管理
menu:
# 根据模块状态去更新相连的菜单状态仅作为微服务时设为false
# 根据模块状态去更新相连的菜单状态
updateStatusByModuleStatus: false
# 国际化管理(专业版)
@@ -332,7 +325,7 @@ shiro:
# 登录提交信息加密(如果不需要加密,设置为空即可)
loginSubmit:
# 登录提交信息安全Key加密用户名、密码、验证码后再提交key设置为3个用逗号分隔
# 登录提交信息安全Key加密用户名、密码、验证码后再提交key设置为3个用逗号分隔默认加密方式DES
secretKey: thinkgem,jeesite,com
# 记住我密钥设置,为空则自动生成一个新密钥,也可以通过 com.jeesite.test.RememberMeKeyGen 生成
@@ -392,6 +385,7 @@ shiro:
# ${adminPath}/sys/corpAdmin/treeData = anon
# ${adminPath}/** = user
filterChainDefinitions: |
${adminPath}/sys/corpAdmin/treeData = anon
${adminPath}/** = user
# 默认的授权过滤定义如果在filterChainDefinitions中已经定义则该定义会被覆盖。
@@ -603,8 +597,8 @@ msg:
fromAddress: jeesite_demo@163.com
fromPassword: jeesitedemo1234
fromHostName: smtp.163.com
sslOnConnect: false
sslSmtpPort: 994
sslOnConnect: true
sslSmtpPort: 465
# 短信网关
sms:
@@ -613,23 +607,3 @@ msg:
data: username=jeesite&password=jeesite.com
prefix: 【JeeSite】
suffix: ~
# 微信相关
weixin:
beanName: weixinSendService
#微信应用ID
appid: ~
#微信应用密钥
secret: ~
# 微信服务器配置
server:
# 微信服务器配置Token
token: ~
# 微信服务器配置EncodingAESKey
aeskey: ~
# 微信服务器是否开启Debug模式开启后发送未知消息时候会返回消息内容
debug: true
# 微信OAuth登录授权回调地址
oauth:
redirectUri: http://demo.jeesite.com/js

View File

@@ -24,6 +24,8 @@
<logger name="org.flowable.ui.modeler.domain" level="DEBUG" />
<logger name="org.flowable.idm.engine.impl.persistence" level="DEBUG" />
<logger name="org.flowable.task.service.impl.persistence" level="DEBUG" />
<logger name="org.flowable.identitylink.service.impl.persistence" level="DEBUG" />
<logger name="org.flowable.variable.service.impl.persistence" level="DEBUG" />
<logger name="org.flowable.engine.impl.persistence" level="DEBUG" />
<logger name="com.jeesite" level="DEBUG" />

View File

@@ -14,8 +14,8 @@ sys.login.accountIsBlank=登录账号不能为空。
sys.login.validCodeError=登录验证码错误,请重试。
sys.login.accountDisabled=该帐号已停用。
sys.login.accountFreezed=该帐号已冻结。
sys.login.accountAudited=该帐号待审核。
sys.login.accountInvalid=该帐号无效。
sys.login.accountAudited=该帐号待审核。
sys.login.accountInvalid=该帐号无效状态
sys.login.tickOutMessage=账号已被管理员移出在线,请重新登录。
sys.login.multiAddrMessage=账号已在其它地方登录,请重新登录。
sys.login.failedNumLock=登录失败,尝试次数过多,账号已锁定,请 {0} 分钟后重试.

View File

@@ -12,8 +12,8 @@
'loading.message':'Loading ...',
'loading.submitMessage':'Submission ...',
'showMessage.error':'failure,error',
'showMessage.success':'success,completion',
'showMessage.warning':'no'
'showMessage.warning':'no,not,Not,already exists',
'showMessage.success':'success,completion'
});
// ============ layer ============
window.layer = window.layer || {};

View File

@@ -12,8 +12,8 @@
'loading.message':'ローディング...お待ちください...',
'loading.submitMessage':'送信中...お待ちください...',
'showMessage.error':'失敗,エラー,未完了',
'showMessage.success':'成功,完了',
'showMessage.warning':'不可,不許可,必須,既に存在,不要,不正確'
'showMessage.warning':'不可,不許可,必須,既に存在,不要,不正確',
'showMessage.success':'成功,完了'
});
// ============ layer ============
window.layer = window.layer || {};

View File

@@ -12,7 +12,7 @@
'loading.message':'正在加载,请稍候...',
'loading.submitMessage':'正在提交,请稍候...',
'showMessage.error':'失败,错误,未完成',
'showMessage.success':'成功,完成',
'showMessage.warning':'不能,不允许,必须,已存在,不需要,不正确'
'showMessage.warning':'不能,不允许,必须,已存在,不需要,不正确',
'showMessage.success':'成功,完成'
});
})(jQuery);

View File

@@ -28,6 +28,7 @@
ipv4: "Please enter a valid IP v4 address",
ipv6: "Please enter a valid IP v6 address",
qq: "Please fill in your qq number correctly",
isBlank: "Cannot input full spaces",
idcard: "Please enter the correct id number (15-18)"
});
}(jQuery));

View File

@@ -28,6 +28,7 @@
ipv4: "有効なIP v4アドレスを入力してください",
ipv6: "有効なIP v6アドレスを入力してください",
qq: "あなたのQQ番号を正しく入力してください",
isBlank: "全フレームを入力することはできません",
idcard: "正しい住民登録番号(15 ~ 18位)を入力してください。"
});
}(jQuery));

View File

@@ -28,6 +28,7 @@
ipv4: "请输入一个有效的 IP v4 地址",
ipv6: "请输入一个有效的 IP v6 地址",
qq: "请正确填写您的QQ号码",
isBlank: "不能输入全空格",
idcard: "请输入正确的身份证号码(15-18位)"
});
}(jQuery));

View File

@@ -28,6 +28,7 @@
ipv4: "請輸入一個有效的 IP v4 地址",
ipv6: "請輸入一個有效的 IP v6 地址",
qq: "請正確填寫您的QQ號碼",
isBlank: "不能輸入全空格",
idcard: "請輸入正確的身份證號碼(15-18位)"
});
}(jQuery));

View File

@@ -23,7 +23,7 @@ if (isBlank(message)){
// 如果是异步请求或是手机端,则直接返回信息
if (@ServletUtils.isAjaxRequest(request)) {
if (@Global.getConfigToBoolean('error.page.printErrorInfo', 'true')
if (@Global.getPropertyToBoolean('error.page.printErrorInfo', 'true')
&& !@StringUtils.equals(message, "演示模式,不允许操作!") && ex != null){
print(@ServletUtils.renderResult(@Global.FALSE, message, @ExceptionUtils.getStackTraceAsString(ex)));
}else{
@@ -49,7 +49,7 @@ else {
href="http://jeesite.com">JeeSite ${@Global.getProperty('jeesiteVersion')}</a>
</div>
</div>
<% if (@Global.getConfigToBoolean('error.page.printErrorInfo', 'true')
<% if (@Global.getPropertyToBoolean('error.page.printErrorInfo', 'true')
&& !@StringUtils.equals(message, "演示模式,不允许操作!")){ %>
<div class="box mt20">
${@StringUtils.toHtml(@ExceptionUtils.getStackTraceAsString(ex))}<br/>

View File

@@ -0,0 +1,173 @@
<% layout('/layouts/default.html', {title: '账号注册', libs: ['validate'], bodyClass: 'login-page'}){ %>
<% include('/include/upgrade.html'){} // 如果客户浏览器版本过低,则显示浏览器升级提示。 %>
<link rel="stylesheet" href="${ctxStatic}/icheck/1.0/square/blue.css?${_version}">
<link rel="stylesheet" href="${ctxStatic}/jquery-toastr/2.0/toastr.min.css?${_version}">
<link rel="stylesheet" href="${ctxStatic}/modules/sys/sysLogin.css?${_version}">
<div class="login-box" style="margin-top:20px">
<div class="login-logo">
<a href="${ctxPath}/account/forgetPwd"><b>${@Global.getConfig('productName')}</b>
<small>${@Global.getConfig('productVersion')}</small></a>
</div>
<div class="login-box-body">
<form id="registerForm" action="${ctxPath}/account/saveRegByValidCode" method="post">
<div class="form-group has-feedback">
<select id="reg_validType" name="op" class="form-control">
<option value="email">使用电子邮箱注册账号</option>
<option value="mobile">使用手机号码注册账号</option>
</select>
<script type="text/javascript">
$(document).ready(function(){
$('#reg_validType').change(function(){
var val = $(this).val(), action = '';
$('.reg-element').addClass('hide').removeClass('block');
$('.reg-'+val).addClass('block').removeClass('hide');
setTimeout(function(){
$('#reg_loginCode').focus();
}, 100);
if (val == 'mobile' || val == 'email'){
var txt = (val == 'mobile' ? '手机' : '邮箱')
$('#regValidCode').attr('placeholder', txt+'验证码')
.attr('data-msg-required', '请填写'+txt+'验证码.');
$('#sendRegValidCode').val('获取'+txt+'验证码');
action = '${ctxPath}/account/saveRegByValidCode';
}else if(val == 'question'){
action = '${ctxPath}/account/savePwdByPwdQuestion';
}
$('#registerForm').attr('action', action);
}).change();
});
</script>
</div>
<% if(@Global.isUseCorpModel()){ %>
<div class="form-group has-feedback">
<#form:treeselect id="reg_corp" title="${text('选择租户')}" allowClear="true"
name="corpCode" value="0" labelName="corpName" labelValue="JeeSite"
url="${ctx}/sys/corpAdmin/treeData?isShowCode=true"
class="required" data-msg-required="请选择所属租户."
placeholder="${text('所属租户')}"/>
</div>
<% } %>
<div class="form-group has-feedback">
<span class="fa fa-user form-control-feedback"></span>
<input type="text" id="reg_loginCode" name="loginCode" class="form-control required" data-msg-required="请填写登录账号." placeholder="登录账号" />
</div>
<div class="form-group has-feedback">
<span class="fa fa-info form-control-feedback"></span>
<input type="text" id="reg_userName" name="userName" class="form-control required" data-msg-required="请填写用户姓名." placeholder="用户姓名" />
</div>
<div class="form-group has-feedback reg-element reg-email">
<span class="fa fa-envelope form-control-feedback"></span>
<input type="text" id="reg_email" name="email" class="form-control required" data-msg-required="请填写邮箱地址." placeholder="邮箱地址" />
</div>
<div class="form-group has-feedback reg-element reg-mobile">
<span class="fa fa-phone-square form-control-feedback"></span>
<input type="text" id="reg_mobile" name="mobile" class="form-control required" data-msg-required="请填写手机号码." placeholder="手机号码" />
</div>
<input type="hidden" id="reg_userType" name="mobile" value="member" />
<div class="form-group has-feedback reg-element reg-mobile reg-email">
<#form:validcode id="reg_validCode" name="validCode" isRequired="true" isRemote="true" isLazy="false"/>
</div>
<div class="form-group has-feedback reg-element reg-mobile reg-email">
<div class="input-group">
<input type="text" id="regValidCode" name="regValidCode" class="form-control required"
data-msg-required="请填写手机验证码." placeholder="手机验证码" />
<span class="input-group-btn">
<input type="button" id="sendRegValidCode" value="获取手机验证码" class="btn btn-flat"/>
</span>
</div>
<script type="text/javascript">
var waitTime = 60;
function sendTime(o) {
if (waitTime == 0) {
o.removeAttribute("disabled");
o.value = "获取验证码";
waitTime = 60;
} else {
o.setAttribute("disabled", true);
o.value = "重新发送(" + waitTime + ")";
waitTime--;
setTimeout(function() {
sendTime(o)
}, 1000);
}
}
$('#sendRegValidCode').click(function() {
var $this = this;
js.ajaxSubmit('${ctxPath}/account/getRegValidCode', {
validType: $('#reg_validType').val(),
corpCode_ : $('#reg_corpCode').val(),
corpName_ : $('#reg_corpName').val(),
loginCode : $('#reg_loginCode').val(),
userName : $('#reg_userName').val(),
email : $('#reg_email').val(),
mobile : $('#reg_mobile').val(),
userType: $('#reg_userType').val(),
validCode : $('#reg_validCode').val()
}, function(data){
js.showMessage(data.message);
if (data.result == 'true'){
sendTime($this);
}
});
});
</script>
</div>
<div class="form-group has-feedback">
<span class="fa fa-lock form-control-feedback"></span>
<input type="password" autocomplete="off" id="reg_password" name="password"
class="form-control required" data-msg-required="请填写登录密码."
rangelength="3,50" data-msg-rangelength="登录密码长度不能小于3并大于50个字符."
placeholder="登录密码" />
</div>
<div class="form-group has-feedback">
<span class="fa fa-lock form-control-feedback"></span>
<input type="password" autocomplete="off" id="reg_confirmPassword" name="confirmPassword"
class="form-control required" data-msg-required="请再填一次登录密码."
rangelength="3,50" data-msg-rangelength="登录密码长度不能小于3并大于50个字符."
equalTo="#reg_password" data-msg-equalTo="填写的密码与登录密码不同."
placeholder="再填一次登录密码" />
</div>
<div class="form-group has-feedback icheck">
<label title="${text('公共场所慎用,下次不需要再填写帐号')}"><input type="checkbox" name="reg_terms"
class="form-control required" data-msg-required="请阅读并同意我们的服务条款."> 我已阅读并同意协议内容 </label> &nbsp;
<a href="https://gitee.com/thinkgem/jeesite4/blob/master/README.md" target="_blank">查看协议</a>
</div>
<div class="row">
<div class="col-xs-6">
<button type="submit" class="btn btn-primary btn-block btn-flat"
id="btnSubmit">${text('提交')}</button>
</div>
<div class="col-xs-6">
<button type="button" class="btn btn-default btn-block btn-flat"
id="btnReset">${text('返回')}</button>
</div>
</div>
<div class="clearfix"></div>
</form>
</div>
<div class="login-copyright">
&copy; ${@DateUtils.getYear()} ${@Global.getConfig('productName')} - Powered By <a
href="http://jeesite.com">JeeSite ${@Global.getProperty('jeesiteVersion')}</a>
</div>
</div>
<% } %>
<script src="${ctxStatic}/jquery-toastr/2.0/toastr.min.js?${_version}"></script>
<script>
$('#registerForm').validate({
ignore: ":hidden",
submitHandler: function(form) {
js.ajaxSubmitForm($(form), function(data){
if (data.result == "true"){
alert(data.message);
location = "${ctx}/login";
}else{
js.showMessage(data.message);
$('#registerForm').reset();
}
});
}
});
$('#btnReset').click(function(){
location = '${ctx}/login';
});
</script>

View File

@@ -67,7 +67,7 @@
<span class="required hide">*</span> ${text('电子邮箱')}<i class="fa icon-question hide"></i></label>
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-fw fa-envelope" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-envelope"></i></span>
<#form:input path="email" maxlength="300" class="form-control email"/>
</div>
</div>
@@ -79,7 +79,7 @@
<span class="required hide">*</span> ${text('手机号码')}<i class="fa icon-question hide"></i></label>
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-fw fa-mobile" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-mobile"></i></span>
<#form:input path="mobile" maxlength="100" class="form-control mobile"/>
</div>
</div>

View File

@@ -77,7 +77,7 @@
<div class="col-sm-8">
<div class="input-group">
<#form:input path="email" maxlength="300" class="form-control email"/>
<span class="input-group-addon"><i class="fa fa-fw fa-envelope" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-envelope"></i></span>
</div>
</div>
</div>
@@ -89,7 +89,7 @@
<div class="col-sm-8">
<div class="input-group">
<#form:input path="mobile" maxlength="100" class="form-control mobile"/>
<span class="input-group-addon"><i class="fa fa-fw fa-mobile" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-mobile"></i></span>
</div>
</div>
</div>

View File

@@ -40,7 +40,7 @@
<div class="col-sm-9">
<div class="input-group">
<#form:input path="userName" maxlength="32" class="form-control required"/>
<span class="input-group-addon"><i class="fa fa-fw fa-user" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-user"></i></span>
</div>
</div>
</div>
@@ -52,7 +52,7 @@
<div class="col-sm-9">
<div class="input-group">
<#form:input path="email" maxlength="300" class="form-control email"/>
<span class="input-group-addon"><i class="fa fa-fw fa-envelope" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-envelope"></i></span>
</div>
</div>
</div>
@@ -64,7 +64,7 @@
<div class="col-sm-9">
<div class="input-group">
<#form:input path="mobile" maxlength="100" class="form-control mobile"/>
<span class="input-group-addon"><i class="fa fa-fw fa-mobile" style="margin-top:-2px;display:block;"></i></span>
<span class="input-group-addon"><i class="fa fa-fw fa-mobile"></i></span>
</div>
</div>
</div>

View File

@@ -71,7 +71,10 @@
}
var li = $("#leftMenu-" + code + " > li");
if (!li.hasClass('menu-open')){
li = li.eq(0).find('> a').click();
li = li.eq(0).find('> a');
if (li.data('href') == 'blank'){
li.click();
}
}
}
window.initMenu = true;

View File

@@ -10,7 +10,7 @@
</div>
<div class="login-box-body">
<#form:form id="loginForm" model="${user!}" action="${ctx}/login" method="post">
<h4 class="login-box-msg">${text('欢迎回来')}</h4>
<h4 class="login-box-msg">${isNotBlank(message!)?message:text('欢迎回来')+''}</h4>
<div class="form-group has-feedback">
<span class="glyphicon glyphicon-user form-control-feedback" title="${text('登录账号')}"></span>
<#form:input type="text" name="username" class="form-control required"
@@ -54,7 +54,7 @@
<div class="row">
<div class="col-xs-12">
<a href="${ctxPath}/account/forgetPwd" class="pull-left">[ ${text('忘记密码')} ]</a>
<% if(@Global.getConfigToBoolean('user.registerUser', 'false')){ %>
<% if(@Global.getConfigToBoolean('sys.account.registerUser', 'false')){ %>
<a href="${ctxPath}/account/registerUser" class="pull-left ml10">[ ${text('注册账号')} ]</a>
<% } %>
<% if (@com.jeesite.common.i18n.I18nLocaleResolver.enabled()){ %>

View File

@@ -0,0 +1,69 @@
/**
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
*/
package com.jeesite.test;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ActiveProfiles;
import com.jeesite.common.config.Global;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.tests.BaseSpringContextTests;
import com.jeesite.modules.gen.entity.GenTable;
import com.jeesite.modules.gen.entity.GenTableColumn;
import com.jeesite.modules.gen.service.GenTableService;
/**
* 代码生成工具API
* @author ThinkGem
* @version 2020-2-1
*/
@ActiveProfiles("test")
@SpringBootTest(classes=ApplicationTest.class)
@Rollback(false)
public class GenTableToolTest extends BaseSpringContextTests {
@Autowired
private GenTableService genTableService;
@Test
public void execute() throws Exception{
GenTable genTable = new GenTable();
genTable.setIsNewRecord(true);
genTable.setTableName("test_data_demo"); // 表名
genTable = genTableService.getFromDb(genTable);
genTable.setClassName(StringUtils.capCamelCase(genTable.getTableName())); // 实体类名
genTable.setFunctionAuthor("ThinkGem"); // 作者名称
genTable.setTplCategory("crud"); // 生成模板crud、treeGrid、service、dao、query
genTable.setPackageName("com.jeesite.modules");// 生成包路径
genTable.setModuleName("test"); // 生成模块名
genTable.setSubModuleName(""); // 生成子模块名
genTable.setFunctionName(genTable.getComments()); // 生成功能名
genTable.setFunctionNameSimple(genTable.getComments()); // 功能名(简称)
genTable.getOptionMap().put("isHaveDisableEnable", Global.NO); // 是否有停用启用
genTable.getOptionMap().put("isHaveDelete", Global.YES); // 是否有删除功能
genTable.getOptionMap().put("isFileUpload", Global.NO); // 是否有上传附件
genTable.getOptionMap().put("isImageUpload", Global.NO); // 是否有上传图片
for(GenTableColumn column : genTable.getColumnList()){
// 字段配置(下拉框)
if ("trade_type".equals(column.getColumnName())){
column.setShowType("select");
column.getOptionMap().put("dictType", "sys_menu_type");
}
}
// 删除旧配置
genTableService.delete(genTable);
// 保存新配置
genTable.setIsNewRecord(true);
genTableService.save(genTable);
// 编译并生成代码
genTable.setGenFlag("1"); // 1编译输出2生成文件
genTable.setReplaceFile(Global.YES); // 如果存在则替换
String result = genTableService.generateCode(genTable);
System.out.println(result);
}
}

View File

@@ -1,4 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding/<project>=UTF-8

View File

@@ -1,2 +0,0 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -28,7 +28,7 @@
<ant.version>1.9.7</ant.version>
<fst.version>2.57</fst.version>
<json.version>20180130</json.version>
<fastjson.version>1.2.61</fastjson.version>
<fastjson.version>1.2.67</fastjson.version>
<jackson.version>2.10.0.pr1</jackson.version>
<jsoup.version>1.11.3</jsoup.version>
<commons-email.version>1.5</commons-email.version>
@@ -55,6 +55,7 @@
<!-- environment setting -->
<java.version>1.8</java.version>
<tomcat.version>8.5.51</tomcat.version>
<maven.test.skip>true</maven.test.skip>
<maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version><!-- 降级到该版本新版本可能会出现VM崩溃 -->
<eclipse-plugin-download-sources>false</eclipse-plugin-download-sources>
@@ -268,6 +269,30 @@
</configuration>
</plugin>
<!-- 依赖插件 -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
@@ -316,12 +341,6 @@
<id>jeesite-repos</id>
<url>http://maven.jeesite.net/repository/maven-public</url>
</repository>
<repository>
<id>sonatype-repos-s</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
@@ -371,8 +390,8 @@
</build>
<distributionManagement>
<snapshotRepository>
<id>sonatype-repos-s</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<id>jeesite-repos-s</id>
<url>http://maven.jeesite.net/repository/maven-snapshots</url>
</snapshotRepository>
</distributionManagement>
</profile>

View File

@@ -1,5 +0,0 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.web"/>
<fixed facet="jst.java"/>
<installed facet="jst.java" version="1.8"/>
<installed facet="jst.web" version="3.1"/>
</faceted-project>

View File

@@ -14,6 +14,6 @@ cd %~dp0
cd ..
title %cd%
set "MAVEN_OPTS=%MAVEN_OPTS% -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
call mvn clean spring-boot:run -Dmaven.test.skip=true -U
call mvn clean spring-boot:run -Dmaven.test.skip=true
pause

View File

@@ -11,4 +11,4 @@ echo ""
cd ..
MAVEN_OPTS="$MAVEN_OPTS -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m"
mvn clean spring-boot:run -Dmaven.test.skip=true -U
mvn clean spring-boot:run -Dmaven.test.skip=true

View File

@@ -187,12 +187,6 @@
<id>jeesite-repos</id>
<url>http://maven.jeesite.net/repository/maven-public</url>
</repository>
<repository>
<id>sonatype-repos-s</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>

View File

@@ -26,6 +26,9 @@ server:
tomcat:
uri-encoding: UTF-8
# 将请求协议转换为 https
schemeHttps: false
#======================================#
#========== Database sttings ==========#
#======================================#
@@ -43,7 +46,7 @@ jdbc:
# # Oracle 数据库配置
# type: oracle
# driver: oracle.jdbc.driver.OracleDriver
# driver: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@127.0.0.1:1521/orcl
# username: jeesite
# password: jeesite
@@ -81,7 +84,7 @@ jdbc:
# # 最小连接数
# minIdle: 3
# # 最大连接数
# maxActive: 20 # 数据库连接池配置
# maxActive: 20
#
# # 获取连接等待超时时间单位毫秒1分钟4.0.6+
# maxWait: 60000
@@ -267,8 +270,8 @@ logging:
# 菜单管理
#menu:
# # 根据模块状态去更新相连的菜单状态仅作为微服务时设为false
# updateStatusByModuleStatus: true
# # 根据模块状态去更新相连的菜单状态
# updateStatusByModuleStatus: false
# 国际化管理(专业版)
#lang:
@@ -361,7 +364,7 @@ shiro:
#
# # 登录提交信息加密(如果不需要加密,设置为空即可)
# loginSubmit:
# # 登录提交信息安全Key加密用户名、密码、验证码后再提交key设置为3个用逗号分隔
# # 登录提交信息安全Key加密用户名、密码、验证码后再提交key设置为3个用逗号分隔默认加密方式DES
# secretKey: thinkgem,jeesite,com
# 记住我密钥设置,为空则自动生成一个新密钥,也可以通过 com.jeesite.test.RememberMeKeyGen 生成

View File

@@ -0,0 +1,115 @@
<% layout('/layouts/default.html', {title: '多表格联动示例', libs: ['layout', 'dataGrid']}){ %>
<div class="ui-layout-north">
<div class="main-content">
<div class="box box-main">
<div class="box-header">
<div class="box-title">
<i class="fa icon-trophy"></i> ${text('岗位列表')}(多表格联动示例)
</div>
</div>
<div class="ui-layout-content">
<#form:form id="searchForm" model="${post!}" action="${ctx}/sys/post/listData" method="post" class="form-inline hide"
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize!3}"
data-order-by="${parameter.orderBy!'postCode desc'}">
<div class="form-group">
<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
</div>
</#form:form>
<table id="dataGrid"></table>
<div id="dataGridPage"></div>
</div>
</div>
</div>
</div>
<div class="ui-layout-center">
<div class="main-content">
<div class="box box-main">
<div class="box-header">
<div class="box-title">
<i class="fa icon-user"></i> ${text('用户列表')}(点击岗位查询对应用户)
</div>
</div>
<div class="ui-layout-content">
<#form:form id="searchForm2" model="${empUser!}" action="${ctx}/sys/empUser/listData" method="post" class="form-inline hide"
data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize!6}"
data-order-by="${parameter.orderBy}">
<div class="form-group">
<label class="control-label">${text('岗位')}</label>
<div class="control-inline width-90">
<#form:input name="employee.postCode" id="postCode" class="form-control"/>
</div>
</div>
</#form:form>
<table id="dataGrid2"></table>
<div id="dataGrid2Page"></div>
</div>
</div>
</div>
</div>
<% } %>
<script>
// 初始化布局
$('body').layout({
north__size: 300,
onresize: function(){
$(window).resize();
}
});
// 初始化DataGrid对象
$('#dataGrid').dataGrid({
searchForm: $("#searchForm"),
dataGridPage: $('#dataGridPage'),
autoGridHeight: function(){
return $('#searchForm').parent().height() - $('#dataGridPage').height() - 45;
},
columnModel: [
{header:'${text("岗位名称")}', name:'postName', index:'a.post_name', width:200, align:"center"},
{header:'${text("岗位编码")}', name:'postCode', index:'a.post_code', width:200, align:"center"},
{header:'${text("排序号")}', name:'postSort', index:'a.post_sort', width:80, align:"center"},
{header:'${text("岗位分类")}', name:'postType', index:'a.post_type', width:100, align:"center", formatter: function(val, obj, row, act){
return js.getDictLabel(${@DictUtils.getDictListJson('sys_post_type')}, val, '未知', true);
}},
{header:'${text("更新时间")}', name:'updateDate', index:'a.update_date', width:150, align:"center"},
{header:'${text("备注信息")}', name:'remarks', index:'a.remarks', width:200, align:"left"},
{header:'${text("状态")}', name:'status', index:'a.status', width:80, align:"center", formatter: function(val, obj, row, act){
return js.getDictLabel(${@DictUtils.getDictListJson('sys_status')}, val, '未知', true);
}}
],
onSelectRow: function(id, isSelect, event){
$('#postCode').val(id);
$('#dataGrid2').dataGrid('refresh');
},
// 加载成功后执行事件
ajaxSuccess: function(data){
}
});
// 初始化DataGrid对象
$('#dataGrid2').dataGrid({
searchForm: $("#searchForm2"),
dataGridPage: $('#dataGrid2Page'),
autoGridHeight: function(){
return $('#searchForm2').parent().height() - $('#dataGrid2Page').height() - 45;
},
columnModel: [
{header:'${text("登录账号")}', name:'loginCode', index:'a.login_code', width:200, align:"center"},
{header:'${text("用户昵称")}', name:'userName', index:'a.user_name', width:200, align:"center"},
{header:'${text("员工姓名")}', name:'refName', index:'a.ref_name', width:200, align:"center"},
{header:'${text("归属机构")}', name:'employee.office.officeName', index:'o.office_name', width:200, align:"center"},
{header:'${text("归属公司")}', name:'employee.company.companyName', index:'c.company_name', width:200, align:"center"},
{header:'${text("电子邮箱")}', name:'email', index:'a.email', width:200, align:"center"},
{header:'${text("手机号码")}', name:'mobile', index:'a.mobile', width:200, align:"center"},
{header:'${text("办公电话")}', name:'phone', index:'a.phone', width:200, align:"center"},
{header:'${text("更新时间")}', name:'updateDate', index:'a.update_date', width:200, align:"center"},
{header:'${text("状态")}', name:'status', index:'a.status', width:140, align:"center", formatter: function(val, obj, row, act){
return js.getDictLabel(${@DictUtils.getDictListJson('sys_status')}, val, '未知', true);
}}
],
// 加载成功后执行事件
ajaxSuccess: function(data){
}
});
</script>

View File

@@ -1,4 +1,4 @@
<% layout('/layouts/default.html', {title: '数据管理', libs: ['validate','fileupload','ueditor','dataGrid']}){ %>
<% layout('/layouts/default.html', {title: '数据管理', libs: ['validate','fileupload','ueditor','dataGrid','inputmask']}){ %>
<div class="main-content">
<div class="box box-main">
<div class="box-header with-border">
@@ -172,6 +172,36 @@
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label class="control-label col-sm-4" title="">
<span class="required hide">*</span> 金额格式:<i class="fa icon-question hide"></i></label>
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-fw fa-rmb"></i></span>
<#form:input path="testInput_money" maxlength="200" class="form-control inputmask"
data-inputmask-alias="money" data-inputmask="'digits':'2'"/>
<span class="input-group-addon">(千分位右对齐保留2位小数)</span>
</div>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="control-label col-sm-4" title="">
<span class="required hide">*</span> 电子邮箱格式:<i class="fa icon-question hide"></i></label>
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-fw fa-envelope"></i></span>
<#form:input path="testInput_regex" maxlength="200" class="form-control inputmask"
data-inputmask-regex="[a-zA-Z0-9._%-]+@[a-zA-Z0-9-]+\\.[a-zA-Z]{2,4}"/>
<span class="input-group-addon">(正则表达式)</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
@@ -320,6 +350,21 @@ $("#testDataChildDataGrid").dataGrid({
});
}
}
},
{header:'${text("用户列表选择")}', name:'testUser2', width:150,
formatter: function(val, obj, row, act){
return js.val(row, 'testUser.userCode')+'|'+js.val(row, 'testUser.userName');
}, editable: true, edittype: "custom", editoptions: {
custom_element: function(val, editOptions) {
return js.template('listselectTpl', {
id: 'user_'+editOptions.id, title: '用户选择',
name: 'testUser.userCode', value: val.split('|')[0],
labelName: 'testUser.userName', labelValue: val.split('|')[1],
url: '${ctx}/sys/empUser/empUserSelect', cssClass: '',
itemCode: 'userCode', itemName: 'userName'
});
}
}
},
{header:'机构选择', name:'testOffice', width:150,
formatter: function(val, obj, row, act){
@@ -380,10 +425,20 @@ $("#testDataChildDataGrid").dataGrid({
<#form:treeselect id="{{d.id}}" title="{{d.title}}" name="{{d.name}}" value="{{d.value}}"
labelName="{{d.labelName}}" labelValue="{{d.labelValue}}" url="{{d.url}}"
class="{{d.cssClass}}" btnClass="btn-sm" allowClear="true"/>
</div>//--></script>
<script id="listselectTpl" type="text/template">//<!--<div>
<#form:listselect id="{{d.id}}" title="{{d.title}}" name="{{d.name}}" value="{{d.value}}"
labelName="{{d.labelName}}" labelValue="{{d.labelValue}}" url="{{d.url}}"
class="{{d.cssClass}}" btnClass="btn-sm" allowClear="true"
itemCode="{{d.itemCode}}" itemName="{{d.itemName}}"/>
</div>//--></script>
<script>
$("#inputForm").validate({
submitHandler: function(form){
// 数据格式化恢复(表单提交之前调用)
$('.inputmask').inputmask('remove');
// js.ajaxSubmitForm($(form), function(data){
// js.showMessage(data.message);
// if(data.result == Global.TRUE){
@@ -392,7 +447,15 @@ $("#inputForm").validate({
// });
// }
// }, "json");
log($(form).serializeArray());
js.showMessage('模拟保存成功');
// 数据格式化(初始化完成表单后调用)
$(".inputmask").inputmask();
}
});
//数据格式化(初始化完成表单后调用)
$(".inputmask").inputmask();
</script>

View File

@@ -0,0 +1,68 @@
<% layout('/layouts/default.html', {title: '多页签应用示例', libs: ['tabPage']}){ %>
<div class="main-content">
<div class="box box-main">
<div class="box-header with-border">
<div class="box-title">
<i class="fa icon-notebook"></i> 多页签应用示例
</div>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" onclick="js.addTabPage(null, '机构列表', '${ctx}/sys/office/list')"><i class="fa fa-plus"></i> 添加页签(1)</button>
<button type="button" class="btn btn-box-tool" onclick="b.addTabPage(null, '公司列表', '${ctx}/sys/company/list')"><i class="fa fa-plus"></i> 添加页签(2)</button>
<button type="button" class="btn btn-box-tool" onclick="top.js.closeCurrentTabPage()"><i class="fa fa-close"></i> 关闭窗口</button>
</div>
</div>
<div class="box-body pt0">
<div class="row">
<div class="col-sm-6 pr0">
<div id="tabpanel1"></div>
</div>
<div class="col-sm-6 pl0">
<div id="tabpanel2"></div>
</div>
</div>
</div>
</div>
</div>
<% } %>
<style>
.tabpanel_tab_content .tabpanel_move_content {background: #fff;}
</style>
<script>
// 一个页面一个 tab 控件
js.initTabPage('tabpanel1', {
height: function () {
var windowHeight = $(window).height(),
headerHeight = $('.box-header').outerHeight(),
footerHeight = $('.box-footer').outerHeight(),
height = windowHeight - headerHeight - footerHeight - 3;
return height < 300 ? 300 : height;
}
});
// 打开示例页面(不可关闭)
js.addTabPage(null, "机构列表", "${ctx}/sys/office/list", false);
js.addTabPage(null, "用户列表", "${ctx}/sys/empUser/list", false);
// 用于机构保存后的刷新列表页面(示例)
window.win = $('#tabpanel1 iframe:first')[0].contentWindow;
// 激活第一个页签
$('#tabpanel1 .tabpanel_mover li:first').click();
// 一个页面多个 tab 控件展示
var b = $.extend([], tabPage);
b.initTabPage('tabpanel2', {
height: function () {
var windowHeight = $(window).height(),
headerHeight = $('.box-header').outerHeight(),
footerHeight = $('.box-footer').outerHeight(),
height = windowHeight - headerHeight - footerHeight - 3;
return height < 300 ? 300 : height;
}
});
b.addTabPage(null, "岗位列表", "${ctx}/sys/post/list", false);
b.addTabPage(null, "公司列表", "${ctx}/sys/company/list", false);
$('#tabpanel2 .tabpanel_mover li:first').click();
// 指定内页调用的 tab 对象
window.tabPage = top.tabPage;
</script>

View File

@@ -270,6 +270,21 @@ $("#testDataChildDataGrid").dataGrid({
}
}
},
{header:'${text("用户列表选择")}', name:'testUser2', width:150,
formatter: function(val, obj, row, act){
return js.val(row, 'testUser.userCode')+'|'+js.val(row, 'testUser.userName');
}, editable: true, edittype: "custom", editoptions: {
custom_element: function(val, editOptions) {
return js.template('listselectTpl', {
id: 'user_'+editOptions.id, title: '用户选择',
name: 'testUser2.userCode', value: val.split('|')[0],
labelName: 'testUser2.userName', labelValue: val.split('|')[1],
url: '${ctx}/sys/empUser/empUserSelect', cssClass: '',
itemCode: 'userCode', itemName: 'userName'
});
}
}
},
{header:'${text("机构选择")}', name:'testOffice', width:150,
formatter: function(val, obj, row, act){
return js.val(row, 'testOffice.officeCode')+'|'+js.val(row, 'testOffice.officeName');
@@ -332,6 +347,12 @@ $("#testDataChildDataGrid").dataGrid({
<#form:treeselect id="{{d.id}}" title="{{d.title}}" name="{{d.name}}" value="{{d.value}}"
labelName="{{d.labelName}}" labelValue="{{d.labelValue}}" url="{{d.url}}"
class="{{d.cssClass}}" btnClass="btn-sm" allowClear="true"/>
</div>//--></script>
<script id="listselectTpl" type="text/template">//<!--<div>
<#form:listselect id="{{d.id}}" title="{{d.title}}" name="{{d.name}}" value="{{d.value}}"
labelName="{{d.labelName}}" labelValue="{{d.labelValue}}" url="{{d.url}}"
class="{{d.cssClass}}" btnClass="btn-sm" allowClear="true"
itemCode="{{d.itemCode}}" itemName="{{d.itemName}}"/>
</div>//--></script>
<script>
$("#inputForm").validate({