Просмотр исходного кода

Merge branch 'wrdp' into 'develop'

Wrdp

See merge request o2oa/o2oa!3036
胡起 4 лет назад
Родитель
Сommit
87187a4eb1
87 измененных файлов с 1984 добавлено и 243 удалено
  1. 54 0
      o2server/configSample/mock.json
  2. 2 3
      o2server/configSample/web.json
  3. 14 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Config.java
  4. 100 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/WebServers.java
  5. 4 8
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/BaseTools.java
  6. 64 18
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionPersistPublishContent.java
  7. 7 0
      o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java
  8. 3 96
      o2server/x_console/src/main/java/com/x/server/console/server/web/WebServerTools.java
  9. 4 4
      o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/view/ActionCreate.java
  10. 4 5
      o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/view/ActionEdit.java
  11. 10 8
      o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/FilterEntry.java
  12. 53 24
      o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/Plan.java
  13. 20 1
      o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/Row.java
  14. 8 0
      o2web/gulpfile.js
  15. 3 1
      o2web/source/o2_core/o2/widget/Calendar.js
  16. 3 0
      o2web/source/o2_core/o2/xDesktop/$Default/blue/layout-menu-pc.html
  17. 72 0
      o2web/source/o2_core/o2/xDesktop/$Default/blue/style-pc.css
  18. 1 1
      o2web/source/o2_core/o2/xDesktop/$Layout/quickStart.json
  19. 544 55
      o2web/source/o2_core/o2/xDesktop/Default.js
  20. 4 4
      o2web/source/x_component_AppCenter/Main.js
  21. 1 1
      o2web/source/x_component_File/lp/zh-cn.js
  22. 2 2
      o2web/source/x_component_Homepage/lp/zh-cn.js
  23. 26 1
      o2web/source/x_component_cms_Xform/Htmleditor.js
  24. 5 0
      o2web/source/x_component_portal_PageDesigner/$Main/default/tools.json
  25. 38 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/datagrid$Data.html
  26. 51 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/css.wcss
  27. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/copy.png
  28. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/copy1.png
  29. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/delete.png
  30. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/delete1.png
  31. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteCol.png
  32. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteCol1.png
  33. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteRow.png
  34. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteRow1.png
  35. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertCol.png
  36. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertCol1.png
  37. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertRow.png
  38. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertRow1.png
  39. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/mergerCell.png
  40. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/move.png
  41. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/move1.png
  42. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/splitCell.png
  43. 16 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/insertCol.html
  44. 16 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/insertRow.html
  45. 17 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/mergerCell.html
  46. 72 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/template.json
  47. 53 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/datagrid$Title.html
  48. 49 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/css.wcss
  49. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/copy.png
  50. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/copy1.png
  51. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/delete.png
  52. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/delete1.png
  53. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteCol.png
  54. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteCol1.png
  55. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteRow.png
  56. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteRow1.png
  57. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertCol.png
  58. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertCol1.png
  59. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertRow.png
  60. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertRow1.png
  61. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/mergerCell.png
  62. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/move.png
  63. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/move1.png
  64. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/splitCell.png
  65. 16 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/insertCol.html
  66. 16 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/insertRow.html
  67. 17 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/mergerCell.html
  68. 72 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/template.json
  69. 29 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid.js
  70. 28 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/__datagrid1.html
  71. 64 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/__template.json
  72. 163 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/datagrid.html
  73. 34 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/datagridCreate.html
  74. 81 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/css.wcss
  75. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/copy.png
  76. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/copy1.png
  77. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/delete.png
  78. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/delete1.png
  79. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/mergerCell.png
  80. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/move.png
  81. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/move1.png
  82. BIN
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/splitCell.png
  83. 130 0
      o2web/source/x_component_portal_PageDesigner/Module/Datagrid/template.json
  84. 3 0
      o2web/source/x_component_portal_PageDesigner/Module/Org/org.html
  85. 2 1
      o2web/source/x_component_portal_PageDesigner/Module/Package.js
  86. 8 4
      o2web/source/x_component_portal_Portal/Main.js
  87. 1 1
      o2web/source/x_desktop/sso.html

+ 54 - 0
o2server/configSample/mock.json

@@ -0,0 +1,54 @@
+{
+  "mock": {
+    "x_processplatform_assemble_surface": {
+      "put": {
+        "to": "post",
+        "append": "mockputtopost"
+      },
+      "delete": {
+        "to": "get",
+        "append": "mockdeletetoget"
+      }
+    },
+    "x_cms_assemble_control": {
+      "put": {
+        "to": "post",
+        "append": "mockputtopost"
+      },
+      "delete": {
+        "to": "get",
+        "append": "mockdeletetoget"
+      }
+    },
+    "x_query_assemble_surface": {
+      "put": {
+        "to": "post",
+        "append": "mockputtopost"
+      },
+      "delete": {
+        "to": "get",
+        "append": "mockdeletetoget"
+      }
+    },
+    "x_organization_assemble_authentication": {
+      "put": {
+        "to": "post",
+        "append": "mockputtopost"
+      },
+      "delete": {
+        "to": "get",
+        "append": "mockdeletetoget"
+      }
+    },
+    "x_organization_assemble_personal": {
+      "put": {
+        "to": "post",
+        "append": "mockputtopost"
+      },
+      "delete": {
+        "to": "get",
+        "append": "mockdeletetoget"
+      }
+    }
+  }
+}

+ 2 - 3
o2server/configSample/web.json

@@ -1,4 +1,3 @@
 {
-  "mock": {},
-  "###mock": "使用Post模拟Put,Get模拟Delete的模块.###"
-}
+  "###web": "web端使用到的全局参数配置,没有特定业务含义,满足json格式即可.###"
+}

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

@@ -81,6 +81,7 @@ public class Config {
 	public static final String PATH_CONFIG_COMPONENTS = "config/components.json";
 	public static final String PATH_CONFIG_EMAIL = "config/email.json";
 	public static final String PATH_CONFIG_WEB = "config/web.json";
+	public static final String PATH_CONFIG_MOCK = "config/mock.json";
 
 	public static final String DIR_COMMONS = "commons";
 	public static final String DIR_COMMONS_TESS4J_TESSDATA = "commons/tess4j/tessdata";
@@ -1176,6 +1177,19 @@ public class Config {
 		return instance().web;
 	}
 
+	public JsonObject mock;
+
+	public static synchronized JsonObject mock() throws Exception {
+		if (null == instance().mock) {
+			JsonObject obj = BaseTools.readConfigObject(PATH_CONFIG_MOCK, JsonObject.class);
+			if (null == obj) {
+				obj = new JsonObject();
+			}
+			instance().mock = obj;
+		}
+		return instance().mock;
+	}
+
 	public Map<String, JsonObject> customConfig = new HashMap<>();
 
 	public static synchronized JsonObject customConfig(String configName) throws Exception {

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

@@ -1,21 +1,28 @@
 package com.x.base.core.project.config;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Random;
+import java.io.File;
+import java.util.*;
 import java.util.concurrent.ConcurrentSkipListMap;
 
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.x.base.core.project.gson.XGsonBuilder;
+import com.x.base.core.project.tools.DefaultCharset;
+import com.x.base.core.project.tools.Host;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.ObjectUtils;
 
 import com.x.base.core.project.tools.ListTools;
+import org.apache.commons.lang3.StringUtils;
 
 public class WebServers extends ConcurrentSkipListMap<String, WebServer> {
 
 	private static final long serialVersionUID = -706102090064680898L;
 
+	private static final String MAP_LOGINPAGE = "loginPage";
+
 	public WebServers() {
 		super();
 	}
@@ -66,4 +73,92 @@ public class WebServers extends ConcurrentSkipListMap<String, WebServer> {
 		});
 	}
 
+	public static void updateWebServerConfigJson() throws Exception {
+		File dir = new File(Config.base(), "servers/webServer/x_desktop/res/config");
+		FileUtils.forceMkdir(dir);
+		File file = new File(dir, "config.json");
+
+		Gson gson = XGsonBuilder.instance();
+
+		LinkedHashMap<String, Object> map = new LinkedHashMap<>();
+		/** 覆盖掉配置的参数 */
+		com.x.base.core.project.config.CenterServer centerServerConfig = Config.nodes().centerServers().first()
+				.getValue();
+		map.putAll(centerServerConfig.getConfig());
+		List<Map<String, String>> centers = new ArrayList<>();
+		map.put("center", centers);
+		/** 写入center地址 */
+		Map<String, String> center = new HashMap<String, String>();
+		center = new HashMap<String, String>();
+		center.put("host", "");
+		center.put("port", centerServerConfig.getPort().toString());
+		centers.add(center);
+		if (!Objects.equals(centerServerConfig.getProxyPort(), centerServerConfig.getPort())) {
+			center = new HashMap<String, String>();
+			center.put("host", "");
+			center.put("port", centerServerConfig.getProxyPort().toString());
+			centers.add(center);
+		}
+		String host = Config.nodes().primaryCenterNode();
+		if (!Host.isRollback(host)) {
+			center = new HashMap<String, String>();
+			center.put("host", host);
+			center.put("port", centerServerConfig.getPort().toString());
+			centers.add(center);
+		}
+		/** 写入proxy地址 */
+		if (StringUtils.isNotEmpty(centerServerConfig.getProxyHost())) {
+			center = new HashMap<String, String>();
+			center.put("host", centerServerConfig.getProxyHost());
+			center.put("port", centerServerConfig.getProxyPort().toString());
+			centers.add(center);
+		}
+
+		/** 写入systemName */
+		map.put("footer", Config.collect().getFooter());
+		map.put("title", Config.collect().getTitle());
+		map.put("appUrl", Config.collect().getAppUrl());
+		/***/
+		if (centerServerConfig.getSslEnable()) {
+			map.put("app_protocol", "https:");
+		} else {
+			map.put("app_protocol", "http:");
+		}
+		/* 上面的无效 */
+		map.put("app_protocol", "auto");
+		if ((null != Config.portal().getLoginPage())
+				&& (BooleanUtils.isTrue(Config.portal().getLoginPage().getEnable()))) {
+			map.put(MAP_LOGINPAGE, Config.portal().getLoginPage());
+		} else if ((null != Config.person().getLoginPage())
+				&& (BooleanUtils.isTrue(Config.person().getLoginPage().getEnable()))) {
+			map.put(MAP_LOGINPAGE, Config.person().getLoginPage());
+		} else {
+			map.put(MAP_LOGINPAGE, Config.portal().getLoginPage());
+		}
+		map.put("indexPage", Config.portal().getIndexPage());
+		map.put("webSocketEnable", Config.communicate().wsEnable());
+		map.put("urlMapping", Config.portal().getUrlMapping());
+
+		/* 密码规则 */
+		map.put("passwordRegex", Config.person().getPasswordRegex());
+		map.put("passwordRegexHint", Config.person().getPasswordRegexHint());
+
+		/* RSA */
+		File publicKeyFile = new File(Config.base(), "config/public.key");
+		if (publicKeyFile.exists() && publicKeyFile.isFile()) {
+			String publicKey = FileUtils.readFileToString(publicKeyFile, "utf-8");
+			byte[] publicKeyB = org.apache.commons.codec.binary.Base64.decodeBase64(publicKey);
+			publicKey = new String(Base64.encodeBase64(publicKeyB));
+			map.put("publicKey", publicKey);
+		}
+
+		for (Entry<String, JsonElement> en : Config.web().entrySet()) {
+			map.put(en.getKey(), en.getValue());
+		}
+		for (Entry<String, JsonElement> en : Config.mock().entrySet()) {
+			map.put(en.getKey(), en.getValue());
+		}
+		FileUtils.writeStringToFile(file, gson.toJson(map), DefaultCharset.charset);
+	}
+
 }

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

@@ -145,16 +145,12 @@ public class BaseTools {
 	public  static boolean executeSyncFile(String syncFilePath) throws Exception {
 
 		boolean Syncflag = false;
-		String localip = getIpAddress();
 		Nodes nodes = Config.nodes();
 		//同步config文件
 		if(Config.nodes().centerServers().first().getValue().getConfigApiEnable()) {
 			for (String node : nodes.keySet()) {
-				//其他服务器
-				if (!node.equalsIgnoreCase(localip)) {
-					if (nodes.get(node).getApplication().getEnable() || nodes.get(node).getCenter().getEnable()) {
-						Syncflag = executeSyncFile(syncFilePath, node, nodes.get(node).nodeAgentPort());
-					}
+				if (nodes.get(node).getApplication().getEnable() || nodes.get(node).getCenter().getEnable()) {
+					Syncflag = executeSyncFile(syncFilePath, node, nodes.get(node).nodeAgentPort());
 				}
 			}
 		}
@@ -172,7 +168,7 @@ public class BaseTools {
 			fileInputStream= new FileInputStream(syncFile);
 
 			socket.setKeepAlive(true);
-			socket.setSoTimeout(5000);
+			socket.setSoTimeout(2000);
 			DataOutputStream dos = null;
 			DataInputStream dis  = null;
 			try {
@@ -236,4 +232,4 @@ public class BaseTools {
 		}
 		return "";
 	}
-}
+}

+ 64 - 18
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/document/ActionPersistPublishContent.java

@@ -201,7 +201,7 @@ public class ActionPersistPublishContent extends BaseAction {
 						wi.setCreatorIdentity( userManagerService.getMajorIdentityWithPerson( wi.getCreatorPerson() ) );
 					}
 				}
-				
+
 				if ( !StringUtils.equals(  "cipher", wi.getCreatorIdentity() ) && !StringUtils.equals(  "xadmin", wi.getCreatorIdentity() )) {
 					//说明是实际的用户,并不使用cipher和xadmin代替
 					if (StringUtils.isNotEmpty( wi.getCreatorIdentity() )) {
@@ -283,8 +283,44 @@ public class ActionPersistPublishContent extends BaseAction {
 			}
 		}
 
+		//从CMS其他文档中复制所有的附件到CMS
 		if (check) {
-			try {				
+			if ( wi.getCms_attachmentIds() != null && wi.getCms_attachmentIds().length > 0 ) {
+				FileInfo fileInfo = null;
+				FileInfo copyFileInfo = null;
+				StorageMapping mapping_attachment = null;
+				StorageMapping mapping_fileInfo = null;
+				byte[] attachment_content = null;
+				for (String attachmentId : wi.getCms_attachmentIds()) {
+					try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+						document = emc.find(document.getId(), Document.class, ExceptionWhen.not_found);
+						copyFileInfo = emc.find(attachmentId, FileInfo.class, ExceptionWhen.not_found);
+						if (copyFileInfo != null) {
+							emc.beginTransaction(FileInfo.class);
+							emc.beginTransaction(Document.class);
+
+							mapping_attachment = ThisApplication.context().storageMappings().get(FileInfo.class, copyFileInfo.getStorage());
+							attachment_content = copyFileInfo.readContent(mapping_attachment);
+
+							mapping_fileInfo = ThisApplication.context().storageMappings().random(FileInfo.class);
+							fileInfo = concreteFileInfo(effectivePerson.getDistinguishedName(), document, mapping_fileInfo, copyFileInfo.getName(), copyFileInfo.getSite());
+							fileInfo.saveContent(mapping_fileInfo, attachment_content, copyFileInfo.getName());
+							fileInfo.setName(copyFileInfo.getName());
+							emc.check(document, CheckPersistType.all);
+							emc.persist(fileInfo, CheckPersistType.all);
+
+							emc.commit();
+						}
+					} catch (Throwable th) {
+						th.printStackTrace();
+						result.error(th);
+					}
+				}
+			}
+		}
+
+		if (check) {
+			try {
 				Wo wo = new Wo();
 				wo.setId( document.getId() );
 				result.setData( wo );
@@ -397,7 +433,7 @@ public class ActionPersistPublishContent extends BaseAction {
 				if( categoryInfo.getSendNotify() == null ) {
 					if( StringUtils.equals("信息", categoryInfo.getDocumentType()) ) {
 						notify = true;
-					}						
+					}
 				}else {
 					if( categoryInfo.getSendNotify() ) {
 						notify = true;
@@ -454,40 +490,43 @@ public class ActionPersistPublishContent extends BaseAction {
 	}
 
 	public static class Wi {
-		
+
 		public static WrapCopier<Wi, Document> copier = WrapCopierFactory.wi( Wi.class, Document.class, null, null);
 
 		private String id = null;
 
 		@FieldDescribe( "文档操作者身份" )
 		private String identity = null;
-		
+
 //		@FieldDescribe( "数据的路径列表." )
 //		private String[] dataPaths = null;
-		
+
 		@FieldDescribe( "启动流程的JobId." )
 		private String wf_jobId = null;
-		
+
 		@FieldDescribe( "启动流程的WorkId." )
 		private String wf_workId = null;
-		
+
 		@FieldDescribe( "启动流程的附件列表." )
-		private String[] wf_attachmentIds = null;	
-		
+		private String[] wf_attachmentIds = null;
+
+		@FieldDescribe( "内容管理其他文档的附件列表,非必填" )
+		private String[] cms_attachmentIds = null;
+
 		@FieldDescribe( "文档数据JSON对象." )
 		private Map<?, ?> docData = null;
-		
+
 		@FieldDescribe( "文档读者,Json数组,权限对象需要包含四个属性:<br/>permission权限类别:读者|阅读|作者|管理,  <br/>permissionObjectType使用者类别:所有人|组织|人员|群组, <br/>permissionObjectCode使用者编码:所有人|组织编码|人员UID|群组编码, <br/>permissionObjectName使用者名称:所有人|组织名称|人员名称|群组名称" )
 		private List<PermissionInfo> readerList = null;
-		
+
 		@FieldDescribe( "文档编辑者, ,Json数组,权限对象需要包含四个属性:<br/>permission权限类别:读者|阅读|作者|管理,  <br/>permissionObjectType使用者类别:所有人|组织|人员|群组, <br/>permissionObjectCode使用者编码:所有人|组织编码|人员UID|群组编码, <br/>permissionObjectName使用者名称:所有人|组织名称|人员名称|群组名称" )
 		private List<PermissionInfo> authorList = null;
-		
+
 		private List<String> cloudPictures = null;
-		
+
 		@FieldDescribe( "不修改权限(跳过权限设置,保留原来的设置), True|False." )
 		private Boolean skipPermission  = false;
-		
+
 		@FieldDescribe("文档摘要,70字以内")
 		private String summary;
 
@@ -538,7 +577,7 @@ public class ActionPersistPublishContent extends BaseAction {
 		private Long commendCount = 0L;
 
 		private Long commentCount = 0L;
-		
+
 		private Date publishTime;
 
 		private Date modifyTime;
@@ -1033,9 +1072,16 @@ public class ActionPersistPublishContent extends BaseAction {
 			this.authorList = authorList;
 		}
 
+		public String[] getCms_attachmentIds() {
+			return cms_attachmentIds;
+		}
+
+		public void setCms_attachmentIds(String[] cms_attachmentIds) {
+			this.cms_attachmentIds = cms_attachmentIds;
+		}
 	}
-	
+
 	public static class Wo extends WoId {
 
 	}
-}
+}

+ 7 - 0
o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java

@@ -23,6 +23,7 @@ import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathFactory;
 
+import com.x.base.core.project.config.WebServers;
 import com.x.base.core.project.tools.*;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.FileUtils;
@@ -133,6 +134,12 @@ public class NodeAgent extends Thread {
 								fos.flush();
 							}
 							fos.close();
+							Config.flush();
+							if(syncFilePath.indexOf("web.json") > -1 || syncFilePath.indexOf("collect.json") > -1
+									|| syncFilePath.indexOf("portal.json") > -1){
+								// 更新web服务配置信息
+								WebServers.updateWebServerConfigJson();
+							}
 							logger.info("同步完成");
 							continue;
 

+ 3 - 96
o2server/x_console/src/main/java/com/x/server/console/server/web/WebServerTools.java

@@ -4,19 +4,13 @@ import java.io.File;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.ArrayList;
 import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.stream.Stream;
 
 import javax.servlet.DispatcherType;
 
-import org.apache.commons.codec.binary.Base64;
+import com.x.base.core.project.config.WebServers;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.BooleanUtils;
@@ -31,8 +25,6 @@ import org.eclipse.jetty.webapp.WebAppContext;
 
 import com.alibaba.druid.support.http.StatViewServlet;
 import com.alibaba.druid.support.http.WebStatFilter;
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
 import com.x.base.core.project.x_program_center;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.config.WebServer;
@@ -40,7 +32,6 @@ import com.x.base.core.project.gson.XGsonBuilder;
 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.Host;
 import com.x.server.console.server.JettySeverTools;
 
 public class WebServerTools extends JettySeverTools {
@@ -54,8 +45,8 @@ public class WebServerTools extends JettySeverTools {
 
 	public static Server start(WebServer webServer) throws Exception {
 
-		// 更新x_desktop的center指向
-		updateCenterConfigJson();
+		// 更新web服务配置信息
+		WebServers.updateWebServerConfigJson();
 		// 更新 favicon.ico
 		updateFavicon();
 		// 创建index.html
@@ -172,90 +163,6 @@ public class WebServerTools extends JettySeverTools {
 
 	}
 
-	private static void updateCenterConfigJson() throws Exception {
-		File dir = new File(Config.base(), "servers/webServer/x_desktop/res/config");
-		FileUtils.forceMkdir(dir);
-		File file = new File(dir, "config.json");
-
-		Gson gson = XGsonBuilder.instance();
-
-		LinkedHashMap<String, Object> map = new LinkedHashMap<>();
-		/** 覆盖掉配置的参数 */
-		com.x.base.core.project.config.CenterServer centerServerConfig = Config.nodes().centerServers().first()
-				.getValue();
-		map.putAll(centerServerConfig.getConfig());
-		List<Map<String, String>> centers = new ArrayList<>();
-		map.put("center", centers);
-		/** 写入center地址 */
-		Map<String, String> center = new HashMap<String, String>();
-		center = new HashMap<String, String>();
-		center.put("host", "");
-		center.put("port", centerServerConfig.getPort().toString());
-		centers.add(center);
-		if (!Objects.equals(centerServerConfig.getProxyPort(), centerServerConfig.getPort())) {
-			center = new HashMap<String, String>();
-			center.put("host", "");
-			center.put("port", centerServerConfig.getProxyPort().toString());
-			centers.add(center);
-		}
-		String host = Config.nodes().primaryCenterNode();
-		if (!Host.isRollback(host)) {
-			center = new HashMap<String, String>();
-			center.put("host", host);
-			center.put("port", centerServerConfig.getPort().toString());
-			centers.add(center);
-		}
-		/** 写入proxy地址 */
-		if (StringUtils.isNotEmpty(centerServerConfig.getProxyHost())) {
-			center = new HashMap<String, String>();
-			center.put("host", centerServerConfig.getProxyHost());
-			center.put("port", centerServerConfig.getProxyPort().toString());
-			centers.add(center);
-		}
-
-		/** 写入systemName */
-		map.put("footer", Config.collect().getFooter());
-		map.put("title", Config.collect().getTitle());
-		map.put("appUrl", Config.collect().getAppUrl());
-		/***/
-		if (centerServerConfig.getSslEnable()) {
-			map.put("app_protocol", "https:");
-		} else {
-			map.put("app_protocol", "http:");
-		}
-		/* 上面的无效 */
-		map.put("app_protocol", "auto");
-		if ((null != Config.portal().getLoginPage())
-				&& (BooleanUtils.isTrue(Config.portal().getLoginPage().getEnable()))) {
-			map.put(MAP_LOGINPAGE, Config.portal().getLoginPage());
-		} else if ((null != Config.person().getLoginPage())
-				&& (BooleanUtils.isTrue(Config.person().getLoginPage().getEnable()))) {
-			map.put(MAP_LOGINPAGE, Config.person().getLoginPage());
-		} else {
-			map.put(MAP_LOGINPAGE, Config.portal().getLoginPage());
-		}
-		map.put("indexPage", Config.portal().getIndexPage());
-		map.put("webSocketEnable", Config.communicate().wsEnable());
-		map.put("urlMapping", Config.portal().getUrlMapping());
-
-		/* 密码规则 */
-		map.put("passwordRegex", Config.person().getPasswordRegex());
-		map.put("passwordRegexHint", Config.person().getPasswordRegexHint());
-
-		/* RSA */
-		File publicKeyFile = new File(Config.base(), "config/public.key");
-		if (publicKeyFile.exists() && publicKeyFile.isFile()) {
-			String publicKey = FileUtils.readFileToString(publicKeyFile, "utf-8");
-			byte[] publicKeyB = Base64.decodeBase64(publicKey);
-			publicKey = new String(Base64.encodeBase64(publicKeyB));
-			map.put("publicKey", publicKey);
-		}
-		for (Entry<String, JsonElement> en : Config.web().entrySet()) {
-			map.put(en.getKey(), en.getValue());
-		}
-		FileUtils.writeStringToFile(file, gson.toJson(map), DefaultCharset.charset);
-	}
-
 	private static void createIndexPage() throws Exception {
 		if (null != Config.nodes().webServers()) {
 			StringBuffer buffer = new StringBuffer();

+ 4 - 4
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/view/ActionCreate.java

@@ -35,12 +35,12 @@ class ActionCreate extends BaseAction {
 			}
 			emc.beginTransaction(View.class);
 			View view = Wi.copier.copy(wi);
-			switch (StringUtils.trimToEmpty(view.getType())) {
+			switch (StringUtils.trimToEmpty(wi.getType())) {
 			case View.TYPE_CMS:
-				view.setData(gson.toJson(gson.fromJson(view.getData(), CmsPlan.class)));
+				//view.setData(gson.toJson(gson.fromJson(view.getData(), CmsPlan.class)));
 				break;
 			case View.TYPE_PROCESSPLATFORM:
-				view.setData(gson.toJson(gson.fromJson(view.getData(), ProcessPlatformPlan.class)));
+				//view.setData(gson.toJson(gson.fromJson(view.getData(), ProcessPlatformPlan.class)));
 				break;
 			default:
 				throw new ExceptionTypeValue(wi.getType());
@@ -75,4 +75,4 @@ class ActionCreate extends BaseAction {
 
 	}
 
-}
+}

+ 4 - 5
o2server/x_query_assemble_designer/src/main/java/com/x/query/assemble/designer/jaxrs/view/ActionEdit.java

@@ -37,13 +37,12 @@ class ActionEdit extends BaseAction {
 			if (!business.editable(effectivePerson, query)) {
 				throw new ExceptionQueryAccessDenied(effectivePerson.getDistinguishedName(), query.getName());
 			}
-			Wi.copier.copy(wi, view);
-			switch (StringUtils.trimToEmpty(view.getType())) {
+			switch (StringUtils.trimToEmpty(wi.getType())) {
 			case View.TYPE_CMS:
-				view.setData(gson.toJson(gson.fromJson(view.getData(), CmsPlan.class)));
+				//view.setData(gson.toJson(gson.fromJson(view.getData(), CmsPlan.class)));
 				break;
 			case View.TYPE_PROCESSPLATFORM:
-				view.setData(gson.toJson(gson.fromJson(view.getData(), ProcessPlatformPlan.class)));
+				//view.setData(gson.toJson(gson.fromJson(view.getData(), ProcessPlatformPlan.class)));
 				break;
 			default:
 				throw new ExceptionTypeValue(wi.getType());
@@ -77,4 +76,4 @@ class ActionEdit extends BaseAction {
 
 		static WrapCopier<Wi, View> copier = WrapCopierFactory.wi(Wi.class, View.class, null, JpaObject.FieldsUnmodify);
 	}
-}
+}

+ 10 - 8
o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/FilterEntry.java

@@ -49,6 +49,8 @@ public class FilterEntry extends GsonPropertyObject {
 
 	public static final String DEFINE_UNITALLLIST = "@unitAllList";
 
+	public static final String WILDCARD = "*";
+
 	/** 用于customFilterEntry */
 	public String title;
 
@@ -137,31 +139,31 @@ public class FilterEntry extends GsonPropertyObject {
 			p = cb.and(p, cb.equal(root.get(Item_.path0), paths[0]));
 		}
 
-		if ((paths.length > 1) && StringUtils.isNotEmpty(paths[1])) {
+		if ((paths.length > 1) && StringUtils.isNotEmpty(paths[1]) && !WILDCARD.equals(paths[1])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path1), paths[1]));
 		}
 
-		if ((paths.length > 2) && StringUtils.isNotEmpty(paths[2])) {
+		if ((paths.length > 2) && StringUtils.isNotEmpty(paths[2]) && !WILDCARD.equals(paths[2])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path2), paths[2]));
 		}
 
-		if ((paths.length > 3) && StringUtils.isNotEmpty(paths[3])) {
+		if ((paths.length > 3) && StringUtils.isNotEmpty(paths[3]) && !WILDCARD.equals(paths[3])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path3), paths[3]));
 		}
 
-		if ((paths.length > 4) && StringUtils.isNotEmpty(paths[4])) {
+		if ((paths.length > 4) && StringUtils.isNotEmpty(paths[4]) && !WILDCARD.equals(paths[4])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path4), paths[4]));
 		}
 
-		if ((paths.length > 5) && StringUtils.isNotEmpty(paths[5])) {
+		if ((paths.length > 5) && StringUtils.isNotEmpty(paths[5]) && !WILDCARD.equals(paths[5])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path5), paths[5]));
 		}
 
-		if ((paths.length > 6) && StringUtils.isNotEmpty(paths[6])) {
+		if ((paths.length > 6) && StringUtils.isNotEmpty(paths[6]) && !WILDCARD.equals(paths[6])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path6), paths[6]));
 		}
 
-		if ((paths.length > 7) && StringUtils.isNotEmpty(paths[7])) {
+		if ((paths.length > 7) && StringUtils.isNotEmpty(paths[7]) && !WILDCARD.equals(paths[7])) {
 			p = cb.and(p, cb.equal(root.get(Item_.path7), paths[7]));
 		}
 
@@ -993,4 +995,4 @@ public class FilterEntry extends GsonPropertyObject {
 		return p;
 	}
 
-}
+}

+ 53 - 24
o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/Plan.java

@@ -1,11 +1,7 @@
 package com.x.query.core.express.plan;
 
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
@@ -13,10 +9,7 @@ import java.util.stream.Collectors;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Tuple;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import javax.persistence.criteria.*;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
@@ -89,7 +82,7 @@ public abstract class Plan extends GsonPropertyObject {
 
 	/**
 	 * !!这个类最后要输出.不能gson scriptEngine对象
-	 * 
+	 *
 	 */
 	private transient ScriptEngine scriptEngine;
 
@@ -135,6 +128,8 @@ public abstract class Plan extends GsonPropertyObject {
 						comp = -1;
 					} else if (null == o2) {
 						comp = 1;
+					} else if (o1 instanceof Collection<?> || o2 instanceof Collection<?>) {
+						comp = 0;
 					} else {
 						if (o1.getClass() == o2.getClass()) {
 							c1 = (Comparable) o1;
@@ -456,43 +451,72 @@ public abstract class Plan extends GsonPropertyObject {
 			Root<Item> root = cq.from(Item.class);
 			Predicate p = cb.isMember(root.get(Item_.bundle), cb.literal(bundles));
 			String[] paths = StringUtils.split(selectEntry.path, ".");
+			List<Order> orderList = new ArrayList<>();
 			if ((paths.length > 0) && StringUtils.isNotEmpty(paths[0])) {
 				p = cb.and(p, cb.equal(root.get(Item_.path0), paths[0]));
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path0)), cb.equal(root.get(Item_.path0), "")));
 			}
 			if ((paths.length > 1) && StringUtils.isNotEmpty(paths[1])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path1), paths[1]));
+				if(!FilterEntry.WILDCARD.equals(paths[1])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path1), paths[1]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path1)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path1)), cb.equal(root.get(Item_.path1), "")));
 			}
 			if ((paths.length > 2) && StringUtils.isNotEmpty(paths[2])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path2), paths[2]));
+				if(!FilterEntry.WILDCARD.equals(paths[2])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path2), paths[2]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path2)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path2)), cb.equal(root.get(Item_.path2), "")));
 			}
 			if ((paths.length > 3) && StringUtils.isNotEmpty(paths[3])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path3), paths[3]));
+				if(!FilterEntry.WILDCARD.equals(paths[3])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path3), paths[3]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path3)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path3)), cb.equal(root.get(Item_.path3), "")));
 			}
 			if ((paths.length > 4) && StringUtils.isNotEmpty(paths[4])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path4), paths[4]));
+				if(!FilterEntry.WILDCARD.equals(paths[4])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path4), paths[4]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path4)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path4)), cb.equal(root.get(Item_.path4), "")));
 			}
 			if ((paths.length > 5) && StringUtils.isNotEmpty(paths[5])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path5), paths[5]));
+				if(!FilterEntry.WILDCARD.equals(paths[5])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path5), paths[5]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path5)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path5)), cb.equal(root.get(Item_.path5), "")));
 			}
 			if ((paths.length > 6) && StringUtils.isNotEmpty(paths[6])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path6), paths[6]));
+				if(!FilterEntry.WILDCARD.equals(paths[6])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path6), paths[6]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path6)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path6)), cb.equal(root.get(Item_.path6), "")));
 			}
 			if ((paths.length > 7) && StringUtils.isNotEmpty(paths[7])) {
-				p = cb.and(p, cb.equal(root.get(Item_.path7), paths[7]));
+				if(!FilterEntry.WILDCARD.equals(paths[7])) {
+					p = cb.and(p, cb.equal(root.get(Item_.path7), paths[7]));
+				}else{
+					orderList.add(cb.asc(root.get(Item_.path7)));
+				}
 			} else {
 				p = cb.and(p, cb.or(cb.isNull(root.get(Item_.path7)), cb.equal(root.get(Item_.path7), "")));
 			}
@@ -500,6 +524,11 @@ public abstract class Plan extends GsonPropertyObject {
 					root.get(Item_.itemStringValueType), root.get(Item_.stringShortValue),
 					root.get(Item_.stringLongValue), root.get(Item_.dateValue), root.get(Item_.timeValue),
 					root.get(Item_.dateTimeValue), root.get(Item_.booleanValue), root.get(Item_.numberValue)).where(p);
+			boolean isList = false;
+			if(!orderList.isEmpty()){
+				isList = true;
+				cq.orderBy(orderList);
+			}
 			List<Tuple> list = em.createQuery(cq).getResultList();
 			Row row = null;
 			for (Tuple o : list) {
@@ -510,25 +539,25 @@ public abstract class Plan extends GsonPropertyObject {
 					case s:
 						if (null != o.get(3)) {
 							if ((null != o.get(4)) && StringUtils.isNotEmpty(Objects.toString(o.get(4)))) {
-								row.put(selectEntry.getColumn(), Objects.toString(o.get(4)));
+								row.put(selectEntry.getColumn(), Objects.toString(o.get(4)), isList);
 							} else {
-								row.put(selectEntry.getColumn(), Objects.toString(o.get(3)));
+								row.put(selectEntry.getColumn(), Objects.toString(o.get(3)), isList);
 							}
 						}
 						break;
 					case d:
 						if (null != o.get(5)) {
-							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(5)));
+							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(5)), isList);
 						}
 						break;
 					case t:
 						if (null != o.get(6)) {
-							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(6)));
+							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(6)), isList);
 						}
 						break;
 					case dt:
 						if (null != o.get(7)) {
-							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(7)));
+							row.put(selectEntry.getColumn(), JpaObjectTools.confirm((Date) o.get(7)), isList);
 						}
 						break;
 					default:
@@ -537,12 +566,12 @@ public abstract class Plan extends GsonPropertyObject {
 					break;
 				case b:
 					if (null != o.get(8)) {
-						row.put(selectEntry.getColumn(), (Boolean) o.get(8));
+						row.put(selectEntry.getColumn(), (Boolean) o.get(8), isList);
 					}
 					break;
 				case n:
 					if (null != o.get(9)) {
-						row.put(selectEntry.getColumn(), (Number) o.get(9));
+						row.put(selectEntry.getColumn(), (Number) o.get(9), isList);
 					}
 					break;
 				default:

+ 20 - 1
o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/Row.java

@@ -1,8 +1,10 @@
 package com.x.query.core.express.plan;
 
+import java.util.List;
 import java.util.Objects;
 import java.util.TreeMap;
 
+import com.x.base.core.project.tools.ListTools;
 import org.apache.commons.lang3.math.NumberUtils;
 
 import com.x.base.core.project.gson.GsonPropertyObject;
@@ -26,6 +28,23 @@ public class Row extends GsonPropertyObject {
 		this.data.put(key, value);
 	}
 
+	public void put(String key, Object value, boolean isList) {
+		if (isList) {
+			Object o = this.data.get(key);
+			if (o != null) {
+				if (o instanceof List<?>) {
+					((List) o).add(value);
+				} else {
+					this.data.put(key, ListTools.toList(value));
+				}
+			} else {
+				this.data.put(key, ListTools.toList(value));
+			}
+		}else{
+			this.data.put(key, value);
+		}
+	}
+
 	/** 统计计算时用于转换值,不可转换的值默认为0 */
 	public Double getAsDouble(String key) {
 		Object o = this.data.get(key);
@@ -37,4 +56,4 @@ public class Row extends GsonPropertyObject {
 		}
 	}
 
-}
+}

+ 8 - 0
o2web/gulpfile.js

@@ -1331,3 +1331,11 @@ function build(){
     options.dest = o_options.dest || uploadOptions.dest || "dest";
 };
 gulp.task("build", gulp.series("clean", gulp.parallel(appTasks, 'index'), "o2:new-v"))
+
+gulp.task("temp_o2", function(){
+    return gulp.src("source/x_test/o2.js")
+        .pipe(uglify())
+        .pipe(rename({ extname: '.min.js' }))
+        .pipe(gulp.dest("source/x_test/"))
+        .pipe(gutil.noop());
+})

+ 3 - 1
o2web/source/o2_core/o2/widget/Calendar.js

@@ -449,7 +449,8 @@ o2.widget.Calendar = o2.Calendar = new Class({
 					this.changeViewToDay();
 					break;
 				case "month" :
-					this.showMonth();
+					//this.showMonth();
+					this.changeViewToMonth();
 					break;
 				case "year" :
 					this.showYear();
@@ -1162,6 +1163,7 @@ o2.widget.Calendar = o2.Calendar = new Class({
 						calendar._selectDate(this.retrieve("dateValue"), this);
 						break;
 					case "month" :
+						debugger;
 						calendar.changeViewToDay(this.retrieve("year"), this.retrieve("month"));
 						break;
 					case "year" :

+ 3 - 0
o2web/source/o2_core/o2/xDesktop/$Default/blue/layout-menu-pc.html

@@ -13,6 +13,9 @@
         <div class="layout_start_content_appTitle" data-o2-element="appTitleNode"></div>
         <div class="layout_start_content_appScrollContent" data-o2-element="appScrollNode">
             <div class="layout_start_content_appContent icon_loading" data-o2-element="appContentNode"></div>
+            <div data-o2-events="click:defaultMenu">恢复默认</div>
         </div>
+
     </div>
+    <div style="height: 0" data-o2-element="groupMenuArea"></div>
 </div>

+ 72 - 0
o2web/source/o2_core/o2/xDesktop/$Default/blue/style-pc.css

@@ -721,3 +721,75 @@
     opacity: 0;
     box-shadow: 3PX 3PX 10px #999999;
 }
+.layout_start_groupItem_menu {
+    position: absolute;
+    width: 40px;
+    height: 40px;
+    border-radius: 20px;
+    background-size: 22px 22px;
+}
+.layout_start_groupItem_menuMask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    opacity: 0.4;
+    top: 0;
+    left: 0;
+}
+.layout_start_groupItem_menu_title {
+    height: 60px;
+    padding: 8px 0 12px 0;
+    line-height: 40px;
+    font-size: 16px;
+    text-align: center;
+    overflow: hidden;
+}
+.layout_start_groupItem_menu_scroll {
+    overflow: hidden;
+}
+.layout_start_item_icon_group {
+    width: 32px;
+    height: 32px;
+    padding: 5px 3px 3px 5px;
+    border-radius: 10px;
+    background-size: 22px 22px;
+}
+.layout_start_groupItem_menu_content {
+    overflow: hidden;
+}
+.layout_start_item_icon_group_sub {
+    width:  14px;
+    height: 14px;
+    margin-right: 2px;
+    margin-bottom: 2px;
+    border-radius: 10px;
+    float: left;
+    background-repeat: no-repeat;
+    background-size: 10px 10px;
+    background-position: center;
+}
+.layout_start_item_icon_group_subIcon {
+    width:  14px;
+    height: 14px;
+    margin-right: 2px;
+    margin-bottom: 2px;
+    border-radius: 10px;
+    float: left;
+    background-repeat: no-repeat;
+    background-size: cover;
+    background-position: center;
+}
+.layout_start_item_sub {
+    margin-left: 12px;
+}
+.layout_start_groupItem_menu_title_edit {
+    border: 0;
+    height: 40px;
+    line-height: 40px;
+    padding: 0 10px;
+    font-size: 16px;
+    text-align: center;
+    width: 90%;
+    margin: auto;
+    border-radius: 20px;
+}

+ 1 - 1
o2web/source/o2_core/o2/xDesktop/$Layout/quickStart.json

@@ -16,7 +16,7 @@
     //      "icon": "cms.png"
     //    },
     {
-      "title": "云文件",
+      "title": "企业网盘",
       "action": "File",
       "icon": "file.png"
     },

+ 544 - 55
o2web/source/o2_core/o2/xDesktop/Default.js

@@ -863,13 +863,28 @@ o2.xDesktop.Default.StartMenu = new Class({
         }
         var nodes = this.appContentNode.getChildren();
         var data = [];
+
         nodes.each(function(node){
             var item = node.retrieve("item");
             if (item){
-                data.push({
-                    "id": item.data.id,
-                    "name": item.data.name
-                });
+                if (item.data.type==="group"){
+                    var d = {
+                        "id": item.data.id,
+                        "name": item.data.name,
+                        "type": item.data.type,
+                        "itemDataList": []
+                    }
+                    if (item.data.itemDataList) item.data.itemDataList.each(function(i){
+                        d.itemDataList.push(i);
+                    });
+                    data.push(d);
+                }else{
+                    data.push({
+                        "id": item.data.id,
+                        "name": item.data.name,
+                        "type": item.data.type,
+                    });
+                }
             }
         }.bind(this));
         if (this.currentTab === this.appCategoryTab){
@@ -904,7 +919,6 @@ o2.xDesktop.Default.StartMenu = new Class({
         this.searchNode.store("currentWidth", currentWidth);
 
         this.appCategoryTab.addEvent("click", function(){
-            debugger;
             this.appTitleNode.getElements(".layout_start_tab").removeClass("mainColor_bg");
             this.appCategoryTab.addClass("mainColor_bg");
             this.currentTab = this.appCategoryTab;
@@ -1202,37 +1216,36 @@ o2.xDesktop.Default.StartMenu = new Class({
         }.bind(this));
     },
 
-    getCurrentName : function( callback ){
+    loadApplicationsItem: function(layoutJson, componentJson, portalJson){
+        debugger;
         var user = this.layout.session.user;
         var currentNames = [user.name, user.distinguishedName, user.id, user.unique];
         if (user.roleList) currentNames = currentNames.concat(user.roleList);
-        // if (user.groupList) currentNames = currentNames.concat(user.groupList);
-        o2.Actions.load("x_organization_assemble_express").GroupAction.listWithPerson(
-            {
-                personList: [user.distinguishedName],
-                recursiveGroupFlag : true,
-                referenceFlag : true,
-                recursiveOrgFlag : true
-            },
-            function(json) {
-                currentNames = currentNames.concat(json.data.groupList);
-                if( callback )callback( currentNames )
-            }
-        )
-    },
+        if (user.groupList) currentNames = currentNames.concat(user.groupList);
 
-    loadApplicationsItem: function(json_layout, json_component, json_portal){
-        // var user = this.layout.session.user;
-        // var currentNames = [user.name, user.distinguishedName, user.id, user.unique];
-        // if (user.roleList) currentNames = currentNames.concat(user.roleList);
-        // if (user.groupList) currentNames = currentNames.concat(user.groupList);
+        var json_layout = Array.clone(layoutJson);
+        var json_component = Array.clone(componentJson);
+        var json_portal = Array.clone(portalJson);
+
+        this.appContentNode.removeClass("icon_loading");
+
+        var loadedApps = {};
+        if (this.menuData && this.menuData.appList && this.menuData.appList.length){
+            this.menuData.appList.each(function(app){
+                if (app.type==="group"){
+                    this.createGroupMenuItem(app);
+                    app.itemDataList.each(function(a){
+                        var d = json_layout.find(function(i){ return (i.id === a.id); });
+                        if (d) json_layout.erase(d);
 
-        this.getCurrentName( function ( currentNames ) {
-            this.appContentNode.removeClass("icon_loading");
+                        d = json_component.find(function(i){ return (i.id === a.id); });
+                        if (d) json_component.erase(d);
 
-            var loadedApps = {};
-            if (this.menuData && this.menuData.appList && this.menuData.appList.length){
-                this.menuData.appList.each(function(app){
+                        d = json_portal.find(function(i){ return (i.id === a.id); });
+                        if (d) json_portal.erase(d);
+
+                    }.bind(this));
+                }else{
                     var appData = null;
                     if (!appData && json_layout && json_layout.length){
                         appData = json_layout.find(function(i){ return (i.id === app.id); });
@@ -1252,6 +1265,7 @@ o2.xDesktop.Default.StartMenu = new Class({
                         appData = json_portal.find(function(i){ return (i.id === app.id); });
                         if (appData){
                             json_portal.erase(appData);
+                            appData.type = "portal";
                             this.createPortalMenuItem(appData);
                         }
                     }
@@ -1270,6 +1284,9 @@ o2.xDesktop.Default.StartMenu = new Class({
                 this.createPortalMenuItem(value);
             }.bind(this));
 
+        if (json_portal && json_portal.length) json_portal.each(function(value){
+            value.type = "portal";
+            this.createPortalMenuItem(value);
         }.bind(this));
     },
 
@@ -1278,9 +1295,34 @@ o2.xDesktop.Default.StartMenu = new Class({
         // o2.Actions.get("x_processplatform_assemble_surface").listApplication(this.loadProcessesItem.bind(this));
         this.loadProcessesItem(this.processJson)
     },
-    loadProcessesItem: function(json){
+    loadProcessesItem: function(list){
         this.appContentNode.removeClass("icon_loading");
+        var json = Array.clone(list);
+
+        if (this.menuData && this.menuData.processList && this.menuData.processList.length){
+            this.menuData.processList.each(function(app){
+                if (app.type==="group"){
+                    this.createGroupMenuItem(app);
+                    app.itemDataList.each(function(a){
+                        var d = json.find(function(i){ return (i.id === a.id); });
+                        if (d) json.erase(d);
+                    }.bind(this));
+                }else{
+                    var appData = null;
+                    if (!appData && json && json.length){
+                        appData = json.find(function(i){ return (i.id === app.id); });
+                        if (appData){
+                            json.erase(appData);
+                            appData.type = "process";
+                            this.createProcessMenuItem(appData);
+                        }
+                    }
+                }
+            }.bind(this));
+        }
+
         if (json && json.length) json.each(function(value){
+            value.type = "process";
             this.createProcessMenuItem(value);
         }.bind(this));
     },
@@ -1290,9 +1332,34 @@ o2.xDesktop.Default.StartMenu = new Class({
         //o2.Actions.get("x_cms_assemble_control").listColumn(this.loadInforsItem.bind(this));
         this.loadInforsItem(this.inforJson)
     },
-    loadInforsItem: function(json){
+    loadInforsItem: function(list){
         this.appContentNode.removeClass("icon_loading");
+        var json = Array.clone(list);
+
+        if (this.menuData && this.menuData.inforList && this.menuData.inforList.length){
+            this.menuData.inforList.each(function(app){
+                if (app.type==="group"){
+                    this.createGroupMenuItem(app);
+                    app.itemDataList.each(function(a){
+                        var d = json.find(function(i){ return (i.id === a.id); });
+                        if (d) json.erase(d);
+                    }.bind(this));
+                }else{
+                    var appData = null;
+                    if (!appData && json && json.length){
+                        appData = json.find(function(i){ return (i.id === app.id); });
+                        if (appData){
+                            json.erase(appData);
+                            appData.type = "cms";
+                            this.createInforMenuItem(appData);
+                        }
+                    }
+                }
+            }.bind(this));
+        }
+
         if (json && json.length) json.each(function(value){
+            value.type = "cms";
             this.createInforMenuItem(value);
         }.bind(this));
     },
@@ -1302,9 +1369,34 @@ o2.xDesktop.Default.StartMenu = new Class({
         // o2.Actions.get("x_query_assemble_surface").listQuery(this.loadQuerysItem.bind(this));
         this.loadQuerysItem(this.queryJson)
     },
-    loadQuerysItem: function(json){
+    loadQuerysItem: function(list){
         this.appContentNode.removeClass("icon_loading");
+        var json = Array.clone(list);
+
+        if (this.menuData && this.menuData.queryList && this.menuData.queryList.length){
+            this.menuData.queryList.each(function(app){
+                if (app.type==="group"){
+                    this.createGroupMenuItem(app);
+                    app.itemDataList.each(function(a){
+                        var d = json.find(function(i){ return (i.id === a.id); });
+                        if (d) json.erase(d);
+                    }.bind(this));
+                }else{
+                    var appData = null;
+                    if (!appData && json && json.length){
+                        appData = json.find(function(i){ return (i.id === app.id); });
+                        if (appData){
+                            json.erase(appData);
+                            appData.type = "query";
+                            this.createQueryMenuItem(appData);
+                        }
+                    }
+                }
+            }.bind(this));
+        }
+
         if (json && json.length) json.each(function(value){
+            value.type = "query";
             this.createQueryMenuItem(value);
         }.bind(this));
     },
@@ -1332,6 +1424,9 @@ o2.xDesktop.Default.StartMenu = new Class({
     createQueryMenuItem: function(value){
         this.items.push(new o2.xDesktop.Default.StartMenu.QueryItem(this, this.appContentNode, value));
     },
+    createGroupMenuItem: function(value){
+        this.items.push(new o2.xDesktop.Default.StartMenu.GroupItem(this, this.appContentNode, value));
+    },
 
     show: function(){
         if (!this.isMorph){
@@ -1350,6 +1445,7 @@ o2.xDesktop.Default.StartMenu = new Class({
             this.maskNode.setStyles({"display": "block"});
             this.node.setStyles({"display": "block"});
             this.triangleNode.setStyles({"display": "block"});
+            this.appAreaNode.setStyles({ "filter": "" });
 
             this.setSize();
             this.setPosition();
@@ -1398,6 +1494,7 @@ o2.xDesktop.Default.StartMenu = new Class({
 
             this.lnkContentNode.empty();
             this.appContentNode.empty();
+            this.groupMenuArea.empty();
             if (this.appScrollBar) this.appScrollBar.destroy();
 
             this.maskMorph.start({"left": ""+left+"px"}).chain(function(){
@@ -1414,18 +1511,31 @@ o2.xDesktop.Default.StartMenu = new Class({
             }.bind(this));
         }
     },
+    defaultMenu: function(){
+        this.layout.menuData = null;
+        if (this.layout.status) this.layout.status.menuData = null;
+        this.menuData = null;
+        this.hide();
+    }
 });
 
 o2.xDesktop.Default.StartMenu.Item = new Class({
-    initialize: function (menu, container, data) {
+    initialize: function (menu, container, data, positionNode) {
         this.menu = menu;
         this.layout = this.menu.layout;
         this.data = data;
         this.container = $(container);
-        this.load();
+        this.load(positionNode);
+        this.init();
     },
-    load: function(){
-        this.node = new Element("div.layout_start_item").inject(this.container);
+    load: function(positionNode){
+        this.node = new Element("div.layout_start_item");
+        if (positionNode){
+            this.node.inject(positionNode, "before");
+        }else{
+            this.node.inject(this.container);
+        }
+
         this.node.set("html", this.menu.itemTempletedHtml);
         this.iconAreaNode = this.node.getElement(".layout_start_item_iconArea");
         this.iconNode = this.node.getElement(".layout_start_item_icon");
@@ -1436,7 +1546,11 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
         this.loadText();
         this.setEvent();
         this.node.store("item", this);
+        if (this.menu.data && this.menu.data.type==="group"){
+            this.node.addClass("layout_start_item_sub");
+        }
     },
+    init: function(){},
     dragOver: function(){
         if (!this.overNode){
             this.overNode = new Element("div.layout_start_item_over").inject(this.container);
@@ -1491,16 +1605,16 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
         this.badgeNode.set("title", o2.LP.desktop.addLnk).addClass("icon_add_red");
     },
     loadText: function(){
-        this.textNode.set("text", this.data.title);
+        this.textNode.set("text", this.data.title || this.data.name);
     },
     setEvent: function(){
         this.node.addEvents({
             "mouseover": function(){ this.badgeNode.fade("in"); }.bind(this),
             "mouseout": function(){ this.badgeNode.fade("out"); }.bind(this),
             "click": function(e){
-                this.menu.hide(function(){
+                //this.menu.hide(function(){
                     this.open(e);
-                }.bind(this));
+                //}.bind(this));
             }.bind(this)
         });
 
@@ -1523,7 +1637,15 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
         this.layout.addLnk(lnkdata, dragTargetLnk, dragPosition);
     },
     open: function(e){
-        layout.openApplication(e, this.data.path);
+        this.menu.hide(function(){
+            if (this.menu.menu){
+                this.menu.menu.hide(function(){
+                    layout.openApplication(e, this.data.path);
+                }.bind(this));
+            }else{
+                layout.openApplication(e, this.data.path);
+            }
+        }.bind(this));
     },
     makeLnk: function(){
         var drag = new Drag(this.node, {
@@ -1553,10 +1675,17 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
     },
     doDragMove: function(e){
         this.getDragNode();
+
+        var droppables = [this.layout.lnkContentNode, this.menu.appContentNode];
+        if (this.menu.appContentNode.hasClass("layout_start_groupItem_menu_content")){
+            this.onGroup = true;
+        }
+        //if (this.menu.maskGroupNode) droppables.push(this.menu.maskGroupNode);
+
         var drag = new Drag.Move(this.dragNode, {
             "stopPropagation": true,
             "compensateScroll": true,
-            "droppables": [this.layout.lnkContentNode, this.menu.appContentNode],
+            "droppables": droppables,
             "onStart": function(el){ this._drag_start(el); }.bind(this),
             "onDrag": function(dragging,e){ this._drag_drag(dragging, e); }.bind(this),
             "onEnter": function(dragging, inObj){ this._drag_enter(dragging, inObj); }.bind(this),
@@ -1573,9 +1702,11 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
         this.dragTargetLnk = null;
         this.dragPosition = "before";
 
-        this.node.setStyle("opacity", 0);
+        this.node.setStyle("opacity", 0.2);
+        this.positionFlagNode = new Element("div", {"styles": {"display": "none"}}).inject(this.node, "after");
     },
     _drag_drag: function(dragging, e){
+        console.log(this.dragStatus);
         if (this.dragStatus == "order"){
             if (this.layout.lnks && this.layout.lnks.length){
                 var current = e.page.y;
@@ -1613,7 +1744,7 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
             }
         }
         if (this.dragStatus == "group"){
-            this.checkDargOver(dragging);
+            if (!this.onGroup) this.checkDargOver(dragging);
             if (!this.overItem){
                 this.checkDargPosition(dragging);
             }
@@ -1665,17 +1796,21 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
     },
 
     _drag_enter: function(el, inObj){
-        if (inObj.hasClass("layout_start_content_appContent")){
+        if (inObj.hasClass("layout_start_content_appContent") || inObj.hasClass("layout_start_groupItem_menu_content")){
             this.dragStatus = "group";
-            this.node.setStyle("opacity", 0);
+            this.node.setStyle("opacity", 0.2);
         }else{
+            if (this.positionFlagNode) this.node.inject(this.positionFlagNode, "before");
             this.dragStatus = "order";
             this.node.setStyle("opacity", 1);
         }
     },
     _drag_leave: function(el, inObj){
         if (inObj.hasClass("layout_start_content_appContent")){
-            this.node.inject(this.menu.appContentNode);
+            //this.node.inject(this.menu.appContentNode);
+        }else if (inObj.hasClass("layout_start_groupItem_menu_content")){
+            this.dragStatus = "ungroup";
+            this.node.setStyle("opacity", 0);
         }else{
             this.dragStatus = "remove";
             if (this.layout.positionNode) this.layout.positionNode.hide();
@@ -1683,14 +1818,22 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
     },
 
     _drag_drop: function(dragging, inObj){
-        if (this.dragStatus == "order" && this.dragTargetLnk && this.dragTargetLnk!=this){
-            this.addLnk(this.dragTargetLnk, this.dragPosition);
+        if (this.dragStatus==="ungroup"){
+            this.removeFormGroup();
+        }else{
+            if (this.dragStatus == "order" && this.dragTargetLnk && this.dragTargetLnk!=this){
+                this.addLnk(this.dragTargetLnk, this.dragPosition);
+            }else if (this.dragStatus == "group" && this.overItem && this.overItem!=this){
+                this.overItem.dragOut();
+                this.addGroup();
+            }
+            this.node.setStyle("opacity", 1);
         }
-        this.node.setStyle("opacity", 1);
         this.menu.resetMenuData();
     },
 
     _drag_cancel: function(dragging){
+        console.log("_drag_cancel");
         dragging.hide();
         if (this.layout.positionNode) this.layout.positionNode.hide();
         if (this.dragRemoveNode) this.dragRemoveNode.hide();
@@ -1699,10 +1842,324 @@ o2.xDesktop.Default.StartMenu.Item = new Class({
         this.menu.resetMenuData();
     },
 
-    _drag_complete: function(dragging){
+    _drag_complete: function(dragging) {
         this._drag_cancel(dragging);
+        if (this.positionFlagNode) this.positionFlagNode.destroy();
+        this.positionFlagNode = null;
+    },
+    removeFormGroup: function(){
+        // this.menu.itemDataList.erase(this.data);
+        // this.menu.items.erase(this);
+        this.menu.data.itemDataList.erase(this.data);
+        switch (this.data.type){
+            case "portal":
+                this.layout.startMenu.createPortalMenuItem(this.data);
+                break;
+            case "process":
+                this.layout.startMenu.createProcessMenuItem(this.data);
+                break;
+            case "cms":
+                this.layout.startMenu.createInforMenuItem(this.data);
+                break;
+            case "query":
+                this.layout.startMenu.createQueryMenuItem(this.data);
+                break;
+            default:
+                this.layout.startMenu.createApplicationMenuItem(this.data);
+
+        }
+        debugger;
+        this.destroy();
+        if (!this.menu.data.itemDataList.length){
+            this.menu.hide(function(){
+                this.menu.destroy();
+            }.bind(this));
+        }else{
+            this.menu.resetSubItemIcon();
+        }
+
+    },
+    addGroup: function(){
+        debugger;
+        if (this.overItem.data.type==="group"){
+            this.overItem.addItem(this.data);
+        }else{
+            var v = {
+                name: "Group",
+                title: "Group",
+                type: "group",
+                visible: true
+            }
+            var group = new o2.xDesktop.Default.StartMenu.GroupItem(this.menu, this.container, v, this.overItem.node);
+            group.addItem(this.overItem.data);
+            group.addItem(this.data);
+            this.menu.items.push(group);
+            this.overItem.node.destroy();
+            group.open(null, function(){
+                group.editTitle();
+            });
+        }
+        this.node.destroy();
+        this.menu.resetMenuData();
+    },
+    destroy: function(){
+        this.menu.items.erase(this);
+        this.node.destroy();
     }
 });
+
+o2.xDesktop.Default.StartMenu.GroupItem = new Class({
+    Extends: o2.xDesktop.Default.StartMenu.Item,
+    loadIcon: function(){
+        this.iconNode.addClass("layout_start_item_icon_group");
+        this.iconNode.addClass("grayColor_bg");
+
+        this.sunIconNodes = [];
+        var node = new Element("div.layout_start_item_icon_group_sub").inject(this.iconNode);
+        this.sunIconNodes.push(node);
+
+        node = new Element("div.layout_start_item_icon_group_sub").inject(this.iconNode);
+        this.sunIconNodes.push(node);
+
+        node = new Element("div.layout_start_item_icon_group_sub").inject(this.iconNode);
+        this.sunIconNodes.push(node);
+
+        node = new Element("div.layout_start_item_icon_group_sub").inject(this.iconNode);
+        this.sunIconNodes.push(node);
+    },
+    init: function(){
+        this.itemTempletedHtml = this.menu.itemTempletedHtml;
+
+        if (this.data.itemDataList && this.data.itemDataList.length){
+            for (var i=0; i<Math.min(this.data.itemDataList.length, 4); i++){
+                var icon = this.setSubItemIcon(this.data.itemDataList[i], this.sunIconNodes[i]);
+            }
+        }
+    },
+    resetSubItemIcon: function(){
+        this.sunIconNodes.each(function(e){
+            e.setStyle("background-image", "");
+            e.setStyle("background-color", "");
+        });
+        if (this.data.itemDataList && this.data.itemDataList.length){
+            for (var i=0; i<Math.min(this.data.itemDataList.length, 4); i++){
+                var icon = this.setSubItemIcon(this.data.itemDataList[i], this.sunIconNodes[i]);
+            }
+        }
+    },
+    open: function(e, callback){
+        if (!this.menuNode) this.createMenuNode();
+        this.maskNode = new Element("div.layout_start_groupItem_menuMask").inject(this.menuNode, "before");
+        this.maskNode.addEvent("click", function(e){
+            this.hide();
+        }.bind(this));
+        this.maskGroupNode = this.maskNode;
+
+        this.menuNode.show();
+
+        var styles = this.getMenuNodeOpenDimensions();
+        this.menuNode.morph.set("transition", Fx.Transitions.Quart.easeOut);
+        this.menuNode.morph.start(styles).chain(function(){
+            this.menuTitleNode.show();
+            this.menuScrollNode.show();
+
+            var s = this.menuNode.getSize();
+            var ts = this.menuTitleNode.getSize();
+            var h = s.y - ts.y;
+            this.menuContentNode.setStyle("height", ""+h+"px");
+            this.loadItems();
+            if (callback) callback();
+        }.bind(this));
+
+        this.menu.appAreaNode.setStyles({ "filter": "blur(5px)" });
+    },
+    hide: function(callback){
+        this.menuTitleNode.hide();
+        this.menuScrollNode.hide();
+        var styles = this.getMenuNodeCloseDimensions();
+        this.menuNode.morph.set("transition", Fx.Transitions.Quart.easeIn);
+        this.menuNode.morph.start(styles).chain(function(){
+            if (this.maskNode) this.maskNode.destroy();
+            if (this.menuNode) this.menuNode.hide();
+            if (callback) callback();
+        }.bind(this));
+        this.menu.appAreaNode.setStyles({ "filter": "" });
+    },
+    loadItems: function(){
+        if (!this.items) this.items = [];
+        this.data.itemDataList.each(function(data){
+            var item = this.items.find(function(i){
+                return i.data.id == data.id;
+            });
+            if (!item){
+                switch (data.type){
+                    case "portal":
+                        this.items.push(new o2.xDesktop.Default.StartMenu.PortalItem(this, this.menuContentNode, data));
+                        break;
+                    case "process":
+                        this.items.push(new o2.xDesktop.Default.StartMenu.ProcessItem(this, this.menuContentNode, data));
+                        break;
+                    case "cms":
+                        this.items.push(new o2.xDesktop.Default.StartMenu.InforItem(this, this.menuContentNode, data));
+                        break;
+                    case "query":
+                        this.items.push(new o2.xDesktop.Default.StartMenu.QueryItem(this, this.menuContentNode, data));
+                        break;
+                    default:
+                        this.items.push(new o2.xDesktop.Default.StartMenu.Item(this, this.menuContentNode, data));
+                }
+            }
+        }.bind(this));
+    },
+    getMenuNodeOpenDimensions: function(){
+        var size = this.menu.appAreaNode.getSize();
+        var w = size.x*0.94;
+        var h = size.y*0.7;
+        var x = (size.x*(1-0.94))/2;
+        var y = (size.y*(1-0.7))/2;
+        return {"width":w, "height": h, "left": x, "top": y}
+    },
+    getMenuNodeCloseDimensions: function(){
+        var size = this.iconNode.getSize();
+        var position = this.iconNode.getPosition(this.menu.node);
+        return {"width":size.x, "height": size.y, "left": position.x, "top": position.y}
+    },
+    createMenuNode: function(){
+        this.menuNode = new Element("div.layout_start_groupItem_menu").inject(this.menu.groupMenuArea);
+        this.menuNode.addClass("grayColor_bg");
+        this.menuTitleNode = new Element("div.layout_start_groupItem_menu_title").inject(this.menuNode);
+        this.menuTitleNode.set("text", this.data.name);
+
+        this.menuScrollNode = new Element("div.layout_start_groupItem_menu_scroll").inject(this.menuNode);
+        this.menuContentNode = new Element("div.layout_start_groupItem_menu_content").inject(this.menuScrollNode);
+        this.appContentNode = this.menuContentNode;
+
+        this.menuNode.position({
+            "relativeTo": this.iconNode,
+            "position": "upperLeft",
+            "edge": "upperLeft"
+        });
+        this.menuNode.morph = new Fx.Morph(this.menuNode, {
+            "duration": 200,
+            "transition": Fx.Transitions.Quart.easeOut
+        });
+        this.menuTitleNode.addEvent("click", function(){
+            
+            var input = this.menuTitleNode.getElement("input");
+            if (!input) this.editTitle();
+        }.bind(this))
+    },
+    destroy: function(){
+        this.menu.items.erase(this);
+        this.node.destroy();
+        this.menuNode.destroy();
+    },
+    editTitle: function(){
+        this.menuTitleNode.empty();
+        this.editotTitleNode = new Element("input.layout_start_groupItem_menu_title_edit", {"type": "text"}).inject(this.menuTitleNode);
+        this.editotTitleNode.set("value", this.data.name);
+        this.editotTitleNode.focus();
+
+        this.editotTitleNode.addEvent("blur", function(){
+            var name = this.editotTitleNode.get("value");
+            if (name) this.data.name = name;
+            this.menuTitleNode.empty();
+            this.menuTitleNode.set("text", this.data.name);
+            this.loadText();
+        }.bind(this));
+    },
+
+    addItem: function(data){
+        if (!this.data.itemDataList) this.data.itemDataList = [];
+        if (this.data.itemDataList.length<4){
+            this.setSubItemIcon(data, this.sunIconNodes[this.data.itemDataList.length]);
+        }
+        this.data.itemDataList.push(data);
+    },
+    setSubItemIcon: function(data, node){
+        switch (data.type){
+            case "process":
+                this.setAppSubItemIcon(node, data.icon, "processDefault", "../x_component_process_ApplicationExplorer/$Main/default/icon/application.png");
+                break;
+            case "portal":
+                this.setAppSubItemIcon(node, data.icon, "portalDefault", "../x_component_portal_PortalExplorer/$Main/default/icon/application.png");
+                break;
+            case "cms":
+                this.setAppSubItemIcon(node, data.icon, "cmsDefault", "../x_component_cms_Index/$Main/default/icon/column.png");
+                break;
+            case "query":
+                this.setAppSubItemIcon(node, data.icon, "queryDefault", "../x_component_query_Query/$Main/appicon.png");
+                break;
+            default:
+                this.setDefaultSubItemIcon(data, node);
+        }
+    },
+    setAppSubItemIcon: function(node, iconData, defaultIcon, defaultUrl){
+        var icon = "";
+        var bgcolor = "";
+        if (iconData){
+            icon = "data:image/png;base64,"+iconData+"";
+            bgcolor = "";
+            node.addClass("layout_start_item_icon_group_subIcon");
+        }else{
+            var p = defaultIcon;
+            if (this.layout.iconsJson[p] && this.layout.iconsJson[p].icon){
+                icon = this.layout.path+"appicons/"+this.layout.iconsJson[p].icon;
+                bgcolor = this.layout.iconsJson[p].color;
+            }else{
+                icon = defaultUrl;
+                bgcolor = "";
+            }
+        }
+        if (icon && bgcolor) node.setStyle("background-color", bgcolor);
+        node.setStyle("background-image", "url("+icon+")");
+    },
+    setDefaultSubItemIcon: function(data, node){
+        var icon;
+        var bgcolor = "";
+        if (data.path.substring(0, 4)==="@url"){
+            if (data.iconPath){
+                icon = data.iconPath;
+            }else{
+                if (this.layout.iconsJson["Url"] && this.layout.iconsJson["Url"].icon){
+                    icon = this.layout.path+"appicons/"+this.layout.iconsJson["Url"].icon;
+                    bgcolor = this.layout.iconsJson["Url"].color;
+                }else{
+                    icon = "../x_component_Setting/$Main/default/icon/site.png";
+                    bgcolor = "";
+                }
+            }
+        }else{
+            if (this.layout.iconsJson[data.path] && this.layout.iconsJson[data.path].icon){
+                icon = this.layout.path+"appicons/"+this.layout.iconsJson[data.path].icon;
+                bgcolor = this.layout.iconsJson[data.path].color;
+            }else{
+                icon = "../x_component_"+data.path.replace(/\./g, "_")+"/$Main/"+data.iconPath;
+                bgcolor = "";
+            }
+        }
+        if (icon && bgcolor){
+            node.setStyle("background-color", bgcolor);
+        }
+        node.setStyle("background-image", "url("+icon+")");
+    },
+
+    resetMenuData: function(){
+        debugger;
+        var nodes = this.menuContentNode.getChildren(".layout_start_item");
+        var data = [];
+
+        nodes.each(function(node){
+            var item = node.retrieve("item");
+            if (item){
+                data.push(item.data);
+            }
+        }.bind(this));
+        this.data.itemDataList = data;
+    }
+});
+
+
 o2.xDesktop.Default.StartMenu.PortalItem = new Class({
     Extends: o2.xDesktop.Default.StartMenu.Item,
     loadIcon: function(){
@@ -1745,7 +2202,15 @@ o2.xDesktop.Default.StartMenu.PortalItem = new Class({
 
     open: function(e){
         var options = {"portalId": this.data.id, "appId": "portal.Portal"+this.data.id};
-        layout.openApplication(e, "portal.Portal", options);
+        this.menu.hide(function(){
+            if (this.menu.menu){
+                this.menu.menu.hide(function(){
+                    layout.openApplication(e, "portal.Portal", options);
+                }.bind(this));
+            }else{
+                layout.openApplication(e, "portal.Portal", options);
+            }
+        }.bind(this));
     }
     // makeLnk: function(){
     //     //@todo
@@ -1793,7 +2258,15 @@ o2.xDesktop.Default.StartMenu.ProcessItem = new Class({
     },
     open: function(e){
         var options = {"id": this.data.id, "appId": "process.Application"+this.data.id};
-        layout.openApplication(e, "process.Application", options);
+        this.menu.hide(function(){
+            if (this.menu.menu){
+                this.menu.menu.hide(function(){
+                    layout.openApplication(e, "process.Application", options);
+                }.bind(this));
+            }else{
+                layout.openApplication(e, "process.Application", options);
+            }
+        }.bind(this));
     }
     // makeLnk: function(){
     //     //@todo
@@ -1842,7 +2315,15 @@ o2.xDesktop.Default.StartMenu.InforItem = new Class({
         this.layout.addLnk(lnkdata, dragTargetLnk, dragPosition);
     },
     open: function(e){
-        layout.openApplication(e, "cms.Module", {"columnData": this.data, "appId": "cms.Module"+this.data.id});
+        this.menu.hide(function(){
+            if (this.menu.menu){
+                this.menu.menu.hide(function(){
+                    layout.openApplication(e, "cms.Module", {"columnData": this.data, "appId": "cms.Module"+this.data.id});
+                }.bind(this));
+            }else{
+                layout.openApplication(e, "cms.Module", {"columnData": this.data, "appId": "cms.Module"+this.data.id});
+            }
+        }.bind(this));
     }
     // makeLnk: function(){
     //     //@todo
@@ -1889,7 +2370,15 @@ o2.xDesktop.Default.StartMenu.QueryItem = new Class({
         this.layout.addLnk(lnkdata, dragTargetLnk, dragPosition);
     },
     open: function(e){
-        layout.openApplication(e, "query.Query", {"id": this.data.id, "appId": "query.Query"+this.data.id});
+        this.menu.hide(function(){
+            if (this.menu.menu){
+                this.menu.menu.hide(function(){
+                    layout.openApplication(e, "query.Query", {"id": this.data.id, "appId": "query.Query"+this.data.id});
+                }.bind(this));
+            }else{
+                layout.openApplication(e, "query.Query", {"id": this.data.id, "appId": "query.Query"+this.data.id});
+            }
+        }.bind(this));
     }
     // makeLnk: function(){
     //     //@todo

+ 4 - 4
o2web/source/x_component_AppCenter/Main.js

@@ -1347,8 +1347,8 @@ MWF.xApplication.AppCenter.Exporter.Element.QuerySelector = new Class({
         this.selectData.viewList = this.getCheckedList(this.listViewContent);
         this.selectData.statList = this.getCheckedList(this.listStatContent);
         this.selectData.revealList = this.getCheckedList(this.listRevealContent);
-        this.selectData.statementList = this.getCheckedList(this.listRevealContent);
-        this.selectData.tableList = this.getCheckedList(this.listRevealContent);
+        this.selectData.statementList = this.getCheckedList(this.listTableContent);
+        this.selectData.tableList = this.getCheckedList(this.listStatementContent);
         this.element.checkSelect(this.selectData);
         this.hide();
     },
@@ -1358,8 +1358,8 @@ MWF.xApplication.AppCenter.Exporter.Element.QuerySelector = new Class({
         this.listStatContent = this.listProcess("statList");
         this.listRevealContent = this.listProcess("revealList");
 
-        this.listRevealContent = this.listProcess("tableList");
-        this.listRevealContent = this.listProcess("statementList");
+        this.listTableContent = this.listProcess("tableList");
+        this.listStatementContent = this.listProcess("statementList");
     }
 });
 MWF.xApplication.AppCenter.Exporter.Element.ServiceSelector = new Class({

+ 1 - 1
o2web/source/x_component_File/lp/zh-cn.js

@@ -1,5 +1,5 @@
 MWF.xApplication.File.LP = {
-	"title": "云文件",
+	"title": "企业网盘",
 	"dropUpload": "将文件拖至此处上传",
 	
 	"upload": "上传",

+ 2 - 2
o2web/source/x_component_Homepage/lp/zh-cn.js

@@ -12,13 +12,13 @@ MWF.xApplication.Homepage.LP = o2.HPLP = {
 	"noHotpic": "暂时没有热点新闻",
 	"noInforItem": "暂时没有信息",
 	"noCalendar": "当天没有日程",
-	"noFile": "点击此处访问云文件",
+	"noFile": "点击此处访问企业网盘",
 	"moreInfor": "更多信息",
 	"allInfor": "最新信息",
 	"moreMeeting": "更多会议",
 	"moreFile": "更多文件",
 	"myMeeting": "我的会议",
-	"myFile": "我的文件",
+	"myFile": "网盘文件",
 	"myMeetingInvited": "会议邀请",
 	"myCalender": "我的日程",
 	"moreCalender": "更多日程",

+ 26 - 1
o2web/source/x_component_cms_Xform/Htmleditor.js

@@ -5,6 +5,8 @@ MWF.xApplication.cms.Xform.Htmleditor = MWF.CMSHtmleditor =  new Class({
 	_loadUserInterface: function(){
 		this.node.empty();
         if (this.readonly){
+            // var html = this.parseImage( this._getBusinessData() );
+            // this.node.set("html", html);
             this.node.set("html", this._getBusinessData());
             this.node.setStyles({
                 "-webkit-user-select": "text",
@@ -32,8 +34,31 @@ MWF.xApplication.cms.Xform.Htmleditor = MWF.CMSHtmleditor =  new Class({
 
             this.loadCkeditor(config);
         }
-    //    this._loadValue();
 	},
+    // parseImage : function( html ){
+    //     html = ( html || "" ).replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function (img, capture) {
+    //         if( img.indexOf( "data-id" ) > -1 && img.indexOf("setImageSrc()") > -1 ){
+    //             var ids = img.match( /(?<=data-id=").*?(?=")/g );
+    //             if( ids && ids.length > 0 ){
+    //                 var newSrc = MWF.xDesktop.getImageSrc( ids[0] );
+    //                 var newImg = this.replaceAttr( img, "img", "src", newSrc );
+    //                 return newImg;
+    //             }
+    //         }
+    //         return img;
+    //     }.bind(this));
+    //     return html
+    // },
+    // replaceAttr: function(src_str, tag, attr, val) {
+    //     if(src_str.indexOf(attr) > 0) {
+    //         //包含attr属性,替换attr
+    //         var sub_reg = new RegExp(attr + '=[\'\"]([^"]*)[\'\"]', 'gi');
+    //         return src_str.replace(sub_reg, attr +'=' + val);
+    //     }else{
+    //         //不包含attr属性,添加attr
+    //         return src_str.substr(0, tag.length + 1) + ' ' + attr + '=' + val + ' ' + src_str.substr(tag.length + 2, src_str.length);
+    //     }
+    // },
     loadCkeditor: function(config){
         _self = this;
         COMMON.AjaxModule.loadDom("ckeditor", function(){

+ 5 - 0
o2web/source/x_component_portal_PageDesigner/$Main/default/tools.json

@@ -128,5 +128,10 @@
     "icon": "statement.png",
     "text": "嵌入查询视图",
     "className": "Statement"
+  },
+  "datagrid": {
+    "icon": "datagrid.png",
+    "text": "数据网格",
+    "className": "Datagrid"
   }
 }

+ 38 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/datagrid$Data.html

@@ -0,0 +1,38 @@
+<div style="background-color: #FFF; overflow: hidden">
+    <div title="基本" class="MWFTab">
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">标识:</td>
+                <td class="editTableValue">text{$.id}</td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">名称:</td>
+                <td class="editTableValue"><input type="text" name="name" value="text{$.name}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">描述:</td>
+                <td class="editTableValue"><input type="text" name="description" value="text{$.description}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">类型:</td>
+                <td class="editTableValue">
+                    <input class="editTableRadio" name="cellType" text{!($.cellType) || ($.cellType=='content')?'checked':''} type="radio" value="content"/>内容
+                    <input class="editTableRadio" name="cellType" text{($.cellType=='sequence')?'checked':''} type="radio" value="sequence"/>序号
+                </td>
+            </tr>
+        </table>
+
+        <div class="MWFMaplist" name="styles" title="样式"></div>
+        <div class="MWFMaplist" name="properties" title="属性"></div>
+
+    </div>
+    <div title="事件"  class="MWFTab">
+        <div class="MWFEventsArea" name="events"></div>
+    </div>
+    <div title="HTML"  class="MWFTab">
+        <div class="MWFHTMLArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+    <div title="JSON"  class="MWFTab">
+        <div class="MWFJSONArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+</div>

+ 51 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/css.wcss

@@ -0,0 +1,51 @@
+{
+	"moduleNodeMove": {
+		"border": "2px dashed #ffa200",
+		"height": "30px",
+		"width": "80px",
+		"overflow": "hidden",
+		"margin": "3px",
+		"display": "block",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "absolute",
+		"z-index": 10002,
+		"opacity": 0.7,
+		"width": "100px",
+		"cursor": "move"
+	},
+	"moduleNodeShow": {
+		"border": "1px dashed #333",
+		"height": "2px",
+		"cursor": "pointer",
+		"line-height": "22px",
+		"overflow": "hidden",
+		"margin": "3px 3px",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"display": "block",
+		"top": "auto",
+		"left": "auto",
+		"width": "auto",
+		"opacity": 0.5,
+		"background": "#ffa200"
+	},
+	"moduleNode": {
+		"border": "1px dashed #999",
+		"height": "20px",
+		"cursor": "pointer",
+		"line-height": "2px",
+		"overflow": "hidden",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"opacity": 1,
+		"background": "transparent"
+	},
+	"sequenceNode": {
+	    "color": "red",
+	    "font-style": "italic"
+	}
+	
+}

BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/copy.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/copy1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/delete.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/delete1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteCol.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteCol1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteRow.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/deleteRow1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertCol.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertCol1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertRow.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/insertRow1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/mergerCell.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/move.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/move1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/default/icon/splitCell.png


+ 16 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/insertCol.html

@@ -0,0 +1,16 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right">列数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFInsertColNumber" type="text" id="MWFInsertColNumber" value="1" style="border:1px solid #999; width: 60px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td>
+      <input name="MWFInsertColPosition" type="radio" value="before" checked="checked" />所选之左<br />
+      <input type="radio" name="MWFInsertColPosition" value="after" />所选之右
+    </td>
+  </tr>
+</table>
+</div>

+ 16 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/insertRow.html

@@ -0,0 +1,16 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right">行数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFInsertRowNumber" type="text" id="MWFInsertRowNumber" value="1" style="border:1px solid #999; width: 60px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td>
+      <input name="MWFInsertRowPosition" type="radio" value="before" checked="checked" />所选之上<br />
+      <input type="radio" name="MWFInsertRowPosition" value="after" />所选之下
+    </td>
+  </tr>
+</table>
+</div>

+ 17 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/mergerCell.html

@@ -0,0 +1,17 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right" style="width:80px">合并单元格数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFMergerCellNumber" type="text" id="MWFMergerCellNumber" value="1" style="border:1px solid #999; width:100px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td colspan="2" align="center">
+      <input name="MWFMergerCellDirection" type="radio" value="right" id="MWFMergerCellDirectionRight"/>向右合并
+      <input type="radio" name="MWFMergerCellDirection" value="left" id="MWFMergerCellDirectionLeft"/>向左合并<br />
+      <input type="radio" name="MWFMergerCellDirection" value="down" id="MWFMergerCellDirectionDown"/>向下合并
+      <input type="radio" name="MWFMergerCellDirection" value="up" id="MWFMergerCellDirectionUp"/>向上合并
+    </td>
+  </tr>
+</table>
+</div>

+ 72 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Data/template.json

@@ -0,0 +1,72 @@
+{
+	"id": "",
+	"name": "",
+	"type": "Datagrid$Data",
+	"description": "",
+	"events": {
+	  "queryLoad": {
+		"code": "",
+		"html": ""
+	  },
+	  "postLoad": {
+		"code": "",
+		"html": ""
+	  },
+		"load": {
+		  "code": "",
+		  "html": ""
+		},
+		"click": {
+			"code": "",
+			"html": ""
+		},
+		"dblclick": {
+			"code": "",
+			"html": ""
+		},
+		"keydown": {
+			"code": "",
+			"html": ""
+		},
+		"keypress": {
+			"code": "",
+			"html": ""
+		},
+		"keyup": {
+			"code": "",
+			"html": ""
+		},
+		"mousedown": {
+			"code": "",
+			"html": ""
+		},
+		"mousemove": {
+			"code": "",
+			"html": ""
+		},
+		"mouseout": {
+			"code": "",
+			"html": ""
+		},
+		"mouseover": {
+			"code": "",
+			"html": ""
+		},
+		"mouseup": {
+			"code": "",
+			"html": ""
+		},
+		"focus": {
+			"code": "",
+			"html": ""
+		},
+		"blur": {
+			"code": "",
+			"html": ""
+		}
+	},
+	"properties": {},
+	"class": "",
+	"styles": {},
+	"container": ""
+}

+ 53 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/datagrid$Title.html

@@ -0,0 +1,53 @@
+<div style="background-color: #FFF; overflow: hidden">
+    <div title="基本" class="MWFTab">
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">标识:</td>
+                <td class="editTableValue"><input type="text" name="id" value="text{$.id}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">名称:</td>
+                <td class="editTableValue"><input type="text" name="name" value="text{$.name}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">描述:</td>
+                <td class="editTableValue"><input type="text" name="description" value="text{$.description}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">合计:</td>
+                <td class="editTableValue">
+                    <input class="editTableRadio" name="total" text{!($.total) || ($.total=='no')?'checked':''} type="radio" value="no"/>不需要 <br/>
+                    <input class="editTableRadio" name="total" text{($.total=='number')?'checked':''} type="radio" value="number"/>合计数值 <br/>
+                    <input class="editTableRadio" name="total" text{($.total=='count')?'checked':''} type="radio" value="count"/>合计数量 <br/>
+                </td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">隐藏:</td>
+                <td class="editTableValue">
+                    <input class="editTableRadio" name="isShow" text{($.isShow!==false)?'checked':''} type="radio" value="true"/>显示该列 <br/>
+                    <input class="editTableRadio" name="isShow" text{($.isShow==false)?'checked':''} type="radio" value="false"/>隐藏该列 <br/>
+                </td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">导入导出:</td>
+                <td class="editTableValue">
+                    <input class="editTableRadio" name="isImpExp" text{($.isImpExp!==false)?'checked':''} type="radio" value="true"/>允许 <br/>
+                    <input class="editTableRadio" name="isImpExp" text{($.isImpExp==false)?'checked':''} type="radio" value="false"/>不允许 <br/>
+                </td>
+            </tr>
+        </table>
+
+        <div class="MWFMaplist" name="styles" title="样式"></div>
+        <div class="MWFMaplist" name="properties" title="属性"></div>
+
+    </div>
+    <div title="事件"  class="MWFTab">
+        <div class="MWFEventsArea" name="events"></div>
+    </div>
+    <div title="HTML"  class="MWFTab">
+        <div class="MWFHTMLArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+    <div title="JSON"  class="MWFTab">
+        <div class="MWFJSONArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+</div>

+ 49 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/css.wcss

@@ -0,0 +1,49 @@
+{
+	"moduleNodeMove": {
+		"border": "2px dashed #ffa200",
+		"height": "30px",
+		"width": "80px",
+		"overflow": "hidden",
+		"margin": "3px",
+		"display": "block",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "absolute",
+		"z-index": 10002,
+		"opacity": 0.7,
+		"width": "100px",
+		"cursor": "move"
+	},
+	"moduleNodeShow": {
+		"border": "1px dashed #333",
+		"height": "2px",
+		"cursor": "pointer",
+		"line-height": "22px",
+		"overflow": "hidden",
+		"margin": "3px 3px",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"display": "block",
+		"top": "auto",
+		"left": "auto",
+		"width": "auto",
+		"opacity": 0.5,
+		"background": "#ffa200"
+	},
+	"moduleNode": {
+		"border": "1px dashed #999",
+		"height": "28px",
+		"line-height": "28px",
+		"cursor": "pointer",
+		"line-height": "2px",
+		"overflow": "hidden",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"opacity": 1,
+		"background": "#C3CEEA",
+		//"background": "#efefef"
+	}
+	
+}

BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/copy.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/copy1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/delete.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/delete1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteCol.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteCol1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteRow.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/deleteRow1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertCol.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertCol1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertRow.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/insertRow1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/mergerCell.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/move.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/move1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/default/icon/splitCell.png


+ 16 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/insertCol.html

@@ -0,0 +1,16 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right">列数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFInsertColNumber" type="text" id="MWFInsertColNumber" value="1" style="border:1px solid #999; width: 60px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td>
+      <input name="MWFInsertColPosition" type="radio" value="before" checked="checked" />所选之左<br />
+      <input type="radio" name="MWFInsertColPosition" value="after" />所选之右
+    </td>
+  </tr>
+</table>
+</div>

+ 16 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/insertRow.html

@@ -0,0 +1,16 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right">行数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFInsertRowNumber" type="text" id="MWFInsertRowNumber" value="1" style="border:1px solid #999; width: 60px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td>&nbsp;</td>
+    <td>
+      <input name="MWFInsertRowPosition" type="radio" value="before" checked="checked" />所选之上<br />
+      <input type="radio" name="MWFInsertRowPosition" value="after" />所选之下
+    </td>
+  </tr>
+</table>
+</div>

+ 17 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/mergerCell.html

@@ -0,0 +1,17 @@
+<div style="font-size:12px">
+  <table width="100%" border="0" cellspacing="5" cellpadding="5">
+  <tr>
+    <td align="right" style="width:80px">合并单元格数</td>
+    <td><label for="textfield"></label>
+    <input name="MWFMergerCellNumber" type="text" id="MWFMergerCellNumber" value="1" style="border:1px solid #999; width:100px; height:18px" /></td>
+  </tr>
+  <tr>
+    <td colspan="2" align="center">
+      <input name="MWFMergerCellDirection" type="radio" value="right" id="MWFMergerCellDirectionRight"/>向右合并
+      <input type="radio" name="MWFMergerCellDirection" value="left" id="MWFMergerCellDirectionLeft"/>向左合并<br />
+      <input type="radio" name="MWFMergerCellDirection" value="down" id="MWFMergerCellDirectionDown"/>向下合并
+      <input type="radio" name="MWFMergerCellDirection" value="up" id="MWFMergerCellDirectionUp"/>向上合并
+    </td>
+  </tr>
+</table>
+</div>

+ 72 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid$Title/template.json

@@ -0,0 +1,72 @@
+{
+	"id": "",
+	"name": "",
+	"type": "Datagrid$Title",
+	"description": "",
+	"events": {
+	  "queryLoad": {
+		"code": "",
+		"html": ""
+	  },
+	  "postLoad": {
+		"code": "",
+		"html": ""
+	  },
+		"load": {
+		  "code": "",
+		  "html": ""
+		},
+		"click": {
+			"code": "",
+			"html": ""
+		},
+		"dblclick": {
+			"code": "",
+			"html": ""
+		},
+		"keydown": {
+			"code": "",
+			"html": ""
+		},
+		"keypress": {
+			"code": "",
+			"html": ""
+		},
+		"keyup": {
+			"code": "",
+			"html": ""
+		},
+		"mousedown": {
+			"code": "",
+			"html": ""
+		},
+		"mousemove": {
+			"code": "",
+			"html": ""
+		},
+		"mouseout": {
+			"code": "",
+			"html": ""
+		},
+		"mouseover": {
+			"code": "",
+			"html": ""
+		},
+		"mouseup": {
+			"code": "",
+			"html": ""
+		},
+		"focus": {
+			"code": "",
+			"html": ""
+		},
+		"blur": {
+			"code": "",
+			"html": ""
+		}
+	},
+	"properties": {},
+	"class": "",
+	"styles": {},
+	"container": ""
+}

+ 29 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid.js

@@ -0,0 +1,29 @@
+
+MWF.xDesktop.requireApp("process.FormDesigner", "Module.Datagrid", null, false);
+
+MWF.xApplication.portal.PageDesigner.Module.Datagrid = MWF.PCDatagrid = new Class({
+    Extends: MWF.FCDatagrid,
+    options: {
+        "style": "default",
+        "propertyPath": "../x_component_portal_PageDesigner/Module/Datagrid/datagrid.html"
+    },
+
+    initialize: function(form, options){
+        this.setOptions(options);
+
+        this.path = "../x_component_portal_PageDesigner/Module/Datagrid/";
+        this.cssPath = "../x_component_portal_PageDesigner/Module/Datagrid/"+this.options.style+"/css.wcss";
+
+        this._loadCss();
+        this.moduleType = "component";
+        this.moduleName = "datagrid";
+
+        this.form = form;
+        this.container = null;
+        this.containerNode = null;
+        this.containers = [];
+        this.elements = [];
+        this.selectedMultiTds = [];
+    },
+
+});

+ 28 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/__datagrid1.html

@@ -0,0 +1,28 @@
+<div style="background-color: #FFF; overflow: hidden">
+	<div title="基本" class="MWFTab">
+		<table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+		  <tr>
+		    <td class="editTableTitle">标识:</td>
+		    <td class="editTableValue"><input type="text" name="id" value="text{$.id}" class="editTableInput"/></td>
+		  </tr>
+		  <tr>
+		    <td class="editTableTitle">名称:</td>
+		    <td class="editTableValue"><input type="text" name="name" value="text{$.name}" class="editTableInput"/></td>
+		  </tr>
+		  <tr>
+		    <td class="editTableTitle">描述:</td>
+		    <td class="editTableValue"><input type="text" name="description" value="text{$.description}" class="editTableInput"/></td>
+		  </tr>
+		</table>
+		
+		<div class="MWFMaplist" name="styles" title="样式"></div>
+		<div class="MWFMaplist" name="properties" title="属性"></div>
+
+	</div>
+	<div title="事件"  class="MWFTab">
+		<div class="MWFEventsArea" name="events"></div>
+	</div>
+	<div title="HTML"  class="MWFTab">
+		<div class="MWFHTMLArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+	</div>
+</div>

+ 64 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/__template.json

@@ -0,0 +1,64 @@
+{
+	"id": "",
+	"name": "",
+	"type": "Datagrid",
+	"description": "",
+	"defaultValue": {
+		"code": "",
+		"html": ""
+	},
+	"events": {
+		"click": {
+			"code": "",
+			"html": ""
+		},
+		"dblclick": {
+			"code": "",
+			"html": ""
+		},
+		"keydown": {
+			"code": "",
+			"html": ""
+		},
+		"keypress": {
+			"code": "",
+			"html": ""
+		},
+		"keyup": {
+			"code": "",
+			"html": ""
+		},
+		"mousedown": {
+			"code": "",
+			"html": ""
+		},
+		"mousemove": {
+			"code": "",
+			"html": ""
+		},
+		"mouseout": {
+			"code": "",
+			"html": ""
+		},
+		"mouseover": {
+			"code": "",
+			"html": ""
+		},
+		"mouseup": {
+			"code": "",
+			"html": ""
+		},
+		"focus": {
+			"code": "",
+			"html": ""
+		},
+		"blur": {
+			"code": "",
+			"html": ""
+		}
+	},
+	"properties": {},
+	"class": "",
+	"styles": {},
+	"container": ""
+}

+ 163 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/datagrid.html

@@ -0,0 +1,163 @@
+<div style="background-color: #FFF; overflow: hidden">
+    <div title="基本" class="MWFTab">
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">标识:</td>
+                <td class="editTableValue"><input type="text" name="id" value="text{$.id}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">名称:</td>
+                <td class="editTableValue"><input type="text" name="name" value="text{$.name}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">描述:</td>
+                <td class="editTableValue"><input type="text" name="description" value="text{$.description}" class="editTableInput"/></td>
+            </tr>
+        </table>
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">边框:</td>
+                <td class="editTableValue"><input type="text" name="border" value="text{$.border}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">背景颜色:</td>
+                <td class="editTableValue"><input type="color" name="backgroundColor" value="text{$.backgroundColor}" class="editTableInput"/></td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">交替行:</td>
+                <td class="editTableValue"><input type="color" name="zebraColor" value="text{$.zebraColor}" class="editTableInput"/></td>
+            </tr>
+            <!--<tr>-->
+            <!--<td class="editTableTitle">序号:</td>-->
+            <!--<td class="editTableValue">-->
+            <!--<input type="radio" name="sequence" value="yes" text{($.sequence=='yes')?'checked':''}/>显示-->
+            <!--<input type="radio" name="sequence" value="no" text{($.sequence=='no')?'checked':''}/>不显示-->
+            <!--</td>-->
+            <!--</tr>-->
+        </table>
+
+        <div class="MWFMaplist" name="styles" collapse="true" title="样式"></div>
+        <div class="MWFMaplist" name="tableStyles" collapse="true" title="表格样式"></div>
+
+        <div class="MWFMaplist" name="properties" collapse="true" title="属性"></div>
+        <div class="MWFScriptArea" name="defaultData" title="默认数据(S)"></div>
+
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">允许删除:</td>
+                <td class="editTableValue">
+                    <input type="radio" name="deleteable" value="yes" text{($.deleteable!=='no')?'checked':''}/>是
+                    <input type="radio" name="deleteable" value="no" text{($.deleteable==='no')?'checked':''}/>否
+                </td>
+            </tr>
+            <tr>
+                <td class="editTableTitle">允许添加:</td>
+                <td class="editTableValue">
+                    <input type="radio" name="addable" value="yes" text{($.addable!=='no')?'checked':''}/>是
+                    <input type="radio" name="addable" value="no" text{($.addable==='no')?'checked':''}/>否
+                </td>
+            </tr>
+        </table>
+        <div class="MWFScriptArea" name="editableScript" title="是否可编辑(S)"></div>
+
+        <div style="height:24px; text-align: center; line-height: 24px; background-color: #EEE; border-top: 1px solid #999;">导出导入</div>
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">启用:</td>
+                <td class="editTableValue">
+                    <input type="radio" name="impexpType" value="none" text{(!$.impexpType || $.impexpType==='none')?'checked':''}
+                           onclick="if (this.checked){ $('text{$.pid}impexpArea').setStyle('display', 'none')}" />禁用
+                    <input type="radio" name="impexpType" value="impexp" text{($.impexpType==='impexp')?'checked':''}
+                           onclick="if (this.checked){ $('text{$.pid}impexpArea').setStyle('display', 'block')}" />导出导入
+                    <input type="radio" name="impexpType" value="exp" text{($.impexpType==='exp')?'checked':''}
+                           onclick="if (this.checked){ $('text{$.pid}impexpArea').setStyle('display', 'block')}" />仅导出
+                    <input type="radio" name="impexpType" value="imp" text{($.impexpType==='imp')?'checked':''}
+                           onclick="if (this.checked){ $('text{$.pid}impexpArea').setStyle('display', 'block')}" />仅导入
+                </td>
+            </tr>
+        </table>
+        <div id="text{$.pid}impexpArea" style="display: text{($.impexpType && $.impexpType!=='none')?'block':'none'};">
+            <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+                <tr>
+                    <td class="editTableTitle"></td>
+                    <td class="editTableValue">
+                        注:序号、图片、附件和隐藏列不能导入导出。
+                    </td>
+                </tr>
+                <tr>
+                    <td class="editTableTitle">按钮位置:</td>
+                    <td class="editTableValue">
+                        <input type="radio" name="impexpPosition" value="leftTop" text{(!$.impexpPosition || $.impexpPosition==='leftTop')?'checked':''}/>左上
+                        <input type="radio" name="impexpPosition" value="centerTop" text{($.impexpPosition==='centerTop')?'checked':''}/>中上
+                        <input type="radio" name="impexpPosition" value="rightTop" text{($.impexpPosition==='rightTop')?'checked':''}/>右上
+                        <input type="radio" name="impexpPosition" value="leftBottom" text{($.impexpPosition==='leftBottom')?'checked':''}/>左下
+                        <input type="radio" name="impexpPosition" value="centerBottom" text{($.impexpPosition==='centerBottom')?'checked':''}/>中下
+                        <input type="radio" name="impexpPosition" value="rightBottom" text{($.impexpPosition==='rightBottom')?'checked':''}/>右下
+                    </td>
+                </tr>
+                <tr>
+                    <td class="editTableTitle">导入按钮文本:</td>
+                    <td class="editTableValue"><input type="text" name="importActionText" value="text{$.importActionText || '导入Excel'}" class="editTableInput"/></td>
+                </tr>
+            </table>
+            <div class="MWFMaplist" name="importActionStyles" collapse="true" title="导入按钮样式"></div>
+            <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+                <tr>
+                    <td class="editTableTitle">导出按钮文本:</td>
+                    <td class="editTableValue"><input type="text" name="exportActionText" value="text{$.exportActionText || '导出Excel'}" class="editTableInput"/></td>
+                </tr>
+            </table>
+            <div class="MWFMaplist" name="exportActionStyles" collapse="true" title="导出按钮样式"></div>
+            <div class="MWFFormulaArea" name="excelName" title="导出文件名称"></div>
+        </div>
+
+        <div class="MWFValidation" name="validationConfig"></div>
+        <div class="MWFScriptArea" name="validation" title="校验脚本 (S)"></div>
+    </div>
+    <div title="样式" class="MWFTab">
+        <div class="MWFMaplist" name="titleStyles" collapse="true" title="标题单元格样式"></div>
+        <div class="MWFMaplist" name="contentStyles" collapse="true" title="内容单元格样式"></div>
+        <div class="MWFMaplist" name="actionStyles" collapse="true" title="操作单元格样式"></div>
+        <div class="MWFMaplist" name="editStyles" collapse="true" title="编辑单元格样式"></div>
+        <div class="MWFMaplist" name="amountStyles" collapse="true" title="总计单元格样式"></div>
+        <div class="MWFMaplist" name="itemTitleStyles" collapse="true" title="条目标题样式(仅移动端)"></div>
+    </div>
+    <div title="区段" class="MWFTab">
+        <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+            <tr>
+                <td class="editTableTitle">启用区段:</td>
+                <td class="editTableValue">
+                    <input onclick="if (this.checked){ $('text{$.pid}sectionByEditArea').setStyle('display', 'block')}" type="radio" name="section" value="yes" text{($.section=='yes')?'checked':''}/>是
+                    <input onclick="if (this.checked){ $('text{$.pid}sectionByEditArea').setStyle('display', 'none')}" type="radio" name="section" value="no" text{($.section!='yes')?'checked':''}/>否
+                </td>
+            </tr>
+        </table>
+
+        <div id="text{$.pid}sectionByEditArea" style="display: text{($.section=='yes')?'block':'none'};">
+            <table width="100%" border="0" cellpadding="5" cellspacing="0" class="editTable">
+                <tr>
+                    <td class="editTableTitle">区段依据:</td>
+                    <td class="editTableValue">
+                        <input class="editTableRadio" onclick="if (this.checked){ $('text{$.pid}sectionByScriptEditArea').setStyle('display', 'none');}" name="sectionBy" text{(($.sectionBy=='person') || ($.sectionBy!='unit' && $.sectionBy!='activity' && $.sectionBy!='script'))?'checked':''} type="radio" value="person"/>处理人<br/>
+                        <input class="editTableRadio" onclick="if (this.checked){ $('text{$.pid}sectionByScriptEditArea').setStyle('display', 'none');}"  name="sectionBy" text{($.sectionBy=='department')?'checked':''} type="radio" value="unit"/>处理人所在组织<br/>
+                        <input class="editTableRadio" onclick="if (this.checked){ $('text{$.pid}sectionByScriptEditArea').setStyle('display', 'none');}"  name="sectionBy" text{($.sectionBy=='activity')?'checked':''} type="radio" value="activity"/>活动ID<br/>
+                        <input class="editTableRadio" onclick="if (this.checked){ $('text{$.pid}sectionByScriptEditArea').setStyle('display', 'none');}"  name="sectionBy" text{($.sectionBy=='splitValue')?'checked':''} type="radio" value="splitValue"/>拆分值<br/>
+                        <input class="editTableRadio" onclick="if (this.checked){ $('text{$.pid}sectionByScriptEditArea').setStyle('display', 'block');}"  name="sectionBy" text{($.sectionBy=='script')?'checked':''} type="radio" value="script"/>脚本<br/>
+                    </td>
+                </tr>
+            </table>
+            <div id="text{$.pid}sectionByScriptEditArea" style="display: text{($.sectionBy=='script')?'block':'none'};">
+                <div class="MWFScriptArea" name="sectionByScript" title="区段依据 (S)"></div>
+            </div>
+        </div>
+    </div>
+    <div title="事件"  class="MWFTab">
+        <div class="MWFEventsArea" name="events"></div>
+    </div>
+    <div title="HTML"  class="MWFTab">
+        <div class="MWFHTMLArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+    <div title="JSON"  class="MWFTab">
+        <div class="MWFJSONArea" style="font-family: Verdana, Geneva, sans-serif; font-size:14px"></div>
+    </div>
+</div>

+ 34 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/datagridCreate.html

@@ -0,0 +1,34 @@
+<div style="font-size:12px">
+  <div style="height:18px; background-color:#EEE; border-bottom: 1px solid #333; maring-bottom:5px">表格大小</div><br/>
+  <table width="100%" border="0" cellspacing="0" cellpadding="3px">
+    <tr>
+      <td align="right">列</td>
+      <td><input type="text" name="MWFNewTableColumn" id="MWFNewTableColumn" value="3" style="border:1px solid #999; width: 60px; height:18px" /></td>
+      <td align="right"></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td align="right">表格宽度</td>
+      <td colspan="3"><input type="text" name="MWFNewTableWidth" id="MWFNewTableWidth" value="100" style="border:1px solid #999; width: 60px; height:18px" />
+        <select name="MWFNewTableWidthUnit" id="MWFNewTableWidthUnit">
+          <option value="px">像素</option>
+          <option value="percent" selected="selected">百分比</option>
+      </select></td>
+    </tr>
+    <tr>
+      <td align="right">边框粗细</td>
+      <td colspan="3"><input type="text" name="MWFNewTableBorder" id="MWFNewTableBorder" value="0" style="border:1px solid #999; width: 60px; height:18px" />
+      像素</td>
+    </tr>
+    <tr>
+      <td align="right">单元格边距</td>
+      <td colspan="3"><input type="text" name="MWFNewTableCellpadding" id="MWFNewTableCellpadding" value="3" style="border:1px solid #999; width: 60px; height:18px" />
+      像素</td>
+    </tr>
+    <tr>
+      <td align="right">单元格间距</td>
+      <td colspan="3"><input type="text" name="MWFNewTableCellspacing" id="MWFNewTableCellspacing" value="0" style="border:1px solid #999; width: 60px; height:18px" />
+      像素</td>
+    </tr>
+  </table>
+</div>

+ 81 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/css.wcss

@@ -0,0 +1,81 @@
+{
+	"moduleNodeMove": {
+		"border": "2px dashed #ffa200",
+		"width": "210px",
+		"overflow": "hidden",
+		"margin": "3px",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "absolute",
+		"display": "block",
+		"z-index": 10002,
+		"opacity": 0.7,
+		"cursor": "move"
+	},
+	"moduleNodeMoveTd": {
+		"border-right": "1px dashed #ffa200",
+		"border-bottom": "1px dashed #ffa200",
+		"height": "16px"
+	},
+	"moduleNodeShow": {
+		"border": "1px dashed #333",
+		"height": "2px",
+		"cursor": "pointer",
+		"line-height": "22px",
+		"overflow": "hidden",
+		"margin": "3px 3px",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"display": "block",
+		"top": "auto",
+		"left": "auto",
+		"width": "auto",
+		"opacity": 0.5,
+		"background": "#ffa200"
+	},
+	"moduleNode": {
+		"border": "1px dashed #CCC",
+		"cursor": "pointer",
+		"line-height": "22px",
+		"overflow": "auto",
+		"margin": "3px 3px",
+		"-webkit-user-select": "none",
+		"-moz-user-select": "none",
+		"position": "static",
+		"display": "block",
+		"top": "auto",
+		"left": "auto",
+		"width": "",
+		"opacity": 1,
+		"background": "transparent"
+	},
+	sequenceTitleTd: {
+        "border": "1px dashed #999",
+        "height": "20px",
+        "cursor": "pointer",
+        "line-height": "2px",
+        "overflow": "hidden",
+        "-webkit-user-select": "none",
+        "-moz-user-select": "none",
+        "position": "static",
+        "opacity": 1,
+        "width": "10px",
+        "background": "#C3CEEA"
+	},
+	sequenceTd: {
+	    "border": "1px dashed #999",
+        "height": "20px",
+        "cursor": "pointer",
+        "line-height": "2px",
+        "overflow": "hidden",
+        "-webkit-user-select": "none",
+        "-moz-user-select": "none",
+        "position": "static",
+        "opacity": 1,
+        "text-align": "center",
+        "width": "10px",
+        "background": "transparent"
+	}
+	
+}

BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/copy.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/copy1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/delete.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/delete1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/mergerCell.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/move.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/move1.png


BIN
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/default/icon/splitCell.png


+ 130 - 0
o2web/source/x_component_portal_PageDesigner/Module/Datagrid/template.json

@@ -0,0 +1,130 @@
+{
+	"id": "",
+	"name": "",
+	"type": "Datagrid",
+	"description": "",
+    "sequence": "yes",
+    "section": "no",
+    "sectionBy": "person",
+	"importActionText" : "导入Excel",
+	"exportActionText" : "导出Excel",
+    "sectionByScript": {
+      "code": "",
+      "html": ""
+    },
+	"defaultValue": {
+		"code": "",
+		"html": ""
+	},
+	"events": {
+	  "queryLoad": {
+		"code": "",
+		"html": ""
+	  },
+	  "postLoad": {
+		"code": "",
+		"html": ""
+	  },
+	  "load" : {
+		"code": "",
+		"html": ""
+	  },
+		"editCheck": {
+		  "code": "",
+		  "html": ""
+		},
+		"completeLineEdit": {
+		  "code": "",
+		  "html": ""
+		},
+		"addLine": {
+		  "code": "",
+		  "html": ""
+		},
+		"deleteLine": {
+		  "code": "",
+		  "html": ""
+		},
+		"afterDeleteLine": {
+		  "code": "",
+		  "html": ""
+		},
+		"editLine": {
+		  "code": "",
+		  "html": ""
+		},
+		"export": {
+			"code": "",
+			"html": ""
+		},
+		"import": {
+			"code": "",
+			"html": ""
+		},
+		"click": {
+			"code": "",
+			"html": ""
+		},
+		"dblclick": {
+			"code": "",
+			"html": ""
+		},
+		"keydown": {
+			"code": "",
+			"html": ""
+		},
+		"keypress": {
+			"code": "",
+			"html": ""
+		},
+		"keyup": {
+			"code": "",
+			"html": ""
+		},
+		"mousedown": {
+			"code": "",
+			"html": ""
+		},
+		"mousemove": {
+			"code": "",
+			"html": ""
+		},
+		"mouseout": {
+			"code": "",
+			"html": ""
+		},
+		"mouseover": {
+			"code": "",
+			"html": ""
+		},
+		"mouseup": {
+			"code": "",
+			"html": ""
+		},
+		"focus": {
+			"code": "",
+			"html": ""
+		},
+		"blur": {
+			"code": "",
+			"html": ""
+		}
+
+	},
+	"properties": {},
+	"class": "",
+	"styles": {},
+    "tableStyles": {},
+	"border": "",
+	"backgroundColor": "",
+	"zebraColor": "",
+	"editableScript": {
+		"code": "",
+		"html": ""
+	},
+	"defaultData": {
+		"code": "",
+		"html": ""
+	},
+	"container": ""
+}

+ 3 - 0
o2web/source/x_component_portal_PageDesigner/Module/Org/org.html

@@ -106,6 +106,9 @@
 
         <div class="MWFFormulaArea" name="defaultValue" title="默认值脚本 (S)"></div>
 
+        <div style="height: 28px; font-weight: bold; line-height:28px; background-color: #EEE; padding: 0px 6px; border-top: 1px solid #999">显示文本:</div>
+        <div class="MWFFormulaArea" name="displayTextScript" title="显示文本脚本 (S)"></div>
+
         <div class="MWFValidation" name="validationConfig"></div>
         <div class="MWFScriptArea" name="validation" title="校验脚本 (S)"></div>
 

+ 2 - 1
o2web/source/x_component_portal_PageDesigner/Module/Package.js

@@ -28,4 +28,5 @@ MWF.xDesktop.requireApp("portal.PageDesigner", "Module.SourceText", null, false)
 MWF.xDesktop.requireApp("portal.PageDesigner", "Module.SubSource", null, false);
 MWF.xDesktop.requireApp("portal.PageDesigner", "Module.Widget", null, false);
 MWF.xDesktop.requireApp("portal.PageDesigner", "Module.Widgetmodules", null, false);
-MWF.xDesktop.requireApp("portal.PageDesigner", "Module.Statement", null, false);
+MWF.xDesktop.requireApp("portal.PageDesigner", "Module.Statement", null, false);
+MWF.xDesktop.requireApp("portal.PageDesigner", "Module.Datagrid", null, false);

+ 8 - 4
o2web/source/x_component_portal_Portal/Main.js

@@ -175,11 +175,15 @@ MWF.xApplication.portal.Portal.Main = new Class({
         var check = function(){
             if (!!pageJson && loadModuleFlag){
                 this.pageJson = pageJson;
-                layout.sessionPromise.then(function(){
+                if (layout.session && layout.session.user){
                     this.openPage(pageJson, par, callback);
-                }.bind(this), function(){
-                    this.openPage(pageJson, par, callback);
-                }.bind(this));
+                }else if( layout.sessionPromise ){
+                    layout.sessionPromise.then(function () {
+                        this.openPage(pageJson, par, callback);
+                    }.bind(this), function () {
+                        this.openPage(pageJson, par, callback);
+                    }.bind(this));
+                }
             }
         }.bind(this);
 

+ 1 - 1
o2web/source/x_desktop/sso.html

@@ -44,7 +44,7 @@
                             }.bind(this)
                         });
                         res.setHeader("Content-Type", "application/json; charset=utf-8");
-                        var json = {"token": xtoken, "client": client};
+                        var json = {"token": encodeURIComponent(xtoken), "client": client};
 
                         res.send(JSON.encode(json));
                     }else{