Răsfoiți Sursa

Merge branch 'wrdp' into 'develop'

Wrdp

See merge request o2oa/o2oa!2646
胡起 5 ani în urmă
părinte
comite
a83dcc0180
26 a modificat fișierele cu 1115 adăugiri și 114 ștergeri
  1. 163 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportPersonStatistic.java
  2. 172 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportTopUnitStatistic.java
  3. 190 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportUnitSubNestedStatistic.java
  4. 156 2
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/BaseAction.java
  5. 12 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionAttendanceStatisticProcess.java
  6. 12 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionPersonNameEmpty.java
  7. 12 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionQueryStatisticUnitNameEmpty.java
  8. 12 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionTopUnitNameEmpty.java
  9. 63 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/FileImportExportAction.java
  10. 84 10
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/WiDesigner.java
  11. 20 10
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/designer/ActionSearch.java
  12. 27 14
      o2server/x_portal_assemble_designer/src/main/java/com/x/portal/assemble/designer/jaxrs/designer/ActionSearch.java
  13. 28 16
      o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/designer/ActionSearch.java
  14. 22 9
      o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/designer/ActionSearch.java
  15. 40 24
      o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/designer/ActionSearch.java
  16. 18 18
      o2server/x_query_service_processing/src/main/java/com/x/query/service/processing/jaxrs/design/ActionSearch.java
  17. 0 6
      o2server/x_query_service_processing/src/main/java/com/x/query/service/processing/jaxrs/design/DesignAction.java
  18. 34 0
      o2web/source/o2_core/o2/xAction/services/x_attendance_assemble_control.js
  19. 6 0
      o2web/source/o2_core/o2/xAction/services/x_attendance_assemble_control.json
  20. 1 1
      o2web/source/o2_core/o2/xDesktop/WebSocket.js
  21. 10 1
      o2web/source/x_component_Attendance/PeopleDetail.js
  22. 9 1
      o2web/source/x_component_Attendance/TopUnitDetail.js
  23. 9 1
      o2web/source/x_component_Attendance/UnitDetail.js
  24. 6 0
      o2web/source/x_component_Setting/Document.js
  25. 3 1
      o2web/source/x_component_Setting/lp/zh-cn.js
  26. 6 0
      o2web/source/x_desktop/js/base_simple_anonymous.js

+ 163 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportPersonStatistic.java

@@ -0,0 +1,163 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.attendance.entity.StatisticPersonForMonth;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoFile;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+public class ActionExportPersonStatistic extends BaseAction {
+	
+	private static  Logger logger = LoggerFactory.getLogger(ActionExportPersonStatistic.class);
+	
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String name, String year, String month ,Boolean stream ) throws Exception {
+			ActionResult<Wo> result = new ActionResult<>();
+			List<String> ids = null;
+			List<StatisticPersonForMonth> statisticPersonForMonth_list = null;
+			Workbook wb = null;
+			Wo wo = null;
+			String fileName = null;
+			String sheetName = null;
+			Boolean check = true;
+
+			if ("(0)".equals(year)) {
+				year = null;
+			}
+			if ("(0)".equals(month)) {
+				month = null;
+			}
+			if( check ){
+				if( name == null || name.isEmpty() ){
+					check = false;
+					Exception exception = new ExceptionPersonNameEmpty();
+					result.error( exception );
+				}
+			}
+
+			if( check ){
+				try {
+					ids = attendanceStatisticServiceAdv.listPersonForMonthByUserYearAndMonth(name, year, month);
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceStatisticProcess( e,
+							"系统根据人员姓名,年份和月份查询统计数据信息ID列表时发生异常.Name:"+name+", Year:"+year+", Month:" + month
+					);
+					result.error( exception );
+					logger.error( e, effectivePerson, request, null);
+				}
+			}
+			if( check ){
+				if( ids != null && !ids.isEmpty() ){
+					try {
+						statisticPersonForMonth_list = attendanceStatisticServiceAdv.listPersonForMonth(ids);
+					} catch (Exception e) {
+						check = false;
+						Exception exception = new ExceptionAttendanceStatisticProcess( e, "系统根据ID列表查询个人每月统计数据信息列表时发生异常." );
+						result.error( exception );
+						logger.error( e, effectivePerson, request, null);
+					}
+				}
+			}
+			
+			// 将结果组织成EXCEL		
+			if( check ) {
+				if(StringUtils.isNotEmpty(name) && StringUtils.contains(name,"@")){
+					fileName = "" + name.split("@")[0] + "的个人出勤率统计记录_"+year+"年"+month+"月.xls";
+				}else{
+					fileName = "" + name + "的个人出勤率统计记录_"+year+"年"+month+"月.xls";
+				}
+				sheetName = "个人出勤率统计记录";
+				wb = composeDetail( fileName, sheetName, statisticPersonForMonth_list );
+			}
+			
+			//输出数据信息
+			if( check ) {
+				ByteArrayOutputStream bos = new ByteArrayOutputStream();
+				try {
+				    wb.write(bos);
+				    wo = new Wo(bos.toByteArray(), 
+							this.contentType(stream, fileName), 
+							this.contentDisposition(stream, fileName));
+				} finally {
+				    bos.close();
+				}
+			}		
+			result.setData(wo);
+			return result;
+		}
+
+		private Workbook composeDetail(String fileName, String sheetName, List<StatisticPersonForMonth> statisticPersonForMonth_list) throws Exception {
+			Workbook wb = new HSSFWorkbook();
+			Row row = null;
+			if (ListTools.isNotEmpty(statisticPersonForMonth_list)) {
+				// 创建新的表格
+				Sheet sheet = wb.createSheet(sheetName);
+				// 先创建表头
+				row = sheet.createRow(0);
+				row.createCell(0).setCellValue("顶层组织名称");
+				row.createCell(1).setCellValue("组织名称");
+				row.createCell(2).setCellValue("姓名");
+				row.createCell(3).setCellValue("月份");
+				row.createCell(4).setCellValue("上班打卡次数");
+				row.createCell(5).setCellValue("下班打卡次数");
+				row.createCell(6).setCellValue("出勤人天数");
+				row.createCell(7).setCellValue("请假或外出报备人天数");
+				row.createCell(8).setCellValue("缺勤人天数");
+				row.createCell(9).setCellValue("迟到次数");
+				row.createCell(10).setCellValue("工时不足人次");
+				row.createCell(11).setCellValue("异常打卡人次");
+
+				logger.info("一共有"+statisticPersonForMonth_list.size()+"条请求记录可以输出。");
+				for (int i = 0; i < statisticPersonForMonth_list.size(); i++) {
+					StatisticPersonForMonth statisticPersonForMonth = null;
+					statisticPersonForMonth = statisticPersonForMonth_list.get(i);
+					if( statisticPersonForMonth != null ){
+						row = sheet.createRow(i + 1);
+						String topUnitName = statisticPersonForMonth.getTopUnitName();
+						String unitName = statisticPersonForMonth.getUnitName();
+						String empName = statisticPersonForMonth.getEmployeeName();
+						if(StringUtils.isNotEmpty(topUnitName) && StringUtils.contains(topUnitName,"@")){
+							topUnitName = topUnitName.split("@")[0];
+						}
+						if(StringUtils.isNotEmpty(unitName) && StringUtils.contains(unitName,"@")){
+							unitName = unitName.split("@")[0];
+						}
+						if(StringUtils.isNotEmpty(empName) && StringUtils.contains(empName,"@")){
+							empName = empName.split("@")[0];
+						}
+						row.createCell(0).setCellValue(topUnitName);
+						row.createCell(1).setCellValue(unitName);
+						row.createCell(2).setCellValue(empName);
+						row.createCell(3).setCellValue(statisticPersonForMonth.getStatisticYear()+"-"+statisticPersonForMonth.getStatisticMonth());
+						row.createCell(4).setCellValue(statisticPersonForMonth.getOnDutyTimes());
+						row.createCell(5).setCellValue(statisticPersonForMonth.getOnDutyTimes());
+						row.createCell(6).setCellValue(statisticPersonForMonth.getOnDutyDayCount());
+						row.createCell(7).setCellValue(statisticPersonForMonth.getOnSelfHolidayCount());
+						row.createCell(8).setCellValue(statisticPersonForMonth.getAbsenceDayCount());
+						row.createCell(9).setCellValue(statisticPersonForMonth.getLateTimes());
+						row.createCell(10).setCellValue(statisticPersonForMonth.getLackOfTimeCount());
+						row.createCell(11).setCellValue(statisticPersonForMonth.getAbNormalDutyCount());
+					}
+				}
+
+			}
+			return wb;
+		}
+
+		public static class Wo extends WoFile {
+			public Wo(byte[] bytes, String contentType, String contentDisposition) {
+				super(bytes, contentType, contentDisposition);
+			}
+		}
+	}

+ 172 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportTopUnitStatistic.java

@@ -0,0 +1,172 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.attendance.entity.StatisticUnitForMonth;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoFile;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActionExportTopUnitStatistic extends BaseAction {
+	
+	private static  Logger logger = LoggerFactory.getLogger(ActionExportTopUnitStatistic.class);
+	
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String name, String year, String month ,Boolean stream ) throws Exception {
+			ActionResult<Wo> result = new ActionResult<>();
+			List<String> ids = null;
+			List<String> unitNames = new ArrayList<String>();
+			List<StatisticUnitForMonth> statisticUnitForMonth_list = null;
+			Workbook wb = null;
+			Wo wo = null;
+			String fileName = null;
+			String sheetName = null;
+			Boolean check = true;
+
+			if ("(0)".equals(year)) {
+				year = null;
+			}
+			if ("(0)".equals(month)) {
+				month = null;
+			}
+			if( check ){
+				if( name == null || name.isEmpty() ){
+					check = false;
+					Exception exception = new ExceptionTopUnitNameEmpty();
+					result.error( exception );
+				}
+			}
+			if( check ){
+				try {
+					//根据顶层组织递归查询下级顶层组织经及顶层组织的顶级组织
+					unitNames = getTopUnitNameList( name, unitNames, effectivePerson.getDebugger() );
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceStatisticProcess( e,
+							"根据顶层组织递归查询下级顶层组织经及顶层组织的顶级组织时发生异常!"
+									+ "Name:" + name
+									+ ", Units:" + unitNames );
+					result.error( exception );
+					logger.error( e, effectivePerson, request, null);
+				}
+			}
+			if( check ){
+				if( unitNames == null ){
+					unitNames = new ArrayList<>();
+				}
+				unitNames.add( name );
+			}
+			if( check ){
+				try {
+					ids = attendanceStatisticServiceAdv.listUnitForMonthByUnitYearAndMonth( unitNames, year, month);
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceStatisticProcess(e,
+							"系统根据组织名称列表,年份和月份查询组织统计数据信息ID列表时发生异常.Name:"+unitNames+", Year:"+year+", Month:" + month
+					);
+					result.error( exception );
+					logger.error( e, effectivePerson, request, null);
+				}
+			}
+			if( check ){
+				if( ids != null && !ids.isEmpty() ){
+					try {
+						statisticUnitForMonth_list = attendanceStatisticServiceAdv.listUnitForMonth( ids );
+					} catch (Exception e) {
+						check = false;
+						Exception exception = new ExceptionAttendanceStatisticProcess( e, "系统根据ID列表查询组织每月统计数据信息列表时发生异常." );
+						result.error( exception );
+						logger.error( e, effectivePerson, request, null);
+					}
+				}
+			}
+			
+			// 将结果组织成EXCEL		
+			if( check ) {
+				if(StringUtils.isNotEmpty(name) && StringUtils.contains(name,"@")){
+					fileName = "" + name.split("@")[0] + "的出勤率统计记录_"+year+"年"+month+"月.xls";
+				}else{
+					fileName = "" + name + "的出勤率统计记录_"+year+"年"+month+"月.xls";
+				}
+				sheetName = "公司出勤率统计记录";
+				wb = composeDetail( fileName, sheetName, statisticUnitForMonth_list );
+			}
+			
+			//输出数据信息
+			if( check ) {
+				ByteArrayOutputStream bos = new ByteArrayOutputStream();
+				try {
+				    wb.write(bos);
+				    wo = new Wo(bos.toByteArray(), 
+							this.contentType(stream, fileName), 
+							this.contentDisposition(stream, fileName));
+				} finally {
+				    bos.close();
+				}
+			}		
+			result.setData(wo);
+			return result;
+		}
+
+		private Workbook composeDetail(String fileName, String sheetName, List<StatisticUnitForMonth> statisticUnitForMonth_list) throws Exception {
+			Workbook wb = new HSSFWorkbook();
+			Row row = null;
+			if (ListTools.isNotEmpty(statisticUnitForMonth_list)) {
+				// 创建新的表格
+				Sheet sheet = wb.createSheet(sheetName);
+				// 先创建表头
+				row = sheet.createRow(0);
+				row.createCell(0).setCellValue("公司");
+				row.createCell(1).setCellValue("月份");
+				row.createCell(2).setCellValue("上班打卡次数");
+				row.createCell(3).setCellValue("下班打卡次数");
+				row.createCell(4).setCellValue("出勤人天数");
+				row.createCell(5).setCellValue("请假或外出报备人天数");
+				row.createCell(6).setCellValue("缺勤人天数");
+				row.createCell(7).setCellValue("迟到次数");
+				row.createCell(8).setCellValue("工时不足人次");
+				row.createCell(9).setCellValue("异常打卡人次");
+
+				logger.info("一共有"+statisticUnitForMonth_list.size()+"条请求记录可以输出。");
+				for (int i = 0; i < statisticUnitForMonth_list.size(); i++) {
+					StatisticUnitForMonth statisticUnitForMonth = null;
+					statisticUnitForMonth = statisticUnitForMonth_list.get(i);
+					if( statisticUnitForMonth != null ){
+						row = sheet.createRow(i + 1);
+						String topUnitName = statisticUnitForMonth.getTopUnitName();
+						if(StringUtils.isNotEmpty(topUnitName) && StringUtils.contains(topUnitName,"@")){
+							topUnitName = topUnitName.split("@")[0];
+						}
+						row.createCell(0).setCellValue(topUnitName);
+						row.createCell(1).setCellValue(statisticUnitForMonth.getStatisticYear()+"-"+statisticUnitForMonth.getStatisticMonth());
+						row.createCell(2).setCellValue(statisticUnitForMonth.getOnDutyCount());
+						row.createCell(3).setCellValue(statisticUnitForMonth.getOffDutyCount());
+						row.createCell(4).setCellValue(statisticUnitForMonth.getOnDutyEmployeeCount());
+						row.createCell(5).setCellValue(statisticUnitForMonth.getOnSelfHolidayCount());
+						row.createCell(6).setCellValue(statisticUnitForMonth.getAbsenceDayCount());
+						row.createCell(7).setCellValue(statisticUnitForMonth.getLateCount());
+						row.createCell(8).setCellValue(statisticUnitForMonth.getLackOfTimeCount());
+						row.createCell(9).setCellValue(statisticUnitForMonth.getAbNormalDutyCount());
+					}
+				}
+			}
+			return wb;
+		}
+
+
+		public static class Wo extends WoFile {
+			public Wo(byte[] bytes, String contentType, String contentDisposition) {
+				super(bytes, contentType, contentDisposition);
+			}
+		}
+	}

+ 190 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ActionExportUnitSubNestedStatistic.java

@@ -0,0 +1,190 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.attendance.entity.StatisticPersonForMonth;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoFile;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ActionExportUnitSubNestedStatistic extends BaseAction {
+	
+	private static  Logger logger = LoggerFactory.getLogger(ActionExportUnitSubNestedStatistic.class);
+	
+	protected ActionResult<Wo> execute( HttpServletRequest request, EffectivePerson effectivePerson, String name, String year, String month ,Boolean stream ) throws Exception {
+			ActionResult<Wo> result = new ActionResult<>();
+			List<String> ids = null;
+			List<String> unitNameList = new ArrayList<String>();
+			List<String> unUnitNameList = new ArrayList<String>();
+			List<String> personNameList = new ArrayList<String>();
+			List<StatisticPersonForMonth> statisticPersonForMonth_list = null;
+			Workbook wb = null;
+			Wo wo = null;
+			String fileName = null;
+			String sheetName = null;
+			Boolean check = true;
+
+			if ("(0)".equals(year)) {
+				year = null;
+			}
+			if ("(0)".equals(month)) {
+				month = null;
+			}
+			if( check ){
+				if( name == null || name.isEmpty() ){
+					check = false;
+					Exception exception = new ExceptionQueryStatisticUnitNameEmpty();
+					result.error( exception );
+				}
+			}
+			if( check ){
+				try {
+					unitNameList = userManagerService.listSubUnitNameWithParent( name );
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceStatisticProcess( e, "根据组织名称列示所有下级组织名称发生异常!Unit:" + name );
+					result.error( exception );
+					logger.error( e, effectivePerson, request, null);
+				}
+			}
+			if( check ){
+				if( unitNameList == null ){
+					unitNameList = new ArrayList<>();
+				}
+				unitNameList.add( name );
+				unUnitNameList = getUnUnitNameList();
+				personNameList = getUnPersonNameList();
+				logger.info("ActionShowStForPersonInUnitSubNested____unitNameList="+unitNameList);
+				logger.info("ActionShowStForPersonInUnitSubNested____unUnitNameList="+unUnitNameList);
+				logger.info("ActionShowStForPersonInUnitSubNested____personNameList="+personNameList);
+			}
+			if( check ){
+				try {
+					//ids = attendanceStatisticServiceAdv.listPersonForMonthByUnitYearAndMonth( unitNameList, year, month);
+					ids = attendanceStatisticServiceAdv.listPersonForMonthByUnitYearMonthAndUn( unitNameList, unUnitNameList,personNameList,year, month);
+					logger.info("ActionShowStForPersonInUnitSubNested____ids="+ids.size());
+				} catch (Exception e) {
+					check = false;
+					Exception exception = new ExceptionAttendanceStatisticProcess(e,
+							"系统根据组织名称列表,年份和月份查询个人统计数据信息ID列表时发生异常.Name:"+unitNameList+", Year:"+year+", Month:" + month
+					);
+					result.error( exception );
+					logger.error( e, effectivePerson, request, null);
+				}
+			}
+			if( check ){
+				if( ids != null && !ids.isEmpty() ){
+					try {
+						statisticPersonForMonth_list = attendanceStatisticServiceAdv.listPersonForMonth( ids );
+					} catch (Exception e) {
+						check = false;
+						Exception exception = new ExceptionAttendanceStatisticProcess( e, "系统根据ID列表查询个人每月统计数据信息列表时发生异常." );
+						result.error( exception );
+						logger.error( e, effectivePerson, request, null);
+					}
+				}
+			}
+			
+			// 将结果组织成EXCEL		
+			if( check ) {
+				if(StringUtils.isNotEmpty(name) && StringUtils.contains(name,"@")){
+					fileName = "" + name.split("@")[0] + "的部门出勤率统计记录_"+year+"年"+month+"月.xls";
+				}else{
+					fileName = "" + name + "的部门出勤率统计记录_"+year+"年"+month+"月.xls";
+				}
+				sheetName = "部门出勤率统计记录";
+				wb = composeDetail( fileName, sheetName, statisticPersonForMonth_list );
+			}
+			
+			//输出数据信息
+			if( check ) {
+				ByteArrayOutputStream bos = new ByteArrayOutputStream();
+				try {
+				    wb.write(bos);
+				    wo = new Wo(bos.toByteArray(), 
+							this.contentType(stream, fileName), 
+							this.contentDisposition(stream, fileName));
+				} finally {
+				    bos.close();
+				}
+			}		
+			result.setData(wo);
+			return result;
+		}
+
+		private Workbook composeDetail(String fileName, String sheetName, List<StatisticPersonForMonth> statisticPersonForMonth_list) throws Exception {
+			Workbook wb = new HSSFWorkbook();
+			Row row = null;
+			if (ListTools.isNotEmpty(statisticPersonForMonth_list)) {
+				// 创建新的表格
+				Sheet sheet = wb.createSheet(sheetName);
+				// 先创建表头
+				row = sheet.createRow(0);
+				row.createCell(0).setCellValue("顶层组织名称");
+				row.createCell(1).setCellValue("组织名称");
+				row.createCell(2).setCellValue("姓名");
+				row.createCell(3).setCellValue("月份");
+				row.createCell(4).setCellValue("上班打卡次数");
+				row.createCell(5).setCellValue("下班打卡次数");
+				row.createCell(6).setCellValue("出勤人天数");
+				row.createCell(7).setCellValue("请假或外出报备人天数");
+				row.createCell(8).setCellValue("缺勤人天数");
+				row.createCell(9).setCellValue("迟到次数");
+				row.createCell(10).setCellValue("工时不足人次");
+				row.createCell(11).setCellValue("异常打卡人次");
+
+				logger.info("一共有"+statisticPersonForMonth_list.size()+"条请求记录可以输出。");
+				for (int i = 0; i < statisticPersonForMonth_list.size(); i++) {
+					StatisticPersonForMonth statisticPersonForMonth = null;
+					statisticPersonForMonth = statisticPersonForMonth_list.get(i);
+					if( statisticPersonForMonth != null ){
+						row = sheet.createRow(i + 1);
+						String topUnitName = statisticPersonForMonth.getTopUnitName();
+						String unitName = statisticPersonForMonth.getUnitName();
+						String empName = statisticPersonForMonth.getEmployeeName();
+						if(StringUtils.isNotEmpty(topUnitName) && StringUtils.contains(topUnitName,"@")){
+							topUnitName = topUnitName.split("@")[0];
+						}
+						if(StringUtils.isNotEmpty(unitName) && StringUtils.contains(unitName,"@")){
+							unitName = unitName.split("@")[0];
+						}
+						if(StringUtils.isNotEmpty(empName) && StringUtils.contains(empName,"@")){
+							empName = empName.split("@")[0];
+						}
+						row.createCell(0).setCellValue(topUnitName);
+						row.createCell(1).setCellValue(unitName);
+						row.createCell(2).setCellValue(empName);
+						row.createCell(3).setCellValue(statisticPersonForMonth.getStatisticYear()+"-"+statisticPersonForMonth.getStatisticMonth());
+						row.createCell(4).setCellValue(statisticPersonForMonth.getOnDutyTimes());
+						row.createCell(5).setCellValue(statisticPersonForMonth.getOnDutyTimes());
+						row.createCell(6).setCellValue(statisticPersonForMonth.getOnDutyDayCount());
+						row.createCell(7).setCellValue(statisticPersonForMonth.getOnSelfHolidayCount());
+						row.createCell(8).setCellValue(statisticPersonForMonth.getAbsenceDayCount());
+						row.createCell(9).setCellValue(statisticPersonForMonth.getLateTimes());
+						row.createCell(10).setCellValue(statisticPersonForMonth.getLackOfTimeCount());
+						row.createCell(11).setCellValue(statisticPersonForMonth.getAbNormalDutyCount());
+					}
+				}
+
+			}
+			return wb;
+		}
+
+
+		public static class Wo extends WoFile {
+			public Wo(byte[] bytes, String contentType, String contentDisposition) {
+				super(bytes, contentType, contentDisposition);
+			}
+		}
+	}

+ 156 - 2
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/BaseAction.java

@@ -1,13 +1,167 @@
 package com.x.attendance.assemble.control.jaxrs.attachment;
 
 import com.x.attendance.assemble.common.date.DateOperation;
-import com.x.attendance.assemble.control.service.AttendanceImportFileInfoServiceAdv;
-import com.x.attendance.assemble.control.service.AttendanceScheduleSettingServiceAdv;
+import com.x.attendance.assemble.control.service.*;
+import com.x.attendance.entity.AttendanceEmployeeConfig;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.jaxrs.StandardJaxrsAction;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public class BaseAction extends StandardJaxrsAction {
+	protected Logger logger = LoggerFactory.getLogger(BaseAction.class );
 	protected AttendanceImportFileInfoServiceAdv importFileInfoServiceAdv = new AttendanceImportFileInfoServiceAdv();
+	protected AttendanceStatisticServiceAdv attendanceStatisticServiceAdv = new AttendanceStatisticServiceAdv();
+	protected UserManagerService userManagerService = new UserManagerService();
 	protected AttendanceScheduleSettingServiceAdv attendanceScheduleSettingServiceAdv = new AttendanceScheduleSettingServiceAdv();
+	protected AttendanceEmployeeConfigServiceAdv attendanceEmployeeConfigServiceAdv = new AttendanceEmployeeConfigServiceAdv();
 	protected DateOperation dateOperation = new DateOperation();
+
+	// 根据组织递归查询下级组织
+	protected List<String> getUnitNameList(String unitName, List<String> unitNameList ) throws Exception {
+		if (unitNameList == null) {
+			unitNameList = new ArrayList<String>();
+		}
+		if ( StringUtils.isNotEmpty( unitName ) && !unitNameList.contains(unitName.trim())) {
+			unitNameList.add(unitName.trim());
+
+			// 查询该组织的下级组织
+			List<String> unitList = null;
+			try {
+				// 对查询的unit进行解析,如果有下级组织的,全部解析出来
+				unitList = userManagerService.listSubUnitNameWithParent( unitName );
+			} catch (Exception e) {
+				throw e;
+			}
+			if (unitList != null && unitList.size() > 0) {
+				for (String unit : unitList) {
+					getUnitNameList( unit, unitNameList);
+				}
+			}
+		}
+		return unitNameList;
+	}
+
+	// 根据顶层组织递归查询下级顶层组织经及顶层组织的顶级组织
+	protected List<String> getTopUnitNameList( String topUnitName, List<String> unitNameList, Boolean debugger )
+			throws Exception {
+		if (unitNameList == null) {
+			unitNameList = new ArrayList<String>();
+		}
+		if ( StringUtils.isNotEmpty( topUnitName ) && !unitNameList.contains(topUnitName.trim())) {
+			unitNameList.add( topUnitName.trim() );
+
+			// 查询该组织的下级组织
+			List<String> unitList = null;
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create();) {
+				// 查询所有的Top组织
+				unitList = userManagerService.listSubUnitNameWithParent(topUnitName);
+				if ( unitList != null && unitList.size() > 0 ) {
+					logger.debug( debugger, ">>>>>>>>>>根据顶层组织名称["+topUnitName+"]查询到"+unitList.size()+"个顶级组织。");
+					for ( String unit : unitList) {
+						if (unitNameList.contains( unit )) {
+							unitNameList.add( unit );
+						}
+						getUnitNameList( unit, unitNameList );
+					}
+				} else {
+					logger.debug( debugger, ">>>>>>>>>>根据顶层组织名称["+topUnitName+"]未查询到任何顶级组织。");
+				}
+			} catch (Exception e) {
+				throw e;
+			}
+		}
+		return unitNameList;
+	}
+
+	/**
+	 * 根据List<String> topUnitNameList, List<String> unitNameList
+	 * 查询所有符合查询范围所组织以及下级组织名称列表
+	 *
+	 * @param topUnitNameList
+	 * @param unitNameList
+	 * @return
+	 * @throws Exception
+	 */
+	protected List<String> getUnitNameList(List<String> topUnitNameList, List<String> unitNameList, Boolean debugger )
+			throws Exception {
+
+		if (unitNameList == null) {
+			unitNameList = new ArrayList<String>();
+		}
+		// 先查询顶层组织所有的下属组织,全部加入List中
+		// 对查询的unit进行解析,如果有下级组织的,全部解析出来
+		if (topUnitNameList != null && topUnitNameList.size() > 0) {
+			for (String topUnitName : topUnitNameList) {
+				// 再递归查询所有的下级顶层组织以及所有组织
+				getTopUnitNameList(topUnitName, unitNameList, debugger );
+			}
+		}
+		// 对查询的unit进行解析,如果有下级组织的,全部解析出来
+		if (unitNameList != null && unitNameList.size() > 0) {
+			for (String unitName : unitNameList) {
+				getUnitNameList(unitName, unitNameList);
+			}
+		}
+		return unitNameList;
+	}
+
+	/**
+	 * 获取不需要考勤的组织
+	 * @return
+	 * @throws Exception
+	 */
+	protected  List<String> getUnUnitNameList() throws Exception {
+		List<String> unUnitNameList = new ArrayList<String>();
+
+		List<AttendanceEmployeeConfig> attendanceEmployeeConfigs = attendanceEmployeeConfigServiceAdv.listByConfigType("NOTREQUIRED");
+
+		if(ListTools.isNotEmpty(attendanceEmployeeConfigs)){
+			for (AttendanceEmployeeConfig attendanceEmployeeConfig : attendanceEmployeeConfigs) {
+				String unitName = attendanceEmployeeConfig.getUnitName();
+				String employeeName = attendanceEmployeeConfig.getEmployeeName();
+
+				if(StringUtils.isEmpty(employeeName) && StringUtils.isNotEmpty(unitName)){
+					unUnitNameList.add(unitName);
+					List<String> tempUnitNameList = userManagerService.listSubUnitNameWithParent(unitName);
+					if(ListTools.isNotEmpty(tempUnitNameList)){
+						for(String tempUnit:tempUnitNameList){
+							if(!ListTools.contains(unUnitNameList, tempUnit)){
+								unUnitNameList.add(tempUnit);
+							}
+						}
+					}
+				}
+			}
+		}
+		return unUnitNameList;
+	}
+
+	/**
+	 * 获取不需要考勤的人员
+	 * @return
+	 * @throws Exception
+	 */
+	protected  List<String> getUnPersonNameList() throws Exception {
+		List<String> personNameList = new ArrayList<String>();
+		List<AttendanceEmployeeConfig> attendanceEmployeeConfigs = attendanceEmployeeConfigServiceAdv.listByConfigType("NOTREQUIRED");
+
+		if(ListTools.isNotEmpty(attendanceEmployeeConfigs)){
+			for (AttendanceEmployeeConfig attendanceEmployeeConfig : attendanceEmployeeConfigs) {
+				String employeeName = attendanceEmployeeConfig.getEmployeeName();
+
+				if(StringUtils.isNotEmpty(employeeName) && !ListTools.contains(personNameList, employeeName)){
+					personNameList.add(employeeName);
+				}
+			}
+		}
+		return personNameList;
+	}
 }
 

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionAttendanceStatisticProcess.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionAttendanceStatisticProcess extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	public ExceptionAttendanceStatisticProcess(Throwable e, String message ) {
+		super("用户在进行考勤统计处理时发生异常!message:" + message, e );
+	}
+}

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionPersonNameEmpty.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionPersonNameEmpty extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	public ExceptionPersonNameEmpty() {
+		super("系统未获取到查询参数员工姓名name,无法进行数据查询");
+	}
+}

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionQueryStatisticUnitNameEmpty.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionQueryStatisticUnitNameEmpty extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	public ExceptionQueryStatisticUnitNameEmpty() {
+		super("系统未获取到查询参数组织名称name,无法进行数据查询");
+	}
+}

+ 12 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/ExceptionTopUnitNameEmpty.java

@@ -0,0 +1,12 @@
+package com.x.attendance.assemble.control.jaxrs.attachment;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionTopUnitNameEmpty extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	public ExceptionTopUnitNameEmpty() {
+		super("系统未获取到查询参数顶层组织名称name,无法进行数据查询");
+	}
+}

+ 63 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/jaxrs/attachment/FileImportExportAction.java

@@ -135,4 +135,67 @@ public class FileImportExportAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
+
+	@JaxrsMethodDescribe(value = "导出个人出勤率统计记录,设定是否使用stream输出", action = ActionExportPersonStatistic.class)
+	@GET
+	@Path("export/person/{name}/{year}/{month}/stream/{stream}")
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void personStatisticExportStream(@Suspended final AsyncResponse asyncResponse,
+											@Context HttpServletRequest request,
+											@JaxrsParameterDescribe("统计员工姓名") @PathParam("name") String name,
+											@JaxrsParameterDescribe("统计周期年份") @PathParam("year") String year,
+											@JaxrsParameterDescribe("统计周期月份") @PathParam("month") String month,
+											@JaxrsParameterDescribe("用.APPLICATION_OCTET_STREAM头输出") @PathParam("stream") Boolean stream) {
+		ActionResult<ActionExportPersonStatistic.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionExportPersonStatistic().execute(request, effectivePerson, name, year, month, stream);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
+	@JaxrsMethodDescribe(value = "导出部门出勤率统计记录,设定是否使用stream输出", action = ActionExportUnitSubNestedStatistic.class)
+	@GET
+	@Path("export/unit/{name}/{year}/{month}/stream/{stream}")
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void unitStatisticExportStream(@Suspended final AsyncResponse asyncResponse,
+										  @Context HttpServletRequest request,
+										  @JaxrsParameterDescribe("统计部门名称") @PathParam("name") String name,
+										  @JaxrsParameterDescribe("统计周期年份") @PathParam("year") String year,
+										  @JaxrsParameterDescribe("统计周期月份") @PathParam("month") String month,
+										  @JaxrsParameterDescribe("用.APPLICATION_OCTET_STREAM头输出") @PathParam("stream") Boolean stream) {
+		ActionResult<ActionExportUnitSubNestedStatistic.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionExportUnitSubNestedStatistic().execute(request, effectivePerson, name, year, month, stream);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
+	@JaxrsMethodDescribe(value = "导出公司出勤率统计记录,设定是否使用stream输出", action = ActionExportTopUnitStatistic.class)
+	@GET
+	@Path("export/topunit/{name}/{year}/{month}/stream/{stream}")
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void topunitStatisticExportStream(@Suspended final AsyncResponse asyncResponse,
+										  @Context HttpServletRequest request,
+										  @JaxrsParameterDescribe("统计公司名称") @PathParam("name") String name,
+										  @JaxrsParameterDescribe("统计周期年份") @PathParam("year") String year,
+										  @JaxrsParameterDescribe("统计周期月份") @PathParam("month") String month,
+										  @JaxrsParameterDescribe("用.APPLICATION_OCTET_STREAM头输出") @PathParam("stream") Boolean stream) {
+		ActionResult<ActionExportTopUnitStatistic.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionExportTopUnitStatistic().execute(request, effectivePerson, name, year, month, stream);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
 }

+ 84 - 10
o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/WiDesigner.java

@@ -2,11 +2,9 @@ package com.x.base.core.project.jaxrs;
 
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.gson.GsonPropertyObject;
+import org.apache.commons.lang3.StringUtils;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 public class WiDesigner extends GsonPropertyObject {
 
@@ -20,8 +18,8 @@ public class WiDesigner extends GsonPropertyObject {
     private Boolean matchRegExp;
     @FieldDescribe("设计类型:script|form|page|widget|process")
     private List<String> designerTypes = new ArrayList<>();
-    @FieldDescribe("应用ID列表.")
-    private List<String> appIdList = new ArrayList<>();
+    @FieldDescribe("模块的应用列表.")
+    private List<ModuleApp> moduleAppList = new ArrayList<>();
 
     public String getKeyword() {
         return keyword;
@@ -63,11 +61,87 @@ public class WiDesigner extends GsonPropertyObject {
         this.designerTypes = designerTypes;
     }
 
-    public List<String> getAppIdList() {
-        return appIdList == null ? new ArrayList<>() : appIdList;
+    public List<ModuleApp> getModuleAppList() {
+        return moduleAppList == null ? new ArrayList<>() : moduleAppList;
     }
 
-    public void setAppIdList(List<String> appIdList) {
-        this.appIdList = appIdList;
+    public void setModuleAppList(List<ModuleApp> moduleAppList) {
+        this.moduleAppList = moduleAppList;
+    }
+
+    public List<String> getAppIdList(){
+        Set<String> set = new HashSet<>();
+        for (ModuleApp app : this.getModuleAppList()){
+            set.add(app.getAppId());
+        }
+        return new ArrayList<>(set);
+    }
+
+    public Map<String, List<String>> getAppDesigner(){
+        Map<String, List<String>> map = new HashMap<>();
+        for (ModuleApp app : this.getModuleAppList()){
+            for(Designer designer : app.getDesignerList()){
+                String designerType = designer.getDesignerType();
+                if(StringUtils.isNotBlank(designerType)){
+                    if (map.containsKey(designerType)){
+                        map.get(designerType).addAll(designer.getDesignerIdList());
+                    } else{
+                        if(!designer.getDesignerIdList().isEmpty()) {
+                            map.put(designerType, designer.getDesignerIdList());
+                        }
+                    }
+                }
+            }
+        }
+        return map;
+    }
+
+    public class ModuleApp extends GsonPropertyObject {
+        @FieldDescribe("应用ID.")
+        private String appId;
+
+        @FieldDescribe("设计列表.")
+        private List<Designer> designerList;
+
+        public String getAppId() {
+            return appId;
+        }
+
+        public void setAppId(String appId) {
+            this.appId = appId;
+        }
+
+        public List<Designer> getDesignerList() {
+            return designerList == null ? new ArrayList<>() : designerList;
+        }
+
+        public void setDesignerList(List<Designer> designerList) {
+            this.designerList = designerList;
+        }
+    }
+
+    public class Designer extends GsonPropertyObject {
+
+        @FieldDescribe("设计类型.")
+        private String designerType;
+
+        @FieldDescribe("设计ID列表.")
+        private List<String> designerIdList;
+
+        public String getDesignerType() {
+            return designerType;
+        }
+
+        public void setDesignerType(String designerType) {
+            this.designerType = designerType;
+        }
+
+        public List<String> getDesignerIdList() {
+            return designerIdList == null ? new ArrayList<>() : designerIdList;
+        }
+
+        public void setDesignerIdList(List<String> designerIdList) {
+            this.designerIdList = designerIdList;
+        }
     }
 }

+ 20 - 10
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/designer/ActionSearch.java

@@ -46,11 +46,15 @@ class ActionSearch extends BaseAction {
 
 		List<Wo> resWos = new ArrayList<>();
 		List<CompletableFuture<List<Wo>>> list = new ArrayList<>();
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.form.toString())){
-			list.add(searchForm(wi, wi.getAppIdList()));
+		Map<String, List<String>> designerMap = wi.getAppDesigner();
+		List<String> appList = wi.getAppIdList();
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.form.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.form.toString()))){
+			list.add(searchForm(wi, appList, designerMap.get(DesignerType.form.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString())){
-			list.add(searchScript(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.script.toString()))){
+			list.add(searchScript(wi, appList, designerMap.get(DesignerType.script.toString())));
 		}
 		for (CompletableFuture<List<Wo>> cf : list){
 			if(resWos.size()<50) {
@@ -65,15 +69,18 @@ class ActionSearch extends BaseAction {
 		return result;
 	}
 
-	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoScript> woScripts;
-				if (ListTools.isEmpty(appIdList)) {
-					woScripts = emc.fetchAll(Script.class, WoScript.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.appId_FIELDNAME, appIdList);
+				} else {
+					woScripts = emc.fetchAll(Script.class, WoScript.copier);
+
 				}
 
 				for (WoScript woScript : woScripts) {
@@ -103,12 +110,15 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchForm(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchForm(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				Business business = new Business(emc);
-				List<String> formIds = business.getFormFactory().listByAppIds(appIdList);
+				List<String> formIds = designerIdList;
+				if(ListTools.isEmpty(formIds)) {
+					formIds = business.getFormFactory().listByAppIds(appIdList);
+				}
 				for (List<String> partFormIds : ListTools.batch(formIds, 100)) {
 					List<WoForm> woForms = emc.fetchIn(Form.class, WoForm.copier, Form.id_FIELDNAME, partFormIds);
 					for (WoForm woForm : woForms) {

+ 27 - 14
o2server/x_portal_assemble_designer/src/main/java/com/x/portal/assemble/designer/jaxrs/designer/ActionSearch.java

@@ -46,14 +46,19 @@ class ActionSearch extends BaseAction {
 
 		List<Wo> resWos = new ArrayList<>();
 		List<CompletableFuture<List<Wo>>> list = new ArrayList<>();
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.form.toString())){
-			list.add(searchPage(wi, wi.getAppIdList()));
+		Map<String, List<String>> designerMap = wi.getAppDesigner();
+		List<String> appList = wi.getAppIdList();
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.page.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.page.toString()))){
+			list.add(searchPage(wi, appList, designerMap.get(DesignerType.page.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString())){
-			list.add(searchScript(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.script.toString()))){
+			list.add(searchScript(wi, appList, designerMap.get(DesignerType.script.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.widget.toString())){
-			list.add(searchWidget(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.widget.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.widget.toString()))){
+			list.add(searchWidget(wi, appList, designerMap.get(DesignerType.widget.toString())));
 		}
 		for (CompletableFuture<List<Wo>> cf : list){
 			if(resWos.size()<50) {
@@ -68,15 +73,17 @@ class ActionSearch extends BaseAction {
 		return result;
 	}
 
-	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoScript> woScripts;
-				if (ListTools.isEmpty(appIdList)) {
-					woScripts = emc.fetchAll(Script.class, WoScript.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.portal_FIELDNAME, appIdList);
+				} else {
+					woScripts = emc.fetchAll(Script.class, WoScript.copier);
 				}
 
 				for (WoScript woScript : woScripts) {
@@ -106,12 +113,15 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchPage(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchPage(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				Business business = new Business(emc);
-				List<String> ids = business.page().listWithPortals(appIdList);
+				List<String> ids = designerIdList;
+				if(ListTools.isEmpty(ids)) {
+					ids = business.page().listWithPortals(appIdList);
+				}
 				for (List<String> partIds : ListTools.batch(ids, 100)) {
 					List<WoPage> wos = emc.fetchIn(Page.class, WoPage.copier, Page.id_FIELDNAME, partIds);
 					for (WoPage wopage : wos) {
@@ -143,12 +153,15 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchWidget(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchWidget(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				Business business = new Business(emc);
-				List<String> ids = business.widget().listWithPortals(appIdList);
+				List<String> ids = designerIdList;
+				if(ListTools.isEmpty(ids)) {
+					ids = business.widget().listWithPortals(appIdList);
+				}
 				for (List<String> partIds : ListTools.batch(ids, 100)) {
 					List<WoWidget> wos = emc.fetchIn(Widget.class, WoWidget.copier, WoWidget.id_FIELDNAME, partIds);
 					for (WoWidget woWidget : wos) {

+ 28 - 16
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/designer/ActionSearch.java

@@ -47,14 +47,19 @@ class ActionSearch extends BaseAction {
 
 		List<Wo> resWos = new ArrayList<>();
 		List<CompletableFuture<List<Wo>>> list = new ArrayList<>();
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.form.toString())){
-			list.add(searchForm(wi, wi.getAppIdList()));
+		Map<String, List<String>> designerMap = wi.getAppDesigner();
+		List<String> appList = wi.getAppIdList();
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.form.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.form.toString()))){
+			list.add(searchForm(wi, appList, designerMap.get(DesignerType.form.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString())){
-			list.add(searchScript(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.script.toString()))){
+			list.add(searchScript(wi, appList, designerMap.get(DesignerType.script.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.process.toString())){
-			resWos.addAll(searchProcess(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.process.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.process.toString()))){
+			resWos.addAll(searchProcess(wi, appList, designerMap.get(DesignerType.process.toString())));
 		}
 		for (CompletableFuture<List<Wo>> cf : list){
 			if(resWos.size()<50) {
@@ -69,15 +74,17 @@ class ActionSearch extends BaseAction {
 		return result;
 	}
 
-	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchScript(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoScript> woScripts;
-				if (ListTools.isEmpty(appIdList)) {
-					woScripts = emc.fetchAll(Script.class, WoScript.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woScripts = emc.fetchIn(Script.class, WoScript.copier, Script.application_FIELDNAME, appIdList);
+				} else {
+					woScripts = emc.fetchAll(Script.class, WoScript.copier);
 				}
 				for (WoScript woScript : woScripts) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoScript.copier.getCopyFields(), woScript, wi.getKeyword(),
@@ -106,12 +113,15 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchForm(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchForm(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				Business business = new Business(emc);
-				List<String> formIds = business.form().listWithApplications(appIdList);
+				List<String> formIds = designerIdList;
+				if(ListTools.isEmpty(formIds)) {
+					formIds = business.form().listWithApplications(appIdList);
+				}
 				for (List<String> partFormIds : ListTools.batch(formIds, 100)) {
 					List<WoForm> woForms = emc.fetchIn(Form.class, WoForm.copier, Form.id_FIELDNAME, partFormIds);
 					for (WoForm woForm : woForms) {
@@ -143,12 +153,14 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private List<Wo> searchProcess(final Wi wi, final List<String> appIdList) {
-
+	private List<Wo> searchProcess(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		List<List<String>> batchList = new ArrayList<>();
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-			Business business = new Business(emc);
-			List<String> processIds = business.process().listWithApplications(appIdList);
+			List<String> processIds = designerIdList;
+			if(ListTools.isEmpty(processIds)) {
+				Business business = new Business(emc);
+				processIds = business.process().listWithApplications(appIdList);
+			}
 			batchList = ListTools.batch(processIds, 20);
 		}catch (Exception e){
 			logger.error(e);

+ 22 - 9
o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/designer/ActionSearch.java

@@ -43,12 +43,15 @@ class ActionSearch extends BaseAction {
 
 		List<Wo> resWos = new ArrayList<>();
 		List<CompletableFuture<List<Wo>>> list = new ArrayList<>();
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString())){
-			if(wi.getAppIdList().isEmpty() || wi.getAppIdList().contains("invoke")) {
-				list.add(searchInvoke(wi));
+		Map<String, List<String>> designerMap = wi.getAppDesigner();
+		List<String> appList = wi.getAppIdList();
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.script.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.script.toString()))){
+			if(appList.isEmpty() || appList.contains("invoke")) {
+				list.add(searchInvoke(wi, designerMap.get(DesignerType.script.toString())));
 			}
-			if(wi.getAppIdList().isEmpty() || wi.getAppIdList().contains("agent")) {
-				list.add(searchAgent(wi));
+			if(appList.isEmpty() || appList.contains("agent")) {
+				list.add(searchAgent(wi, designerMap.get(DesignerType.script.toString())));
 			}
 		}
 		for (CompletableFuture<List<Wo>> cf : list){
@@ -64,11 +67,16 @@ class ActionSearch extends BaseAction {
 		return result;
 	}
 
-	private CompletableFuture<List<Wo>> searchAgent(final Wi wi) {
+	private CompletableFuture<List<Wo>> searchAgent(final Wi wi, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-				List<WoAgent> woAgents = emc.fetchAll(Agent.class, WoAgent.copier);
+				List<WoAgent> woAgents;
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woAgents = emc.fetchIn(Agent.class, WoAgent.copier, Agent.id_FIELDNAME, designerIdList);
+				} else {
+					woAgents = emc.fetchAll(Agent.class, WoAgent.copier);
+				}
 				for (WoAgent woAgent : woAgents) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoAgent.copier.getCopyFields(), woAgent, wi.getKeyword(),
 							wi.getCaseSensitive(), wi.getMatchWholeWord(), wi.getMatchRegExp());
@@ -93,11 +101,16 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchInvoke(final Wi wi) {
+	private CompletableFuture<List<Wo>> searchInvoke(final Wi wi, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
-				List<WoInvoke> woInvokes = emc.fetchAll(Invoke.class, WoInvoke.copier);
+				List<WoInvoke> woInvokes;
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woInvokes = emc.fetchIn(Invoke.class, WoInvoke.copier, Invoke.id_FIELDNAME, designerIdList);
+				} else {
+					woInvokes = emc.fetchAll(Invoke.class, WoInvoke.copier);
+				}
 				for (WoInvoke woInvoke : woInvokes) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoInvoke.copier.getCopyFields(), woInvoke, wi.getKeyword(),
 							wi.getCaseSensitive(), wi.getMatchWholeWord(), wi.getMatchRegExp());

+ 40 - 24
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/designer/ActionSearch.java

@@ -46,18 +46,26 @@ class ActionSearch extends BaseAction {
 
 		List<Wo> resWos = new ArrayList<>();
 		List<CompletableFuture<List<Wo>>> list = new ArrayList<>();
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.view.toString())){
-			list.add(searchView(wi, wi.getAppIdList()));
+		Map<String, List<String>> designerMap = wi.getAppDesigner();
+		List<String> appList = wi.getAppIdList();
+
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.view.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.view.toString()))){
+			list.add(searchView(wi, appList, designerMap.get(DesignerType.view.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.table.toString())){
-			list.add(searchTable(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.table.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.table.toString()))){
+			list.add(searchTable(wi, appList, designerMap.get(DesignerType.table.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.statement.toString())){
-			list.add(searchStatement(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.statement.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.statement.toString()))){
+			list.add(searchStatement(wi, appList, designerMap.get(DesignerType.statement.toString())));
 		}
-		if (wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.stat.toString())){
-			list.add(searchStat(wi, wi.getAppIdList()));
+		if ((wi.getDesignerTypes().isEmpty() || wi.getDesignerTypes().contains(DesignerType.stat.toString()))
+				&& (designerMap.isEmpty() || designerMap.containsKey(DesignerType.stat.toString()))){
+			list.add(searchStat(wi, appList, designerMap.get(DesignerType.stat.toString())));
 		}
+
 		for (CompletableFuture<List<Wo>> cf : list){
 			if(resWos.size()<50) {
 				resWos.addAll(cf.get(60, TimeUnit.SECONDS));
@@ -71,15 +79,17 @@ class ActionSearch extends BaseAction {
 		return result;
 	}
 
-	private CompletableFuture<List<Wo>> searchView(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchView(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoView> woViews;
-				if (ListTools.isEmpty(appIdList)) {
-					woViews = emc.fetchAll(View.class, WoView.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woViews = emc.fetchIn(View.class, WoView.copier, View.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woViews = emc.fetchIn(View.class, WoView.copier, View.query_FIELDNAME, appIdList);
+				} else {
+					woViews = emc.fetchAll(View.class, WoView.copier);
 				}
 				for (WoView woView : woViews) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoView.copier.getCopyFields(), woView, wi.getKeyword(),
@@ -108,15 +118,17 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchTable(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchTable(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoTable> woTables;
-				if (ListTools.isEmpty(appIdList)) {
-					woTables = emc.fetchAll(Table.class, WoTable.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woTables = emc.fetchIn(Table.class, WoTable.copier, Table.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woTables = emc.fetchIn(Table.class, WoTable.copier, Table.query_FIELDNAME, appIdList);
+				} else {
+					woTables = emc.fetchAll(Table.class, WoTable.copier);
 				}
 				for (WoTable woTable : woTables) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoTable.copier.getCopyFields(), woTable, wi.getKeyword(),
@@ -145,15 +157,17 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchStat(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchStat(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoStat> woStats;
-				if (ListTools.isEmpty(appIdList)) {
-					woStats = emc.fetchAll(Stat.class, WoStat.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woStats = emc.fetchIn(Stat.class, WoStat.copier, Stat.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woStats = emc.fetchIn(Stat.class, WoStat.copier, Stat.query_FIELDNAME, appIdList);
+				} else {
+					woStats = emc.fetchAll(Stat.class, WoStat.copier);
 				}
 				for (WoStat woStat : woStats) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoStat.copier.getCopyFields(), woStat, wi.getKeyword(),
@@ -182,15 +196,17 @@ class ActionSearch extends BaseAction {
 		return cf;
 	}
 
-	private CompletableFuture<List<Wo>> searchStatement(final Wi wi, final List<String> appIdList) {
+	private CompletableFuture<List<Wo>> searchStatement(final Wi wi, final List<String> appIdList, final List<String> designerIdList) {
 		CompletableFuture<List<Wo>> cf = CompletableFuture.supplyAsync(() -> {
 			List<Wo> resWos = new ArrayList<>();
 			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 				List<WoStatement> woStatements;
-				if (ListTools.isEmpty(appIdList)) {
-					woStatements = emc.fetchAll(Statement.class, WoStatement.copier);
-				} else {
+				if (ListTools.isNotEmpty(designerIdList)) {
+					woStatements = emc.fetchIn(Statement.class, WoStatement.copier, Statement.id_FIELDNAME, designerIdList);
+				}else if (ListTools.isNotEmpty(appIdList)) {
 					woStatements = emc.fetchIn(Statement.class, WoStatement.copier, Statement.query_FIELDNAME, appIdList);
+				} else {
+					woStatements = emc.fetchAll(Statement.class, WoStatement.copier);
 				}
 				for (WoStatement woStatement : woStatements) {
 					Map<String, String> map = PropertyTools.fieldMatchKeyword(WoStatement.copier.getCopyFields(), woStatement, wi.getKeyword(),

+ 18 - 18
o2server/x_query_service_processing/src/main/java/com/x/query/service/processing/jaxrs/design/ActionSearch.java

@@ -37,27 +37,27 @@ class ActionSearch extends BaseAction {
 	}
 
 	private Wo search(final Wi wi) {
-		final Map<String, List<String>> moduleMap = new HashMap<>();
+		final Map<String, List<WiDesigner.ModuleApp>> moduleMap = new HashMap<>();
 		if(!ListTools.isEmpty(wi.getModuleList())){
 			for (Module module: wi.getModuleList()){
 				if(module.getModuleType().equalsIgnoreCase(ModuleType.cms.toString())){
-					moduleMap.put(ModuleType.cms.toString(), module.getFlagList());
+					moduleMap.put(ModuleType.cms.toString(), module.getModuleAppList());
 				}
 				if(module.getModuleType().equalsIgnoreCase(ModuleType.portal.toString())){
-					moduleMap.put(ModuleType.portal.toString(), module.getFlagList());
+					moduleMap.put(ModuleType.portal.toString(), module.getModuleAppList());
 				}
 				if(module.getModuleType().equalsIgnoreCase(ModuleType.processPlatform.toString())){
-					moduleMap.put(ModuleType.processPlatform.toString(), module.getFlagList());
+					moduleMap.put(ModuleType.processPlatform.toString(), module.getModuleAppList());
 				}
 				if(module.getModuleType().equalsIgnoreCase(ModuleType.query.toString())){
-					moduleMap.put(ModuleType.query.toString(), module.getFlagList());
+					moduleMap.put(ModuleType.query.toString(), module.getModuleAppList());
 				}
 				if(module.getModuleType().equalsIgnoreCase(ModuleType.service.toString())){
-					moduleMap.put(ModuleType.service.toString(), module.getFlagList());
+					moduleMap.put(ModuleType.service.toString(), module.getModuleAppList());
 				}
 			}
 		}else{
-			List<String> list = new ArrayList<>();
+			List<WiDesigner.ModuleApp> list = new ArrayList<>();
 			moduleMap.put(ModuleType.cms.toString(), list);
 			moduleMap.put(ModuleType.portal.toString(), list);
 			moduleMap.put(ModuleType.processPlatform.toString(), list);
@@ -99,14 +99,14 @@ class ActionSearch extends BaseAction {
 		return wo;
 	}
 
-	private CompletableFuture<List<WrapDesigner>> searchAsync(final Wi wi, final Map<String, List<String>> moduleMap, final String moduleType, final Class<?> applicationClass, Executor executor){
+	private CompletableFuture<List<WrapDesigner>> searchAsync(final Wi wi, final Map<String, List<WiDesigner.ModuleApp>> moduleMap, final String moduleType, final Class<?> applicationClass, Executor executor){
 		CompletableFuture<List<WrapDesigner>> cf = CompletableFuture.supplyAsync(() -> {
 			List<WrapDesigner> swList = new ArrayList<>();
 			if(moduleMap.containsKey(moduleType)) {
 				try {
 					WiDesigner wiDesigner = new WiDesigner();
 					BeanUtils.copyProperties(wiDesigner, wi);
-					wiDesigner.setAppIdList(moduleMap.get(moduleType));
+					wiDesigner.setModuleAppList(moduleMap.get(moduleType));
 					List<WrapDesigner> designerList = ThisApplication.context().applications().postQuery(applicationClass,
 							Applications.joinQueryUri("designer", "search"), wiDesigner).getDataAsList(WrapDesigner.class);
 					logger.info("设计搜索关联{}的匹配设计个数:{}", moduleType, designerList.size());
@@ -146,7 +146,7 @@ class ActionSearch extends BaseAction {
 
 		@FieldDescribe("搜索关键字.")
 		private String keyword;
-		@FieldDescribe("搜索设计类型:script|form|page|widget|process")
+		@FieldDescribe("搜索设计类型:script|form|page|widget|process|view|table|stat|statement")
 		private List<String> designerTypes;
 		@FieldDescribe("是否区分大小写.")
 		private Boolean caseSensitive;
@@ -154,8 +154,8 @@ class ActionSearch extends BaseAction {
 		private Boolean matchWholeWord;
 		@FieldDescribe("是否正则表达式匹配.")
 		private Boolean matchRegExp;
-		@FieldDescribe("限制查询的模块列表(模块类型:processPlatform|cms|portal|query|service).")
-		@FieldTypeDescribe(fieldType = "class", fieldTypeName = "Module", fieldValue = "{\"moduleType\": \"cms\", \"flagList\": []}")
+		@FieldDescribe("限制查询的模块列表(模块类型:processPlatform|cms|portal|query|service)<br/>\r\n")
+		@FieldTypeDescribe(fieldType = "class", fieldTypeName = "Module", fieldValue = "{\"moduleType\": \"processPlatform\", \"moduleAppList\": [{\"appId\":\"\", \"designerList\": [{\"designerType\":\"process\", \"designerIdList\": []}]}]}")
 		private List<Module> moduleList;
 
 		public String getKeyword() {
@@ -208,17 +208,17 @@ class ActionSearch extends BaseAction {
 	}
 
 	public static class Module extends GsonPropertyObject {
-		@FieldDescribe("模块的应用id列表.")
-		private List<String> flagList;
+		@FieldDescribe("模块的应用列表.")
+		private List<WiDesigner.ModuleApp> moduleAppList = new ArrayList<>();
 		@FieldDescribe("模块类型.")
 		private String moduleType;
 
-		public List<String> getFlagList() {
-			return flagList == null ? new ArrayList<>() : flagList;
+		public List<WiDesigner.ModuleApp> getModuleAppList() {
+			return moduleAppList;
 		}
 
-		public void setFlagList(List<String> flagList) {
-			this.flagList = flagList;
+		public void setModuleAppList(List<WiDesigner.ModuleApp> moduleAppList) {
+			this.moduleAppList = moduleAppList;
 		}
 
 		public String getModuleType() {

+ 0 - 6
o2server/x_query_service_processing/src/main/java/com/x/query/service/processing/jaxrs/design/DesignAction.java

@@ -17,7 +17,6 @@ import javax.ws.rs.container.AsyncResponse;
 import javax.ws.rs.container.Suspended;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
-import java.util.concurrent.locks.ReentrantLock;
 
 @Path("design")
 @JaxrsDescribe("全平台设计")
@@ -25,8 +24,6 @@ public class DesignAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(DesignAction.class);
 
-	private static ReentrantLock lock = new ReentrantLock();
-
 	@JaxrsMethodDescribe(value = "全平台设计搜索.", action = ActionSearch.class)
 	@POST
 	@Path("search")
@@ -36,14 +33,11 @@ public class DesignAction extends StandardJaxrsAction {
 					   JsonElement jsonElement) {
 		ActionResult<ActionSearch.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
-		lock.lock();
 		try {
 			result = new ActionSearch().execute(effectivePerson, jsonElement);
 		} catch (Exception e) {
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);
-		} finally {
-			lock.unlock();
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}

+ 34 - 0
o2web/source/o2_core/o2/xAction/services/x_attendance_assemble_control.js

@@ -53,6 +53,40 @@ MWF.xAction.RestActions.Action["x_attendance_assemble_control"] = new Class({
             window.open(this.action.address+url , "_blank");
         }.bind(this));
     },
+    //个人出勤率导出
+    exportPersonStatisticAttachment: function(name,year, month, stream){
+        this.action.getActions(function(){
+            var url = this.action.actions.exportPersonStatisticAttachment.uri;
+            url = url.replace("{name}", name);
+            url = url.replace("{year}", year);
+            url = url.replace("{month}", month);
+            url = url.replace("{stream}", stream);
+            window.open(this.action.address+url , "_blank");
+        }.bind(this));
+    },
+    //部门出勤率导出
+    exportUnitStatisticAttachment: function(name,year, month, stream){
+        this.action.getActions(function(){
+            var url = this.action.actions.exportUnitStatisticAttachment.uri;
+            url = url.replace("{name}", name);
+            url = url.replace("{year}", year);
+            url = url.replace("{month}", month);
+            url = url.replace("{stream}", stream);
+            window.open(this.action.address+url , "_blank");
+        }.bind(this));
+    },
+    //公司出勤率导出
+    exportTopUnitStatisticAttachment: function(name,year, month, stream){
+        this.action.getActions(function(){
+            var url = this.action.actions.exportTopUnitStatisticAttachment.uri;
+            url = url.replace("{name}", name);
+            url = url.replace("{year}", year);
+            url = url.replace("{month}", month);
+            url = url.replace("{stream}", stream);
+            window.open(this.action.address+url , "_blank");
+        }.bind(this));
+    },
+
     listHolidayByYearAndName: function(year,name,success, failure, async){
         this.action.invoke({"name": "listHolidayFilter","data": {"q_Year": year, "q_Name" : name },"async": async, "success": success,	"failure": failure});
     },

+ 6 - 0
o2web/source/o2_core/o2/xAction/services/x_attendance_assemble_control.json

@@ -178,6 +178,12 @@ URL:x_attendance_assemble_control/jaxrs/attendancedetail/filter/list/{id}/prev
 
   //统计导出
   "detailsExportStream" : {"uri" : "/jaxrs/file/export/filter/{q_topUnitName}/{q_unitName}/{q_empName}/{cycleYear}/{cycleMonth}/{q_date}/{isAbsent}/{isLackOfTime}/{isLate}/stream/{stream}", "method": "GET"},
+  //个人出勤率导出
+  "exportPersonStatisticAttachment" : {"uri":"/jaxrs/file/export/person/{name}/{year}/{month}/stream/{stream}", "method": "GET"},
+  //部门出勤率导出
+  "exportUnitStatisticAttachment" : {"uri":"/jaxrs/file/export/unit/{name}/{year}/{month}/stream/{stream}", "method": "GET"},
+  //公司出勤率导出
+  "exportTopUnitStatisticAttachment" : {"uri":"/jaxrs/file/export/topunit/{name}/{year}/{month}/stream/{stream}", "method": "GET"},
 
   "clazz": "x_attendance_assemble_control"
 }

+ 1 - 1
o2web/source/o2_core/o2/xDesktop/WebSocket.js

@@ -14,7 +14,7 @@ MWF.xDesktop.WebSocket = new Class({
 
         this.reConnect = true;
         this.checking = false;
-        this.heartTimeout = 60000;
+        this.heartTimeout = 30000;
         this.checkingTimeout = 4000;
         this.heartMsg = "heartbeat";
         this.maxErrorCount = 10;

+ 10 - 1
o2web/source/x_component_Attendance/PeopleDetail.js

@@ -490,6 +490,7 @@ MWF.xApplication.Attendance.PeopleDetail.DetailStaticExplorer = new Class({
             "    <td styles='filterTableTitle' lable='cycleMonth'></td>"+
             "    <td styles='filterTableValue' item='cycleMonth'></td>" +
             "    <td styles='filterTableValue' item='action'></td>" +
+            "    <td styles='filterTableValue' item='export'></td>" +
             "</tr>" +
             "</table>";
         this.fileterNode.set("html",html);
@@ -526,7 +527,15 @@ MWF.xApplication.Attendance.PeopleDetail.DetailStaticExplorer = new Class({
                             if( !result )return;
                             this.loadView( result );
                         }.bind(this)
-                    }}
+                    }},
+                    export : { "value" : "导出", type : "button", className : "filterButton", event : {
+                            click : function(){
+                                var result = this.form.getResult(true,",",true,true,false);
+                                if( !result )return;
+                                debugger;
+                                this.actions.exportPersonStatisticAttachment(result.q_empName,result.cycleYear,result.cycleMonth,true);
+                            }.bind(this)
+                        }}
                 }
             }, this.app, this.css);
             this.form.load();

+ 9 - 1
o2web/source/x_component_Attendance/TopUnitDetail.js

@@ -484,6 +484,7 @@ MWF.xApplication.Attendance.TopUnitDetail.DetailStaticExplorer = new Class({
             "    <td styles='filterTableTitle' lable='cycleMonth'></td>"+
             "    <td styles='filterTableValue' item='cycleMonth'></td>" +
             "    <td styles='filterTableValue' item='action'></td>" +
+            "    <td styles='filterTableValue' item='export'></td>" +
             "</tr>" +
             "</table>";
         this.fileterNode.set("html",html);
@@ -520,7 +521,14 @@ MWF.xApplication.Attendance.TopUnitDetail.DetailStaticExplorer = new Class({
                             if( !result )return;
                             this.loadView( result );
                         }.bind(this)
-                    }}
+                    }},
+                    export : { "value" : "导出", type : "button", className : "filterButton", event : {
+                            click : function(){
+                                var result = this.form.getResult(true,",",true,true,false);
+                                if( !result )return;
+                                this.actions.exportTopUnitStatisticAttachment(result.q_topUnitName,result.cycleYear,result.cycleMonth,true);
+                            }.bind(this)
+                        }}
                 }
             }, this.app, this.css);
             this.form.load();

+ 9 - 1
o2web/source/x_component_Attendance/UnitDetail.js

@@ -483,6 +483,7 @@ MWF.xApplication.Attendance.UnitDetail.DetailStaticExplorer = new Class({
             "    <td styles='filterTableTitle' lable='cycleMonth'></td>"+
             "    <td styles='filterTableValue' item='cycleMonth'></td>" +
             "    <td styles='filterTableValue' item='action'></td>" +
+            "    <td styles='filterTableValue' item='export'></td>" +
             "</tr>" +
             "</table>";
         this.fileterNode.set("html",html);
@@ -519,7 +520,14 @@ MWF.xApplication.Attendance.UnitDetail.DetailStaticExplorer = new Class({
                             if( !result )return;
                             this.loadView( result );
                         }.bind(this)
-                    }}
+                    }},
+                    export : { "value" : "导出", type : "button", className : "filterButton", event : {
+                            click : function(){
+                                var result = this.form.getResult(true,",",true,true,false);
+                                if( !result )return;
+                                this.actions.exportUnitStatisticAttachment(result.q_unitName,result.cycleYear,result.cycleMonth,true);
+                            }.bind(this)
+                        }}
                 }
             }, this.app, this.css);
             this.form.load();

+ 6 - 0
o2web/source/x_component_Setting/Document.js

@@ -729,6 +729,12 @@ MWF.xApplication.Setting.Document.List.ItemEditor = new Class({
                 }else{
                     values[k] = value;
                 }
+                if(k === "proxyHost"){
+                    if(value.indexOf("http")>-1){
+                        flag = false;
+                        this.app.notice(this.lp.list.infoProxyHost, "error");
+                    }
+                }
             }
         }.bind(this));
 

+ 3 - 1
o2web/source/x_component_Setting/lp/zh-cn.js

@@ -267,7 +267,9 @@ MWF.xApplication.Setting.LP = {
         "infoParameter": "请求信息方法参数",
         "infoMethod": "请求信息方法(GET或POST)",
         "infoType": "info信息格式(json或form)",
-        "infoCredentialField": "info信息中用于标识个人的字段"
+        "infoCredentialField": "info信息中用于标识个人的字段",
+
+        "infoProxyHost" : "域名不需要包含http"
     },
 
     "module": {

+ 6 - 0
o2web/source/x_desktop/js/base_simple_anonymous.js

@@ -74,6 +74,12 @@ o2.addReady(function () {
         if (configLoaded && commonLoaded && lpLoaded) _getDistribute(function () { _load(); });
     });
 
+    var _setLayoutService = function(service, center){
+        layout.serviceAddressList = service;
+        layout.centerServer = center;
+        layout.desktop.serviceAddressList = service;
+        layout.desktop.centerServer = center;
+    };
     var _getDistribute = function (callback) {
         if (layout.config.app_protocol === "auto") {
             layout.config.app_protocol = window.location.protocol;