roo00 6 лет назад
Родитель
Сommit
05479f8cbf
100 измененных файлов с 11579 добавлено и 703 удалено
  1. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/container/factory/SlicePropertiesBuilder.java
  2. 5 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CreateSample.java
  3. 126 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/LogLevel.java
  4. 5 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Messages.java
  5. 1 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Person.java
  6. 44 2
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java
  7. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Token.java
  8. 11 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionPersonNotExist.java
  9. 9 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/http/HttpToken.java
  10. 11 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/message/MessageConnector.java
  11. 8 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/NumberTools.java
  12. 11 2
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/factory/DocumentFactory.java
  13. 350 0
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionCountLatestDocumentWithFilter.java
  14. 2 2
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionCountViewTimes.java
  15. 22 2
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionListNextWithFilter.java
  16. 21 2
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionListNextWithFilter_NEW.java
  17. 25 3
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/DocumentAction.java
  18. 4 4
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/DocumentInfoService.java
  19. 5 4
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/DocumentInfoServiceAdv.java
  20. 14 15
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/common/image/maincolor/ImageMainColorUtil.java
  21. 2 2
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/CategoryExt.java
  22. 7 7
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/CategoryInfo.java
  23. 1 1
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/DocumentViewRecord.java
  24. 7 6
      o2server/x_console/src/main/java/com/x/server/console/Main.java
  25. 33 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/CalendarConsumeQueue.java
  26. 78 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/DingdingConsumeQueue.java
  27. 12 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionDingdingMessage.java
  28. 12 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionQiyeweixinMessage.java
  29. 12 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionZhengwuDingdingMessage.java
  30. 40 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ImConsumeQueue.java
  31. 31 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/PmsConsumeQueue.java
  32. 102 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/QiyeweixinConsumeQueue.java
  33. 45 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ThisApplication.java
  34. 117 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ZhengwuDingdingConsumeQueue.java
  35. 2 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/ActionApplication.java
  36. 10 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/MessageJaxrsFilter.java
  37. 419 312
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/connector/ActionCreate.java
  38. 2 3
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionList.java
  39. 66 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionListWithCurrentPerson.java
  40. 70 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionListWithPerson.java
  41. 6 20
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionUpdate.java
  42. 5 23
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionUpdateSingle.java
  43. 39 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ConsumeAction.java
  44. 103 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ActionCustomCreate.java
  45. 7 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/BaseAction.java
  46. 12 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ExceptionNotCustomMessage.java
  47. 12 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ExceptionUndefinedMessageType.java
  48. 48 0
      o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/MessageAction.java
  49. 31 25
      o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/Message.java
  50. 1 1
      o2server/x_okr_core_entity/src/main/java/com/x/okr/entity/OkrCenterWorkInfo.java
  51. 37 30
      o2server/x_okr_core_entity/src/main/java/com/x/okr/entity/OkrWorkReportBaseInfo.java
  52. 11 2
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/ActionCaptchaLogin.java
  53. 19 0
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/BaseAction.java
  54. 12 0
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/ExceptionFailureLocked.java
  55. 64 0
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionGetEncrypt.java
  56. 1 1
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionGetLogin.java
  57. 16 13
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionPostEncrypt.java
  58. 1 1
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionPostLogin.java
  59. 2 0
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/BaseAction.java
  60. 2 2
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionEmptyCredential.java
  61. 2 2
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionEmptyKey.java
  62. 29 8
      o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/SsoAction.java
  63. 3 0
      o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/ThisApplication.java
  64. 22 17
      o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/inputperson/ActionInput.java
  65. 4 3
      o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/person/ActionEdit.java
  66. 3 2
      o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/person/PersonAction.java
  67. 29 1
      o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Person.java
  68. 0 1
      o2server/x_organization_core_express/src/main/java/com/x/organization/core/express/Organization.java
  69. 8276 0
      o2server/x_processplatform_assemble_designer/a.json
  70. 2 2
      o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/input/ActionCover.java
  71. 8 8
      o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/input/ActionPrepareCover.java
  72. 4 4
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/Business.java
  73. 6 4
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/ActionCopyToWork.java
  74. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/ActionEdit.java
  75. 15 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/control/ActionGetWorkOrWorkCompleted.java
  76. 10 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/control/BaseAction.java
  77. 6 6
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/data/DataAction.java
  78. 82 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionPress.java
  79. 12 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionJobNotMatch.java
  80. 12 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressLimit.java
  81. 12 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressNoneTask.java
  82. 12 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressNoneTaskCompleted.java
  83. 18 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/TaskCompletedAction.java
  84. 67 30
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionRetract.java
  85. 2 3
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ExceptionRetractNoneWorkLog.java
  86. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListRollbackWithWorkOrWorkCompleted.java
  87. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListWithWorkOrWorkCompleted.java
  88. 51 0
      o2server/x_processplatform_assemble_surface/src/main/resources/data.json
  89. 175 0
      o2server/x_processplatform_assemble_surface/src/test/java/com/x/processplatform/assemble/surface/test/stress/TestClient.java
  90. 43 9
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/TaskCompleted.java
  91. 0 2
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java
  92. 45 0
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Manual.java
  93. 7 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/MessageFactory.java
  94. 0 37
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ScriptHelperFactory.java
  95. 94 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/taskcompleted/ActionPress.java
  96. 22 1
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/taskcompleted/TaskCompletedAction.java
  97. 4 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionAssignCreate.java
  98. 189 58
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRetract.java
  99. 130 0
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRetractBack.java
  100. 7 2
      o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AeiObjects.java

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/container/factory/SlicePropertiesBuilder.java

@@ -24,7 +24,7 @@ public class SlicePropertiesBuilder {
 	public static String driver_gbase = "com.gbasedbt.jdbc.IfxDriver";
 	/** 避免db2在aix版本和lwl版本字段长度不一致的问题 */
 	public static String dictionary_db2 = "db2(createPrimaryKeys=false,characterColumnSize=255,maxColumnNameLength=128,maxIndexNameLength=128,maxConstraintNameLength=128)";
-	public static String dictionary_oracle = "oracle(maxTableNameLength=128,maxColumnNameLength=128,maxIndexNameLength=128,maxConstraintNameLength=128,maxEmbeddedClobSize=104857600)";
+	public static String dictionary_oracle = "oracle(maxTableNameLength=128,maxColumnNameLength=128,maxIndexNameLength=128,maxConstraintNameLength=128,maxEmbeddedClobSize=-1,maxEmbeddedBlobSize=-1)";
 	public static String dictionary_mysql = "mysql(clobTypeName=LONGTEXT,blobTypeName=LONGBLOB,createPrimaryKeys=false,maxIndexesPerTable=64)";
 	public static String dictionary_postgresql = "postgres";
 	public static String dictionary_informix = "informix";

+ 5 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CreateSample.java

@@ -65,7 +65,7 @@ public class CreateSample {
 			map = this.describe(cls, map);
 			String name = StringUtils.lowerCase(cls.getSimpleName().substring(0, 1)) + cls.getSimpleName().substring(1)
 					+ ".json";
-			File file = new File(FileTools.parent(FileTools.parent(new File("./"))), "config/sample/" + name);
+			File file = new File(FileTools.parent(FileTools.parent(new File("./"))), "configSample/" + name);
 			logger.print("create file:{}.", file.getAbsoluteFile());
 			FileUtils.write(file, XGsonBuilder.toJson(map), DefaultCharset.charset);
 		}
@@ -76,9 +76,9 @@ public class CreateSample {
 
 	private void convertExternalDataSource2ExternalDataSources() throws Exception, IOException {
 		File file_externalDataSource = new File(FileTools.parent(FileTools.parent(new File("./"))),
-				"config/sample/externalDataSource.json");
+				"configSample/externalDataSource.json");
 		File file_externalDataSources = new File(FileTools.parent(FileTools.parent(new File("./"))),
-				"config/sample/externalDataSources.json");
+				"configSample/externalDataSources.json");
 		JsonElement jsonElement = XGsonBuilder.instance().fromJson(FileUtils.readFileToString(file_externalDataSource),
 				JsonElement.class);
 		List<JsonElement> list = new ArrayList<>();
@@ -88,9 +88,9 @@ public class CreateSample {
 	}
 
 	private void renameNode() throws Exception, IOException {
-		File file_node = new File(FileTools.parent(FileTools.parent(new File("./"))), "config/sample/node.json");
+		File file_node = new File(FileTools.parent(FileTools.parent(new File("./"))), "configSample/node.json");
 		File file_node_local = new File(FileTools.parent(FileTools.parent(new File("./"))),
-				"config/sample/node_127.0.0.1.json");
+				"configSample/node_127.0.0.1.json");
 		if (file_node_local.exists()) {
 			file_node_local.delete();
 		}

+ 126 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/LogLevel.java

@@ -40,16 +40,138 @@ public class LogLevel extends ConfigObject {
 	@FieldDescribe("是否启用调试")
 	private String x_organization_assemble_authentication = "";
 
+	@FieldDescribe("是否启用调试")
+	private String x_organization_assemble_control = "";
+
 	@FieldDescribe("是否启用调试")
 	private String x_general_assemble_control = "";
 
 	@FieldDescribe("是否启用调试")
 	private String x_file_assemble_control = "";
 
+	@FieldDescribe("是否启用调试")
+	private String x_attendance_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_collaboration_core_message = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_organization_core_express = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_query_core_express = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_bbs_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_calendar_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_cms_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_component_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_hotpic_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_message_assemble_communicate = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_mind_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_okr_assemble_control = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_organization_assemble_express = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_organization_assemble_personal = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_portal_assemble_designer = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_portal_assemble_surface = "";
+
+	@FieldDescribe("是否启用调试")
+	private String x_processplatform_assemble_bam = "";
+
 	public static LogLevel defaultInstance() {
 		return new LogLevel();
 	}
 
+	public String x_attendance_assemble_control() {
+		return this.get(this.x_attendance_assemble_control);
+	}
+
+	public String x_collaboration_core_message() {
+		return this.get(this.x_collaboration_core_message);
+	}
+
+	public String x_organization_core_express() {
+		return this.get(this.x_organization_core_express);
+	}
+
+	public String x_query_core_express() {
+		return this.get(this.x_query_core_express);
+	}
+
+	public String x_bbs_assemble_control() {
+		return this.get(this.x_bbs_assemble_control);
+	}
+
+	public String x_calendar_assemble_control() {
+		return this.get(this.x_calendar_assemble_control);
+	}
+
+	public String x_cms_assemble_control() {
+		return this.get(this.x_cms_assemble_control);
+	}
+
+	public String x_component_assemble_control() {
+		return this.get(this.x_component_assemble_control);
+	}
+
+	public String x_hotpic_assemble_control() {
+		return this.get(this.x_hotpic_assemble_control);
+	}
+
+	public String x_message_assemble_communicate() {
+		return this.get(this.x_message_assemble_communicate);
+	}
+
+	public String x_mind_assemble_control() {
+		return this.get(this.x_mind_assemble_control);
+	}
+
+	public String x_okr_assemble_control() {
+		return this.get(this.x_okr_assemble_control);
+	}
+
+	public String x_organization_assemble_express() {
+		return this.get(this.x_organization_assemble_express);
+	}
+
+	public String x_organization_assemble_personal() {
+		return this.get(this.x_organization_assemble_personal);
+	}
+
+	public String x_portal_assemble_designer() {
+		return this.get(this.x_portal_assemble_designer);
+	}
+
+	public String x_portal_assemble_surface() {
+		return this.get(this.x_portal_assemble_surface);
+	}
+
+	public String x_processplatform_assemble_bam() {
+		return this.get(this.x_processplatform_assemble_bam);
+	}
+
 	public String x_program_center() {
 		return this.get(this.x_program_center);
 	}
@@ -94,6 +216,10 @@ public class LogLevel extends ConfigObject {
 		return this.get(this.x_organization_assemble_authentication);
 	}
 
+	public String x_organization_assemble_control() {
+		return this.get(this.x_organization_assemble_control);
+	}
+
 	public String x_general_assemble_control() {
 		return this.get(this.x_general_assemble_control);
 	}

+ 5 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Messages.java

@@ -61,6 +61,11 @@ public class Messages extends ConcurrentSkipListMap<String, Message> {
 				new Message(MessageConnector.CONSUME_IM, MessageConnector.CONSUME_PMS,
 						MessageConnector.CONSUME_DINGDING, MessageConnector.CONSUME_ZHENGWUDINGDING,
 						MessageConnector.CONSUME_QIYEWEIXIN));
+		/* 待办提醒通知 */
+		o.put(MessageConnector.TYPE_TASK_PRESS,
+				new Message(MessageConnector.CONSUME_IM, MessageConnector.CONSUME_PMS,
+						MessageConnector.CONSUME_DINGDING, MessageConnector.CONSUME_ZHENGWUDINGDING,
+						MessageConnector.CONSUME_QIYEWEIXIN));
 
 		o.put(MessageConnector.TYPE_TASK_DELETE, new Message());
 

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Person.java


+ 44 - 2
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java

@@ -25,6 +25,9 @@ public class ProcessPlatform extends ConfigObject {
 		this.maintenanceIdentity = "";
 	}
 
+	@FieldDescribe("提醒设置,设置提醒间隔.")
+	private Press press;
+
 	@FieldDescribe("催办任务设置,发现即将过期时发送提醒消息.")
 	private Urge urge;
 
@@ -40,6 +43,10 @@ public class ProcessPlatform extends ConfigObject {
 	@FieldDescribe("维护身份,当工作发生意外错误,无法找到对应的处理人情况下,先尝试将工作分配给创建身份,如果创建身份也不可获取,那么分配给指定人员,默认情况下这个值为空.")
 	private String maintenanceIdentity;
 
+	public Press getPress() {
+		return this.press == null ? new Press() : this.press;
+	}
+
 	public Urge getUrge() {
 		return this.urge == null ? new Urge() : this.urge;
 	}
@@ -61,6 +68,41 @@ public class ProcessPlatform extends ConfigObject {
 		FileUtils.write(file, XGsonBuilder.toJson(this), DefaultCharset.charset);
 	}
 
+	public static class Press extends ConfigObject {
+
+		public static Press defaultInstance() {
+			Press o = new Press();
+			return o;
+		}
+
+		public final static Integer DEFAULT_INTERVALMINUTES = 10;
+
+		public final static Integer DEFAULT_COUNT = 3;
+
+		@FieldDescribe("提醒间隔(分钟)")
+		private Integer intervalMinutes;
+
+		@FieldDescribe("提醒数量限制.")
+		private Integer count;
+
+		public Integer getIntervalMinutes() {
+			return (intervalMinutes == null || intervalMinutes < 0) ? DEFAULT_INTERVALMINUTES : this.intervalMinutes;
+		}
+
+		public Integer getCount() {
+			return (count == null || count < 0) ? DEFAULT_COUNT : this.count;
+		}
+
+		public void setIntervalMinutes(Integer intervalMinutes) {
+			this.intervalMinutes = intervalMinutes;
+		}
+
+		public void setCount(Integer count) {
+			this.count = count;
+		}
+
+	}
+
 	public static class Urge extends ConfigObject {
 
 		public static Urge defaultInstance() {
@@ -156,7 +198,7 @@ public class ProcessPlatform extends ConfigObject {
 	}
 
 	public static class Delay extends ConfigObject {
-		
+
 		public static Delay defaultInstance() {
 			Delay o = new Delay();
 			return o;
@@ -199,7 +241,7 @@ public class ProcessPlatform extends ConfigObject {
 			Reorganize o = new Reorganize();
 			return o;
 		}
-		
+
 		public final static String DEFAULT_CRON = "30 15 8,12,14 * * ?";
 
 		public final static Boolean DEFAULT_ENABLE = true;

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Token.java

@@ -190,7 +190,7 @@ public class Token extends ConfigObject {
 		o.id = name;
 		o.employee = name;
 		o.display = name;
-		o.mail = name + "@o2oa.io";
+		o.mail = name + "@o2oa.net";
 		o.setDistinguishedName(defaultInitialManagerDistinguishedName);
 		o.weixin = "";
 		o.qq = "";

+ 11 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionPersonNotExist.java

@@ -0,0 +1,11 @@
+package com.x.base.core.project.exception;
+
+public class ExceptionPersonNotExist extends PromptException {
+
+	private static final long serialVersionUID = -7354813827434276962L;
+
+	public ExceptionPersonNotExist(String flag) {
+		super("指定的用户不存在:{}.", flag);
+	}
+
+}

+ 9 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/http/HttpToken.java

@@ -14,11 +14,16 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.time.DateUtils;
 
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.Crypto;
 import com.x.base.core.project.tools.DateTools;
 
 public class HttpToken {
 
+	private static Logger logger = LoggerFactory.getLogger(HttpToken.class);
+
 	public static final String X_Token = "x-token";
 	public static final String X_Authorization = "authorization";
 	public static final String X_Person = "x-person";
@@ -52,14 +57,14 @@ public class HttpToken {
 			try {
 				plain = Crypto.decrypt(token, key);
 			} catch (Exception e) {
-				System.out.println("can not decrypt token:" + token + ". " + e.getMessage());
+				logger.warn("can not decrypt token:{}, {}.", token, e.getMessage());
 				return EffectivePerson.anonymous();
 			}
 			Pattern pattern = Pattern.compile(RegularExpression_Token, Pattern.CASE_INSENSITIVE);
 			Matcher matcher = pattern.matcher(plain);
 			if (!matcher.find()) {
 				/* 不报错,跳过错误,将用户设置为anonymous */
-				System.out.println("token format error:" + plain + ".");
+				logger.warn("token format error:{}.", plain);
 				return EffectivePerson.anonymous();
 			}
 			Date date = DateUtils.parseDate(matcher.group(2), DateTools.formatCompact_yyyyMMddHHmmss);
@@ -67,17 +72,16 @@ public class HttpToken {
 			long diff = (new Date().getTime() - date.getTime());
 			diff = Math.abs(diff);
 			if (TokenType.user.equals(tokenType) || TokenType.manager.equals(tokenType)) {
-				if (diff > (60000L * 60 * 24 * 15)) {
+				if (diff > (60000L * Config.person().getTokenExpiredMinutes())) {
 					// throw new Exception("token expired." + token);
 					/* 不报错,跳过错误,将用户设置为anonymous */
-					System.out.println("token expired." + plain);
+					logger.warn("token expired:{}.", plain);
 					return EffectivePerson.anonymous();
 				}
 			}
 			if (TokenType.cipher.equals(tokenType)) {
 				if (diff > (60000 * 20)) {
 					/* 不报错,跳过错误,将用户设置为anonymous */
-					System.out.println("cipher token expired." + plain);
 					return EffectivePerson.anonymous();
 				}
 			}

+ 11 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/message/MessageConnector.java

@@ -6,6 +6,8 @@ import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.x.base.core.project.Context;
 import com.x.base.core.project.x_message_assemble_communicate;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.logger.LoggerFactory;
 
@@ -23,6 +25,8 @@ public class MessageConnector {
 
 	public static final String TYPE_TASK_EXPIRE = "task_expire";
 
+	public static final String TYPE_TASK_PRESS = "task_press";
+
 	public static final String TYPE_TASKCOMPLETED_CREATE = "taskCompleted_create";
 
 	public static final String TYPE_TASKCOMPLETED_DELETE = "taskCompleted_delete";
@@ -59,6 +63,8 @@ public class MessageConnector {
 
 	public static final String TYPE_CALENDAR_ALARM = "calendar_alarm";
 
+	public static final String TYPE_CUSTOM_CREATE = "custom_create";
+
 	public static final String CONSUME_IM = "im";
 
 	public static final String CONSUME_PMS = "pms";
@@ -116,14 +122,18 @@ public class MessageConnector {
 		}
 	}
 
-	public static class Wrap {
+	public static class Wrap extends GsonPropertyObject {
 
+		@FieldDescribe("类型")
 		private String type;
 
+		@FieldDescribe("人员")
 		private String person;
 
+		@FieldDescribe("标题")
 		private String title;
 
+		@FieldDescribe("推送内容")
 		private JsonElement body;
 
 		public String getType() {

+ 8 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/NumberTools.java

@@ -36,7 +36,7 @@ public class NumberTools {
 	}
 
 	public static Double ofDouble(String str) {
-		if (NumberUtils.isNumber(str)) {
+		if (NumberUtils.isCreatable(str)) {
 			return NumberUtils.toDouble(str);
 		} else if (stirngOfPercent(str)) {
 			return NumberUtils.toDouble(StringUtils.replace(str, "%", "")) / 100;
@@ -74,4 +74,11 @@ public class NumberTools {
 		return null;
 	}
 
+	public static boolean nullOrLessThan(Integer value, Number number) {
+		if (value == null) {
+			return true;
+		}
+		return value < number.intValue();
+	}
+
 }

+ 11 - 2
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/factory/DocumentFactory.java

@@ -130,7 +130,7 @@ public class DocumentFactory<T> extends AbstractFactory {
 	public List<Document> listNextWithCondition( 
 			Integer maxCount, List<String> viewAbleCategoryIds, String title, List<String> publisherList, List<String> createDateList, 
 			List<String> publishDateList,  List<String> statusList, String documentType, List<String> creatorUnitNameList, List<String> importBatchNames, List<String> personNames, List<String> unitNames, List<String> groupNames, 
-			Object sequenceFieldValue, String orderField, String order, Boolean manager
+			Object sequenceFieldValue, String orderField, String order, Boolean manager, Date lastedPublishTime 
 	) throws Exception {
 		if( ListTools.isEmpty( viewAbleCategoryIds ) ){
 			order = "DESC";
@@ -220,7 +220,12 @@ public class DocumentFactory<T> extends AbstractFactory {
 				}
 			}
 		}
+		
 		//组织查询条件
+		//根据最晚发布时间来过滤
+		if( lastedPublishTime != null ) {
+			p = cb.and( p, cb.greaterThan( root.get( Document_.publishTime ) , lastedPublishTime));
+		}
 		if( StringUtils.isNotEmpty( documentType ) && !"全部".equals( documentType ) ){
 			p = cb.and( p, cb.equal( root.get( Document_.documentType ) , documentType));
 		}
@@ -329,7 +334,7 @@ public class DocumentFactory<T> extends AbstractFactory {
 	public Long countWithCondition( 
 			List<String> viewAbleCategoryIds, String title, List<String> publisherList, List<String> createDateList,  List<String> publishDateList,  
 			List<String> statusList, String documentType, List<String>  creatorUnitNameList, List<String> importBatchNames, List<String> personNames, List<String> unitNames,
-			List<String> groupNames, Boolean manager
+			List<String> groupNames, Boolean manager, Date lastedPublishTime
 	) throws Exception {
 		Date startDate = null;
 		Date endDate = null;
@@ -367,6 +372,10 @@ public class DocumentFactory<T> extends AbstractFactory {
 			p = cb.and( p, permission );
 		}
 		
+		//根据最晚发布时间来过滤
+		if( lastedPublishTime != null ) {
+			p = cb.and( p, cb.greaterThan( root.get( Document_.publishTime ) , lastedPublishTime));
+		}
 		//组织查询条件
 		if( StringUtils.isNotEmpty( documentType ) && !"全部".equals( documentType ) ){
 			p = cb.and( p, cb.equal( root.get( Document_.documentType ) , documentType));

+ 350 - 0
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionCountLatestDocumentWithFilter.java

@@ -0,0 +1,350 @@
+package com.x.cms.assemble.control.jaxrs.document;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ListTools;
+
+public class ActionCountLatestDocumentWithFilter extends BaseAction {
+
+	private static  Logger logger = LoggerFactory.getLogger(ActionCountLatestDocumentWithFilter.class);
+
+	protected ActionResult<Wo> execute( HttpServletRequest request, JsonElement jsonElement, EffectivePerson effectivePerson ) {
+		ActionResult<Wo> result = new ActionResult<>();
+		
+		Long total = 0L;
+		Wi wi = null;
+		Wo wo = new Wo();
+		List<String> queryCategoryIds = new ArrayList<>();
+		
+		Boolean manager = false;
+		Boolean check = true;
+		
+		List<String> personNames = new ArrayList<>();
+		List<String> unitNames = null;
+		List<String> groupNames = null;
+		Boolean isAnonymous = effectivePerson.isAnonymous();
+		String personName = effectivePerson.getDistinguishedName();
+		Integer minutes = null;		
+		Date lastedPublishTime = null;
+		
+		personNames.add( "所有人" );
+		personNames.add( personName );
+		
+		try {
+			wi = this.convertToWrapIn( jsonElement, Wi.class );
+		} catch (Exception e ) {
+			check = false;
+			Exception exception = new ExceptionDocumentInfoProcess( e, "系统在将JSON信息转换为对象时发生异常。JSON:" + jsonElement.toString() );
+			result.error( exception );
+			logger.error( e, effectivePerson, request, null);
+		}
+		
+		if (wi == null) {
+			wi = new Wi();
+		}
+		
+		if( StringUtils.isEmpty( wi.getDocumentType() )) {
+			wi.setDocumentType( "信息" );
+		}
+		
+		try {
+			manager = userManagerService.isManager( request, effectivePerson );
+		} catch (Exception e) {
+			check = false;
+			Exception exception = new ExceptionDocumentInfoProcess(e, "系统在检查用户是否是平台管理员时发生异常。Name:" + personName);
+			result.error(exception);
+			logger.error(e, effectivePerson, request, null);
+		}
+		
+		if (check) {
+			// 根据权限,把用户传入的AppId和categoryId进行过滤,最终形成一个可访问的queryCategoryIds
+			try {
+				queryCategoryIds = listAllViewAbleCategoryIds( 
+						wi.getAppIdList(),  wi.getAppAliasList(), wi.getCategoryIdList(), wi.getCategoryAliasList(), wi.getDocumentType(), 
+						personName, isAnonymous, manager, 500
+				);
+				if ( queryCategoryIds == null) {
+					queryCategoryIds = new ArrayList<>();
+				}
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在根据应用栏目列表和分类列表计算可访问的分类ID列表时发生异常。");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+		
+		if (check) {
+			if ( ListTools.isEmpty( queryCategoryIds )) {
+				// 看看是不是从所有的栏目和分类里取,如果不是,则添加无可见分类,如果是,则整体排序
+				if ( ListTools.isEmpty( wi.getAppIdList() ) && ListTools.isEmpty( wi.getAppAliasList() )
+						&& ListTools.isEmpty( wi.getCategoryIdList() ) && ListTools.isEmpty( wi.getCategoryAliasList() )
+				) {
+					// 手机办公首页,是从所有文档里直接查询的,没有带查询条件, 查询所有
+				} else {
+					queryCategoryIds = new ArrayList<>();
+					queryCategoryIds.add("无可见分类");
+				}
+			}
+		}
+
+		if( check ) {
+			try {
+				unitNames = userManagerService.listUnitNamesWithPerson( personName );
+				groupNames = userManagerService.listGroupNamesByPerson( personName );
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在根据过滤条件查询用户可访问的文档ID列表时发生异常。");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}
+
+		if (check) {
+			minutes = wi.getMinutes();
+			if ( minutes == null || minutes <= 0) {
+				lastedPublishTime = null;
+			}else {
+				lastedPublishTime = new Date ( new Date().getTime() - minutes*60*1000L );
+			}
+		
+			// 从数据库中查询符合条件的对象总数
+			try {
+				total = documentInfoServiceAdv.countWithCondition( queryCategoryIds, wi.getTitle(), 
+						wi.getPublisherList(), wi.getCreateDateList(), wi.getPublishDateList(), wi.getStatusList(), wi.getDocumentType(), 
+						wi.getCreatorUnitNameList(),
+						wi.getImportBatchNames(), personNames, unitNames, groupNames,  manager, lastedPublishTime );
+				if( total == null || total < 0 ) {
+					total = 0L;
+				}
+				wo.setDocCount(total);
+				result.setCount(total);
+			} catch (Exception e) {
+				check = false;
+				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在获取用户可查询到的文档数据条目数量时发生异常。");
+				result.error(exception);
+				logger.error(e, effectivePerson, request, null);
+			}
+		}		
+		result.setData(wo);
+		return result;
+	}
+	
+	public static class Wi {
+		
+		@FieldDescribe( "只查询minutes分钟之类发布的文档,值为null或者为0时不作限制" )
+		private Integer minutes = null;
+
+		@FieldDescribe( "作为过滤条件的CMS应用ID列表, 可多个, String数组." )
+		private List<String> appIdList;
+		
+		@FieldDescribe( "作为过滤条件的CMS应用别名列表, 可多个, String数组." )
+		private List<String> appAliasList;
+		
+		@FieldDescribe( "作为过滤条件的CMS分类ID列表, 可多个, String数组." )
+		private List<String> categoryIdList;
+
+		@FieldDescribe( "作为过滤条件的CMS应用别名列表, 可多个, String数组." )
+		private List<String> categoryAliasList;
+		
+		@FieldDescribe( "作为过滤条件的创建者姓名列表, 可多个, String数组." )
+		private List<String> creatorList;
+
+		@FieldDescribe( "作为过滤条件的文档状态列表, 可多个, String数组,值:published | draft | checking | error" )
+		private List<String> statusList;
+		
+		@FieldDescribe( "作为过滤条件的文档发布者姓名, 可多个, String数组." )
+		private List<String> publisherList;
+		
+		@FieldDescribe( "创建日期列表,可以传入1个(开始时间)或者2个(开始和结束时间), String, yyyy-mm-dd." )
+		private List<String> createDateList;	//
+		
+		@FieldDescribe( "发布日期列表,可以传入1个(开始时间)或者2个(开始和结束时间), String, yyyy-mm-dd." )
+		private List<String> publishDateList;	//
+		
+		@FieldDescribe( "作为过滤条件的发布者所属组织, 可多个, String数组." )
+		private List<String> creatorUnitNameList;
+
+		@FieldDescribe( "文档类型:全部 | 信息 | 数据" )
+		private String documentType = "信息";
+
+		@FieldDescribe( "文档导入的批次号:在导入文件时系统返回的批次号(数组)" )
+		private List<String> importBatchNames = null;
+		
+		@FieldDescribe( "排序列名" )
+		private String orderField = "publishTime";
+		
+		@FieldDescribe( "排序方式:ASC|DESC." )
+		private String orderType = "DESC";
+		
+		@FieldDescribe( "是否需要查询数据,默认不查询." )
+		private Boolean needData = false;
+
+		@FieldDescribe( "作为过滤条件的CMS文档关键字, 通常是标题, String, 模糊查询." )
+		private String title;
+
+		public List<String> getCreatorUnitNameList() {
+			return creatorUnitNameList;
+		}
+
+		public void setCreatorUnitNameList(List<String> creatorUnitNameList) {
+			this.creatorUnitNameList = creatorUnitNameList;
+		}
+
+		public List<String> getAppIdList() {
+			return appIdList == null?new ArrayList<>():appIdList;
+		}
+
+		public void setAppIdList(List<String> appIdList) {
+			this.appIdList = appIdList;
+		}
+
+		public List<String> getCategoryIdList() {
+			return categoryIdList == null?new ArrayList<>():categoryIdList;
+		}
+
+		public void setCategoryIdList(List<String> categoryIdList) {
+			this.categoryIdList = categoryIdList;
+		}
+
+		public List<String> getCreatorList() {
+			return creatorList == null?new ArrayList<>():creatorList;
+		}
+
+		public void setCreatorList(List<String> creatorList) {
+			this.creatorList = creatorList;
+		}
+
+		public List<String> getStatusList() {
+			return statusList == null?new ArrayList<>():statusList;
+		}
+
+		public void setStatusList(List<String> statusList) {
+			this.statusList = statusList;
+		}
+
+		public List<String> getPublisherList() {
+			return publisherList == null?new ArrayList<>():publisherList;
+		}
+
+		public void setPublisherList(List<String> publisherList) {
+			this.publisherList = publisherList;
+		}
+
+		public List<String> getCreateDateList() {
+			return createDateList == null?new ArrayList<>():createDateList;
+		}
+
+		public void setCreateDateList(List<String> createDateList) {
+			this.createDateList = createDateList;
+		}
+		
+		public String getTitle() {
+			return title;
+		}
+
+		public void setTitle(String title) {
+			this.title = title;
+		}
+
+		public List<String> getPublishDateList() {
+			return publishDateList == null?new ArrayList<>():publishDateList;
+		}
+
+		public void setPublishDateList(List<String> publishDateList) {
+			this.publishDateList = publishDateList;
+		}
+
+		public String getOrderField() {
+			return orderField;
+		}
+
+		public String getOrderType() {
+			return orderType;
+		}
+
+		public void setOrderField(String orderField) {
+			this.orderField = orderField;
+		}
+
+		public void setOrderType(String orderType) {
+			this.orderType = orderType;
+		}
+
+		public List<String> getAppAliasList() {
+			return appAliasList == null?new ArrayList<>():appAliasList;
+		}
+
+		public List<String> getCategoryAliasList() {
+			return categoryAliasList == null?new ArrayList<>():categoryAliasList;
+		}
+
+		public void setAppAliasList(List<String> appAliasList) {
+			this.appAliasList = appAliasList;
+		}
+
+		public void setCategoryAliasList(List<String> categoryAliasList) {
+			this.categoryAliasList = categoryAliasList;
+		}
+
+		public String getDocumentType() {
+			return documentType;
+		}
+
+		public void setDocumentType(String documentType) {
+			this.documentType = documentType;
+		}		
+
+		public List<String> getImportBatchNames() {
+			return importBatchNames;
+		}
+
+		public void setImportBatchNames(List<String> importBatchNames) {
+			this.importBatchNames = importBatchNames;
+		}
+
+		public Boolean getNeedData() {
+			return needData;
+		}
+
+		public void setNeedData(Boolean needData) {
+			this.needData = needData;
+		}
+
+		public Integer getMinutes() {
+			return minutes;
+		}
+
+		public void setMinutes(Integer minutes) {
+			this.minutes = minutes;
+		}
+		
+	}
+	
+	public static class Wo {
+		
+		@FieldDescribe( "查询到的文档数量" )
+		Long docCount = 0L;
+
+		public Long getDocCount() {
+			return docCount;
+		}
+
+		public void setDocCount(Long docCount) {
+			this.docCount = docCount;
+		}
+		
+	}
+}

+ 2 - 2
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionGetViewCount.java → o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionCountViewTimes.java

@@ -8,9 +8,9 @@ import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 
-public class ActionGetViewCount extends BaseAction {
+public class ActionCountViewTimes extends BaseAction {
 
-	private static  Logger logger = LoggerFactory.getLogger( ActionGetViewCount.class );
+	private static  Logger logger = LoggerFactory.getLogger( ActionCountViewTimes.class );
 	
 	protected ActionResult<Wo> execute( HttpServletRequest request, String id, EffectivePerson effectivePerson ) throws Exception {
 		ActionResult<Wo> result = new ActionResult<>();

+ 22 - 2
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionListNextWithFilter.java

@@ -42,6 +42,8 @@ public class ActionListNextWithFilter extends BaseAction {
 		List<String> groupNames = null;
 		Boolean isAnonymous = effectivePerson.isAnonymous();
 		String personName = effectivePerson.getDistinguishedName();
+		Integer minutes = null;		
+		Date lastedPublishTime = null;
 		
 		personNames.add( "所有人" );
 		personNames.add( personName );
@@ -117,12 +119,18 @@ public class ActionListNextWithFilter extends BaseAction {
 		}
 
 		if (check) {
+			minutes = wi.getMinutes();
+			if ( minutes == null || minutes <= 0) {
+				lastedPublishTime = null;
+			}else {
+				lastedPublishTime = new Date ( new Date().getTime() - minutes*60*1000L );
+			}
 			// 从数据库中查询符合条件的对象总数
 			try {
 				total = documentInfoServiceAdv.countWithCondition( queryCategoryIds, wi.getTitle(), 
 						wi.getPublisherList(), wi.getCreateDateList(), wi.getPublishDateList(), wi.getStatusList(), wi.getDocumentType(), 
 						wi.getCreatorUnitNameList(),
-						wi.getImportBatchNames(), personNames, unitNames, groupNames, 	manager );
+						wi.getImportBatchNames(), personNames, unitNames, groupNames, manager, lastedPublishTime );
 			} catch (Exception e) {
 				check = false;
 				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在获取用户可查询到的文档数据条目数量时发生异常。");
@@ -135,7 +143,7 @@ public class ActionListNextWithFilter extends BaseAction {
 				documentList = documentInfoServiceAdv.listNextWithCondition( id, count, queryCategoryIds, wi.getTitle(), 
 						wi.getPublisherList(), wi.getCreateDateList(), wi.getPublishDateList(), wi.getStatusList(), wi.getDocumentType(), 
 						wi.getCreatorUnitNameList(),
-						wi.importBatchNames, personNames, unitNames, groupNames, wi.getOrderField(), wi.getOrderType(), 	manager);
+						wi.importBatchNames, personNames, unitNames, groupNames, wi.getOrderField(), wi.getOrderType(), 	manager, lastedPublishTime );
 			} catch (Exception e) {
 				check = false;
 				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在根据用户可访问的文档ID列表对文档进行分页查询时发生异常。");
@@ -205,6 +213,9 @@ public class ActionListNextWithFilter extends BaseAction {
 	
 	public static class Wi {
 
+		@FieldDescribe( "只查询minutes分钟之类发布的文档,值为null或者为0时不作限制" )
+		private Integer minutes = null;
+		
 		@FieldDescribe( "作为过滤条件的CMS应用ID列表, 可多个, String数组." )
 		private List<String> appIdList;
 		
@@ -253,6 +264,15 @@ public class ActionListNextWithFilter extends BaseAction {
 		@FieldDescribe( "作为过滤条件的CMS文档关键字, 通常是标题, String, 模糊查询." )
 		private String title;
 
+		
+		public Integer getMinutes() {
+			return minutes;
+		}
+
+		public void setMinutes(Integer minutes) {
+			this.minutes = minutes;
+		}
+
 		public List<String> getCreatorUnitNameList() {
 			return creatorUnitNameList;
 		}

+ 21 - 2
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionListNextWithFilter_NEW.java

@@ -40,6 +40,8 @@ public class ActionListNextWithFilter_NEW extends BaseAction {
 		List<String> groupNames = null;
 		Boolean isAnonymous = effectivePerson.isAnonymous();
 		String personName = effectivePerson.getDistinguishedName();
+		Integer minutes = null;		
+		Date lastedPublishTime = null;
 		
 		personNames.add( "所有人" );
 		personNames.add( personName );
@@ -114,12 +116,18 @@ public class ActionListNextWithFilter_NEW extends BaseAction {
 		}
 
 		if (check) {
+			minutes = wi.getMinutes();
+			if ( minutes == null || minutes <= 0) {
+				lastedPublishTime = null;
+			}else {
+				lastedPublishTime = new Date ( new Date().getTime() - minutes*60*1000L );
+			}
 			// 从数据库中查询符合条件的对象总数
 			try {
 				total = documentInfoServiceAdv.countWithCondition( queryCategoryIds, wi.getTitle(), 
 						wi.getPublisherList(), wi.getCreateDateList(), wi.getPublishDateList(), wi.getStatusList(), wi.getDocumentType(), 
 						wi.getCreatorUnitNameList(),
-						wi.getImportBatchNames(), personNames, unitNames, groupNames, manager );
+						wi.getImportBatchNames(), personNames, unitNames, groupNames, manager, lastedPublishTime );
 			} catch (Exception e) {
 				check = false;
 				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在获取用户可查询到的文档数据条目数量时发生异常。");
@@ -132,7 +140,7 @@ public class ActionListNextWithFilter_NEW extends BaseAction {
 				documentList = documentInfoServiceAdv.listNextWithCondition( id, count, queryCategoryIds, wi.getTitle(), 
 						wi.getPublisherList(), wi.getCreateDateList(), wi.getPublishDateList(), wi.getStatusList(), wi.getDocumentType(), 
 						wi.getCreatorUnitNameList(),
-						wi.importBatchNames, personNames, unitNames, groupNames, wi.getOrderField(), wi.getOrderType(), manager);
+						wi.importBatchNames, personNames, unitNames, groupNames, wi.getOrderField(), wi.getOrderType(), manager, lastedPublishTime );
 			} catch (Exception e) {
 				check = false;
 				Exception exception = new ExceptionDocumentInfoProcess(e, "系统在根据用户可访问的文档ID列表对文档进行分页查询时发生异常。");
@@ -202,6 +210,9 @@ public class ActionListNextWithFilter_NEW extends BaseAction {
 	
 	public static class Wi {
 		
+		@FieldDescribe( "只查询minutes分钟之类发布的文档,值为null或者为0时不作限制" )
+		private Integer minutes = null;
+		
 		@FieldDescribe( "作为过滤条件的CMS应用ID列表, 可多个, String数组." )
 		private List<String> appIdList;
 		
@@ -251,6 +262,14 @@ public class ActionListNextWithFilter_NEW extends BaseAction {
 		private String title;
 
 		
+		public Integer getMinutes() {
+			return minutes;
+		}
+
+		public void setMinutes(Integer minutes) {
+			this.minutes = minutes;
+		}
+
 		public List<String> getCreatorUnitNameList() {
 			return creatorUnitNameList;
 		}

+ 25 - 3
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/DocumentAction.java

@@ -178,7 +178,7 @@ public class DocumentAction extends StandardJaxrsAction{
 		return ResponseFactory.getDefaultActionResultResponse(result);
 	}
 	
-	@JaxrsMethodDescribe(value = "根据ID获取信息发布文档信息被访问次数.", action = ActionGetViewCount.class)
+	@JaxrsMethodDescribe(value = "根据ID获取信息发布文档信息被访问次数.", action = ActionCountViewTimes.class)
 	@GET
 	@Path("{id}/view/count")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
@@ -186,9 +186,9 @@ public class DocumentAction extends StandardJaxrsAction{
 	public Response getViewCount(@Context HttpServletRequest request, 
 			@JaxrsParameterDescribe("信息文档ID") @PathParam("id") String id) {
 		EffectivePerson effectivePerson = this.effectivePerson( request );
-		ActionResult<ActionGetViewCount.Wo> result = new ActionResult<>();
+		ActionResult<ActionCountViewTimes.Wo> result = new ActionResult<>();
 		try {
-			result = new ActionGetViewCount().execute( request, id, effectivePerson );
+			result = new ActionCountViewTimes().execute( request, id, effectivePerson );
 		} catch (Exception e) {
 			result = new ActionResult<>();
 			result.error( e );
@@ -197,6 +197,28 @@ public class DocumentAction extends StandardJaxrsAction{
 		return ResponseFactory.getDefaultActionResultResponse(result);
 	}
 	
+	@JaxrsMethodDescribe(value = "查询符合过滤条件的已发布的信息数量.", action = ActionCountLatestDocumentWithFilter.class)
+	@PUT
+	@Path("filter/count")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public Response countDocumentWithFilter( @Context HttpServletRequest request, JsonElement jsonElement ) {
+		EffectivePerson effectivePerson = this.effectivePerson( request );
+		ActionResult<ActionCountLatestDocumentWithFilter.Wo> result = new ActionResult<>();
+		Boolean check = true;
+
+		if( check ){
+			try {
+				result = new ActionCountLatestDocumentWithFilter().execute( request,  jsonElement, effectivePerson );
+			} catch (Exception e) {
+				result = new ActionResult<>();
+				result.error( e );
+				logger.error( e, effectivePerson, request, null);
+			}
+		}
+		return ResponseFactory.getDefaultActionResultResponse(result);
+	}
+	
 	@JaxrsMethodDescribe(value = "根据ID删除信息发布文档信息.", action = ActionDelete.class)
 	@DELETE
 	@Path("{id}")

+ 4 - 4
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/DocumentInfoService.java

@@ -167,10 +167,10 @@ public class DocumentInfoService {
 			List<String> viewAbleCategoryIds, String title, List<String> publisherList, List<String> createDateList,  
 			List<String> publishDateList,  List<String> statusList, String documentType, List<String>  creatorUnitNameList,
 			List<String> importBatchNames, List<String> personNames, List<String> unitNames, 
-			List<String> groupNames,  Boolean manager ) throws Exception {
+			List<String> groupNames,  Boolean manager, Date lastedPublishTime ) throws Exception {
 		Business business = new Business(emc);	
 		return business.getDocumentFactory().countWithCondition( viewAbleCategoryIds, title, publisherList, createDateList, 
-				publishDateList, statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, manager );
+				publishDateList, statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, manager, lastedPublishTime );
 	}
 	
 	@SuppressWarnings("unchecked")
@@ -178,7 +178,7 @@ public class DocumentInfoService {
 			String id, Integer maxCount, List<String> viewAbleCategoryIds, String title, List<String> publisherList, List<String> createDateList,  
 			List<String> publishDateList,  List<String> statusList, String documentType, List<String>  creatorUnitNameList, 
 			List<String> importBatchNames, List<String> personNames, List<String> unitNames, 
-			List<String> groupNames, String orderField, String order, Boolean manager ) throws Exception {
+			List<String> groupNames, String orderField, String order, Boolean manager, Date lastedPublishTime ) throws Exception {
 		Business business = new Business(emc);
 		Document document = null;
 		Object sequenceFieldValue = null;
@@ -192,7 +192,7 @@ public class DocumentInfoService {
 			}
 		}		
 		return business.getDocumentFactory().listNextWithCondition( maxCount, viewAbleCategoryIds, title, publisherList, createDateList, publishDateList, 
-				statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, sequenceFieldValue, orderField, order,  manager );
+				statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, sequenceFieldValue, orderField, order,  manager, lastedPublishTime );
 	}
 
 	@SuppressWarnings("unchecked")

+ 5 - 4
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/DocumentInfoServiceAdv.java

@@ -1,5 +1,6 @@
 package com.x.cms.assemble.control.service;
 
+import java.util.Date;
 import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
@@ -219,13 +220,13 @@ public class DocumentInfoServiceAdv {
 			List<String> createDateList,  List<String> publishDateList,  List<String> statusList, String documentType, 
 			List<String>  creatorUnitNameList,
 			List<String> importBatchNames, List<String> personNames, 
-			List<String> unitNames, List<String> groupNames, Boolean manager) throws Exception {
+			List<String> unitNames, List<String> groupNames, Boolean manager, Date lastedPublishTime ) throws Exception {
 		if( ListTools.isEmpty( viewAbleCategoryIds ) && !manager ){
 			return 0L;
 		}
 		try ( EntityManagerContainer emc = EntityManagerContainerFactory.instance().create() ) {
 			return documentInfoService.countWithCondition( emc, viewAbleCategoryIds, title, publisherList, createDateList, publishDateList, 
-					statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, manager );
+					statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames, groupNames, manager, lastedPublishTime );
 		} catch ( Exception e ) {
 			throw e;
 		}
@@ -234,7 +235,7 @@ public class DocumentInfoServiceAdv {
 	public List<Document> listNextWithCondition(String id, Integer count, List<String> viewAbleCategoryIds, String title, List<String> publisherList, 
 			List<String> createDateList,  List<String> publishDateList,  List<String> statusList, String documentType, 
 			List<String>  creatorUnitNameList, List<String> importBatchNames, List<String> personNames, 
-			List<String> unitNames, List<String> groupNames,  String orderField, String order, Boolean manager) throws Exception {
+			List<String> unitNames, List<String> groupNames,  String orderField, String order, Boolean manager, Date lastedPublishTime ) throws Exception {
 		if( ListTools.isEmpty( viewAbleCategoryIds ) && !manager ){
 			return null;
 		}
@@ -246,7 +247,7 @@ public class DocumentInfoServiceAdv {
 		}
 		try ( EntityManagerContainer emc = EntityManagerContainerFactory.instance().create() ) {
 			return documentInfoService.listNextWithCondition( emc, id, count, viewAbleCategoryIds, title, publisherList, createDateList, publishDateList, 
-					statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames,  groupNames, orderField, order, manager );
+					statusList, documentType, creatorUnitNameList, importBatchNames, personNames, unitNames,  groupNames, orderField, order, manager, lastedPublishTime );
 		} catch ( Exception e ) {
 			throw e;
 		}

+ 14 - 15
o2server/x_cms_assemble_control/src/main/java/com/x/cms/common/image/maincolor/ImageMainColorUtil.java

@@ -1,14 +1,12 @@
 package com.x.cms.common.image.maincolor;
 
 import java.awt.image.BufferedImage;
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 
-import javax.imageio.ImageIO;
-
 public class ImageMainColorUtil {
 	
 	BufferedImage image = null;
@@ -287,18 +285,19 @@ public class ImageMainColorUtil {
 	}
 
 	public static void main(String[] args){
-		File file = new File("E:/icon_okr72x.png");
-		BufferedImage bi = null;
-		try {
-			bi = ImageIO.read(file);
-			ImageMainColorUtil ImageUtil = new ImageMainColorUtil();
-			List<String> list = ImageUtil.getColorSolution( bi, 30, 1);
-			if( list != null && !list.isEmpty() ){
-				list.forEach( s -> System.out.println(s));
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+//		File file = new File("E:/icon_okr72x.png");
+//		BufferedImage bi = null;
+//		try {
+//			bi = ImageIO.read(file);
+//			ImageMainColorUtil ImageUtil = new ImageMainColorUtil();
+//			List<String> list = ImageUtil.getColorSolution( bi, 30, 1);
+//			if( list != null && !list.isEmpty() ){
+//				list.forEach( s -> System.out.println(s));
+//			}
+//		} catch (Exception e) {
+//			e.printStackTrace();
+//		}
+		
 	}
 	
 }

+ 2 - 2
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/CategoryExt.java

@@ -32,7 +32,7 @@ import com.x.base.core.project.annotation.FieldDescribe;
 public class CategoryExt extends SliceJpaObject {
 
 	private static final long serialVersionUID = 3856138316794473794L;
-	//private static final String TABLE = PersistenceProperties.CategoryExt.table;
+	private static final String TABLE = PersistenceProperties.CategoryExt.table;
 
 	public String getId() {
 		return id;
@@ -66,7 +66,7 @@ public class CategoryExt extends SliceJpaObject {
 	@FieldDescribe("扩展信息JSON内容")
 	@Lob
 	@Basic(fetch = FetchType.EAGER)
-	@Column( length = JpaObject.length_1M, name = ColumnNamePrefix + content_FIELDNAME)
+	@Column(length = JpaObject.length_1M, name = ColumnNamePrefix + content_FIELDNAME)
 	private String content;
 
 	public String getContent() {

+ 7 - 7
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/CategoryInfo.java

@@ -273,24 +273,24 @@ public class CategoryInfo extends SliceJpaObject {
 	@Column(length = JpaObject.length_id, name = ColumnNamePrefix + importViewName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String importViewName = null;
-	
+
 	public static final String anonymousAble_FIELDNAME = "anonymousAble";
 	@FieldDescribe("是否允许匿名访问.")
-	@Column( name = ColumnNamePrefix + anonymousAble_FIELDNAME)
+	@Column(name = ColumnNamePrefix + anonymousAble_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	@Index(name = TABLE + IndexNameMiddle + anonymousAble_FIELDNAME)
 	private Boolean anonymousAble = true;
-	
+
 	public static final String viewablePersonList_FIELDNAME = "viewablePersonList";
 	@FieldDescribe("发布可见人员")
 	@PersistentCollection(fetch = FetchType.EAGER)
 	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
-			+ viewableGroupList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
-					+ viewableGroupList_FIELDNAME + JoinIndexNameSuffix))
+			+ viewablePersonList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
+					+ viewablePersonList_FIELDNAME + JoinIndexNameSuffix))
 	@ElementColumn(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
-			+ viewableGroupList_FIELDNAME)
-	@ElementIndex(name = TABLE + IndexNameMiddle + viewableGroupList_FIELDNAME + ElementIndexNameSuffix)
+			+ viewablePersonList_FIELDNAME)
+	@ElementIndex(name = TABLE + IndexNameMiddle + viewablePersonList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
 	private List<String> viewablePersonList;
 

+ 1 - 1
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/DocumentViewRecord.java

@@ -113,7 +113,7 @@ public class DocumentViewRecord extends SliceJpaObject {
 
 	public static final String viewerUnitName_FIELDNAME = "viewerUnitName";
 	@FieldDescribe("访问者所属组织名称")
-	@Column(length = JpaObject.length_255B, name = ColumnNamePrefix + viewerTopUnitName_FIELDNAME)
+	@Column(length = JpaObject.length_255B, name = ColumnNamePrefix + viewerUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String viewerUnitName;
 

+ 7 - 6
o2server/x_console/src/main/java/com/x/server/console/Main.java

@@ -420,8 +420,7 @@ public class Main {
 
 	private static boolean update(String password, String backup, String latest) {
 		try {
-			return new ActionUpdate().execute(password, BooleanUtils.toBoolean(backup),
-					BooleanUtils.toBoolean(latest));
+			return new ActionUpdate().execute(password, BooleanUtils.toBoolean(backup), BooleanUtils.toBoolean(latest));
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -647,20 +646,22 @@ public class Main {
 		}
 	}
 
-	private static void dumpData(String password) {
+	private static boolean dumpData(String password) {
 		try {
-			(new ActionDumpData()).execute(password);
+			return (new ActionDumpData()).execute(password);
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
+		return true;
 	}
 
-	private static void dumpStorage(String password) {
+	private static boolean dumpStorage(String password) {
 		try {
-			(new ActionDumpStorage()).execute(password);
+			return (new ActionDumpStorage()).execute(password);
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
+		return true;
 	}
 
 	private static void resotreData(String dateString, String password) {

+ 33 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/CalendarConsumeQueue.java

@@ -0,0 +1,33 @@
+package com.x.message.assemble.communicate;
+
+import org.apache.commons.lang3.BooleanUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.Application;
+import com.x.base.core.project.x_calendar_assemble_control;
+import com.x.base.core.project.jaxrs.WrapBoolean;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class CalendarConsumeQueue extends AbstractQueue<Message> {
+
+	protected void execute(Message message) throws Exception {
+		Application app = ThisApplication.context().applications()
+				.randomWithWeight(x_calendar_assemble_control.class.getName());
+		if (null != app) {
+			WrapBoolean wrapBoolean = ThisApplication.context().applications().postQuery(false, app, "message", message)
+					.getData(WrapBoolean.class);
+			if (BooleanUtils.isTrue(wrapBoolean.getValue())) {
+				try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+					Message messageEntityObject = emc.find(message.getId(), Message.class);
+					if (null != messageEntityObject) {
+						emc.beginTransaction(Message.class);
+						emc.remove(messageEntityObject);
+						emc.commit();
+					}
+				}
+			}
+		}
+	}
+}

+ 78 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/DingdingConsumeQueue.java

@@ -0,0 +1,78 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.connection.HttpConnection;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.DingdingMessage;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class DingdingConsumeQueue extends AbstractQueue<Message> {
+
+	private static Logger logger = LoggerFactory.getLogger(DingdingConsumeQueue.class);
+
+	protected void execute(Message message) throws Exception {
+
+		if (Config.dingding().getEnable() && Config.dingding().getMessageEnable()) {
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Business business = new Business(emc);
+				DingdingMessage m = new DingdingMessage();
+				m.setAgent_id(Long.parseLong(Config.dingding().getAgentId(), 10));
+				m.setUserid_list(business.organization().person().getObject(message.getPerson()).getDingdingId());
+				m.getMsg().getText().setContent(message.getTitle());
+				// https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=ACCESS_TOKEN
+				String address = Config.dingding().getOapiAddress()
+						+ "/topapi/message/corpconversation/asyncsend_v2?access_token="
+						+ Config.dingding().corpAccessToken();
+				DingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+						DingdingMessageResp.class);
+				if (resp.getErrcode() != 0) {
+					ExceptionDingdingMessage e = new ExceptionDingdingMessage(resp.getErrcode(), resp.getErrmsg());
+					logger.error(e);
+				} else {
+					Message messageEntityObject = emc.find(message.getId(), Message.class);
+					if (null != messageEntityObject) {
+						emc.beginTransaction(Message.class);
+						emc.remove(messageEntityObject);
+						emc.commit();
+					}
+				}
+			}
+		}
+	}
+
+	public static class DingdingMessageResp {
+
+		private Integer errcode;
+		private String errmsg;
+		private Long task_id;
+
+		public String getErrmsg() {
+			return errmsg;
+		}
+
+		public void setErrmsg(String errmsg) {
+			this.errmsg = errmsg;
+		}
+
+		public Long getTask_id() {
+			return task_id;
+		}
+
+		public void setTask_id(Long task_id) {
+			this.task_id = task_id;
+		}
+
+		public Integer getErrcode() {
+			return errcode;
+		}
+
+		public void setErrcode(Integer errcode) {
+			this.errcode = errcode;
+		}
+
+	}
+}

+ 12 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionDingdingMessage.java

@@ -0,0 +1,12 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionDingdingMessage extends PromptException {
+
+	private static final long serialVersionUID = 4132300948670472899L;
+
+	ExceptionDingdingMessage(Integer retCode, String retMessage) {
+		super("发送钉钉消息失败,错误代码:{},错误消息:{}.", retCode, retMessage);
+	}
+}

+ 12 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionQiyeweixinMessage.java

@@ -0,0 +1,12 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionQiyeweixinMessage extends PromptException {
+
+	private static final long serialVersionUID = 4132300948670472899L;
+
+	ExceptionQiyeweixinMessage(Integer retCode, String retMessage) {
+		super("发送企业微信消息失败,错误代码:{},错误消息:{}.", retCode, retMessage);
+	}
+}

+ 12 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ExceptionZhengwuDingdingMessage.java

@@ -0,0 +1,12 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionZhengwuDingdingMessage extends PromptException {
+
+	private static final long serialVersionUID = 4132300948670472899L;
+
+	ExceptionZhengwuDingdingMessage(Integer retCode, String retMessage) {
+		super("发送政务钉钉消息失败,错误代码:{},错误消息:{}.", retCode, retMessage);
+	}
+}

+ 40 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ImConsumeQueue.java

@@ -0,0 +1,40 @@
+package com.x.message.assemble.communicate;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.Application;
+import com.x.base.core.project.x_message_assemble_communicate;
+import com.x.base.core.project.gson.XGsonBuilder;
+import com.x.base.core.project.jaxrs.WrapBoolean;
+import com.x.base.core.project.message.ImMessage;
+import com.x.base.core.project.message.MessageConnector;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class ImConsumeQueue extends AbstractQueue<Message> {
+
+	protected void execute(Message message) throws Exception {
+		ImMessage im = new ImMessage();
+		im.setType(message.getType());
+		im.setPerson(message.getPerson());
+		im.setTitle(message.getTitle());
+		im.setBody(XGsonBuilder.instance().fromJson(message.getBody(), JsonElement.class));
+		Boolean result = false;
+		for (Application app : ThisApplication.context().applications().get(x_message_assemble_communicate.class)) {
+			WrapBoolean wrapBoolean = ThisApplication.context().applications()
+					.postQuery(app, MessageConnector.CONSUME_IM, im).getData(WrapBoolean.class);
+			result = result || wrapBoolean.getValue();
+		}
+		if (result) {
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Message messageEntityObject = emc.find(message.getId(), Message.class);
+				if (null != messageEntityObject) {
+					emc.beginTransaction(Message.class);
+					emc.remove(messageEntityObject);
+					emc.commit();
+				}
+			}
+		}
+	}
+}

+ 31 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/PmsConsumeQueue.java

@@ -0,0 +1,31 @@
+package com.x.message.assemble.communicate;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.connection.CipherConnectionAction;
+import com.x.base.core.project.message.MessageConnector;
+import com.x.base.core.project.message.PmsMessage;
+import com.x.base.core.project.organization.Person;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class PmsConsumeQueue extends AbstractQueue<Message> {
+
+	protected void execute(Message message) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			Person person = business.organization().person().getObject(message.getPerson());
+			if ((null != person) && StringUtils.isNotEmpty(person.getMobile())) {
+				PmsMessage pms = new PmsMessage();
+				pms.setAccount(person.getMobile());
+				pms.setTitle(message.getTitle());
+				pms.setText(message.getTitle());
+				String url = Config.x_program_centerUrlRoot() + MessageConnector.CONSUME_PMS;
+				CipherConnectionAction.post(false, url, pms);
+			}
+		}
+	}
+}

+ 102 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/QiyeweixinConsumeQueue.java

@@ -0,0 +1,102 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.connection.HttpConnection;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.QiyeweixinMessage;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class QiyeweixinConsumeQueue extends AbstractQueue<Message> {
+
+	private static Logger logger = LoggerFactory.getLogger(QiyeweixinConsumeQueue.class);
+
+	protected void execute(Message message) throws Exception {
+
+		if (Config.qiyeweixin().getEnable() && Config.qiyeweixin().getMessageEnable()) {
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Business business = new Business(emc);
+				QiyeweixinMessage m = new QiyeweixinMessage();
+				m.setAgentid(Long.parseLong(Config.qiyeweixin().getAgentId(), 10));
+				m.setTouser(business.organization().person().getObject(message.getPerson()).getQiyeweixinId());
+				m.getText().setContent(message.getTitle());
+				String address = Config.qiyeweixin().getApiAddress() + "/cgi-bin/message/send?access_token="
+						+ Config.qiyeweixin().corpAccessToken();
+				QiyeweixinMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+						QiyeweixinMessageResp.class);
+				if (resp.getErrcode() != 0) {
+					ExceptionQiyeweixinMessage e = new ExceptionQiyeweixinMessage(resp.getErrcode(), resp.getErrmsg());
+					logger.error(e);
+				} else {
+					Message messageEntityObject = emc.find(message.getId(), Message.class);
+					if (null != messageEntityObject) {
+						emc.beginTransaction(Message.class);
+						emc.remove(messageEntityObject);
+						emc.commit();
+					}
+				}
+			}
+		}
+	}
+
+	public static class QiyeweixinMessageResp {
+
+		// {
+		// "errcode" : 0,
+		// "errmsg" : "ok",
+		// "invaliduser" : "userid1|userid2", // 不区分大小写,返回的列表都统一转为小写
+		// "invalidparty" : "partyid1|partyid2",
+		// "invalidtag":"tagid1|tagid2"
+		// }
+
+		private Integer errcode;
+		private String errmsg;
+		private String invaliduser;
+		private String invalidparty;
+		private String invalidtag;
+
+		public String getErrmsg() {
+			return errmsg;
+		}
+
+		public void setErrmsg(String errmsg) {
+			this.errmsg = errmsg;
+		}
+
+		public String getInvaliduser() {
+			return invaliduser;
+		}
+
+		public void setInvaliduser(String invaliduser) {
+			this.invaliduser = invaliduser;
+		}
+
+		public String getInvalidparty() {
+			return invalidparty;
+		}
+
+		public void setInvalidparty(String invalidparty) {
+			this.invalidparty = invalidparty;
+		}
+
+		public String getInvalidtag() {
+			return invalidtag;
+		}
+
+		public void setInvalidtag(String invalidtag) {
+			this.invalidtag = invalidtag;
+		}
+
+		public Integer getErrcode() {
+			return errcode;
+		}
+
+		public void setErrcode(Integer errcode) {
+			this.errcode = errcode;
+		}
+
+	}
+}

+ 45 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ThisApplication.java

@@ -4,12 +4,27 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import javax.websocket.Session;
 
+import org.apache.commons.lang3.BooleanUtils;
+
 import com.x.base.core.project.Context;
+import com.x.base.core.project.config.Config;
 
 public class ThisApplication {
 
 	protected static Context context;
 
+	public static ImConsumeQueue imConsumeQueue = new ImConsumeQueue();
+
+	public static PmsConsumeQueue pmsConsumeQueue = new PmsConsumeQueue();
+
+	public static CalendarConsumeQueue calendarConsumeQueue = new CalendarConsumeQueue();
+
+	public static QiyeweixinConsumeQueue qiyeweixinConsumeQueue = new QiyeweixinConsumeQueue();
+
+	public static ZhengwuDingdingConsumeQueue zhengwuDingdingConsumeQueue = new ZhengwuDingdingConsumeQueue();
+
+	public static DingdingConsumeQueue dingdingConsumeQueue = new DingdingConsumeQueue();
+
 	public static final ConcurrentHashMap<String, Session> connections = new ConcurrentHashMap<>();
 
 	public static Context context() {
@@ -18,6 +33,21 @@ public class ThisApplication {
 
 	public static void init() {
 		try {
+			imConsumeQueue.start();
+			pmsConsumeQueue.start();
+			calendarConsumeQueue.start();
+			if (BooleanUtils.isTrue(Config.qiyeweixin().getEnable())
+					&& BooleanUtils.isTrue(Config.qiyeweixin().getMessageEnable())) {
+				qiyeweixinConsumeQueue.start();
+			}
+			if (BooleanUtils.isTrue(Config.zhengwuDingding().getEnable())
+					&& BooleanUtils.isTrue(Config.zhengwuDingding().getMessageEnable())) {
+				zhengwuDingdingConsumeQueue.start();
+			}
+			if (BooleanUtils.isTrue(Config.dingding().getEnable())
+					&& BooleanUtils.isTrue(Config.dingding().getMessageEnable())) {
+				dingdingConsumeQueue.start();
+			}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}
@@ -25,6 +55,21 @@ public class ThisApplication {
 
 	public static void destroy() {
 		try {
+			imConsumeQueue.stop();
+			pmsConsumeQueue.stop();
+			calendarConsumeQueue.stop();
+			if (BooleanUtils.isTrue(Config.qiyeweixin().getEnable())
+					&& BooleanUtils.isTrue(Config.qiyeweixin().getMessageEnable())) {
+				qiyeweixinConsumeQueue.stop();
+			}
+			if (BooleanUtils.isTrue(Config.zhengwuDingding().getEnable())
+					&& BooleanUtils.isTrue(Config.zhengwuDingding().getMessageEnable())) {
+				zhengwuDingdingConsumeQueue.stop();
+			}
+			if (BooleanUtils.isTrue(Config.dingding().getEnable())
+					&& BooleanUtils.isTrue(Config.dingding().getMessageEnable())) {
+				dingdingConsumeQueue.stop();
+			}
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 117 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/ZhengwuDingdingConsumeQueue.java

@@ -0,0 +1,117 @@
+package com.x.message.assemble.communicate;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.connection.HttpConnection;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.ZhengwuDingdingMessage;
+import com.x.base.core.project.queue.AbstractQueue;
+import com.x.message.core.entity.Message;
+
+public class ZhengwuDingdingConsumeQueue extends AbstractQueue<Message> {
+
+	private static Logger logger = LoggerFactory.getLogger(ZhengwuDingdingConsumeQueue.class);
+
+	protected void execute(Message message) throws Exception {
+
+		if (Config.zhengwuDingding().getEnable() && Config.zhengwuDingding().getMessageEnable()) {
+			try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+				Business business = new Business(emc);
+				ZhengwuDingdingMessage m = new ZhengwuDingdingMessage();
+				m.setAgentId(Long.parseLong(Config.zhengwuDingding().getAgentId(), 10));
+				m.setTouser(business.organization().person().getObject(message.getPerson()).getZhengwuDingdingId());
+				m.getMsg().getText().setContent(message.getTitle());
+				String address = Config.zhengwuDingding().getOapiAddress() + "/ent_message/send?access_token="
+						+ Config.zhengwuDingding().appAccessToken();
+				ZhengwuDingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+						ZhengwuDingdingMessageResp.class);
+				if (resp.getRetCode() != 0) {
+					ExceptionZhengwuDingdingMessage e = new ExceptionZhengwuDingdingMessage(resp.getRetCode(),
+							resp.getRetMessage());
+					logger.error(e);
+				} else {
+					Message messageEntityObject = emc.find(message.getId(), Message.class);
+					if (null != messageEntityObject) {
+						emc.beginTransaction(Message.class);
+						emc.remove(messageEntityObject);
+						emc.commit();
+					}
+				}
+			}
+		}
+	}
+
+	public static class ZhengwuDingdingMessageResp {
+
+		private Integer retCode;
+		private String retMessage;
+		private RetData retData;
+
+		public static class RetData {
+			private String invaliduser;
+			private String invalidparty;
+			private String errorparty;
+			private String erroruser;
+
+			public String getInvaliduser() {
+				return invaliduser;
+			}
+
+			public void setInvaliduser(String invaliduser) {
+				this.invaliduser = invaliduser;
+			}
+
+			public String getInvalidparty() {
+				return invalidparty;
+			}
+
+			public void setInvalidparty(String invalidparty) {
+				this.invalidparty = invalidparty;
+			}
+
+			public String getErrorparty() {
+				return errorparty;
+			}
+
+			public void setErrorparty(String errorparty) {
+				this.errorparty = errorparty;
+			}
+
+			public String getErroruser() {
+				return erroruser;
+			}
+
+			public void setErroruser(String erroruser) {
+				this.erroruser = erroruser;
+			}
+
+		}
+
+		public Integer getRetCode() {
+			return retCode;
+		}
+
+		public void setRetCode(Integer retCode) {
+			this.retCode = retCode;
+		}
+
+		public String getRetMessage() {
+			return retMessage;
+		}
+
+		public void setRetMessage(String retMessage) {
+			this.retMessage = retMessage;
+		}
+
+		public RetData getRetData() {
+			return retData;
+		}
+
+		public void setRetData(RetData retData) {
+			this.retData = retData;
+		}
+
+	}
+}

+ 2 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/ActionApplication.java

@@ -9,6 +9,7 @@ import com.x.message.assemble.communicate.jaxrs.connector.ConnectorAction;
 import com.x.message.assemble.communicate.jaxrs.consume.ConsumeAction;
 import com.x.message.assemble.communicate.jaxrs.im.ImAction;
 import com.x.message.assemble.communicate.jaxrs.mass.MassAction;
+import com.x.message.assemble.communicate.jaxrs.message.MessageAction;
 
 @ApplicationPath("jaxrs")
 public class ActionApplication extends AbstractActionApplication {
@@ -18,6 +19,7 @@ public class ActionApplication extends AbstractActionApplication {
 		classes.add(ImAction.class);
 		classes.add(ConsumeAction.class);
 		classes.add(MassAction.class);
+		classes.add(MessageAction.class);
 		return classes;
 	}
 

+ 10 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/MessageJaxrsFilter.java

@@ -0,0 +1,10 @@
+package com.x.message.assemble.communicate.jaxrs;
+
+import javax.servlet.annotation.WebFilter;
+
+import com.x.base.core.project.jaxrs.CipherManagerUserJaxrsFilter;
+
+@WebFilter(urlPatterns = "/jaxrs/message/*", asyncSupported = true)
+public class MessageJaxrsFilter extends CipherManagerUserJaxrsFilter {
+
+}

+ 419 - 312
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/connector/ActionCreate.java

@@ -1,34 +1,20 @@
 package com.x.message.assemble.communicate.jaxrs.connector;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
-import org.apache.commons.lang3.BooleanUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.math.NumberUtils;
-
 import com.google.gson.JsonElement;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.annotation.CheckPersistType;
-import com.x.base.core.project.Application;
-import com.x.base.core.project.x_calendar_assemble_control;
-import com.x.base.core.project.x_message_assemble_communicate;
 import com.x.base.core.project.config.Config;
-import com.x.base.core.project.connection.CipherConnectionAction;
-import com.x.base.core.project.connection.HttpConnection;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
-import com.x.base.core.project.jaxrs.WoId;
 import com.x.base.core.project.jaxrs.WrapBoolean;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
-import com.x.base.core.project.message.DingdingMessage;
-import com.x.base.core.project.message.ImMessage;
 import com.x.base.core.project.message.MessageConnector;
-import com.x.base.core.project.message.PmsMessage;
-import com.x.base.core.project.message.QiyeweixinMessage;
-import com.x.base.core.project.message.ZhengwuDingdingMessage;
-import com.x.base.core.project.organization.Person;
 import com.x.base.core.project.tools.ListTools;
 import com.x.message.assemble.communicate.Business;
 import com.x.message.assemble.communicate.ThisApplication;
@@ -43,330 +29,451 @@ class ActionCreate extends BaseAction {
 			Business business = new Business(emc);
 			ActionResult<Wo> result = new ActionResult<>();
 			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
-			Message message = new Message();
-			message.setBody(Objects.toString(wi.getBody()));
-			message.setType(wi.getType());
-			message.setPerson(wi.getPerson());
-			message.setTitle(wi.getTitle());
-			message.setConsumerList(Config.messages().getConsumers(wi.getType()));
-			this.im_consume(effectivePerson, business, message);
-			this.pms_consume(effectivePerson, business, message);
-			this.calendar_consume(effectivePerson, business, message);
-			this.dingding_consume(effectivePerson, business, message);
-			this.qiyeweixin_consume(effectivePerson, business, message);
-			this.zhengwudingding_consume(effectivePerson, business, message);
-			if (!message.getConsumerList().isEmpty()) {
+			List<String> consumers = Config.messages().getConsumers(wi.getType());
+			if (ListTools.isNotEmpty(consumers)) {
+				List<Message> messages = new ArrayList<>();
 				emc.beginTransaction(Message.class);
-				emc.persist(message, CheckPersistType.all);
-				emc.commit();
-			}
-			Wo wo = new Wo();
-			result.setData(wo);
-			return result;
-		}
-	}
-
-	private void dingding_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_DINGDING)) {
-				message.getConsumerList().remove(MessageConnector.CONSUME_DINGDING);
-				if (Config.dingding().getEnable() && Config.dingding().getMessageEnable()) {
-					DingdingMessage m = new DingdingMessage();
-					m.setAgent_id(Long.parseLong(Config.dingding().getAgentId(), 10));
-					m.setUserid_list(business.organization().person().getObject(message.getPerson()).getDingdingId());
-					m.getMsg().getText().setContent(message.getTitle());
-					// https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=ACCESS_TOKEN
-					String address = Config.dingding().getOapiAddress()
-							+ "/topapi/message/corpconversation/asyncsend_v2?access_token="
-							+ Config.dingding().corpAccessToken();
-					DingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
-							DingdingMessageResp.class);
-					if (resp.getErrcode() != 0) {
-						throw new ExceptionDingdingMessage(resp.getErrcode(), resp.getErrmsg());
+				for (String consumer : consumers) {
+					Message message = null;
+					switch (Objects.toString(consumer, "")) {
+					case MessageConnector.CONSUME_IM:
+						message = this.imMessage(effectivePerson, business, wi);
+						break;
+					case MessageConnector.CONSUME_PMS:
+						message = this.pmsMessage(effectivePerson, business, wi);
+						break;
+					case MessageConnector.CONSUME_DINGDING:
+						message = this.dingdingMessage(effectivePerson, business, wi);
+						break;
+					case MessageConnector.CONSUME_ZHENGWUDINGDING:
+						message = this.zhegnwudingdingMessage(effectivePerson, business, wi);
+						break;
+					case MessageConnector.CONSUME_QIYEWEIXIN:
+						message = this.qiyeweixinMessage(effectivePerson, business, wi);
+						break;
+					case MessageConnector.CONSUME_CALENDAR:
+						message = this.calendarMessage(effectivePerson, business, wi);
+						break;
+					default:
+						message = this.defaultMessage(effectivePerson, business, wi, consumer);
+						break;
 					}
+					emc.persist(message, CheckPersistType.all);
+					messages.add(message);
 				}
-			}
-		} catch (Exception e) {
-			logger.error(e);
-		}
-	}
+				emc.commit();
 
-	private void zhengwudingding_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_ZHENGWUDINGDING)) {
-				message.getConsumerList().remove(MessageConnector.CONSUME_ZHENGWUDINGDING);
-				if (Config.zhengwuDingding().getEnable() && Config.zhengwuDingding().getMessageEnable()) {
-					ZhengwuDingdingMessage m = new ZhengwuDingdingMessage();
-					m.setAgentId(Long.parseLong(Config.zhengwuDingding().getAgentId(), 10));
-					m.setTouser(business.organization().person().getObject(message.getPerson()).getZhengwuDingdingId());
-					m.getMsg().getText().setContent(message.getTitle());
-					String address = Config.zhengwuDingding().getOapiAddress() + "/ent_message/send?access_token="
-							+ Config.zhengwuDingding().appAccessToken();
-					ZhengwuDingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
-							ZhengwuDingdingMessageResp.class);
-					if (resp.getRetCode() != 0) {
-						throw new ExceptionZhengwuDingdingMessage(resp.getRetCode(), resp.getRetMessage());
+				for (Message message : messages) {
+					switch (message.getConsumer()) {
+					case MessageConnector.CONSUME_IM:
+						ThisApplication.imConsumeQueue.send(message);
+						break;
+					case MessageConnector.CONSUME_PMS:
+						ThisApplication.pmsConsumeQueue.send(message);
+						break;
+					case MessageConnector.CONSUME_DINGDING:
+						ThisApplication.dingdingConsumeQueue.send(message);
+						break;
+					case MessageConnector.CONSUME_ZHENGWUDINGDING:
+						ThisApplication.zhengwuDingdingConsumeQueue.send(message);
+						break;
+					case MessageConnector.CONSUME_QIYEWEIXIN:
+						ThisApplication.qiyeweixinConsumeQueue.send(message);
+						break;
+					case MessageConnector.CONSUME_CALENDAR:
+						ThisApplication.calendarConsumeQueue.send(message);
+						break;
+					default:
+						break;
 					}
 				}
 			}
-		} catch (Exception e) {
-			logger.error(e);
-		}
-	}
 
-	private void qiyeweixin_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_QIYEWEIXIN)) {
-				message.getConsumerList().remove(MessageConnector.CONSUME_QIYEWEIXIN);
-				if (Config.qiyeweixin().getEnable() && Config.qiyeweixin().getMessageEnable()) {
-					QiyeweixinMessage m = new QiyeweixinMessage();
-					m.setAgentid(Long.parseLong(Config.qiyeweixin().getAgentId(), 10));
-					m.setTouser(business.organization().person().getObject(message.getPerson()).getQiyeweixinId());
-					m.getText().setContent(message.getTitle());
-					String address = Config.qiyeweixin().getApiAddress() + "/cgi-bin/message/send?access_token="
-							+ Config.qiyeweixin().corpAccessToken();
-					QiyeweixinMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
-							QiyeweixinMessageResp.class);
-					if (resp.getErrcode() != 0) {
-						throw new ExceptionQiyeweixinMessage(resp.getErrcode(), resp.getErrmsg());
-					}
-				}
-			}
-		} catch (Exception e) {
-			logger.error(e);
-		}
-	}
+//			this.im_consume(effectivePerson, business, message);
+//			this.pms_consume(effectivePerson, business, message);
+//			this.calendar_consume(effectivePerson, business, message);
+//			this.dingding_consume(effectivePerson, business, message);
+//			this.qiyeweixin_consume(effectivePerson, business, message);
+//			this.zhengwudingding_consume(effectivePerson, business, message);
 
-	private void im_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_IM)) {
-				ImMessage im = new ImMessage();
-				im.setType(message.getType());
-				im.setPerson(message.getPerson());
-				im.setTitle(message.getTitle());
-				im.setBody(gson.fromJson(message.getBody(), JsonElement.class));
-				for (Application app : ThisApplication.context().applications()
-						.get(x_message_assemble_communicate.class)) {
-					WrapBoolean wrapBoolean = ThisApplication.context().applications()
-							.postQuery(effectivePerson.getDebugger(), app, MessageConnector.CONSUME_IM, im)
-							.getData(WrapBoolean.class);
-					if (BooleanUtils.isTrue(wrapBoolean.getValue())) {
-						message.getConsumerList().remove(MessageConnector.CONSUME_IM);
-					}
-				}
-			}
-		} catch (Exception e) {
-			logger.error(e);
+			Wo wo = new Wo();
+			wo.setValue(true);
+			result.setData(wo);
+			return result;
 		}
 	}
 
-	private void pms_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_PMS)) {
-				message.getConsumerList().remove(MessageConnector.CONSUME_PMS);
-				Person person = business.organization().person().getObject(message.getPerson());
-				if ((null != person) && StringUtils.isNotEmpty(person.getMobile())) {
-					PmsMessage pms = new PmsMessage();
-					pms.setAccount(person.getMobile());
-					pms.setTitle(message.getTitle());
-					pms.setText(message.getTitle());
-					String url = Config.x_program_centerUrlRoot() + MessageConnector.CONSUME_PMS;
-					CipherConnectionAction.post(effectivePerson.getDebugger(), url, pms);
-				}
-			}
-		} catch (Exception e) {
-			logger.error(e);
-		}
+	private Message imMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_IM);
+		return message;
 	}
 
-	private void calendar_consume(EffectivePerson effectivePerson, Business business, Message message) {
-		try {
-			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_CALENDAR)) {
-				Application app = ThisApplication.context().applications()
-						.randomWithWeight(x_calendar_assemble_control.class.getName());
-				if (null != app) {
-					WrapBoolean wrapBoolean = ThisApplication.context().applications()
-							.postQuery(effectivePerson.getDebugger(), app, "message", message)
-							.getData(WrapBoolean.class);
-					if (BooleanUtils.isTrue(wrapBoolean.getValue())) {
-						message.getConsumerList().remove(MessageConnector.CONSUME_CALENDAR);
-					}
-				} else {
-					throw new ExceptionCalendarApplicationNotFound();
-				}
-			}
-		} catch (Exception e) {
-			logger.error(e);
-		}
+	private Message pmsMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_PMS);
+		return message;
 	}
 
-	public static class Wi extends MessageConnector.Wrap {
+	private Message dingdingMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_DINGDING);
+		return message;
 	}
 
-	public static class Wo extends WoId {
-
+	private Message zhegnwudingdingMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_ZHENGWUDINGDING);
+		return message;
 	}
 
-	public static class ZhengwuDingdingMessageResp {
-
-		private Integer retCode;
-		private String retMessage;
-		private RetData retData;
-
-		public static class RetData {
-			private String invaliduser;
-			private String invalidparty;
-			private String errorparty;
-			private String erroruser;
-
-			public String getInvaliduser() {
-				return invaliduser;
-			}
-
-			public void setInvaliduser(String invaliduser) {
-				this.invaliduser = invaliduser;
-			}
-
-			public String getInvalidparty() {
-				return invalidparty;
-			}
-
-			public void setInvalidparty(String invalidparty) {
-				this.invalidparty = invalidparty;
-			}
-
-			public String getErrorparty() {
-				return errorparty;
-			}
-
-			public void setErrorparty(String errorparty) {
-				this.errorparty = errorparty;
-			}
-
-			public String getErroruser() {
-				return erroruser;
-			}
-
-			public void setErroruser(String erroruser) {
-				this.erroruser = erroruser;
-			}
-
-		}
-
-		public Integer getRetCode() {
-			return retCode;
-		}
-
-		public void setRetCode(Integer retCode) {
-			this.retCode = retCode;
-		}
-
-		public String getRetMessage() {
-			return retMessage;
-		}
-
-		public void setRetMessage(String retMessage) {
-			this.retMessage = retMessage;
-		}
-
-		public RetData getRetData() {
-			return retData;
-		}
-
-		public void setRetData(RetData retData) {
-			this.retData = retData;
-		}
-
+	private Message qiyeweixinMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_QIYEWEIXIN);
+		return message;
 	}
 
-	public static class DingdingMessageResp {
-
-		private Integer errcode;
-		private String errmsg;
-		private Long task_id;
-
-		public String getErrmsg() {
-			return errmsg;
-		}
-
-		public void setErrmsg(String errmsg) {
-			this.errmsg = errmsg;
-		}
-
-		public Long getTask_id() {
-			return task_id;
-		}
-
-		public void setTask_id(Long task_id) {
-			this.task_id = task_id;
-		}
-
-		public Integer getErrcode() {
-			return errcode;
-		}
-
-		public void setErrcode(Integer errcode) {
-			this.errcode = errcode;
-		}
-
+	private Message calendarMessage(EffectivePerson effectivePerson, Business business, Wi wi) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(MessageConnector.CONSUME_CALENDAR);
+		return message;
 	}
 
-	public static class QiyeweixinMessageResp {
-
-		// {
-		// "errcode" : 0,
-		// "errmsg" : "ok",
-		// "invaliduser" : "userid1|userid2", // 不区分大小写,返回的列表都统一转为小写
-		// "invalidparty" : "partyid1|partyid2",
-		// "invalidtag":"tagid1|tagid2"
-		// }
-
-		private Integer errcode;
-		private String errmsg;
-		private String invaliduser;
-		private String invalidparty;
-		private String invalidtag;
-
-		public String getErrmsg() {
-			return errmsg;
-		}
-
-		public void setErrmsg(String errmsg) {
-			this.errmsg = errmsg;
-		}
-
-		public String getInvaliduser() {
-			return invaliduser;
-		}
-
-		public void setInvaliduser(String invaliduser) {
-			this.invaliduser = invaliduser;
-		}
-
-		public String getInvalidparty() {
-			return invalidparty;
-		}
-
-		public void setInvalidparty(String invalidparty) {
-			this.invalidparty = invalidparty;
-		}
+	private Message defaultMessage(EffectivePerson effectivePerson, Business business, Wi wi, String consumer) {
+		Message message = new Message();
+		message.setBody(Objects.toString(wi.getBody()));
+		message.setType(wi.getType());
+		message.setPerson(wi.getPerson());
+		message.setTitle(wi.getTitle());
+		message.setConsumer(consumer);
+		return message;
+	}
 
-		public String getInvalidtag() {
-			return invalidtag;
-		}
+//	private void dingding_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_DINGDING)) {
+//				message.getConsumerList().remove(MessageConnector.CONSUME_DINGDING);
+//				if (Config.dingding().getEnable() && Config.dingding().getMessageEnable()) {
+//					DingdingMessage m = new DingdingMessage();
+//					m.setAgent_id(Long.parseLong(Config.dingding().getAgentId(), 10));
+//					m.setUserid_list(business.organization().person().getObject(message.getPerson()).getDingdingId());
+//					m.getMsg().getText().setContent(message.getTitle());
+//					// https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=ACCESS_TOKEN
+//					String address = Config.dingding().getOapiAddress()
+//							+ "/topapi/message/corpconversation/asyncsend_v2?access_token="
+//							+ Config.dingding().corpAccessToken();
+//					DingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+//							DingdingMessageResp.class);
+//					if (resp.getErrcode() != 0) {
+//						throw new ExceptionDingdingMessage(resp.getErrcode(), resp.getErrmsg());
+//					}
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
+//
+//	private void zhengwudingding_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_ZHENGWUDINGDING)) {
+//				message.getConsumerList().remove(MessageConnector.CONSUME_ZHENGWUDINGDING);
+//				if (Config.zhengwuDingding().getEnable() && Config.zhengwuDingding().getMessageEnable()) {
+//					ZhengwuDingdingMessage m = new ZhengwuDingdingMessage();
+//					m.setAgentId(Long.parseLong(Config.zhengwuDingding().getAgentId(), 10));
+//					m.setTouser(business.organization().person().getObject(message.getPerson()).getZhengwuDingdingId());
+//					m.getMsg().getText().setContent(message.getTitle());
+//					String address = Config.zhengwuDingding().getOapiAddress() + "/ent_message/send?access_token="
+//							+ Config.zhengwuDingding().appAccessToken();
+//					ZhengwuDingdingMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+//							ZhengwuDingdingMessageResp.class);
+//					if (resp.getRetCode() != 0) {
+//						throw new ExceptionZhengwuDingdingMessage(resp.getRetCode(), resp.getRetMessage());
+//					}
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
+//
+//	private void qiyeweixin_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_QIYEWEIXIN)) {
+//				message.getConsumerList().remove(MessageConnector.CONSUME_QIYEWEIXIN);
+//				if (Config.qiyeweixin().getEnable() && Config.qiyeweixin().getMessageEnable()) {
+//					QiyeweixinMessage m = new QiyeweixinMessage();
+//					m.setAgentid(Long.parseLong(Config.qiyeweixin().getAgentId(), 10));
+//					m.setTouser(business.organization().person().getObject(message.getPerson()).getQiyeweixinId());
+//					m.getText().setContent(message.getTitle());
+//					String address = Config.qiyeweixin().getApiAddress() + "/cgi-bin/message/send?access_token="
+//							+ Config.qiyeweixin().corpAccessToken();
+//					QiyeweixinMessageResp resp = HttpConnection.postAsObject(address, null, m.toString(),
+//							QiyeweixinMessageResp.class);
+//					if (resp.getErrcode() != 0) {
+//						throw new ExceptionQiyeweixinMessage(resp.getErrcode(), resp.getErrmsg());
+//					}
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
+//
+//	private void im_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_IM)) {
+//				ImMessage im = new ImMessage();
+//				im.setType(message.getType());
+//				im.setPerson(message.getPerson());
+//				im.setTitle(message.getTitle());
+//				im.setBody(gson.fromJson(message.getBody(), JsonElement.class));
+//				for (Application app : ThisApplication.context().applications()
+//						.get(x_message_assemble_communicate.class)) {
+//					WrapBoolean wrapBoolean = ThisApplication.context().applications()
+//							.postQuery(effectivePerson.getDebugger(), app, MessageConnector.CONSUME_IM, im)
+//							.getData(WrapBoolean.class);
+//					if (BooleanUtils.isTrue(wrapBoolean.getValue())) {
+//						message.getConsumerList().remove(MessageConnector.CONSUME_IM);
+//					}
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
+//
+//	private void pms_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_PMS)) {
+//				message.getConsumerList().remove(MessageConnector.CONSUME_PMS);
+//				Person person = business.organization().person().getObject(message.getPerson());
+//				if ((null != person) && StringUtils.isNotEmpty(person.getMobile())) {
+//					PmsMessage pms = new PmsMessage();
+//					pms.setAccount(person.getMobile());
+//					pms.setTitle(message.getTitle());
+//					pms.setText(message.getTitle());
+//					String url = Config.x_program_centerUrlRoot() + MessageConnector.CONSUME_PMS;
+//					CipherConnectionAction.post(effectivePerson.getDebugger(), url, pms);
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
+//
+//	private void calendar_consume(EffectivePerson effectivePerson, Business business, Message message) {
+//		try {
+//			if (ListTools.contains(message.getConsumerList(), MessageConnector.CONSUME_CALENDAR)) {
+//				Application app = ThisApplication.context().applications()
+//						.randomWithWeight(x_calendar_assemble_control.class.getName());
+//				if (null != app) {
+//					WrapBoolean wrapBoolean = ThisApplication.context().applications()
+//							.postQuery(effectivePerson.getDebugger(), app, "message", message)
+//							.getData(WrapBoolean.class);
+//					if (BooleanUtils.isTrue(wrapBoolean.getValue())) {
+//						message.getConsumerList().remove(MessageConnector.CONSUME_CALENDAR);
+//					}
+//				} else {
+//					throw new ExceptionCalendarApplicationNotFound();
+//				}
+//			}
+//		} catch (Exception e) {
+//			logger.error(e);
+//		}
+//	}
 
-		public void setInvalidtag(String invalidtag) {
-			this.invalidtag = invalidtag;
-		}
-
-		public Integer getErrcode() {
-			return errcode;
-		}
+	public static class Wi extends MessageConnector.Wrap {
+	}
 
-		public void setErrcode(Integer errcode) {
-			this.errcode = errcode;
-		}
+	public static class Wo extends WrapBoolean {
 
 	}
 
+//	public static class ZhengwuDingdingMessageResp {
+//
+//		private Integer retCode;
+//		private String retMessage;
+//		private RetData retData;
+//
+//		public static class RetData {
+//			private String invaliduser;
+//			private String invalidparty;
+//			private String errorparty;
+//			private String erroruser;
+//
+//			public String getInvaliduser() {
+//				return invaliduser;
+//			}
+//
+//			public void setInvaliduser(String invaliduser) {
+//				this.invaliduser = invaliduser;
+//			}
+//
+//			public String getInvalidparty() {
+//				return invalidparty;
+//			}
+//
+//			public void setInvalidparty(String invalidparty) {
+//				this.invalidparty = invalidparty;
+//			}
+//
+//			public String getErrorparty() {
+//				return errorparty;
+//			}
+//
+//			public void setErrorparty(String errorparty) {
+//				this.errorparty = errorparty;
+//			}
+//
+//			public String getErroruser() {
+//				return erroruser;
+//			}
+//
+//			public void setErroruser(String erroruser) {
+//				this.erroruser = erroruser;
+//			}
+//
+//		}
+//
+//		public Integer getRetCode() {
+//			return retCode;
+//		}
+//
+//		public void setRetCode(Integer retCode) {
+//			this.retCode = retCode;
+//		}
+//
+//		public String getRetMessage() {
+//			return retMessage;
+//		}
+//
+//		public void setRetMessage(String retMessage) {
+//			this.retMessage = retMessage;
+//		}
+//
+//		public RetData getRetData() {
+//			return retData;
+//		}
+//
+//		public void setRetData(RetData retData) {
+//			this.retData = retData;
+//		}
+//
+//	}
+
+//	public static class DingdingMessageResp {
+//
+//		private Integer errcode;
+//		private String errmsg;
+//		private Long task_id;
+//
+//		public String getErrmsg() {
+//			return errmsg;
+//		}
+//
+//		public void setErrmsg(String errmsg) {
+//			this.errmsg = errmsg;
+//		}
+//
+//		public Long getTask_id() {
+//			return task_id;
+//		}
+//
+//		public void setTask_id(Long task_id) {
+//			this.task_id = task_id;
+//		}
+//
+//		public Integer getErrcode() {
+//			return errcode;
+//		}
+//
+//		public void setErrcode(Integer errcode) {
+//			this.errcode = errcode;
+//		}
+//
+//	}
+
+//	public static class QiyeweixinMessageResp {
+//
+//		// {
+//		// "errcode" : 0,
+//		// "errmsg" : "ok",
+//		// "invaliduser" : "userid1|userid2", // 不区分大小写,返回的列表都统一转为小写
+//		// "invalidparty" : "partyid1|partyid2",
+//		// "invalidtag":"tagid1|tagid2"
+//		// }
+//
+//		private Integer errcode;
+//		private String errmsg;
+//		private String invaliduser;
+//		private String invalidparty;
+//		private String invalidtag;
+//
+//		public String getErrmsg() {
+//			return errmsg;
+//		}
+//
+//		public void setErrmsg(String errmsg) {
+//			this.errmsg = errmsg;
+//		}
+//
+//		public String getInvaliduser() {
+//			return invaliduser;
+//		}
+//
+//		public void setInvaliduser(String invaliduser) {
+//			this.invaliduser = invaliduser;
+//		}
+//
+//		public String getInvalidparty() {
+//			return invalidparty;
+//		}
+//
+//		public void setInvalidparty(String invalidparty) {
+//			this.invalidparty = invalidparty;
+//		}
+//
+//		public String getInvalidtag() {
+//			return invalidtag;
+//		}
+//
+//		public void setInvalidtag(String invalidtag) {
+//			this.invalidtag = invalidtag;
+//		}
+//
+//		public Integer getErrcode() {
+//			return errcode;
+//		}
+//
+//		public void setErrcode(Integer errcode) {
+//			this.errcode = errcode;
+//		}
+//
+//	}
+
 }

+ 2 - 3
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionList.java

@@ -20,7 +20,6 @@ import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.message.ImMessage;
-import com.x.base.core.project.tools.ListTools;
 import com.x.message.assemble.communicate.Business;
 import com.x.message.core.entity.Message;
 import com.x.message.core.entity.Message_;
@@ -44,7 +43,7 @@ class ActionList extends BaseAction {
 		CriteriaBuilder cb = em.getCriteriaBuilder();
 		CriteriaQuery<Message> cq = cb.createQuery(Message.class);
 		Root<Message> root = cq.from(Message.class);
-		Predicate p = cb.isMember(consume, root.get(Message_.consumerList));
+		Predicate p = cb.equal(root.get(Message_.consumer), consume);
 		List<Message> os = em.createQuery(cq.select(root).where(p).orderBy(cb.asc(root.get(Message_.createTime))))
 				.setMaxResults(count).getResultList();
 		return Wo.copier.copy(os);
@@ -57,7 +56,7 @@ class ActionList extends BaseAction {
 
 		private static final long serialVersionUID = 681982898431236763L;
 		static WrapCopier<Message, Wo> copier = WrapCopierFactory.wo(Message.class, Wo.class, null,
-				ListTools.toList(JpaObject.FieldsInvisible, Message.consumerList_FIELDNAME));
+				JpaObject.FieldsInvisible);
 	}
 
 }

+ 66 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionListWithCurrentPerson.java

@@ -0,0 +1,66 @@
+package com.x.message.assemble.communicate.jaxrs.consume;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionPersonNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.ImMessage;
+import com.x.message.assemble.communicate.Business;
+import com.x.message.core.entity.Message;
+import com.x.message.core.entity.Message_;
+
+class ActionListWithCurrentPerson extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionListWithCurrentPerson.class);
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String consume, Integer count) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			ActionResult<List<Wo>> result = new ActionResult<>();
+			List<Wo> wos = this.list(business, consume, NumberUtils.min(200, NumberUtils.max(1, count)),
+					effectivePerson.getDistinguishedName());
+			result.setData(wos);
+			return result;
+		}
+	}
+
+	private List<Wo> list(Business business, String consume, Integer count, String name) throws Exception {
+		EntityManager em = business.entityManagerContainer().get(Message.class);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<Message> cq = cb.createQuery(Message.class);
+		Root<Message> root = cq.from(Message.class);
+		Predicate p = cb.equal(root.get(Message_.consumer), consume);
+		p = cb.and(p, cb.equal(root.get(Message_.person), name));
+		List<Message> os = em.createQuery(cq.select(root).where(p).orderBy(cb.asc(root.get(Message_.createTime))))
+				.setMaxResults(count).getResultList();
+		return Wo.copier.copy(os);
+	}
+
+	public static class Wi extends ImMessage {
+	}
+
+	public static class Wo extends Message {
+
+		private static final long serialVersionUID = 681982898431236763L;
+		static WrapCopier<Message, Wo> copier = WrapCopierFactory.wo(Message.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+	}
+
+}

+ 70 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionListWithPerson.java

@@ -0,0 +1,70 @@
+package com.x.message.assemble.communicate.jaxrs.consume;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.exception.ExceptionPersonNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.ImMessage;
+import com.x.message.assemble.communicate.Business;
+import com.x.message.core.entity.Message;
+import com.x.message.core.entity.Message_;
+
+class ActionListWithPerson extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionListWithPerson.class);
+
+	ActionResult<List<Wo>> execute(EffectivePerson effectivePerson, String consume, Integer count, String person)
+			throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			Business business = new Business(emc);
+			String name = business.organization().person().get(person);
+			if (StringUtils.isEmpty(name)) {
+				throw new ExceptionPersonNotExist(name);
+			}
+			ActionResult<List<Wo>> result = new ActionResult<>();
+			List<Wo> wos = this.list(business, consume, NumberUtils.min(200, NumberUtils.max(1, count)), name);
+			result.setData(wos);
+			return result;
+		}
+	}
+
+	private List<Wo> list(Business business, String consume, Integer count, String name) throws Exception {
+		EntityManager em = business.entityManagerContainer().get(Message.class);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<Message> cq = cb.createQuery(Message.class);
+		Root<Message> root = cq.from(Message.class);
+		Predicate p = cb.equal(root.get(Message_.consumer), consume);
+		p = cb.and(p, cb.equal(root.get(Message_.person), name));
+		List<Message> os = em.createQuery(cq.select(root).where(p).orderBy(cb.asc(root.get(Message_.createTime))))
+				.setMaxResults(count).getResultList();
+		return Wo.copier.copy(os);
+	}
+
+	public static class Wi extends ImMessage {
+	}
+
+	public static class Wo extends Message {
+
+		private static final long serialVersionUID = 681982898431236763L;
+		static WrapCopier<Message, Wo> copier = WrapCopierFactory.wo(Message.class, Wo.class, null,
+				JpaObject.FieldsInvisible);
+	}
+
+}

+ 6 - 20
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionUpdate.java

@@ -3,16 +3,9 @@ package com.x.message.assemble.communicate.jaxrs.consume;
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-
 import com.google.gson.JsonElement;
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
-import com.x.base.core.entity.annotation.CheckRemoveType;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
@@ -21,7 +14,6 @@ import com.x.base.core.project.jaxrs.WrapNumber;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.message.core.entity.Message;
-import com.x.message.core.entity.Message_;
 
 class ActionUpdate extends BaseAction {
 
@@ -31,20 +23,14 @@ class ActionUpdate extends BaseAction {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			ActionResult<Wo> result = new ActionResult<>();
 			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
-			EntityManager em = emc.beginTransaction(Message.class);
-			CriteriaBuilder cb = em.getCriteriaBuilder();
-			CriteriaQuery<Message> cq = cb.createQuery(Message.class);
-			Root<Message> root = cq.from(Message.class);
-			Predicate p = cb.isMember(type, root.get(Message_.consumerList));
-			p = cb.and(p, root.get(Message_.id).in(wi.getIdList()));
-			List<Message> os = em.createQuery(cq.select(root).where(p)).getResultList();
-			for (Message o : os) {
-				o.getConsumerList().remove(type);
-				if (o.getConsumerList().isEmpty()) {
-					emc.remove(o, CheckRemoveType.all);
+			List<Message> os = emc.list(Message.class, wi.getIdList());
+			if (!os.isEmpty()) {
+				emc.beginTransaction(Message.class);
+				for (Message o : os) {
+					emc.remove(o);
 				}
+				emc.commit();
 			}
-			emc.commit();
 			Wo wo = new Wo();
 			wo.setValue(os.size());
 			result.setData(wo);

+ 5 - 23
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ActionUpdateSingle.java

@@ -1,23 +1,13 @@
 package com.x.message.assemble.communicate.jaxrs.consume;
 
-import java.util.List;
-
-import javax.persistence.EntityManager;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
-import com.x.base.core.entity.annotation.CheckRemoveType;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WrapBoolean;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.message.core.entity.Message;
-import com.x.message.core.entity.Message_;
 
 class ActionUpdateSingle extends BaseAction {
 
@@ -26,20 +16,12 @@ class ActionUpdateSingle extends BaseAction {
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, String type) throws Exception {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			ActionResult<Wo> result = new ActionResult<>();
-			EntityManager em = emc.beginTransaction(Message.class);
-			CriteriaBuilder cb = em.getCriteriaBuilder();
-			CriteriaQuery<Message> cq = cb.createQuery(Message.class);
-			Root<Message> root = cq.from(Message.class);
-			Predicate p = cb.isMember(type, root.get(Message_.consumerList));
-			p = cb.and(p, cb.equal(root.get(Message_.id), id));
-			List<Message> os = em.createQuery(cq.select(root).where(p)).getResultList();
-			for (Message o : os) {
-				o.getConsumerList().remove(type);
-				if (o.getConsumerList().isEmpty()) {
-					emc.remove(o, CheckRemoveType.all);
-				}
+			Message message = emc.find(id, Message.class);
+			if (null != message) {
+				emc.beginTransaction(Message.class);
+				emc.remove(message);
+				emc.commit();
 			}
-			emc.commit();
 			Wo wo = new Wo();
 			wo.setValue(true);
 			result.setData(wo);

+ 39 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/consume/ConsumeAction.java

@@ -51,6 +51,45 @@ public class ConsumeAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@JaxrsMethodDescribe(value = "获取消息,当前人员.", action = ActionListWithCurrentPerson.class)
+	@GET
+	@Path("list/{consume}/currentperson/count/{count}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithCurrentPerson(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("消费者") @PathParam("consume") String consume,
+			@JaxrsParameterDescribe("数量") @PathParam("count") Integer count) {
+		ActionResult<List<ActionListWithCurrentPerson.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithCurrentPerson().execute(effectivePerson, consume, count);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+	@JaxrsMethodDescribe(value = "获取消息,指定人员.", action = ActionListWithPerson.class)
+	@GET
+	@Path("list/{consume}/person/{person}/count/{count}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void listWithPerson(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("消费者") @PathParam("consume") String consume,
+			@JaxrsParameterDescribe("人员") @PathParam("person") String person,
+			@JaxrsParameterDescribe("数量") @PathParam("count") Integer count) {
+		ActionResult<List<ActionListWithPerson.Wo>> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionListWithPerson().execute(effectivePerson, consume, count, person);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "更新消息,将消息标志为已处理.", action = ActionUpdateSingle.class)
 	@GET
 	@Path("{id}/type/{type}")

+ 103 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ActionCustomCreate.java

@@ -0,0 +1,103 @@
+package com.x.message.assemble.communicate.jaxrs.message;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.gson.JsonElement;
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.entity.JpaObject;
+import com.x.base.core.project.x_message_assemble_communicate;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.WrapCopier;
+import com.x.base.core.project.bean.WrapCopierFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+import com.x.base.core.project.jaxrs.WrapBoolean;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.message.MessageConnector;
+import com.x.message.assemble.communicate.ThisApplication;
+import com.x.message.core.entity.Message;
+
+class ActionCustomCreate extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionCustomCreate.class);
+
+	private static final String CUSTOM_PREFIX = "custom_";
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			if (!StringUtils.startsWith(wi.getType(), CUSTOM_PREFIX)) {
+				throw new ExceptionNotCustomMessage(wi.getType());
+			}
+			if (!Config.messages().containsKey(wi.getType())) {
+				throw new ExceptionUndefinedMessageType(wi.getType());
+			}
+			Wo wo = ThisApplication.context().applications()
+					.postQuery(x_message_assemble_communicate.class, "connector", wi).getData(Wo.class);
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		static WrapCopier<Wi, MessageConnector.Wrap> copier = WrapCopierFactory.wi(Wi.class,
+				MessageConnector.Wrap.class, null, JpaObject.FieldsUnmodify);
+		
+		@FieldDescribe("类型")
+		private String type;
+
+		@FieldDescribe("人员")
+		private String person;
+
+		@FieldDescribe("标题")
+		private String title;
+
+		@FieldDescribe("推送内容")
+		private JsonElement body;
+
+		public String getType() {
+			return type;
+		}
+
+		public void setType(String type) {
+			this.type = type;
+		}
+
+		public String getTitle() {
+			return title;
+		}
+
+		public void setTitle(String title) {
+			this.title = title;
+		}
+
+		public String getPerson() {
+			return person;
+		}
+
+		public void setPerson(String person) {
+			this.person = person;
+		}
+
+		public JsonElement getBody() {
+			return body;
+		}
+
+		public void setBody(JsonElement body) {
+			this.body = body;
+		}
+
+	}
+
+	public static class Wo extends WrapBoolean {
+
+	}
+
+}

+ 7 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/BaseAction.java

@@ -0,0 +1,7 @@
+package com.x.message.assemble.communicate.jaxrs.message;
+
+import com.x.base.core.project.jaxrs.StandardJaxrsAction;
+
+abstract class BaseAction extends StandardJaxrsAction {
+
+}

+ 12 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ExceptionNotCustomMessage.java

@@ -0,0 +1,12 @@
+package com.x.message.assemble.communicate.jaxrs.message;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionNotCustomMessage extends PromptException {
+
+	private static final long serialVersionUID = 4132300948670472899L;
+
+	ExceptionNotCustomMessage(String type) {
+		super("无法接收非定制内容:{}.", type);
+	}
+}

+ 12 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/ExceptionUndefinedMessageType.java

@@ -0,0 +1,12 @@
+package com.x.message.assemble.communicate.jaxrs.message;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionUndefinedMessageType extends PromptException {
+
+	private static final long serialVersionUID = 4132300948670472899L;
+
+	ExceptionUndefinedMessageType(String type) {
+		super("未定义的消息类型:{}.", type);
+	}
+}

+ 48 - 0
o2server/x_message_assemble_communicate/src/main/java/com/x/message/assemble/communicate/jaxrs/message/MessageAction.java

@@ -0,0 +1,48 @@
+package com.x.message.assemble.communicate.jaxrs.message;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+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 com.google.gson.JsonElement;
+import com.x.base.core.project.annotation.JaxrsDescribe;
+import com.x.base.core.project.annotation.JaxrsMethodDescribe;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.http.HttpMediaType;
+import com.x.base.core.project.jaxrs.ResponseFactory;
+import com.x.base.core.project.jaxrs.StandardJaxrsAction;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+
+@Path("message")
+@JaxrsDescribe("消息")
+public class MessageAction extends StandardJaxrsAction {
+
+	private static Logger logger = LoggerFactory.getLogger(MessageAction.class);
+
+	@JaxrsMethodDescribe(value = "创建定制消息.", action = ActionCustomCreate.class)
+	@POST
+	@Path("custom/create")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void customCreate(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			JsonElement jsonElement) {
+		ActionResult<ActionCustomCreate.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionCustomCreate().execute(effectivePerson, jsonElement);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
+}

+ 31 - 25
o2server/x_message_core_entity/src/main/java/com/x/message/core/entity/Message.java

@@ -1,7 +1,5 @@
 package com.x.message.core.entity;
 
-import java.util.List;
-
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -10,14 +8,9 @@ import javax.persistence.Id;
 import javax.persistence.Inheritance;
 import javax.persistence.InheritanceType;
 import javax.persistence.Lob;
-import javax.persistence.OrderColumn;
 import javax.persistence.Table;
 import javax.persistence.UniqueConstraint;
 
-import org.apache.openjpa.persistence.PersistentCollection;
-import org.apache.openjpa.persistence.jdbc.ContainerTable;
-import org.apache.openjpa.persistence.jdbc.ElementColumn;
-import org.apache.openjpa.persistence.jdbc.ElementIndex;
 import org.apache.openjpa.persistence.jdbc.Index;
 
 import com.x.base.core.entity.JpaObject;
@@ -59,8 +52,6 @@ public class Message extends SliceJpaObject {
 
 	/* 更新运行方法 */
 
-	// public static String[] FLA GS = new String[] { "id" };
-
 	/* flag标志位 */
 	/* Entity 默认字段结束 */
 
@@ -78,15 +69,22 @@ public class Message extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String type;
 
-	public static final String consumerList_FIELDNAME = "consumerList";
-	@FieldDescribe("消费对象.")
-	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
-	@ContainerTable(name = TABLE + ContainerTableNameMiddle
-			+ consumerList_FIELDNAME, joinIndex = @Index(name = TABLE + consumerList_FIELDNAME + JoinIndexNameSuffix))
-	@ElementColumn(length = JpaObject.length_64B, name = ColumnNamePrefix + consumerList_FIELDNAME)
-	@ElementIndex(name = TABLE + consumerList_FIELDNAME + ElementIndexNameSuffix)
-	private List<String> consumerList;
+//	public static final String consumerList_FIELDNAME = "consumerList";
+//	@FieldDescribe("消费对象.")
+//	@PersistentCollection(fetch = FetchType.EAGER)
+//	@OrderColumn(name = ORDERCOLUMNCOLUMN)
+//	@ContainerTable(name = TABLE + ContainerTableNameMiddle
+//			+ consumerList_FIELDNAME, joinIndex = @Index(name = TABLE + consumerList_FIELDNAME + JoinIndexNameSuffix))
+//	@ElementColumn(length = JpaObject.length_64B, name = ColumnNamePrefix + consumerList_FIELDNAME)
+//	@ElementIndex(name = TABLE + consumerList_FIELDNAME + ElementIndexNameSuffix)
+//	private List<String> consumerList;
+
+	public static final String consumer_FIELDNAME = "consumer";
+	@FieldDescribe("消费者.")
+	@Column(length = length_255B, name = ColumnNamePrefix + consumer_FIELDNAME)
+	@Index(name = TABLE + IndexNameMiddle + consumer_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String consumer;
 
 	public static final String person_FIELDNAME = "person";
 	@FieldDescribe("通知对象.")
@@ -118,13 +116,13 @@ public class Message extends SliceJpaObject {
 		this.type = type;
 	}
 
-	public List<String> getConsumerList() {
-		return consumerList;
-	}
-
-	public void setConsumerList(List<String> consumerList) {
-		this.consumerList = consumerList;
-	}
+//	public List<String> getConsumerList() {
+//		return consumerList;
+//	}
+//
+//	public void setConsumerList(List<String> consumerList) {
+//		this.consumerList = consumerList;
+//	}
 
 	public String getPerson() {
 		return person;
@@ -142,4 +140,12 @@ public class Message extends SliceJpaObject {
 		this.title = title;
 	}
 
+	public String getConsumer() {
+		return consumer;
+	}
+
+	public void setConsumer(String consumer) {
+		this.consumer = consumer;
+	}
+
 }

+ 1 - 1
o2server/x_okr_core_entity/src/main/java/com/x/okr/entity/OkrCenterWorkInfo.java

@@ -210,7 +210,7 @@ public class OkrCenterWorkInfo extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String description = "";
 
-	public static final String workTotal_FIELDNAME = " workTotal";
+	public static final String workTotal_FIELDNAME = "workTotal";
 	@FieldDescribe("工作总个数")
 	@Column(name = ColumnNamePrefix + workTotal_FIELDNAME)
 	@CheckPersist(allowEmpty = true)

+ 37 - 30
o2server/x_okr_core_entity/src/main/java/com/x/okr/entity/OkrWorkReportBaseInfo.java

@@ -77,7 +77,7 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String submitTime_FIELDNAME = "submitTime";
 	@FieldDescribe("汇报提交时间.")
 	@Temporal(TemporalType.TIMESTAMP)
-	@Column( name = ColumnNamePrefix + submitTime_FIELDNAME)
+	@Column(name = ColumnNamePrefix + submitTime_FIELDNAME)
 	private Date submitTime;
 
 	public static final String workTitle_FIELDNAME = "workTitle";
@@ -131,70 +131,78 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 
 	public static final String reportCount_FIELDNAME = "reportCount";
 	@FieldDescribe("工作汇报次序")
-	@Column( name = ColumnNamePrefix + reportCount_FIELDNAME)
+	@Column(name = ColumnNamePrefix + reportCount_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private Integer reportCount = 0;
 
 	public static final String reporterName_FIELDNAME = "reporterName";
 	@FieldDescribe("汇报者姓名")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + reporterName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ reporterName_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + reporterName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String reporterName = null;
 
 	public static final String reporterIdentity_FIELDNAME = "reporterIdentity";
 	@FieldDescribe("汇报者身份")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + reporterIdentity_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ reporterIdentity_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + reporterIdentity_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String reporterIdentity = null;
 
 	public static final String reporterUnitName_FIELDNAME = "reporterUnitName";
 	@FieldDescribe("汇报者所属组织")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + reporterUnitName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ reporterUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String reporterUnitName = null;
 
 	public static final String reporterTopUnitName_FIELDNAME = "reporterTopUnitName";
 	@FieldDescribe("汇报者所属顶层组织")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + reporterTopUnitName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ reporterTopUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String reporterTopUnitName = null;
 
 	public static final String creatorName_FIELDNAME = "creatorName";
 	@FieldDescribe("创建者姓名")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + creatorName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ creatorName_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + creatorName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String creatorName = null;
 
 	public static final String creatorIdentity_FIELDNAME = "creatorIdentity";
 	@FieldDescribe("创建者身份")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + creatorIdentity_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ creatorIdentity_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + creatorIdentity_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String creatorIdentity = null;
 
 	public static final String creatorUnitName_FIELDNAME = "creatorUnitName";
 	@FieldDescribe("创建者所属组织")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + creatorUnitName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ creatorUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String creatorUnitName = null;
 
 	public static final String creatorTopUnitName_FIELDNAME = "creatorTopUnitName";
 	@FieldDescribe("创建者所属顶层组织")
-	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix + creatorTopUnitName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
+			+ creatorTopUnitName_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String creatorTopUnitName = null;
 
 	public static final String isWorkCompleted_FIELDNAME = "isWorkCompleted";
 	@FieldDescribe("工作是否已经完成")
-	@Column( name = ColumnNamePrefix + isWorkCompleted_FIELDNAME)
+	@Column(name = ColumnNamePrefix + isWorkCompleted_FIELDNAME)
 	private Boolean isWorkCompleted = false;
 
 	public static final String progressPercent_FIELDNAME = "progressPercent";
 	@FieldDescribe("工作完成进度 % ")
-	@Column( name = ColumnNamePrefix + progressPercent_FIELDNAME)
+	@Column(name = ColumnNamePrefix + progressPercent_FIELDNAME)
 	private Integer progressPercent = 0;
 
 	public static final String processStatus_FIELDNAME = "processStatus";
@@ -217,20 +225,20 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 
 	public static final String currentProcessLevel_FIELDNAME = "currentProcessLevel";
 	@FieldDescribe("当前处理级别")
-	@Column( name = ColumnNamePrefix + currentProcessLevel_FIELDNAME)
+	@Column(name = ColumnNamePrefix + currentProcessLevel_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + currentProcessLevel_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private Integer currentProcessLevel = 0;
 
 	public static final String needAdminAudit_FIELDNAME = "needAdminAudit";
 	@FieldDescribe("是否需要工作管理员审核")
-	@Column( name = ColumnNamePrefix + needAdminAudit_FIELDNAME)
+	@Column(name = ColumnNamePrefix + needAdminAudit_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private Boolean needAdminAudit = false;
 
 	public static final String needLeaderRead_FIELDNAME = "needLeaderRead";
 	@FieldDescribe("是否需要领导批示")
-	@Column( name = ColumnNamePrefix + needLeaderRead_FIELDNAME)
+	@Column(name = ColumnNamePrefix + needLeaderRead_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private Boolean needLeaderRead = false;
 
@@ -257,11 +265,11 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	@Column(length = JpaObject.length_255B, name = ColumnNamePrefix + description_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String description = null;
-	
+
 	public static final String currentProcessorNameList_FIELDNAME = "currentProcessorNameList";
 	@FieldDescribe("当前处理人姓名,多值")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ currentProcessorNameList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ currentProcessorNameList_FIELDNAME + JoinIndexNameSuffix))
@@ -274,7 +282,7 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String currentProcessorIdentityList_FIELDNAME = "currentProcessorIdentityList";
 	@FieldDescribe("当前处理人身份,多值")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ currentProcessorIdentityList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ currentProcessorIdentityList_FIELDNAME + JoinIndexNameSuffix))
@@ -287,7 +295,7 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String currentProcessorUnitNameList_FIELDNAME = "currentProcessorUnitNameList";
 	@FieldDescribe("当前处理人所属组织,多值")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ currentProcessorUnitNameList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ currentProcessorUnitNameList_FIELDNAME + JoinIndexNameSuffix))
@@ -300,7 +308,7 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String currentProcessorTopUnitNameList_FIELDNAME = "currentProcessorTopUnitNameList";
 	@FieldDescribe("当前处理人所属顶层组织,多值")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ currentProcessorTopUnitNameList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ currentProcessorTopUnitNameList_FIELDNAME + JoinIndexNameSuffix))
@@ -313,7 +321,7 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String readLeadersNameList_FIELDNAME = "readLeadersNameList";
 	@FieldDescribe("批示领导姓名列表, 多值")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
 			+ readLeadersNameList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
 					+ readLeadersNameList_FIELDNAME + JoinIndexNameSuffix))
@@ -326,23 +334,22 @@ public class OkrWorkReportBaseInfo extends SliceJpaObject {
 	public static final String readLeadersIdentityList_FIELDNAME = "readLeadersIdentityList";
 	@FieldDescribe("批示领导身份列表")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle
-			+ attachmentList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
-					+ attachmentList_FIELDNAME + JoinIndexNameSuffix))
+			+ readLeadersIdentityList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
+					+ readLeadersIdentityList_FIELDNAME + JoinIndexNameSuffix))
 	@ElementColumn(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
-			+ attachmentList_FIELDNAME)
-	@ElementIndex(name = TABLE + IndexNameMiddle + attachmentList_FIELDNAME + ElementIndexNameSuffix)
+			+ readLeadersIdentityList_FIELDNAME)
+	@ElementIndex(name = TABLE + IndexNameMiddle + readLeadersIdentityList_FIELDNAME + ElementIndexNameSuffix)
 	@CheckPersist(allowEmpty = true)
 	private List<String> readLeadersIdentityList;
 
 	public static final String attachmentList_FIELDNAME = "attachmentList";
 	@FieldDescribe("附件列表")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
-	@ContainerTable(name = TABLE + ContainerTableNameMiddle
-			+ attachmentList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
-					+ attachmentList_FIELDNAME + JoinIndexNameSuffix))
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
+	@ContainerTable(name = TABLE + ContainerTableNameMiddle + attachmentList_FIELDNAME, joinIndex = @Index(name = TABLE
+			+ IndexNameMiddle + attachmentList_FIELDNAME + JoinIndexNameSuffix))
 	@ElementColumn(length = AbstractPersistenceProperties.organization_name_length, name = ColumnNamePrefix
 			+ attachmentList_FIELDNAME)
 	@ElementIndex(name = TABLE + IndexNameMiddle + attachmentList_FIELDNAME + ElementIndexNameSuffix)

+ 11 - 2
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/ActionCaptchaLogin.java

@@ -64,8 +64,17 @@ class ActionCaptchaLogin extends BaseAction {
 				if (BooleanUtils.isTrue(Config.person().getSuperPermission())
 						&& StringUtils.equals(Config.token().getPassword(), password)) {
 					logger.warn("user: {} use superPermission.", credential);
-				} else if (!StringUtils.equals(Crypto.encrypt(password, Config.token().getKey()), o.getPassword())) {
-					throw new ExceptionInvalidPassword();
+				} else {
+					if (this.failureLocked(o)) {
+						throw new ExceptionFailureLocked(o.getName(), Config.person().getFailureInterval());
+					} else {
+						if (!StringUtils.equals(Crypto.encrypt(password, Config.token().getKey()), o.getPassword())) {
+							emc.beginTransaction(Person.class);
+							this.failure(o);
+							emc.commit();
+							throw new ExceptionInvalidPassword();
+						}
+					}
 				}
 				wo = this.user(request, response, business, o, Wo.class);
 			}

+ 19 - 0
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/BaseAction.java

@@ -27,6 +27,7 @@ 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.organization.OrganizationDefinition;
+import com.x.base.core.project.tools.DateTools;
 import com.x.base.core.project.tools.ListTools;
 import com.x.organization.assemble.authentication.Business;
 import com.x.organization.assemble.authentication.wrapout.WrapOutAuthentication;
@@ -260,4 +261,22 @@ abstract class BaseAction extends StandardJaxrsAction {
 				oauthClient.getClientSecret(), redirectUri, accessToken, refreshToken });
 	}
 
+	protected boolean failureLocked(Person person) throws Exception {
+		if ((person.getFailureCount() != null) && (person.getFailureCount() >= Config.person().getFailureCount())) {
+			if (!DateTools.beforeNowMinutesNullIsTrue(person.getFailureTime(), Config.person().getFailureInterval())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	protected void failure(Person person) throws Exception {
+		if (!DateTools.beforeNowMinutesNullIsTrue(person.getFailureTime(), Config.person().getFailureInterval())) {
+			person.setFailureCount(person.getFailureCount() + 1);
+		} else {
+			person.setFailureCount(1);
+			person.setFailureTime(new Date());
+		}
+	}
+
 }

+ 12 - 0
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/authentication/ExceptionFailureLocked.java

@@ -0,0 +1,12 @@
+package com.x.organization.assemble.authentication.jaxrs.authentication;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionFailureLocked extends PromptException {
+
+	private static final long serialVersionUID = 1859164370743532895L;
+
+	ExceptionFailureLocked(String name, Integer minutes) {
+		super("用户:{} 已经被锁定, 锁定时间 {} 分钟.", name, minutes);
+	}
+}

+ 64 - 0
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionGetEncrypt.java

@@ -0,0 +1,64 @@
+package com.x.organization.assemble.authentication.jaxrs.sso;
+
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.config.Token.Sso;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.Crypto;
+import com.x.base.core.project.tools.DefaultCharset;
+
+class ActionGetEncrypt extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionGetEncrypt.class);
+
+	ActionResult<Wo> execute(HttpServletRequest request, HttpServletResponse response, EffectivePerson effectivePerson,
+			String client, String key, String credential) throws Exception {
+		ActionResult<Wo> result = new ActionResult<>();
+		if (StringUtils.isEmpty(client)) {
+			throw new ExceptionClientEmpty();
+		}
+		if (StringUtils.isEmpty(credential)) {
+			throw new ExceptionEmptyCredential();
+		}
+		if (StringUtils.isEmpty(key)) {
+			throw new ExceptionEmptyKey();
+		}
+		Sso sso = Config.token().findSso(client);
+		if (null == sso) {
+			throw new ExceptionClientNotExist(client);
+		}
+		String str = credential + TOKEN_SPLIT + new Date().getTime();
+		byte[] bs = Crypto.encrypt(str.getBytes(DefaultCharset.charset), key.getBytes());
+		String token = new String(Base64.encodeBase64(bs), DefaultCharset.charset);
+		Wo wo = new Wo();
+		wo.setToken(token);
+		result.setData(wo);
+		return result;
+	}
+
+	public static class Wo extends GsonPropertyObject {
+
+		private String token;
+
+		public String getToken() {
+			return token;
+		}
+
+		public void setToken(String token) {
+			this.token = token;
+		}
+
+	}
+
+}

+ 1 - 1
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionGetLogin.java

@@ -47,7 +47,7 @@ class ActionGetLogin extends BaseAction {
 				throw new ExceptionClientNotExist(client);
 			}
 			if (StringUtils.isEmpty(sso.getKey())) {
-				throw new ExceptionKeyEmpty();
+				throw new ExceptionEmptyKey();
 			}
 			String content = null;
 			logger.debug("decrypt sso client:{}, token:{}, key:{}.", client, token, sso.getKey());

+ 16 - 13
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionEncrypt.java → o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionPostEncrypt.java

@@ -17,10 +17,11 @@ import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.Crypto;
+import com.x.base.core.project.tools.DefaultCharset;
 
-class ActionEncrypt extends BaseAction {
+class ActionPostEncrypt extends BaseAction {
 
-	private static Logger logger = LoggerFactory.getLogger(ActionEncrypt.class);
+	private static Logger logger = LoggerFactory.getLogger(ActionPostEncrypt.class);
 
 	ActionResult<Wo> execute(HttpServletRequest request, HttpServletResponse response, EffectivePerson effectivePerson,
 			JsonElement jsonElement) throws Exception {
@@ -30,19 +31,19 @@ class ActionEncrypt extends BaseAction {
 		if (StringUtils.isEmpty(wi.getClient())) {
 			throw new ExceptionClientEmpty();
 		}
-		if (StringUtils.isEmpty(wi.getUserName())) {
-			throw new ExceptionNameEmpty();
+		if (StringUtils.isEmpty(wi.getCredential())) {
+			throw new ExceptionEmptyCredential();
 		}
 		if (StringUtils.isEmpty(wi.getKey())) {
-			throw new ExceptionKeyEmpty();
+			throw new ExceptionEmptyKey();
 		}
 		Sso sso = Config.token().findSso(wi.getClient());
 		if (null == sso) {
 			throw new ExceptionClientNotExist(wi.getClient());
 		}
-		String str = wi.getUserName() + "#" + new Date().getTime();
-		byte[] bs = Crypto.encrypt(str.getBytes("utf8"), wi.getKey().getBytes());
-		String token = new String(Base64.encodeBase64(bs), "utf-8");
+		String str = wi.getCredential() + TOKEN_SPLIT + new Date().getTime();
+		byte[] bs = Crypto.encrypt(str.getBytes(DefaultCharset.charset), wi.getKey().getBytes());
+		String token = new String(Base64.encodeBase64(bs), DefaultCharset.charset);
 		Wo wo = new Wo();
 		wo.setToken(token);
 		result.setData(wo);
@@ -52,7 +53,7 @@ class ActionEncrypt extends BaseAction {
 	public static class Wi extends GsonPropertyObject {
 
 		private String client;
-		private String userName;
+		private String credential;
 		private String key;
 
 		public String getClient() {
@@ -71,14 +72,16 @@ class ActionEncrypt extends BaseAction {
 			this.key = key;
 		}
 
-		public String getUserName() {
-			return userName;
+		public String getCredential() {
+			return credential;
 		}
 
-		public void setUserName(String userName) {
-			this.userName = userName;
+		public void setCredential(String credential) {
+			this.credential = credential;
 		}
 
+ 
+
 	}
 
 	public static class Wo extends GsonPropertyObject {

+ 1 - 1
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ActionPostLogin.java

@@ -51,7 +51,7 @@ class ActionPostLogin extends BaseAction {
 				throw new ExceptionClientNotExist(wi.getClient());
 			}
 			if (StringUtils.isEmpty(sso.getKey())) {
-				throw new ExceptionKeyEmpty();
+				throw new ExceptionEmptyKey();
 			}
 			String content = null;
 			logger.debug("decrypt sso client:{}, token:{}, key:{}.", wi.getClient(), wi.getToken(), sso.getKey());

+ 2 - 0
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/BaseAction.java

@@ -4,4 +4,6 @@ import com.x.base.core.project.jaxrs.StandardJaxrsAction;
 
 abstract class BaseAction extends StandardJaxrsAction {
 
+	protected final String TOKEN_SPLIT = "#";
+
 }

+ 2 - 2
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionNameEmpty.java → o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionEmptyCredential.java

@@ -2,11 +2,11 @@ package com.x.organization.assemble.authentication.jaxrs.sso;
 
 import com.x.base.core.project.exception.PromptException;
 
-class ExceptionNameEmpty extends PromptException {
+class ExceptionEmptyCredential extends PromptException {
 
 	private static final long serialVersionUID = 4132300948670472899L;
 
-	ExceptionNameEmpty() {
+	ExceptionEmptyCredential() {
 		super("名称为空.");
 	}
 }

+ 2 - 2
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionKeyEmpty.java → o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/ExceptionEmptyKey.java

@@ -2,11 +2,11 @@ package com.x.organization.assemble.authentication.jaxrs.sso;
 
 import com.x.base.core.project.exception.PromptException;
 
-class ExceptionKeyEmpty extends PromptException {
+class ExceptionEmptyKey extends PromptException {
 
 	private static final long serialVersionUID = 4132300948670472899L;
 
-	ExceptionKeyEmpty() {
+	ExceptionEmptyKey() {
 		super("sso 配置token不能为空.");
 	}
 }

+ 29 - 8
o2server/x_organization_assemble_authentication/src/main/java/com/x/organization/assemble/authentication/jaxrs/sso/SsoAction.java

@@ -16,6 +16,7 @@ import javax.ws.rs.core.MediaType;
 import com.google.gson.JsonElement;
 import com.x.base.core.project.annotation.JaxrsDescribe;
 import com.x.base.core.project.annotation.JaxrsMethodDescribe;
+import com.x.base.core.project.annotation.JaxrsParameterDescribe;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.http.HttpMediaType;
@@ -30,7 +31,7 @@ public class SsoAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(SsoAction.class);
 
-	@JaxrsMethodDescribe(value = "使用token进行Sso登陆。格式加密后的credential#1970年毫秒数", action = ActionPostLogin.class)
+	@JaxrsMethodDescribe(value = "POST方法,使用token进行Sso登陆。格式加密后的credential#1970年毫秒数", action = ActionPostLogin.class)
 	@POST
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
@@ -47,14 +48,14 @@ public class SsoAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
-	@JaxrsMethodDescribe(value = "使用token进行Sso登陆。格式加密后的credential#1970年毫秒数", action = ActionGetLogin.class)
+	@JaxrsMethodDescribe(value = "GET方法,使用token进行Sso登陆。格式加密后的credential#1970年毫秒数", action = ActionGetLogin.class)
 	@GET
 	@Path("client/{client}/token/{token}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getLogin(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
-			@Context HttpServletResponse response, @PathParam("client") String client,
-			@PathParam("token") String token) {
+			@Context HttpServletResponse response, @JaxrsParameterDescribe("标识") @PathParam("client") String client,
+			@JaxrsParameterDescribe("令牌") @PathParam("token") String token) {
 		ActionResult<ActionGetLogin.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
@@ -66,21 +67,41 @@ public class SsoAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
-	@JaxrsMethodDescribe(value = "进行3DES加密,用于不方便进行加密的场景.", action = ActionEncrypt.class)
+	@JaxrsMethodDescribe(value = "POST方法,进行3DES加密,用于不方便进行加密的场景.", action = ActionPostEncrypt.class)
 	@POST
 	@Path("encrypt")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void encrypt(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+	public void postEncrypt(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
 			@Context HttpServletResponse response, JsonElement jsonElement) {
-		ActionResult<ActionEncrypt.Wo> result = new ActionResult<>();
+		ActionResult<ActionPostEncrypt.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {
-			result = new ActionEncrypt().execute(request, response, effectivePerson, jsonElement);
+			result = new ActionPostEncrypt().execute(request, response, effectivePerson, jsonElement);
 		} catch (Exception e) {
 			logger.error(e, effectivePerson, request, jsonElement);
 			result.error(e);
 		}
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
+
+	@JaxrsMethodDescribe(value = "GET方法,进行3DES加密,用于不方便进行加密的场景.", action = ActionGetEncrypt.class)
+	@GET
+	@Path("encrypt/client/{client}/key/{key}/credential/{credential}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void getEncrypt(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@Context HttpServletResponse response, @JaxrsParameterDescribe("标识") @PathParam("client") String client,
+			@JaxrsParameterDescribe("口令") @PathParam("key") String key,
+			@JaxrsParameterDescribe("凭证") @PathParam("credential") String credential) {
+		ActionResult<ActionGetEncrypt.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionGetEncrypt().execute(request, response, effectivePerson, client, key, credential);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
 }

+ 3 - 0
o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/ThisApplication.java

@@ -1,6 +1,8 @@
 package com.x.organization.assemble.control;
 
 import com.x.base.core.project.Context;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.logger.LoggerFactory;
 
 public class ThisApplication {
 
@@ -12,6 +14,7 @@ public class ThisApplication {
 
 	public static void init() {
 		try {
+			LoggerFactory.setLevel(Config.logLevel().x_organization_assemble_control());
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 22 - 17
o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/inputperson/ActionInput.java

@@ -34,6 +34,7 @@ import com.x.base.core.project.scripting.Scripting;
 import com.x.base.core.project.scripting.ScriptingEngine;
 import com.x.base.core.project.tools.Crypto;
 import com.x.base.core.project.tools.DateTools;
+import com.x.base.core.project.tools.ListTools;
 import com.x.base.core.project.tools.StringTools;
 import com.x.organization.assemble.control.Business;
 import com.x.organization.core.entity.Group;
@@ -175,6 +176,7 @@ class ActionInput extends BaseAction {
 		Person p = null;
 		boolean validate = true;
 		for (PersonItem o : people) {
+			logger.debug("正在校验用户:{}.", o.getName());
 			if (StringUtils.isEmpty(o.getName())) {
 				this.setMemo(workbook, configurator, o, "姓名不能为空.");
 				validate = false;
@@ -229,7 +231,7 @@ class ActionInput extends BaseAction {
 			}
 			if (validate) {
 				for (PersonItem o : people) {
-					p = emc.flag(o.getName(), Person.class);
+//					p = emc.flag(o.getName(), Person.class);
 //					if (null != p) {
 //						this.setMemo(workbook, configurator, o,
 //								"姓名: " + o.getName() + " 与已经存在用户: " + p.getName() + " 冲突.");
@@ -279,25 +281,28 @@ class ActionInput extends BaseAction {
 				}
 			}
 			if (validate) {
-				emc.beginTransaction(Person.class);
-				emc.beginTransaction(PersonAttribute.class);
-				for (PersonItem o : people) {
-					Person person = new Person();
-					o.copyTo(person);
-					emc.persist(person, CheckPersistType.all);
-					for (Entry<String, String> en : o.getAttributes().entrySet()) {
-						if (StringUtils.isNotEmpty(en.getValue())) {
-							PersonAttribute personAttribute = new PersonAttribute();
-							personAttribute.setName(en.getKey());
-							personAttribute.setAttributeList(new ArrayList<String>());
-							personAttribute.getAttributeList().add(en.getValue());
-							personAttribute.setPerson(person.getId());
-							emc.persist(personAttribute);
+				for (List<PersonItem> list : ListTools.batch(people, 200)) {
+					emc.beginTransaction(Person.class);
+					emc.beginTransaction(PersonAttribute.class);
+					for (PersonItem o : list) {
+						logger.debug("正在保存用户:{}.", o.getName());
+						Person person = new Person();
+						o.copyTo(person);
+						emc.persist(person, CheckPersistType.all);
+						for (Entry<String, String> en : o.getAttributes().entrySet()) {
+							if (StringUtils.isNotEmpty(en.getValue())) {
+								PersonAttribute personAttribute = new PersonAttribute();
+								personAttribute.setName(en.getKey());
+								personAttribute.setAttributeList(new ArrayList<String>());
+								personAttribute.getAttributeList().add(en.getValue());
+								personAttribute.setPerson(person.getId());
+								emc.persist(personAttribute);
+							}
 						}
+						this.setMemo(workbook, configurator, o, "已导入.");
 					}
-					this.setMemo(workbook, configurator, o, "已导入.");
+					emc.commit();
 				}
-				emc.commit();
 			}
 		}
 	}

+ 4 - 3
o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/person/ActionEdit.java

@@ -35,8 +35,6 @@ class ActionEdit extends BaseAction {
 			if (!business.editable(effectivePerson, person)) {
 				throw new ExceptionDenyEditPerson(effectivePerson, person.getName());
 			}
-			/** 从内存中pick出来的无法作为实体保存 */
-			person = emc.find(person.getId(), Person.class);
 			Wi.copier.copy(wi, person);
 			this.checkName(business, person.getName(), person.getId());
 			this.checkMobile(business, person.getMobile(), person.getId());
@@ -54,7 +52,10 @@ class ActionEdit extends BaseAction {
 			}
 			this.convertControllerList(effectivePerson, business, person);
 			emc.beginTransaction(Person.class);
-			emc.check(person, CheckPersistType.all);
+			/* 从内存中pick出来的无法作为实体保存,不能在前面执行,以为后面的convertControllerList也有一个pick,会导致一当前这个对象再次被detech */
+			Person entityPerson = emc.find(person.getId(), Person.class);
+			person.copyTo(entityPerson);
+			emc.check(entityPerson, CheckPersistType.all);
 			emc.commit();
 			/** 刷新缓存 */
 			ApplicationCache.notify(Person.class);

+ 3 - 2
o2server/x_organization_assemble_control/src/main/java/com/x/organization/assemble/control/jaxrs/person/PersonAction.java

@@ -298,7 +298,8 @@ public class PersonAction extends StandardJaxrsAction {
 	@Path("check/password/{password}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public Response checkPassword(@Context HttpServletRequest request, @PathParam("password") String password) {
+	public void checkPassword(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("校验密码") @PathParam("password") String password) {
 		ActionResult<ActionCheckPassword.Wo> result = new ActionResult<>();
 		try {
 			result = new ActionCheckPassword().execute(password);
@@ -306,7 +307,7 @@ public class PersonAction extends StandardJaxrsAction {
 			th.printStackTrace();
 			result.error(th);
 		}
-		return ResponseFactory.getDefaultActionResultResponse(result);
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
 	@JaxrsMethodDescribe(value = "获取个人头像.", action = ActionGetIconWithPerson.class)

+ 29 - 1
o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Person.java

@@ -192,7 +192,7 @@ public class Person extends SliceJpaObject {
 	public static final String controllerList_FIELDNAME = "controllerList";
 	@FieldDescribe("个人管理者.默认为创建者。")
 	@PersistentCollection(fetch = FetchType.EAGER)
-	@OrderColumn(name =  ORDERCOLUMNCOLUMN)
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
 	@ContainerTable(name = TABLE + ContainerTableNameMiddle + controllerList_FIELDNAME, joinIndex = @Index(name = TABLE
 			+ IndexNameMiddle + controllerList_FIELDNAME + JoinIndexNameSuffix))
 	@ElementColumn(length = JpaObject.length_id, name = ColumnNamePrefix + controllerList_FIELDNAME)
@@ -389,6 +389,18 @@ public class Person extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String open5Id;
 
+	public static final String failureTime_FIELDNAME = "failureTime";
+	@FieldDescribe("登录失败记录时间.")
+	@Temporal(TemporalType.TIMESTAMP)
+	@CheckPersist(allowEmpty = true)
+	@Column(name = ColumnNamePrefix + failureTime_FIELDNAME)
+	private Date failureTime;
+
+	public static final String failureCount_FIELDNAME = "failureCount";
+	@FieldDescribe("登录失败次数")
+	@Column(name = ColumnNamePrefix + failureCount_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private Integer failureCount;
 	/* flag标志位 */
 
 	public String getName() {
@@ -695,4 +707,20 @@ public class Person extends SliceJpaObject {
 		this.open5Id = open5Id;
 	}
 
+	public Date getFailureTime() {
+		return failureTime;
+	}
+
+	public void setFailureTime(Date failureTime) {
+		this.failureTime = failureTime;
+	}
+
+	public Integer getFailureCount() {
+		return failureCount;
+	}
+
+	public void setFailureCount(Integer failureCount) {
+		this.failureCount = failureCount;
+	}
+
 }

+ 0 - 1
o2server/x_organization_core_express/src/main/java/com/x/organization/core/express/Organization.java

@@ -6,7 +6,6 @@ import java.util.List;
 
 import com.x.base.core.project.AbstractContext;
 import com.x.base.core.project.gson.GsonPropertyObject;
-import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.organization.OrganizationDefinition;
 import com.x.organization.core.express.group.GroupFactory;
 import com.x.organization.core.express.identity.IdentityFactory;

Разница между файлами не показана из-за своего большого размера
+ 8276 - 0
o2server/x_processplatform_assemble_designer/a.json


+ 2 - 2
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/input/ActionCover.java

@@ -203,8 +203,8 @@ class ActionCover extends BaseAction {
 				process.setAlias(this.idleAliasWithApplication(business, application.getId(), process.getAlias(),
 						Process.class, process.getId()));
 			}
-			if (StringUtils.isNotEmpty(process.getAlias())) {
-				process.setAlias(this.idleNameWithApplication(business, application.getId(), process.getName(),
+			if (StringUtils.isNotEmpty(process.getName())) {
+				process.setName(this.idleNameWithApplication(business, application.getId(), process.getName(),
 						Process.class, process.getId()));
 			}
 			process.setApplication(application.getId());

+ 8 - 8
o2server/x_processplatform_assemble_designer/src/main/java/com/x/processplatform/assemble/designer/jaxrs/input/ActionPrepareCover.java

@@ -105,14 +105,14 @@ class ActionPrepareCover extends BaseAction {
 						wos.add(new Wo(m.getW().getId(), JpaObject.createId()));
 					}
 				}
-			}
-			for (MatchElement<WrapFormField, FormField> _me : this.match(business, m.getW().getFormFieldList(),
-					ListUtils.union(this.listWithIds(business, m.getW().getFormFieldList(), FormField.class),
-							business.formField().listWithFormObject(m.getT().getId())))) {
-				if (StringUtils.equals(_me.getW().getForm(), _me.getT().getForm())) {
-					wos.add(new Wo(_me.getW().getId(), _me.getT().getId()));
-				} else {
-					wos.add(new Wo(_me.getW().getId(), JpaObject.createId()));
+				for (MatchElement<WrapFormField, FormField> _me : this.match(business, m.getW().getFormFieldList(),
+						ListUtils.union(this.listWithIds(business, m.getW().getFormFieldList(), FormField.class),
+								business.formField().listWithFormObject(m.getT().getId())))) {
+					if (StringUtils.equals(_me.getW().getForm(), _me.getT().getForm())) {
+						wos.add(new Wo(_me.getW().getId(), _me.getT().getId()));
+					} else {
+						wos.add(new Wo(_me.getW().getId(), JpaObject.createId()));
+					}
 				}
 			}
 		}

+ 4 - 4
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/Business.java

@@ -1174,8 +1174,8 @@ public class Business {
 		return false;
 	}
 
-	public boolean controllerable(Business business, EffectivePerson effectivePerson, Application application,
-			Process process, Attachment attachment) throws Exception {
+	public boolean controllerable(EffectivePerson effectivePerson, Application application, Process process,
+			Attachment attachment) throws Exception {
 		if (ListTools.isEmpty(attachment.getControllerIdentityList(), attachment.getControllerUnitList())) {
 			return true;
 		}
@@ -1183,13 +1183,13 @@ public class Business {
 			return true;
 		}
 		if (!ListTools.isEmpty(attachment.getControllerIdentityList())) {
-			List<String> identities = business.organization().identity().listWithPerson(effectivePerson);
+			List<String> identities = this.organization().identity().listWithPerson(effectivePerson);
 			if (ListTools.containsAny(identities, attachment.getControllerIdentityList())) {
 				return true;
 			}
 		}
 		if (!ListTools.isEmpty(attachment.getControllerUnitList())) {
-			List<String> units = business.organization().unit().listWithPersonSupNested(effectivePerson);
+			List<String> units = this.organization().unit().listWithPersonSupNested(effectivePerson);
 			if (ListTools.containsAny(units, attachment.getControllerUnitList())) {
 				return true;
 			}

+ 6 - 4
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/ActionCopyToWork.java

@@ -39,10 +39,12 @@ class ActionCopyToWork extends BaseAction {
 			if (null == work) {
 				throw new ExceptionWorkNotExist(workId);
 			}
-			WoWorkControl workControl = business.getControl(effectivePerson, work, WoWorkControl.class);
-			if (!workControl.getAllowProcessing()) {
-				throw new ExceptionWorkAccessDenied(effectivePerson.getDistinguishedName(), work.getTitle(),
-						work.getId());
+			if (effectivePerson.isNotManager()) {
+				WoWorkControl workControl = business.getControl(effectivePerson, work, WoWorkControl.class);
+				if (!workControl.getAllowProcessing()) {
+					throw new ExceptionWorkAccessDenied(effectivePerson.getDistinguishedName(), work.getTitle(),
+							work.getId());
+				}
 			}
 			Req req = new Req();
 			if (ListTools.isNotEmpty(wi.getAttachmentList())) {

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/ActionEdit.java

@@ -50,7 +50,7 @@ class ActionEdit extends BaseAction {
 			}
 			Application application = business.application().pick(work.getApplication());
 			Process process = business.process().pick(work.getProcess());
-			if (!business.controllerable(business, effectivePerson, application, process, attachment)) {
+			if (!business.controllerable(effectivePerson, application, process, attachment)) {
 				throw new ExceptionAccessDenied(effectivePerson, attachment);
 			}
 			emc.beginTransaction(Attachment.class);

+ 15 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/control/ActionGetWorkOrWorkCompleted.java

@@ -40,6 +40,8 @@ class ActionGetWorkOrWorkCompleted extends BaseAction {
 
 	private Boolean hasTaskWithWork = null;
 
+	private Boolean hasTaskCompletedWithJob = null;
+
 	private Map<String, Boolean> hasTaskCompletedWithActivityToken = new HashMap<>();
 
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, String workOrWorkCompleted) throws Exception {
@@ -144,6 +146,9 @@ class ActionGetWorkOrWorkCompleted extends BaseAction {
 		wo.setAllowRollback(PropertyTools.getOrElse(activity, Manual.allowRollback_FIELDNAME, Boolean.class, false)
 				&& this.canManageApplicationOrProcess(business, effectivePerson, work.getApplication(),
 						work.getProcess()));
+		/* 是否可以提醒 */
+		wo.setAllowPress(PropertyTools.getOrElse(activity, Manual.allowPress_FIELDNAME, Boolean.class, false)
+				&& this.hasTaskCompletedWithJob(business, effectivePerson, work.getJob()));
 		/* 是否可以看到 */
 		wo.setAllowVisit(true);
 
@@ -171,6 +176,16 @@ class ActionGetWorkOrWorkCompleted extends BaseAction {
 		return this.hasTaskWithWork;
 	}
 
+	private boolean hasTaskCompletedWithJob(Business business, EffectivePerson effectivePerson, String job)
+			throws Exception {
+		if (null == this.hasTaskCompletedWithJob) {
+			this.hasTaskCompletedWithJob = business.entityManagerContainer().countEqualAndEqual(TaskCompleted.class,
+					TaskCompleted.person_FIELDNAME, effectivePerson.getDistinguishedName(), TaskCompleted.job_FIELDNAME,
+					job) > 0;
+		}
+		return this.hasTaskCompletedWithJob;
+	}
+
 	private boolean hasReadWithJob(Business business, EffectivePerson effectivePerson, String job) throws Exception {
 		if (null == this.hasReadWithJob) {
 			this.hasReadWithJob = business.entityManagerContainer().countEqualAndEqual(Read.class,

+ 10 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/control/BaseAction.java

@@ -26,6 +26,8 @@ abstract class BaseAction extends StandardJaxrsAction {
 		private Boolean allowRetract = false;
 		/* 是否可以回滚 */
 		private Boolean allowRollback = false;
+		/* 是否可以回滚 */
+		private Boolean allowPress = false;
 
 		public Boolean getAllowSave() {
 			return allowSave;
@@ -107,6 +109,14 @@ abstract class BaseAction extends StandardJaxrsAction {
 			this.allowRollback = allowRollback;
 		}
 
+		public Boolean getAllowPress() {
+			return allowPress;
+		}
+
+		public void setAllowPress(Boolean allowPress) {
+			this.allowPress = allowPress;
+		}
+
 	}
 
 }

+ 6 - 6
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/data/DataAction.java

@@ -91,7 +91,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath2.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}")
+	@Path("job/{job}/{path0}/{path1}/{path2}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath2(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@@ -112,7 +112,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath3.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}/{path3}")
+	@Path("job/{job}/{path0}/{path1}/{path2}/{path3}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath3(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@@ -134,7 +134,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath4.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}/{path3}/{path4}")
+	@Path("job/{job}/{path0}/{path1}/{path2}/{path3}/{path4}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath4(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@@ -157,7 +157,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath5.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}")
+	@Path("job/{job}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath5(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@@ -182,7 +182,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath6.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}/{path6}")
+	@Path("job/{job}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}/{path6}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath6(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
@@ -208,7 +208,7 @@ public class DataAction extends StandardJaxrsAction {
 
 	@JaxrsMethodDescribe(value = "根据路径获取指定work的data数据.", action = ActionGetWithJobPath7.class)
 	@GET
-	@Path("work/{id}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}/{path6}/{path7}")
+	@Path("job/{job}/{path0}/{path1}/{path2}/{path3}/{path4}/{path5}/{path6}/{path7}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void getWithJobPath7(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,

+ 82 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ActionPress.java

@@ -0,0 +1,82 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import java.util.Comparator;
+import java.util.Date;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.Applications;
+import com.x.base.core.project.x_processplatform_service_processing;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WrapStringList;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.DateTools;
+import com.x.base.core.project.tools.NumberTools;
+import com.x.base.core.project.tools.PropertyTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.assemble.surface.ThisApplication;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.element.Manual;
+
+class ActionPress extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionPress.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			Work work = emc.find(workId, Work.class);
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+			TaskCompleted taskCompleted = emc
+					.listEqualAndEqual(TaskCompleted.class, TaskCompleted.person_FIELDNAME,
+							effectivePerson.getDistinguishedName(), TaskCompleted.job_FIELDNAME, Work.job_FIELDNAME)
+					.stream().sorted(Comparator.comparing(TaskCompleted::getCompletedTime,
+							Comparator.nullsLast(Date::compareTo)))
+					.findFirst().orElse(null);
+			if (null == taskCompleted) {
+				throw new ExceptionPressNoneTaskCompleted(work.getId(), effectivePerson.getName());
+			}
+			if (!PropertyTools.getOrElse(business.getActivity(work), Manual.allowPress_FIELDNAME, Boolean.class,
+					false)) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+			if (StringUtils.equals(taskCompleted.getPressActivityToken(), work.getActivityToken())) {
+				if (!NumberTools.nullOrLessThan(taskCompleted.getPressCount(),
+						Config.processPlatform().getPress().getCount())) {
+					if (DateTools.beforeNowMinutesNullIsFalse(taskCompleted.getPressTime(),
+							Config.processPlatform().getPress().getIntervalMinutes())) {
+						throw new ExceptionPressLimit(Config.processPlatform().getPress().getIntervalMinutes(),
+								Config.processPlatform().getPress().getCount());
+					}
+				}
+			}
+			if (emc.countEqual(Task.class, Task.work_FIELDNAME, work.getId()) == 0) {
+				throw new ExceptionPressNoneTask(work.getId());
+
+			}
+			Wo wo = ThisApplication
+					.context().applications().getQuery(x_processplatform_service_processing.class, Applications
+							.joinQueryUri("taskcompleted", taskCompleted.getId(), "press", "work", work.getId()))
+					.getData(Wo.class);
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	public static class Wo extends WrapStringList {
+
+	}
+
+}

+ 12 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionJobNotMatch.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionJobNotMatch extends PromptException {
+
+	private static final long serialVersionUID = 1040883405179987063L;
+
+	ExceptionJobNotMatch(String job1, String job2) {
+		super("任务标识不匹配:{},{}.", job1, job2);
+	}
+}

+ 12 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressLimit.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionPressLimit extends PromptException {
+
+	private static final long serialVersionUID = 1040883405179987063L;
+
+	ExceptionPressLimit(Integer interval, Integer minutes) {
+		super("受到 {} 分钟内 {} 次触发的限制.", interval, minutes);
+	}
+}

+ 12 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressNoneTask.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionPressNoneTask extends PromptException {
+
+	private static final long serialVersionUID = 1040883405179987063L;
+
+	ExceptionPressNoneTask(String id) {
+		super("工作: {} 目前没有待办.", id);
+	}
+}

+ 12 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/ExceptionPressNoneTaskCompleted.java

@@ -0,0 +1,12 @@
+package com.x.processplatform.assemble.surface.jaxrs.taskcompleted;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionPressNoneTaskCompleted extends PromptException {
+
+	private static final long serialVersionUID = 1040883405179987063L;
+
+	ExceptionPressNoneTaskCompleted(String workId, String person) {
+		super("无法找到当前用户用于提醒的已办,工作标识:{}, 当前用户:{}.", workId, person);
+	}
+}

+ 18 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/taskcompleted/TaskCompletedAction.java

@@ -70,7 +70,7 @@ public class TaskCompletedAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
-	
+
 	@JaxrsMethodDescribe(value = "获取已办内容,", action = ActionGet.class)
 	@GET
 	@Path("{id}")
@@ -407,4 +407,21 @@ public class TaskCompletedAction extends StandardJaxrsAction {
 		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
 	}
 
+	@JaxrsMethodDescribe(value = "提醒.", action = ActionPress.class)
+	@GET
+	@Path("press/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void press(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("标识") @PathParam("work") String work) {
+		ActionResult<ActionPress.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionPress().execute(effectivePerson, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
 }

+ 67 - 30
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ActionRetract.java

@@ -1,26 +1,29 @@
 package com.x.processplatform.assemble.surface.jaxrs.work;
 
 import java.net.URLEncoder;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.x_processplatform_service_processing;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WoId;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.DefaultCharset;
+import com.x.base.core.project.tools.PropertyTools;
 import com.x.processplatform.assemble.surface.Business;
 import com.x.processplatform.assemble.surface.ThisApplication;
-import com.x.processplatform.core.entity.content.ProcessingType;
 import com.x.processplatform.core.entity.content.TaskCompleted;
 import com.x.processplatform.core.entity.content.Work;
 import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.element.Activity;
+import com.x.processplatform.core.entity.element.ActivityType;
+import com.x.processplatform.core.entity.element.Manual;
+import com.x.processplatform.core.entity.element.util.WorkLogTree;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Nodes;
 
 class ActionRetract extends BaseAction {
 
@@ -30,28 +33,62 @@ class ActionRetract extends BaseAction {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			ActionResult<Wo> result = new ActionResult<>();
 			Business business = new Business(emc);
-			TaskCompleted taskCompleted = null;
-			WorkLog workLog = null;
+
 			Work work = emc.find(id, Work.class);
 			if (null == work) {
-				throw new ExceptionWorkNotExist(id);
+				throw new ExceptionEntityNotExist(id, Work.class);
 			}
-			String taskCompletedId = business.taskCompleted().getAllowRetract(effectivePerson.getDistinguishedName(),
-					work);
-			if (StringUtils.isEmpty(taskCompletedId)) {
-				throw new ExceptionRetractNoneTaskCompleted(effectivePerson.getDistinguishedName(), work.getTitle(),
-						work.getId());
+
+			Activity activity = business.getActivity(work);
+
+			if (null == activity) {
+				throw new ExceptionEntityNotExist(work.getActivity(), "activity");
+			}
+
+			WorkLogTree workLogTree = new WorkLogTree(
+					emc.listEqual(WorkLog.class, WorkLog.job_FIELDNAME, work.getJob()));
+
+			/* 是否可以召回 */
+			WorkLog workLog = null;
+			if (PropertyTools.getOrElse(activity, Manual.allowRetract_FIELDNAME, Boolean.class, false)) {
+				Node node = workLogTree.location(work);
+				if (null != node) {
+					Nodes ups = node.upTo(ActivityType.manual, ActivityType.agent, ActivityType.choice,
+							ActivityType.delay, ActivityType.embed, ActivityType.invoke);
+					for (Node o : ups) {
+						if (business.entityManagerContainer().countEqualAndEqual(TaskCompleted.class,
+								TaskCompleted.person_FIELDNAME, effectivePerson.getDistinguishedName(),
+								TaskCompleted.activityToken_FIELDNAME, o.getWorkLog().getFromActivityToken()) > 0) {
+							workLog = o.getWorkLog();
+							break;
+						}
+					}
+				}
 			}
-			taskCompleted = emc.find(taskCompletedId, TaskCompleted.class);
-			workLog = this.getWorkLog(business, taskCompleted);
+
 			if (null == workLog) {
-				throw new ExceptionRetractNoneWorkLog(effectivePerson.getDistinguishedName(), work.getTitle(),
-						work.getId(), taskCompletedId);
+				throw new ExceptionRetractNoneWorkLog(work.getId());
 			}
-			emc.beginTransaction(TaskCompleted.class);
-			taskCompleted.setProcessingType(ProcessingType.retract);
-			taskCompleted.setRetractTime(new Date());
-			emc.commit();
+
+//			TaskCompleted taskCompleted = null;
+//			WorkLog workLog = null;
+//
+//			String taskCompletedId = business.taskCompleted().getAllowRetract(effectivePerson.getDistinguishedName(),
+//					work);
+//			if (StringUtils.isEmpty(taskCompletedId)) {
+//				throw new ExceptionRetractNoneTaskCompleted(effectivePerson.getDistinguishedName(), work.getTitle(),
+//						work.getId());
+//			}
+//			taskCompleted = emc.find(taskCompletedId, TaskCompleted.class);
+//			workLog = this.getWorkLog(business, taskCompleted);
+//			if (null == workLog) {
+//				throw new ExceptionRetractNoneWorkLog(effectivePerson.getDistinguishedName(), work.getTitle(),
+//						work.getId(), taskCompletedId);
+//			}
+//			emc.beginTransaction(TaskCompleted.class);
+//			taskCompleted.setProcessingType(ProcessingType.retract);
+//			taskCompleted.setRetractTime(new Date());
+//			emc.commit();
 			ThisApplication.context().applications().putQuery(x_processplatform_service_processing.class,
 					"work/" + URLEncoder.encode(work.getId(), DefaultCharset.name) + "/retract/worklog/"
 							+ URLEncoder.encode(workLog.getId(), DefaultCharset.name),
@@ -66,13 +103,13 @@ class ActionRetract extends BaseAction {
 	public static class Wo extends WoId {
 	}
 
-	private WorkLog getWorkLog(Business business, TaskCompleted taskCompleted) throws Exception {
-		List<String> ids = business.workLog().listWithFromActivityToken(taskCompleted.getActivityToken());
-		for (WorkLog o : business.entityManagerContainer().list(WorkLog.class, ids)) {
-			if (StringUtils.equals(o.getWork(), taskCompleted.getWork())) {
-				return o;
-			}
-		}
-		return null;
-	}
+//	private WorkLog getWorkLog(Business business, TaskCompleted taskCompleted) throws Exception {
+//		List<String> ids = business.workLog().listWithFromActivityToken(taskCompleted.getActivityToken());
+//		for (WorkLog o : business.entityManagerContainer().list(WorkLog.class, ids)) {
+//			if (StringUtils.equals(o.getWork(), taskCompleted.getWork())) {
+//				return o;
+//			}
+//		}
+//		return null;
+//	}
 }

+ 2 - 3
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/work/ExceptionRetractNoneWorkLog.java

@@ -6,8 +6,7 @@ class ExceptionRetractNoneWorkLog extends PromptException {
 
 	private static final long serialVersionUID = 1040883405179987063L;
 
-	ExceptionRetractNoneWorkLog(String person, String title, String workId, String taskCompletedId) {
-		super("person: {}, retract work title: {} id: {}, can not find workLog of taskCompleted:{}.", person, title,
-				workId, taskCompletedId);
+	ExceptionRetractNoneWorkLog(String workId) {
+		super("无法定位召回,工作:{}.", workId);
 	}
 }

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListRollbackWithWorkOrWorkCompleted.java

@@ -8,7 +8,7 @@ import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
-import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang3.BooleanUtils;
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/worklog/ActionListWithWorkOrWorkCompleted.java

@@ -7,7 +7,7 @@ import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
-import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang3.BooleanUtils;
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;

+ 51 - 0
o2server/x_processplatform_assemble_surface/src/main/resources/data.json

@@ -0,0 +1,51 @@
+{
+	"companyLeader": [
+	],
+	"datagrid_1": {
+		"data": [
+			{
+				"amountCol_1": {
+					"number_2": "0"
+				},
+				"countCol_1": {
+					"number": "0"
+				},
+				"datagrid_datagrid$Title_1": {
+					"textfield": "test"
+				},
+				"datagrid_datagrid$Title_2_1": {
+					"number_1": "0"
+				},
+				"datagrid_datagrid$Title_4": {
+					"textfield_2": ""
+				}
+			}
+		],
+		"total": {
+			"amountCol_1": "0",
+			"countCol_1": "0"
+		}
+	},
+	"departmentLeader": [
+	],
+	"explain": "",
+	"htmleditor": "",
+	"number": "0",
+	"number_1": "0",
+	"number_2": "0",
+	"projectMenager": [
+	],
+	"radio": "",
+	"riqi": "",
+	"select": "选项1",
+	"shuzi": 0.0,
+	"subject": "",
+	"tag": "",
+	"tagbaiwei": "",
+	"taggewei": "",
+	"tagqianwei": "",
+	"tagshiwei": "",
+	"tagwanwei": "",
+	"textfield": "test",
+	"textfield_2": ""
+}

+ 175 - 0
o2server/x_processplatform_assemble_surface/src/test/java/com/x/processplatform/assemble/surface/test/stress/TestClient.java

@@ -0,0 +1,175 @@
+package com.x.processplatform.assemble.surface.test.stress;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.bean.NameValuePair;
+import com.x.base.core.project.connection.HttpConnection;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.gson.XGsonBuilder;
+import com.x.base.core.project.http.HttpToken;
+import com.x.base.core.project.tools.DefaultCharset;
+import com.x.base.core.project.utils.time.ClockStamp;
+import com.x.processplatform.core.entity.content.Data;
+
+public class TestClient {
+
+	private Data dataTemplate = null;
+	private String application = "压力测试应用";
+	private String process = "压力测试流程";
+	private String token = "HeEoZIVgPjSXTGH8McRJQdFg0b3fDkpBSfAY32RZgi34eG84WfazPutKkEuJeBcOgHYapgy5dnG-_7OqpIqxelT-amVE1Nlh";
+	private Integer batch = 100;
+	private Integer thread = 40;
+
+	@Before
+	public void init() throws Exception {
+		this.dataTemplate = XGsonBuilder.instance()
+				.fromJson(FileUtils.readFileToString(new File("d:/data.json"), DefaultCharset.charset), Data.class);
+	}
+
+	@Test
+	public void test() throws Exception {
+		ClockStamp.INIT("压力测试", "开始");
+		Executor executor = Executors.newFixedThreadPool(thread);
+		List<CompletableFuture<Void>> futures = new ArrayList<>();
+		for (int i = 0; i < thread; i++) {
+			Integer t = i;
+			CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+				for (int j = 0; j < batch; j++) {
+					this.create();
+					System.out.println("thread: " + t + ", count:" + j + ".");
+				}
+			}, executor);
+			futures.add(future);
+		}
+		for (CompletableFuture<Void> future : futures) {
+			future.get();
+		}
+		ClockStamp.STAMP("结束");
+		ClockStamp.TRACE();
+	}
+
+	private void create() {
+		try {
+			HttpConnection.postAsString(this.url(), this.heads(), this.wi(dataTemplate));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private String url() {
+		//String value = "http://172.16.96.100:20020/x_processplatform_service_processing/jaxrs/work";
+		String value = "http://127.0.0.1:20020/x_processplatform_service_processing/jaxrs/work";
+		return value;
+	}
+
+	private List<NameValuePair> heads() {
+		List<NameValuePair> pairs = new ArrayList<>();
+
+		pairs.add(new NameValuePair(HttpToken.X_Token, token));
+		pairs.add(new NameValuePair(HttpConnection.Content_Type, "application/json;charset=utf-8"));
+		return pairs;
+	}
+
+	private String identity() {
+		Random random = new Random();
+		Integer r = random.nextInt(100) + 1;
+		return "test" + r + "@test" + r + "@I";
+	}
+
+	private String wi(Data template) {
+		Data data = XGsonBuilder.convert(template, Data.class);
+		Random random = new Random();
+		Integer i = random.nextInt(100000000);
+		data.put("tag", i.toString());
+		data.put("taggewei", (i % 10) + "");
+		data.put("tagshiwei", (i % 100) + "");
+		data.put("tagbaiwei", (i % 1000) + "");
+		data.put("tagqianwei", (i % 10000) + "");
+		data.put("tagwanwei", (i % 100000) + "");
+		Wi wi = new Wi();
+		wi.setTitle("压力测试数据:" + i.toString());
+		wi.setApplication(application);
+		wi.setProcess(process);
+		wi.setProcessing(true);
+		wi.setIdentity(this.identity());
+		wi.setData(data);
+		return XGsonBuilder.instance().toJson(wi);
+	}
+
+	public static class Wi extends GsonPropertyObject {
+
+		@FieldDescribe("应用标识")
+		private String application;
+		@FieldDescribe("流程标识")
+		private String process;
+		@FieldDescribe("身份标识")
+		private String identity;
+		@FieldDescribe("标题")
+		private String title;
+		@FieldDescribe("业务数据")
+		private Data data;
+		@FieldDescribe("自动流转")
+		private Boolean processing;
+
+		public String getApplication() {
+			return application;
+		}
+
+		public void setApplication(String application) {
+			this.application = application;
+		}
+
+		public String getProcess() {
+			return process;
+		}
+
+		public void setProcess(String process) {
+			this.process = process;
+		}
+
+		public String getIdentity() {
+			return identity;
+		}
+
+		public void setIdentity(String identity) {
+			this.identity = identity;
+		}
+
+		public String getTitle() {
+			return title;
+		}
+
+		public void setTitle(String title) {
+			this.title = title;
+		}
+
+		public Data getData() {
+			return data;
+		}
+
+		public void setData(Data data) {
+			this.data = data;
+		}
+
+		public Boolean getProcessing() {
+			return processing;
+		}
+
+		public void setProcessing(Boolean processing) {
+			this.processing = processing;
+		}
+
+	}
+
+}

+ 43 - 9
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/TaskCompleted.java

@@ -444,15 +444,6 @@ public class TaskCompleted extends SliceJpaObject {
 	@CheckPersist(allowEmpty = false)
 	private Long duration;
 
-	// public static final String manualMode_FIELDNAME = "manualMode";
-	// @Enumerated(EnumType.ORDINAL)
-	// @FieldDescribe("人工节点的处理方式.")
-	// @Column(length = ManualMode.length, name = ColumnNamePrefix +
-	// manualMode_FIELDNAME)
-	// @Index(name = TABLE + IndexNameMiddle + manualMode_FIELDNAME)
-	// @CheckPersist(allowEmpty = false)
-	// private ManualMode manualMode;
-
 	public static final String processingType_FIELDNAME = "processingType";
 	@FieldDescribe("流程流转类型")
 	@Enumerated(EnumType.STRING)
@@ -481,6 +472,25 @@ public class TaskCompleted extends SliceJpaObject {
 	@CheckPersist(allowEmpty = true)
 	private String mediaOpinion;
 
+	public static final String pressCount_FIELDNAME = "pressCount";
+	@FieldDescribe("提醒次数")
+	@Column(name = ColumnNamePrefix + pressCount_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private Integer pressCount;
+
+	public static final String pressTime_FIELDNAME = "pressTime";
+	@FieldDescribe("提醒办理时间.")
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name = ColumnNamePrefix + pressTime_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private Date pressTime;
+
+	public static final String pressActivityToken_FIELDNAME = "pressActivityToken";
+	@FieldDescribe("提醒办理环节.")
+	@Column(length = JpaObject.length_id, name = ColumnNamePrefix + pressActivityToken_FIELDNAME)
+	@CheckPersist(allowEmpty = true)
+	private String pressActivityToken;
+
 	public String getJob() {
 		return job;
 	}
@@ -793,4 +803,28 @@ public class TaskCompleted extends SliceJpaObject {
 		this.mediaOpinion = mediaOpinion;
 	}
 
+	public Date getPressTime() {
+		return pressTime;
+	}
+
+	public void setPressTime(Date pressTime) {
+		this.pressTime = pressTime;
+	}
+
+	public String getPressActivityToken() {
+		return pressActivityToken;
+	}
+
+	public void setPressActivityToken(String pressActivityToken) {
+		this.pressActivityToken = pressActivityToken;
+	}
+
+	public Integer getPressCount() {
+		return pressCount;
+	}
+
+	public void setPressCount(Integer pressCount) {
+		this.pressCount = pressCount;
+	}
+
 }

+ 0 - 2
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/Work.java

@@ -19,7 +19,6 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 
-import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.openjpa.persistence.PersistentCollection;
 import org.apache.openjpa.persistence.jdbc.ContainerTable;
@@ -34,7 +33,6 @@ import com.x.base.core.entity.annotation.ContainerEntity;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.tools.DateTools;
-import com.x.base.core.project.tools.ListTools;
 import com.x.base.core.project.tools.StringTools;
 import com.x.processplatform.core.entity.PersistenceProperties;
 import com.x.processplatform.core.entity.element.ActivityType;

+ 45 - 0
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Manual.java

@@ -489,6 +489,12 @@ public class Manual extends Activity {
 	@Column(name = ColumnNamePrefix + allowAddSplit_FIELDNAME)
 	private Boolean allowAddSplit;
 
+	public static final String allowPress_FIELDNAME = "allowPress";
+	@FieldDescribe("允许提醒.")
+	@CheckPersist(allowEmpty = true)
+	@Column(name = ColumnNamePrefix + allowPress_FIELDNAME)
+	private Boolean allowPress;
+
 	public static final String group_FIELDNAME = "group";
 	@FieldDescribe("分组")
 	@CheckPersist(allowEmpty = true)
@@ -555,6 +561,21 @@ public class Manual extends Activity {
 	@CheckPersist(allowEmpty = true)
 	private String manualStayScriptText;
 
+//	public static final String manualPressScript_FIELDNAME = "manualPressScript";
+//	@IdReference(Script.class)
+//	@FieldDescribe("提醒内容脚本.")
+//	@Column(length = length_255B, name = ColumnNamePrefix + manualPressScript_FIELDNAME)
+//	@CheckPersist(allowEmpty = true)
+//	private String manualPressScript;
+//
+//	public static final String manualPressScriptText_FIELDNAME = "manualPressScriptText";
+//	@FieldDescribe("提醒内容脚本文本.")
+//	@Lob
+//	@Basic(fetch = FetchType.EAGER)
+//	@Column(length = JpaObject.length_1M, name = ColumnNamePrefix + manualPressScriptText_FIELDNAME)
+//	@CheckPersist(allowEmpty = true)
+//	private String manualPressScriptText;
+
 	public String getName() {
 		return name;
 	}
@@ -1111,4 +1132,28 @@ public class Manual extends Activity {
 		this.allowAddSplit = allowAddSplit;
 	}
 
+	public Boolean getAllowPress() {
+		return allowPress;
+	}
+
+	public void setAllowPress(Boolean allowPress) {
+		this.allowPress = allowPress;
+	}
+
+//	public String getManualPressScript() {
+//		return manualPressScript;
+//	}
+//
+//	public void setManualPressScript(String manualPressScript) {
+//		this.manualPressScript = manualPressScript;
+//	}
+//
+//	public String getManualPressScriptText() {
+//		return manualPressScriptText;
+//	}
+//
+//	public void setManualPressScriptText(String manualPressScriptText) {
+//		this.manualPressScriptText = manualPressScriptText;
+//	}
+
 }

+ 7 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/MessageFactory.java

@@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.message.MessageConnector;
+import com.x.base.core.project.organization.OrganizationDefinition;
 import com.x.base.core.project.tools.DateTools;
 import com.x.base.core.project.tools.StringTools;
 import com.x.processplatform.core.entity.content.Read;
@@ -15,6 +16,12 @@ import com.x.processplatform.core.entity.content.Work;
 
 public class MessageFactory {
 
+	public static void task_press(Task task, String from) throws Exception {
+		String title = OrganizationDefinition.name(from) + "提醒您处理待办:" + adjustTitle(task);
+		title = StringTools.utf8SubString(title, JpaObject.length_255B);
+		MessageConnector.send(MessageConnector.TYPE_TASK_PRESS, title, task.getPerson(), task);
+	}
+
 	public static void task_urge(Task task) throws Exception {
 		String title = "您的待办即将超时:" + adjustTitle(task);
 		title = StringTools.utf8SubString(title, JpaObject.length_255B);

+ 0 - 37
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/ScriptHelperFactory.java

@@ -18,14 +18,6 @@ public class ScriptHelperFactory {
 
 	public static String initialScriptText;
 
-//	private static final String data_binding_name = "data";
-//	private static final String workContext_binding_name = "workContext";
-//	private static final String organization_binding_name = "organization";
-//	private static final String webservicesClient_binding_name = "webservicesClient";
-//	private static final String dictionary_binding_name = "dictionary";
-//	private static final String lookup_binding_name = "lookup";
-//	private static final String applications_binding_name = "applications";
-
 	public static ScriptHelper create(AeiObjects aeiObjects, BindingPair... bindingPairs) throws Exception {
 		WorkContext workContext = new WorkContext(aeiObjects);
 		Map<String, Object> map = new HashMap<>();
@@ -52,35 +44,6 @@ public class ScriptHelperFactory {
 		return sh;
 	}
 
-	/**
-	 * 用于单独生成脚本运行环境,ManualBeforeTaskScript,ManualAfterTaskScript
-	 * 
-	 * @param business
-	 * @param work
-	 * @param data
-	 * @param activity
-	 * @param bindingPairs
-	 * @return
-	 * @throws Exception
-	 */
-//	public static ScriptHelper create(Business business, Work work, Data data, Activity activity,
-//			BindingPair... bindingPairs) throws Exception {
-//		WorkContext workContext = new WorkContext(business, work, activity);
-//		Map<String, Object> map = new HashMap<>();
-//		map.put(ScriptingEngine.BINDINGNAME_WORKCONTEXT, workContext);
-//		map.put(ScriptingEngine.BINDINGNAME_DATA, data);
-//		map.put(ScriptingEngine.BINDINGNAME_ORGANIZATION, new Organization(ThisApplication.context()));
-//		map.put(ScriptingEngine.BINDINGNAME_WEBSERVICESCLIENT, new WebservicesClient());
-//		map.put(ScriptingEngine.BINDINGNAME_DICTIONARY,
-//				new ApplicationDictHelper(business.entityManagerContainer(), work.getApplication()));
-//		map.put(ScriptingEngine.BINDINGNAME_APPLICATIONS, ThisApplication.context().applications());
-//		for (BindingPair o : bindingPairs) {
-//			map.put(o.getName(), o.getValue());
-//		}
-//		ScriptHelper sh = new ScriptHelper(business, map, initialScriptText);
-//		return sh;
-//	}
-
 	public static ScriptHelper createWithTask(Business business, Work work, Data data, Activity activity, Task task,
 			BindingPair... bindingPairs) throws Exception {
 		WorkContext workContext = new WorkContext(business, work, activity, task);

+ 94 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/taskcompleted/ActionPress.java

@@ -0,0 +1,94 @@
+package com.x.processplatform.service.processing.jaxrs.taskcompleted;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.config.Config;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WrapStringList;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.DateTools;
+import com.x.base.core.project.tools.PropertyTools;
+import com.x.processplatform.core.entity.content.Data;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.element.Activity;
+import com.x.processplatform.core.entity.element.Manual;
+import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.MessageFactory;
+import com.x.processplatform.service.processing.WorkDataHelper;
+
+class ActionPress extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionPress.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, String workId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			TaskCompleted taskCompleted = emc.find(id, TaskCompleted.class);
+			if (null == taskCompleted) {
+				throw new ExceptionEntityNotExist(id, TaskCompleted.class);
+			}
+			Work work = emc.find(workId, Work.class);
+			if (null == work) {
+				throw new ExceptionEntityNotExist(workId, Work.class);
+			}
+
+			List<Task> list = emc.listEqual(Task.class, Task.work_FIELDNAME, work.getId());
+
+			Activity activity = business.element().getActivity(work.getActivity());
+
+			if (null == activity) {
+
+			}
+
+//			String script = PropertyTools.getOrElse(activity, Manual.manualPressScript_FIELDNAME, String.class, "");
+//
+//			String scriptText = PropertyTools.getOrElse(activity, Manual.manualPressScriptText_FIELDNAME, String.class,
+//					"");
+
+//			Data data = new WorkDataHelper(business.entityManagerContainer(), work).get();
+
+			Wo wo = new Wo();
+
+			for (Task task : list) {
+				MessageFactory.task_press(task, taskCompleted.getPerson());
+				wo.getValueList().add(task.getPerson());
+			}
+
+			emc.beginTransaction(TaskCompleted.class);
+			if (!StringUtils.equals(taskCompleted.getPressActivityToken(), work.getActivityToken())) {
+				taskCompleted.setPressTime(new Date());
+				taskCompleted.setPressActivityToken(work.getActivityToken());
+				taskCompleted.setPressCount(1);
+			} else {
+				if (DateTools.beforeNowMinutesNullIsFalse(taskCompleted.getPressTime(),
+						Config.processPlatform().getPress().getIntervalMinutes())) {
+					taskCompleted.setPressCount(taskCompleted.getPressCount() + 1);
+				} else {
+					taskCompleted.setPressTime(new Date());
+					taskCompleted.setPressActivityToken(work.getActivityToken());
+					taskCompleted.setPressCount(1);
+				}
+
+			}
+			emc.commit();
+			result.setData(wo);
+			return result;
+		}
+
+	}
+
+	public static class Wo extends WrapStringList {
+	}
+
+}

+ 22 - 1
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/taskcompleted/TaskCompletedAction.java

@@ -3,6 +3,7 @@ package com.x.processplatform.service.processing.jaxrs.taskcompleted;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -12,6 +13,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 
 import com.x.base.core.project.annotation.JaxrsMethodDescribe;
+import com.x.base.core.project.annotation.JaxrsParameterDescribe;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.http.HttpMediaType;
@@ -25,13 +27,32 @@ public class TaskCompletedAction extends StandardJaxrsAction {
 
 	private static Logger logger = LoggerFactory.getLogger(TaskCompletedAction.class);
 
+	@JaxrsMethodDescribe(value = "提醒.", action = ActionPress.class)
+	@GET
+	@Path("{id}/press/work/{work}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void press(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
+			@JaxrsParameterDescribe("标识") @PathParam("id") String id,
+			@JaxrsParameterDescribe("工作") @PathParam("work") String work) {
+		ActionResult<ActionPress.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new ActionPress().execute(effectivePerson, id, work);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getDefaultActionResultResponse(result));
+	}
+
 	@JaxrsMethodDescribe(value = "删除已办.", action = ActionDelete.class)
 	@DELETE
 	@Path("{id}")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
 	public void delete(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
-			@PathParam("id") String id) {
+			@JaxrsParameterDescribe("标识") @PathParam("id") String id) {
 		ActionResult<ActionDelete.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
 		try {

+ 4 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionAssignCreate.java

@@ -26,6 +26,8 @@ import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WoId;
+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 com.x.base.core.project.tools.StringTools;
 import com.x.processplatform.core.entity.content.Attachment;
@@ -52,6 +54,8 @@ import com.x.processplatform.service.processing.WorkDataHelper;
  */
 class ActionAssignCreate extends BaseAction {
 
+	private static Logger logger = LoggerFactory.getLogger(ActionAssignCreate.class);
+
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception {
 		ActionResult<Wo> result = new ActionResult<>();
 		String workId = "";

+ 189 - 58
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRetract.java

@@ -1,13 +1,17 @@
 package com.x.processplatform.service.processing.jaxrs.work;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.apache.commons.collections4.list.SetUniqueList;
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WoId;
@@ -21,10 +25,19 @@ import com.x.processplatform.core.entity.content.Task;
 import com.x.processplatform.core.entity.content.TaskCompleted;
 import com.x.processplatform.core.entity.content.Work;
 import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.core.entity.content.WorkStatus;
+import com.x.processplatform.core.entity.element.Application;
+import com.x.processplatform.core.entity.element.Process;
+import com.x.processplatform.core.entity.element.util.WorkLogTree;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Node;
+import com.x.processplatform.core.entity.element.util.WorkLogTree.Nodes;
 import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.MessageFactory;
 import com.x.processplatform.service.processing.Processing;
 import com.x.processplatform.service.processing.ProcessingAttributes;
 import com.x.processplatform.service.processing.configurator.ProcessingConfigurator;
+import com.x.processplatform.service.processing.jaxrs.work.ActionRollback.Wi;
+import com.x.processplatform.service.processing.jaxrs.work.ActionRollback.Wo;
 
 /**
  * 根据WorkLogId进行召回
@@ -38,93 +51,211 @@ class ActionRetract extends BaseAction {
 
 	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, String workLogId) throws Exception {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+
 			ActionResult<Wo> result = new ActionResult<>();
+
 			Business business = new Business(emc);
-			Work work = null;
-			WorkLog workLog = null;
-			work = emc.find(id, Work.class);
+
+			Work work = emc.find(id, Work.class);
+
 			if (null == work) {
-				throw new ExceptionWorkNotExist(id);
+				throw new ExceptionEntityNotExist(id, Work.class);
 			}
-			workLog = emc.find(workLogId, WorkLog.class);
+
+			Application application = business.element().get(work.getApplication(), Application.class);
+
+			if (null == application) {
+				throw new ExceptionEntityNotExist(work.getApplication(), Application.class);
+			}
+
+			Process process = business.element().get(work.getProcess(), Process.class);
+
+			if (null == process) {
+				throw new ExceptionEntityNotExist(work.getProcess(), Process.class);
+			}
+
+			WorkLog workLog = emc.find(workLogId, WorkLog.class);
+
 			if (null == workLog) {
-				throw new ExceptionWorkLogNotExist(workLogId);
+				throw new ExceptionEntityNotExist(workLogId, WorkLog.class);
 			}
-			if (!StringUtils.equals(work.getJob(), workLog.getJob())) {
-				throw new ExceptionWorkNotMatchWithWorkLog(work.getTitle(), work.getId(), work.getJob(),
-						workLog.getId(), workLog.getJob());
+
+			if (BooleanUtils.isTrue(workLog.getSplitting())) {
+				throw new ExceptionSplittingNotRollback(work.getId(), workLog.getId());
 			}
-			List<Work> works = this.listForwardWork(business, workLog);
+
+			List<WorkLog> workLogs = emc.listEqual(WorkLog.class, WorkLog.job_FIELDNAME, workLog.getJob());
+
+			WorkLogTree workLogTree = new WorkLogTree(workLogs);
+
+			Node node = workLogTree.find(workLog);
+
+			Nodes nodes = workLogTree.rootTo(node);
+
 			emc.beginTransaction(Work.class);
+			emc.beginTransaction(WorkLog.class);
 			emc.beginTransaction(Task.class);
 			emc.beginTransaction(TaskCompleted.class);
 			emc.beginTransaction(Read.class);
 			emc.beginTransaction(ReadCompleted.class);
 			emc.beginTransaction(Review.class);
-			emc.beginTransaction(WorkLog.class);
-			for (Work o : works) {
-				this.cleanComplex(business, o);
-				if (!StringUtils.equals(work.getId(), o.getId())) {
-					business.entityManagerContainer().remove(o);
-				}
-			}
-			this.retractAsWorkLog(work, workLog);
-			emc.delete(WorkLog.class,
-					business.workLog().listWithFromActivityTokenForward(workLog.getFromActivityToken()));
+
+			this.rollbackWork(work, workLog);
+
+			this.disconnectWorkLog(work, workLog);
+
+			this.rollbackTask(business, emc.listEqual(Task.class, Task.job_FIELDNAME, work.getJob()));
+
+			this.rollbackTaskCompleted(business, work, nodes, workLog,
+					emc.listEqual(TaskCompleted.class, TaskCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackRead(business, work, nodes, workLog,
+					emc.listEqual(Read.class, Read.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReadCompleted(business, work, nodes, workLog,
+					emc.listEqual(ReadCompleted.class, ReadCompleted.job_FIELDNAME, work.getJob()));
+
+			this.rollbackReview(business, nodes, emc.listEqual(Review.class, Review.job_FIELDNAME, work.getJob()));
+
+			this.rollbackWorkLog(business, work, nodes, workLogs);
+
 			emc.commit();
+
 			Processing processing = new Processing(0, new ProcessingAttributes(), emc);
-			ProcessingConfigurator processingConfigurator = new ProcessingConfigurator();
-			processingConfigurator.setContinueLoop(false);
-			processingConfigurator.setActivityCreateRead(false);
-			processingConfigurator.setActivityCreateReview(false);
-			processingConfigurator.setChangeActivityToken(false);
-			processingConfigurator.setJoinAtExecute(false);
-			processingConfigurator.setActivityStampArrivedWorkLog(false);
-			processing.processing(work.getId(), processingConfigurator);
+			processing.processing(work.getId());
 			Wo wo = new Wo();
-			wo.setId(id);
+			wo.setId(work.getId());
 			result.setData(wo);
 			return result;
 		}
 	}
 
-	public static class Wo extends WoId {
+	private void rollbackWork(Work work, WorkLog workLog) throws Exception {
+		work.setSplitting(false);
+		work.setActivityName(workLog.getFromActivityName());
+		work.setManualTaskIdentityList(new ArrayList<String>());
+		work.setActivity(workLog.getFromActivity());
+		work.setActivityAlias(workLog.getFromActivityAlias());
+		work.setActivityArrivedTime(workLog.getFromTime());
+		work.setActivityDescription("");
+		work.setActivityToken(workLog.getFromActivityToken());
+		work.setActivityType(workLog.getFromActivityType());
+		work.setErrorRetry(0);
+		work.setWorkStatus(WorkStatus.processing);
+	}
 
+	private void disconnectWorkLog(Work work, WorkLog workLog) {
+		workLog.setConnected(false);
+		workLog.setArrivedActivity("");
+		workLog.setArrivedActivityAlias("");
+		workLog.setArrivedActivityName("");
+		workLog.setArrivedActivityToken("");
+		workLog.setArrivedActivityType(null);
+		workLog.setArrivedTime(null);
+		workLog.setDuration(0L);
+		workLog.setWorkCompleted("");
+		workLog.setWork(work.getId());
 	}
 
-	private void cleanComplex(Business business, Work work) throws Exception {
-		business.entityManagerContainer().delete(Task.class,
-				business.task().listWithActivityToken(work.getActivityToken()));
-		business.entityManagerContainer().delete(TaskCompleted.class,
-				business.taskCompleted().listWithActivityToken(work.getActivityToken()));
-		business.entityManagerContainer().delete(Read.class,
-				business.read().listWithActivityToken(work.getActivityToken()));
-		business.entityManagerContainer().delete(ReadCompleted.class,
-				business.readCompleted().listWithActivityToken(work.getActivityToken()));
-		// business.entityManagerContainer().delete(Review.class,
-		// business.review().listWithActivityToken(work.getActivityToken()));
+	private void rollbackTask(Business business, List<Task> list) throws Exception {
+		for (Task o : list) {
+			business.entityManagerContainer().remove(o);
+			MessageFactory.task_delete(o);
+		}
 	}
 
-	private List<Work> listForwardWork(Business business, WorkLog workLog) throws Exception {
-		List<String> ids = business.workLog()
-				.listWithFromActivityTokenForwardNotConnected(workLog.getFromActivityToken());
-		List<String> activityTokens = SetUniqueList.setUniqueList(new ArrayList<String>());
-		for (WorkLog o : business.entityManagerContainer().fetch(ids, WorkLog.class,
-				ListTools.toList(WorkLog.fromActivityToken_FIELDNAME))) {
-			activityTokens.add(o.getFromActivityToken());
+	private void rollbackTaskCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<TaskCompleted> list) throws Exception {
+		for (TaskCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.taskCompleted_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setCompletedTime(null);
+				o.setCompletedTimeMonth("");
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
 		}
-		List<String> workIds = business.work().listWithActivityToken(activityTokens);
-		return business.entityManagerContainer().list(Work.class, workIds);
 	}
 
-	private void retractAsWorkLog(Work work, WorkLog workLog) throws Exception {
-		work.setDestinationActivity(workLog.getFromActivity());
-		work.setDestinationActivityType(workLog.getFromActivityType());
-		work.setActivityToken(workLog.getFromActivityToken());
-		work.setSplitting(workLog.getSplitting());
-		work.setSplitValue(workLog.getSplitValue());
-		work.setSplitToken(workLog.getSplitToken());
-		work.setSplitTokenList(workLog.getSplitTokenList());
+	private void rollbackRead(Business business, Work work, Nodes nodes, WorkLog workLog, List<Read> list)
+			throws Exception {
+		for (Read o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.read_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReadCompleted(Business business, Work work, Nodes nodes, WorkLog workLog,
+			List<ReadCompleted> list) throws Exception {
+		for (ReadCompleted o : list) {
+			if (!nodes.containsWorkLogWithActivityToken(o.getActivityToken())
+					|| StringUtils.equals(o.getActivityToken(), workLog.getFromActivityToken())) {
+				business.entityManagerContainer().remove(o);
+				MessageFactory.readCompleted_delete(o);
+			} else {
+				o.setCompleted(false);
+				o.setCompletedTime(null);
+				o.setCompletedTimeMonth("");
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	private void rollbackReview(Business business, Nodes nodes, List<Review> list) throws Exception {
+		Date date = nodes.latestArrivedTime();
+		if (null != date) {
+			for (Review o : list) {
+				if (null != o.getStartTime() && o.getStartTime().after(date)) {
+					business.entityManagerContainer().remove(o);
+					MessageFactory.review_delete(o);
+				} else {
+					o.setCompleted(false);
+					o.setCompletedTime(null);
+					o.setCompletedTimeMonth("");
+				}
+			}
+		}
+	}
+
+	private void rollbackWorkLog(Business business, Work work, Nodes nodes, List<WorkLog> list) throws Exception {
+		for (WorkLog o : list) {
+			if (!nodes.containsWorkLog(o)) {
+				business.entityManagerContainer().remove(o);
+			} else {
+				o.setCompleted(false);
+				o.setWorkCompleted("");
+				o.setWork(work.getId());
+			}
+		}
+	}
+
+	public static class Wi extends ProcessingAttributes {
+
+		@FieldDescribe("工作日志标识")
+		private String workLog;
+
+		public String getWorkLog() {
+			return workLog;
+		}
+
+		public void setWorkLog(String workLog) {
+			this.workLog = workLog;
+		}
+
 	}
 
+	public static class Wo extends WoId {
+	}
 }

+ 130 - 0
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/jaxrs/work/ActionRetractBack.java

@@ -0,0 +1,130 @@
+package com.x.processplatform.service.processing.jaxrs.work;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.collections4.list.SetUniqueList;
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.jaxrs.WoId;
+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 com.x.processplatform.core.entity.content.Read;
+import com.x.processplatform.core.entity.content.ReadCompleted;
+import com.x.processplatform.core.entity.content.Review;
+import com.x.processplatform.core.entity.content.Task;
+import com.x.processplatform.core.entity.content.TaskCompleted;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.content.WorkLog;
+import com.x.processplatform.service.processing.Business;
+import com.x.processplatform.service.processing.Processing;
+import com.x.processplatform.service.processing.ProcessingAttributes;
+import com.x.processplatform.service.processing.configurator.ProcessingConfigurator;
+
+/**
+ * 根据WorkLogId进行召回
+ * 
+ * @author Rui
+ *
+ */
+class ActionRetractBack extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(ActionRetractBack.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String id, String workLogId) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			Work work = null;
+			WorkLog workLog = null;
+			work = emc.find(id, Work.class);
+			if (null == work) {
+				throw new ExceptionWorkNotExist(id);
+			}
+			workLog = emc.find(workLogId, WorkLog.class);
+			if (null == workLog) {
+				throw new ExceptionWorkLogNotExist(workLogId);
+			}
+			if (!StringUtils.equals(work.getJob(), workLog.getJob())) {
+				throw new ExceptionWorkNotMatchWithWorkLog(work.getTitle(), work.getId(), work.getJob(),
+						workLog.getId(), workLog.getJob());
+			}
+			List<Work> works = this.listForwardWork(business, workLog);
+			emc.beginTransaction(Work.class);
+			emc.beginTransaction(Task.class);
+			emc.beginTransaction(TaskCompleted.class);
+			emc.beginTransaction(Read.class);
+			emc.beginTransaction(ReadCompleted.class);
+			emc.beginTransaction(Review.class);
+			emc.beginTransaction(WorkLog.class);
+			for (Work o : works) {
+				this.cleanComplex(business, o);
+				if (!StringUtils.equals(work.getId(), o.getId())) {
+					business.entityManagerContainer().remove(o);
+				}
+			}
+			this.retractAsWorkLog(work, workLog);
+			emc.delete(WorkLog.class,
+					business.workLog().listWithFromActivityTokenForward(workLog.getFromActivityToken()));
+			emc.commit();
+			Processing processing = new Processing(0, new ProcessingAttributes(), emc);
+			ProcessingConfigurator processingConfigurator = new ProcessingConfigurator();
+			processingConfigurator.setContinueLoop(false);
+			processingConfigurator.setActivityCreateRead(false);
+			processingConfigurator.setActivityCreateReview(false);
+			processingConfigurator.setChangeActivityToken(false);
+			processingConfigurator.setJoinAtExecute(false);
+			processingConfigurator.setActivityStampArrivedWorkLog(false);
+			processing.processing(work.getId(), processingConfigurator);
+			Wo wo = new Wo();
+			wo.setId(id);
+			result.setData(wo);
+			return result;
+		}
+	}
+
+	public static class Wo extends WoId {
+
+	}
+
+	private void cleanComplex(Business business, Work work) throws Exception {
+		business.entityManagerContainer().delete(Task.class,
+				business.task().listWithActivityToken(work.getActivityToken()));
+		business.entityManagerContainer().delete(TaskCompleted.class,
+				business.taskCompleted().listWithActivityToken(work.getActivityToken()));
+		business.entityManagerContainer().delete(Read.class,
+				business.read().listWithActivityToken(work.getActivityToken()));
+		business.entityManagerContainer().delete(ReadCompleted.class,
+				business.readCompleted().listWithActivityToken(work.getActivityToken()));
+		// business.entityManagerContainer().delete(Review.class,
+		// business.review().listWithActivityToken(work.getActivityToken()));
+	}
+
+	private List<Work> listForwardWork(Business business, WorkLog workLog) throws Exception {
+		List<String> ids = business.workLog()
+				.listWithFromActivityTokenForwardNotConnected(workLog.getFromActivityToken());
+		List<String> activityTokens = SetUniqueList.setUniqueList(new ArrayList<String>());
+		for (WorkLog o : business.entityManagerContainer().fetch(ids, WorkLog.class,
+				ListTools.toList(WorkLog.fromActivityToken_FIELDNAME))) {
+			activityTokens.add(o.getFromActivityToken());
+		}
+		List<String> workIds = business.work().listWithActivityToken(activityTokens);
+		return business.entityManagerContainer().list(Work.class, workIds);
+	}
+
+	private void retractAsWorkLog(Work work, WorkLog workLog) throws Exception {
+		work.setDestinationActivity(workLog.getFromActivity());
+		work.setDestinationActivityType(workLog.getFromActivityType());
+		work.setActivityToken(workLog.getFromActivityToken());
+		work.setSplitting(workLog.getSplitting());
+		work.setSplitValue(workLog.getSplitValue());
+		work.setSplitToken(workLog.getSplitToken());
+		work.setSplitTokenList(workLog.getSplitTokenList());
+	}
+
+}

+ 7 - 2
o2server/x_processplatform_service_processing/src/main/java/com/x/processplatform/service/processing/processor/AeiObjects.java

@@ -799,8 +799,13 @@ public class AeiObjects extends GsonPropertyObject {
 	private void commitData() throws Exception {
 		List<Attachment> os = ListUtils.subtract(this.getAttachments(), this.getDeleteAttachments());
 		os = ListUtils.sum(os, this.getCreateAttachments());
-		this.getWorkDataHelper()
-				.update(this.getData().removeWork().removeAttachmentList().setWork(this.work).setAttachmentList(os));
+		Data data = this.getData().removeWork().removeAttachmentList().setAttachmentList(os);
+		if (ListTools.isNotEmpty(this.createWorkCompleteds)) {
+			data.setWork(this.createWorkCompleteds.get(0));
+		} else {
+			data.setWork(this.work);
+		}
+		this.getWorkDataHelper().update(data);
 	}
 
 	public List<Work> getUpdateWorks() {

Некоторые файлы не были показаны из-за большого количества измененных файлов