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

Merge branch 'develop' into 'feature/optimize'

# Conflicts:
#   o2web/source/x_component_process_Xform/Form.js
胡起 5 лет назад
Родитель
Сommit
2fb35d6f84
38 измененных файлов с 1479 добавлено и 46 удалено
  1. 9 0
      o2server/pom.xml
  2. 95 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/ClassLoaderTools.java
  3. 7 1
      o2server/x_console/pom.xml
  4. 116 0
      o2server/x_console/src/main/java/com/x/server/console/InstrumentationAgent.java
  5. 1 1
      o2server/x_console/src/main/java/com/x/server/console/Main.java
  6. 4 1
      o2server/x_console/src/main/java/com/x/server/console/ResourceFactory.java
  7. 22 4
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/FormAction.java
  8. 210 0
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/V2GetWithWorkOrWorkCompleted.java
  9. 1 1
      o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/task/ActionProcessing.java
  10. 36 1
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkCompletedProperties.java
  11. 48 3
      o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Form.java
  12. 4 1
      o2web/source/o2_core/o2/lp/zh-cn.js
  13. 157 1
      o2web/source/o2_core/o2/widget/O2Identity.js
  14. 18 0
      o2web/source/o2_core/o2/xScript/CMSEnvironment.js
  15. 18 0
      o2web/source/o2_core/o2/xScript/Environment.js
  16. 18 0
      o2web/source/o2_core/o2/xScript/PageEnvironment.js
  17. 18 0
      o2web/source/o2_core/o2/xScript/ViewEnvironment.js
  18. 6 0
      o2web/source/x_component_Selector/Dictionary.js
  19. 6 0
      o2web/source/x_component_Selector/FormStyle.js
  20. 7 1
      o2web/source/x_component_Selector/Script.js
  21. 1 1
      o2web/source/x_component_portal_PageDesigner/Module/View/view.html
  22. 14 4
      o2web/source/x_component_process_FormDesigner/Module/Form/form.html
  23. 1 1
      o2web/source/x_component_process_FormDesigner/Module/View/view.html
  24. 1 0
      o2web/source/x_component_process_FormDesigner/Module/ViewSelector/ViewSelector.html
  25. 54 0
      o2web/source/x_component_process_FormDesigner/Property.js
  26. 12 0
      o2web/source/x_component_process_FormDesigner/lp/zh-cn.js
  27. 150 0
      o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/css.wcss
  28. BIN
      o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/icon/delete1.png
  29. BIN
      o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/icon/error.png
  30. 286 0
      o2web/source/x_component_process_FormDesigner/widget/ScriptIncluder.js
  31. 12 4
      o2web/source/x_component_process_ProcessDesigner/widget/PersonSelector.js
  32. 1 1
      o2web/source/x_component_process_Xform/Attachment.js
  33. 88 7
      o2web/source/x_component_process_Xform/Form.js
  34. 4 1
      o2web/source/x_component_process_Xform/View.js
  35. 2 1
      o2web/source/x_component_process_Xform/ViewSelector.js
  36. 32 9
      o2web/source/x_component_query_Query/Viewer.js
  37. 2 0
      o2web/source/x_component_query_ViewDesigner/$View/view.html
  38. 18 2
      o2web/source/x_component_query_ViewDesigner/Property.js

+ 9 - 0
o2server/pom.xml

@@ -338,6 +338,10 @@
 			<groupId>org.apache.commons</groupId>
 			<artifactId>commons-email</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>javax.activation</groupId>
+			<artifactId>activation</artifactId>
+		</dependency>
 	</dependencies>
 
 	<build>
@@ -837,6 +841,11 @@
 				<artifactId>commons-email</artifactId>
 				<version>1.5</version>
 			</dependency>
+			<dependency>
+				<groupId>javax.activation</groupId>
+				<artifactId>activation</artifactId>
+				<version>1.1.1</version>
+			</dependency>
 			<dependency>
 				<groupId>o2oa</groupId>
 				<artifactId>x_base_core_project</artifactId>

+ 95 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/ClassLoaderTools.java

@@ -0,0 +1,95 @@
+package com.x.base.core.project.tools;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.project.config.Config;
+
+public class ClassLoaderTools {
+
+	private ClassLoaderTools() {
+		// nothing
+	}
+
+	private static final String CFG = "manifest.cfg";
+	private static final String GIT = ".gitignore";
+	private static final String JAR = ".jar";
+	private static final String ZIP = ".zip";
+
+	public static URLClassLoader urlClassLoader(boolean systemParent, boolean ext, boolean store, boolean custom,
+			boolean dynamic, Path... paths) throws Exception {
+		return urlClassLoader(systemParent, ext, store, custom, dynamic, ListTools.toList(paths));
+	}
+
+	public static URLClassLoader urlClassLoader(boolean systemParent, boolean ext, boolean store, boolean custom,
+			boolean dynamic, List<Path> paths) throws Exception {
+		Set<Path> set = new HashSet<>();
+		if (ext) {
+			set.addAll(dirCfg(Config.dir_commons_ext().toPath()));
+		}
+		if (store) {
+			set.addAll(dirCfg(Config.dir_store_jars().toPath()));
+		}
+		if (custom) {
+			set.addAll(dir(Config.dir_custom_jars().toPath()));
+		}
+		if (dynamic) {
+			set.addAll(dir(Config.dir_dynamic_jars().toPath()));
+		}
+		set.addAll(paths);
+		if (systemParent) {
+			return URLClassLoader.newInstance(toURL(set), ClassLoader.getSystemClassLoader());
+		} else {
+			return URLClassLoader.newInstance(toURL(set));
+		}
+	}
+
+	private static URL[] toURL(Set<Path> set) throws MalformedURLException {
+		URL[] urls = new URL[set.size()];
+		int idx = 0;
+		for (Path p : set) {
+			urls[idx++] = p.toUri().toURL();
+		}
+		return urls;
+	}
+
+	private static List<Path> dirCfg(Path dir) throws IOException {
+		List<Path> paths = new ArrayList<>();
+		Path cfg = dir.resolve(CFG);
+		if (Files.exists(dir) && Files.isDirectory(dir) && Files.exists(cfg) && Files.isRegularFile(cfg)) {
+			List<String> names = Files.readAllLines(cfg);
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> !(o.getFileName().toString().equalsIgnoreCase(CFG)
+						|| o.getFileName().toString().equalsIgnoreCase(GIT))).forEach(o -> {
+							if (names.remove(o.getFileName().toString())) {
+								paths.add(o);
+							}
+						});
+			}
+		}
+		return paths;
+	}
+
+	private static List<Path> dir(Path dir) throws IOException {
+		List<Path> paths = new ArrayList<>();
+		if (Files.exists(dir) && Files.isDirectory(dir)) {
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> StringUtils.endsWithAny(StringUtils.lowerCase(o.getFileName().toString()), JAR, ZIP))
+						.forEach(paths::add);
+			}
+		}
+		return paths;
+	}
+
+}

+ 7 - 1
o2server/x_console/pom.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+	xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<groupId>o2oa</groupId>
@@ -58,6 +61,9 @@
 							<addClasspath>false</addClasspath>
 							<mainClass>com.x.server.console.Main</mainClass>
 						</manifest>
+						<manifestEntries>
+							<Premain-Class>com.x.server.console.InstrumentationAgent</Premain-Class>
+						</manifestEntries>
 					</archive>
 				</configuration>
 			</plugin>

+ 116 - 0
o2server/x_console/src/main/java/com/x/server/console/InstrumentationAgent.java

@@ -0,0 +1,116 @@
+package com.x.server.console;
+
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
+
+public class InstrumentationAgent {
+
+	private static Instrumentation INST;
+
+	private static final String CFG = "manifest.cfg";
+	private static final String GIT = ".gitignore";
+
+	public static void agentmain(String args, Instrumentation inst) {
+		INST = inst;
+		try {
+			Path base = getBasePath();
+			if (Files.exists(base.resolve("custom/jars"))) {
+				load(base, "custom/jars");
+			}
+			if (Files.exists(base.resolve("dynamic/jars"))) {
+				load(base, "dynamic/jars");
+			}
+			load(base, "store/jars");
+			load(base, "commons/ext");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	public static void premain(String args, Instrumentation inst) {
+		INST = inst;
+		try {
+			Path base = getBasePath();
+			if (Files.exists(base.resolve("custom/jars"))) {
+				load(base, "custom/jars");
+			}
+			if (Files.exists(base.resolve("dynamic/jars"))) {
+				load(base, "dynamic/jars");
+			}
+			load(base, "store/jars");
+			load(base, "commons/ext");
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private static void load(Path base, String sub) throws Exception {
+		Path dir = base.resolve(sub);
+		Path cfg = dir.resolve(CFG);
+		if (Files.exists(dir) && Files.isDirectory(dir) && Files.exists(cfg) && Files.isRegularFile(cfg)) {
+			List<String> names = Files.readAllLines(cfg);
+			if (names.isEmpty()) {
+				throw new Exception(String.format("%s manifest is empty.", sub));
+			}
+			try (Stream<Path> stream = Files.list(dir)) {
+				stream.filter(o -> !(o.getFileName().toString().equalsIgnoreCase(CFG)
+						|| o.getFileName().toString().equalsIgnoreCase(GIT))).forEach(o -> {
+							try {
+								if (names.remove(o.getFileName().toString())) {
+									// addURLToClassPath(o);
+									System.out.println("load jar:" + o.toString());
+									INST.appendToSystemClassLoaderSearch(new JarFile(o.toString()));
+								} else {
+									Files.delete(o);
+									System.out.printf("delete unnecessary file from %s: %s.", sub,
+											o.getFileName().toString());
+								}
+							} catch (IOException e) {
+								e.printStackTrace();
+							}
+						});
+			}
+			for (String name : names) {
+				System.out.printf("can not load jar from %s: %s", sub, name);
+			}
+		} else {
+			throw new Exception(String.format("invalid directory: %s", sub));
+		}
+	}
+
+	private static Path getBasePath() throws Exception {
+		Path path = Paths.get(InstrumentationAgent.class.getProtectionDomain().getCodeSource().getLocation().toURI());
+		Path version = path.resolveSibling("version.o2");
+		if (Files.exists(version) && Files.isRegularFile(version)) {
+			return version.getParent();
+		}
+		throw new Exception("can not define o2server base directory.");
+	}
+
+	private static void addURLToClassPath(Path jarPath) {
+		ClassLoader classLoader = ClassLoader.getSystemClassLoader();
+		try {
+			if (classLoader instanceof URLClassLoader) {
+				Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class);
+				method.setAccessible(true);
+				method.invoke(classLoader, jarPath.toUri().toURL());
+			} else {
+				Method method = classLoader.getClass().getDeclaredMethod("appendToClassPathForInstrumentation",
+						String.class);
+				method.setAccessible(true);
+				method.invoke(classLoader, jarPath.toAbsolutePath().toString());
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}

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

@@ -57,7 +57,7 @@ public class Main {
 		String base = getBasePath();
 		pid(base);
 		scanWar(base);
-		loadJars(base);
+		// loadJars(base);
 		/* getVersion需要FileUtils在后面运行 */
 		cleanTempDir(base);
 		createTempClassesDirectory(base);

+ 4 - 1
o2server/x_console/src/main/java/com/x/server/console/ResourceFactory.java

@@ -30,6 +30,7 @@ import com.x.base.core.project.config.DataServer;
 import com.x.base.core.project.config.ExternalDataSource;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.ClassLoaderTools;
 import com.x.base.core.project.tools.DefaultCharset;
 import com.x.base.core.project.tools.ListTools;
 import com.x.server.console.node.EventQueueExecutor;
@@ -43,7 +44,9 @@ public class ResourceFactory {
 	private static Logger logger = LoggerFactory.getLogger(ResourceFactory.class);
 
 	public static void bind() throws Exception {
-		try (ScanResult sr = new ClassGraph().enableAnnotationInfo().scan()) {
+		try (ScanResult sr = new ClassGraph()
+				.addClassLoader(ClassLoaderTools.urlClassLoader(true, false, true, true, true)).enableAnnotationInfo()
+				.scan()) {
 			node(sr);
 			containerEntities(sr);
 			containerEntityNames(sr);

+ 22 - 4
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/FormAction.java

@@ -45,7 +45,6 @@ public class FormAction extends StandardJaxrsAction {
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);
 		}
-		/* 修改过的方法 */
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
@@ -65,7 +64,6 @@ public class FormAction extends StandardJaxrsAction {
 			logger.error(e, effectivePerson, request, null);
 			result.error(e);
 		}
-		/* 修改过的方法 */
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
 
@@ -129,8 +127,8 @@ public class FormAction extends StandardJaxrsAction {
 	@Path("{flag}/application/{applicationFlag}/mobile")
 	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
 	@Consumes(MediaType.APPLICATION_JSON)
-	public void getWithApplicationMobile(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request,
-			@JaxrsParameterDescribe("表单标识") @PathParam("flag") String flag,
+	public void getWithApplicationMobile(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request, @JaxrsParameterDescribe("表单标识") @PathParam("flag") String flag,
 			@JaxrsParameterDescribe("应用标识") @PathParam("applicationFlag") String applicationFlag) {
 		ActionResult<ActionGetWithApplicationMobile.Wo> result = new ActionResult<>();
 		EffectivePerson effectivePerson = this.effectivePerson(request);
@@ -142,4 +140,24 @@ public class FormAction extends StandardJaxrsAction {
 		}
 		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
 	}
+
+	@JaxrsMethodDescribe(value = "V2根据工作或完成工作标识获取表单,合并关联表单和关联脚本输出.", action = V2GetWithWorkOrWorkCompleted.class)
+	@GET
+	@Path("v2/workorworkcompleted/{workOrWorkCompleted}")
+	@Produces(HttpMediaType.APPLICATION_JSON_UTF_8)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void V2GetWithWorkOrWorkCompleted(@Suspended final AsyncResponse asyncResponse,
+			@Context HttpServletRequest request,
+			@JaxrsParameterDescribe("工作或完成工作标识") @PathParam("workOrWorkCompleted") String workOrWorkCompleted) {
+		ActionResult<V2GetWithWorkOrWorkCompleted.Wo> result = new ActionResult<>();
+		EffectivePerson effectivePerson = this.effectivePerson(request);
+		try {
+			result = new V2GetWithWorkOrWorkCompleted().execute(effectivePerson, workOrWorkCompleted);
+		} catch (Exception e) {
+			logger.error(e, effectivePerson, request, null);
+			result.error(e);
+		}
+		asyncResponse.resume(ResponseFactory.getEntityTagActionResultResponse(request, result));
+	}
+
 }

+ 210 - 0
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/form/V2GetWithWorkOrWorkCompleted.java

@@ -0,0 +1,210 @@
+package com.x.processplatform.assemble.surface.jaxrs.form;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.x.base.core.container.EntityManagerContainer;
+import com.x.base.core.container.factory.EntityManagerContainerFactory;
+import com.x.base.core.project.cache.Cache.CacheCategory;
+import com.x.base.core.project.cache.Cache.CacheKey;
+import com.x.base.core.project.cache.CacheManager;
+import com.x.base.core.project.exception.ExceptionAccessDenied;
+import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.http.EffectivePerson;
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.tools.PropertyTools;
+import com.x.processplatform.assemble.surface.Business;
+import com.x.processplatform.core.entity.content.Work;
+import com.x.processplatform.core.entity.content.WorkCompleted;
+import com.x.processplatform.core.entity.element.Activity;
+import com.x.processplatform.core.entity.element.Form;
+import com.x.processplatform.core.entity.element.Script;
+
+import net.sf.ehcache.Element;
+
+class V2GetWithWorkOrWorkCompleted extends BaseAction {
+
+	private static Logger logger = LoggerFactory.getLogger(V2GetWithWorkOrWorkCompleted.class);
+
+	ActionResult<Wo> execute(EffectivePerson effectivePerson, String workOrWorkCompleted) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			ActionResult<Wo> result = new ActionResult<>();
+			Business business = new Business(emc);
+			if (!business.readableWithWorkOrWorkCompleted(effectivePerson, workOrWorkCompleted,
+					new ExceptionEntityNotExist(workOrWorkCompleted))) {
+				throw new ExceptionAccessDenied(effectivePerson);
+			}
+			Wo wo = null;
+			CacheCategory cacheCategory = new CacheCategory(Form.class, Script.class);
+			CacheKey cacheKey = new CacheKey(this.getClass(), workOrWorkCompleted);
+			Optional<?> optional = CacheManager.get(cacheCategory, cacheKey);
+			if (optional.isPresent()) {
+				wo = (Wo) optional.get();
+			} else {
+				Work work = emc.find(workOrWorkCompleted, Work.class);
+				if (null != work) {
+					wo = this.work(business, work);
+				} else {
+					wo = this.workCompleted(business, emc.flag(workOrWorkCompleted, WorkCompleted.class));
+				}
+				CacheManager.put(cacheCategory, cacheKey, wo);
+				result.setData(wo);
+			}
+			return result;
+		}
+	}
+
+	private Wo work(Business business, Work work) throws Exception {
+		Wo wo = new Wo();
+		String id = work.getForm();
+		if (StringUtils.isEmpty(id)) {
+			Activity activity = business.getActivity(work);
+			id = PropertyTools.getOrElse(activity, Activity.form_FIELDNAME, String.class, "");
+		}
+		if (StringUtils.isNotEmpty(id)) {
+			Form form = business.form().pick(id);
+			if (null != form) {
+				wo.setForm(toWoForm(form));
+				related(business, wo, form);
+			}
+		}
+		return wo;
+	}
+
+	private void related(Business business, Wo wo, Form form) throws Exception {
+		for (String relatedFormId : form.getRelatedFormList()) {
+			Form relatedForm = business.form().pick(relatedFormId);
+			if (null != relatedForm) {
+				wo.getRelatedFormMap().put(relatedFormId, toWoForm(relatedForm));
+			}
+		}
+		for (String relatedScriptId : form.getRelatedScriptList()) {
+			Script relatedScript = business.script().pick(relatedScriptId);
+			if (null != relatedScript) {
+				wo.getRelatedScriptMap().put(relatedScriptId, toWoScript(relatedScript));
+			}
+		}
+	}
+
+	private Wo workCompleted(Business business, WorkCompleted workCompleted) throws Exception {
+		Wo wo = new Wo();
+		// 先使用当前库的表单,如果不存在使用储存的表单.
+		if (StringUtils.isNotEmpty(workCompleted.getForm())) {
+			Form form = business.form().pick(workCompleted.getForm());
+			if (null != form) {
+				wo.setForm(toWoForm(form));
+				related(business, wo, form);
+			}
+		} else {
+			if (null != workCompleted.getProperties().getForm()) {
+				wo.form = toWoForm(workCompleted.getProperties().getForm());
+			}
+			for (Form f : workCompleted.getProperties().getRelatedFormList()) {
+				wo.getRelatedFormMap().put(f.getId(), toWoForm(f));
+			}
+			for (Script s : workCompleted.getProperties().getRelatedScriptList()) {
+				wo.getRelatedScriptMap().put(s.getId(), toWoScript(s));
+			}
+		}
+		return wo;
+	}
+
+	private WoForm toWoForm(Form form) {
+		WoForm wo = new WoForm();
+		wo.setId(form.getId());
+		wo.setData(form.getDataOrMobileData());
+		return wo;
+	}
+
+	private WoScript toWoScript(Script script) {
+		WoScript wo = new WoScript();
+		wo.setId(script.getId());
+		wo.setText(script.getText());
+		return wo;
+	}
+
+	public static class WoForm extends GsonPropertyObject {
+		private String id;
+		private String data;
+
+		public String getId() {
+			return id;
+		}
+
+		public void setId(String id) {
+			this.id = id;
+		}
+
+		public String getData() {
+			return data;
+		}
+
+		public void setData(String data) {
+			this.data = data;
+		}
+	}
+
+	public static class WoScript extends GsonPropertyObject {
+
+		private String id;
+
+		private String text;
+
+		public String getId() {
+			return id;
+		}
+
+		public void setId(String id) {
+			this.id = id;
+		}
+
+		public String getText() {
+			return text;
+		}
+
+		public void setText(String text) {
+			this.text = text;
+		}
+
+	}
+
+	public static class Wo extends GsonPropertyObject {
+
+		private WoForm form;
+
+		private Map<String, WoForm> relatedFormMap = new HashMap<>();
+
+		private Map<String, WoScript> relatedScriptMap = new HashMap<>();
+
+		public WoForm getForm() {
+			return form;
+		}
+
+		public void setForm(WoForm form) {
+			this.form = form;
+		}
+
+		public Map<String, WoForm> getRelatedFormMap() {
+			return relatedFormMap;
+		}
+
+		public void setRelatedFormMap(Map<String, WoForm> relatedFormMap) {
+			this.relatedFormMap = relatedFormMap;
+		}
+
+		public Map<String, WoScript> getRelatedScriptMap() {
+			return relatedScriptMap;
+		}
+
+		public void setRelatedScriptMap(Map<String, WoScript> relatedScriptMap) {
+			this.relatedScriptMap = relatedScriptMap;
+		}
+
+	}
+}

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

@@ -93,7 +93,7 @@ class ActionProcessing extends BaseAction {
 			if (null == this.work) {
 				throw new ExceptionEntityNotExist(this.task.getWork(), Work.class);
 			}
-			if (effectivePerson.isNotPerson(this.task.getPerson())) {
+			if ((!effectivePerson.isCipher()) && effectivePerson.isNotPerson(this.task.getPerson())) {
 				throw new ExceptionAccessDenied(effectivePerson, this.task);
 			}
 			if (StringUtils.isNotEmpty(wi.getRouteName()) || StringUtils.isNotEmpty(wi.getOpinion())

+ 36 - 1
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/content/WorkCompletedProperties.java

@@ -5,6 +5,8 @@ import java.util.List;
 
 import com.x.base.core.entity.JsonProperties;
 import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.processplatform.core.entity.element.Form;
+import com.x.processplatform.core.entity.element.Script;
 
 public class WorkCompletedProperties extends JsonProperties {
 
@@ -15,7 +17,16 @@ public class WorkCompletedProperties extends JsonProperties {
 	private Data data;
 
 	@FieldDescribe("合并工作日志对象")
-	public List<WorkLog> workLogList = new ArrayList<>();
+	private List<WorkLog> workLogList = new ArrayList<>();
+
+	@FieldDescribe("合并工作Form")
+	private Form form;
+
+	@FieldDescribe("合并工作relatedFormList")
+	private List<Form> relatedFormList = new ArrayList<>();
+
+	@FieldDescribe("合并工作relatedScriptList")
+	private List<Script> relatedScriptList = new ArrayList<>();
 
 	@FieldDescribe("标题")
 	private String title;
@@ -52,4 +63,28 @@ public class WorkCompletedProperties extends JsonProperties {
 		this.title = title;
 	}
 
+	public Form getForm() {
+		return form;
+	}
+
+	public void setForm(Form form) {
+		this.form = form;
+	}
+
+	public List<Form> getRelatedFormList() {
+		return relatedFormList;
+	}
+
+	public List<Script> getRelatedScriptList() {
+		return relatedScriptList;
+	}
+
+	public void setRelatedFormList(List<Form> relatedFormList) {
+		this.relatedFormList = relatedFormList;
+	}
+
+	public void setRelatedScriptList(List<Script> relatedScriptList) {
+		this.relatedScriptList = relatedScriptList;
+	}
+
 }

+ 48 - 3
o2server/x_processplatform_core_entity/src/main/java/com/x/processplatform/core/entity/element/Form.java

@@ -1,6 +1,7 @@
 package com.x.processplatform.core.entity.element;
 
 import java.util.Date;
+import java.util.List;
 import java.util.Objects;
 
 import javax.persistence.Basic;
@@ -11,12 +12,10 @@ import javax.persistence.Id;
 import javax.persistence.Inheritance;
 import javax.persistence.InheritanceType;
 import javax.persistence.Lob;
+import javax.persistence.OrderColumn;
 import javax.persistence.Table;
 import javax.persistence.UniqueConstraint;
 
-import org.apache.commons.lang3.StringUtils;
-import org.apache.openjpa.persistence.jdbc.Index;
-
 import com.x.base.core.entity.AbstractPersistenceProperties;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.SliceJpaObject;
@@ -32,6 +31,13 @@ import com.x.base.core.entity.annotation.RestrictFlag;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.processplatform.core.entity.PersistenceProperties;
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.openjpa.persistence.PersistentCollection;
+import org.apache.openjpa.persistence.jdbc.ContainerTable;
+import org.apache.openjpa.persistence.jdbc.ElementColumn;
+import org.apache.openjpa.persistence.jdbc.ElementIndex;
+import org.apache.openjpa.persistence.jdbc.Index;
+
 @Entity
 @ContainerEntity(dumpSize = 5, type = ContainerEntity.Type.element, reference = ContainerEntity.Reference.strong)
 @Table(name = PersistenceProperties.Element.Form.table, uniqueConstraints = {
@@ -200,6 +206,29 @@ public class Form extends SliceJpaObject {
 	@Column(name = ColumnNamePrefix + hasMobile_FIELDNAME)
 	private Boolean hasMobile;
 
+	public static final String relatedFormList_FIELDNAME = "relatedFormList";
+	@FieldDescribe("related form.")
+	@PersistentCollection(fetch = FetchType.EAGER)
+	@ContainerTable(name = TABLE + ContainerTableNameMiddle + relatedFormList_FIELDNAME, joinIndex = @Index(name = TABLE
+			+ IndexNameMiddle + relatedFormList_FIELDNAME + JoinIndexNameSuffix))
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
+	@ElementColumn(length = length_255B, name = ColumnNamePrefix + relatedFormList_FIELDNAME)
+	@ElementIndex(name = TABLE + IndexNameMiddle + relatedFormList_FIELDNAME + ElementIndexNameSuffix)
+	@CheckPersist(allowEmpty = true)
+	private List<String> relatedFormList;
+
+	public static final String relatedScriptList_FIELDNAME = "relatedScriptList";
+	@FieldDescribe("related form.")
+	@PersistentCollection(fetch = FetchType.EAGER)
+	@ContainerTable(name = TABLE + ContainerTableNameMiddle
+			+ relatedScriptList_FIELDNAME, joinIndex = @Index(name = TABLE + IndexNameMiddle
+					+ relatedScriptList_FIELDNAME + JoinIndexNameSuffix))
+	@OrderColumn(name = ORDERCOLUMNCOLUMN)
+	@ElementColumn(length = length_255B, name = ColumnNamePrefix + relatedScriptList_FIELDNAME)
+	@ElementIndex(name = TABLE + IndexNameMiddle + relatedScriptList_FIELDNAME + ElementIndexNameSuffix)
+	@CheckPersist(allowEmpty = true)
+	private List<String> relatedScriptList;
+
 	public void setCategory(String category) {
 		this.category = category;
 	}
@@ -284,4 +313,20 @@ public class Form extends SliceJpaObject {
 		this.hasMobile = hasMobile;
 	}
 
+	public List<String> getRelatedFormList() {
+		return relatedFormList;
+	}
+
+	public void setRelatedFormList(List<String> relatedFormList) {
+		this.relatedFormList = relatedFormList;
+	}
+
+	public List<String> getRelatedScriptList() {
+		return relatedScriptList;
+	}
+
+	public void setRelatedScriptList(List<String> relatedScriptList) {
+		this.relatedScriptList = relatedScriptList;
+	}
+
 }

+ 4 - 1
o2web/source/o2_core/o2/lp/zh-cn.js

@@ -3,7 +3,10 @@ o2.LP = window.LP || {
     "description": "描述",
     "searchKey": "请输入搜索关键字",
     "desktop_style": "桌面风格",
-    "flat_style": "扁平风格"
+    "flat_style": "扁平风格",
+    "cmsName" : "内容管理",
+    "processName" : "流程管理",
+    "portalName" : "门户管理"
 };
 
 o2.LP.process = {

+ 157 - 1
o2web/source/o2_core/o2/widget/O2Identity.js

@@ -100,7 +100,16 @@ o2.widget.O2Identity = new Class({
             }.bind(this)
         });
     },
-    setEvent: function(){},
+    setEvent: function(){
+	    if( this.open ){
+            this.node.addEvents({
+                "click": function(ev){
+                    this.open(ev);
+                    ev.stopPropagation();
+                }.bind(this)
+            });
+        }
+    },
     getPersonData: function(){
         if (!this.data.dutys){
             var action = o2.Actions.get("x_organization_assemble_control");
@@ -446,6 +455,17 @@ o2.widget.O2QueryView = new Class({
         }else{
             return this.data;
         }
+    },
+    open : function (e) {
+        if( this.data.id && this.data.query ){
+            var appId = "query.ViewDesigner" + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id, "application": this.data.query, "appId": appId};
+                layout.desktop.openApplication(e, "query.ViewDesigner", options);
+            }
+        }
     }
 });
 o2.widget.O2QueryStat = new Class({
@@ -461,6 +481,17 @@ o2.widget.O2QueryStat = new Class({
         }else{
             return this.data;
         }
+    },
+    open : function (e) {
+        if( this.data.id && this.data.query){
+            var appId = "query.StatDesigner" + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id,"application": this.data.query, "appId": appId};
+                layout.desktop.openApplication(e, "query.StatDesigner", options);
+            }
+        }
     }
 });
 o2.widget.O2QueryTable = new Class({
@@ -476,6 +507,17 @@ o2.widget.O2QueryTable = new Class({
         }else{
             return this.data;
         }
+    },
+    open : function (e) {
+        if( this.data.id && this.data.query){
+            var appId = "query.TableDesigner" + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id,"application": this.data.query, "appId": appId};
+                layout.desktop.openApplication(e, "query.TableDesigner", options);
+            }
+        }
     }
 });
 o2.widget.O2FormField = new Class({
@@ -524,6 +566,120 @@ o2.widget.O2File = new Class({
         return this.data;
     }
 });
+
+o2.widget.O2Script = new Class({
+    Extends: o2.widget.O2Group,
+    getPersonData: function(){
+        return this.data;
+    },
+    createInforNode: function(){
+        if( !this.data.appType )return false;
+
+        this.inforNode = new Element("div", {
+            "styles": this.style.identityInforNode
+        });
+        var nameNode = new Element("div", {
+            "text": o2.LP[this.data.appType+"Name"]
+        }).inject(this.inforNode);
+        var nameTextNode = new Element("div", {
+            "text": this.data.applicationName || this.data.appName
+        }).inject(this.inforNode);
+        this.tooltip = new mBox.Tooltip({
+            content: this.inforNode,
+            setStyles: {content: {padding: 15, lineHeight: 20}},
+            attach: this.node,
+            transition: 'flyin'
+        });
+    },
+    open : function (e) {
+        if( this.data.id && this.data.appId &&  this.data.appType){
+            var appName;
+            if( this.data.appType === "cms" ){
+                appName = "cms.ScriptDesigner";
+            }else if( this.data.appType === "portal" ){
+                appName = "portal.ScriptDesigner";
+            }else if( this.data.appType === "process" ) {
+                appName = "process.ScriptDesigner";
+            }
+            var appId = appName + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id, "appId": appId, "application":this.data.appId};
+                layout.desktop.openApplication(e, appName, options);
+            }
+        }
+    }
+});
+
+o2.widget.O2FormStyle = new Class({
+    Extends: o2.widget.O2Group,
+    getPersonData: function(){
+        return this.data;
+    },
+    open : function (e) {
+        if( typeOf(this.data)==="object" && this.data.id && this.data.appId && this.data.type === "script"){
+            var appName;
+            if( this.data.appType === "cms" ){
+                appName = "cms.ScriptDesigner";
+            }else{
+                appName = "process.ScriptDesigner";
+            }
+            var appId = appName + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id, "appId": appId, "application":this.data.appId};
+                layout.desktop.openApplication(e, appName, options);
+            }
+        }
+    }
+});
+
+o2.widget.O2Dictionary = new Class({
+    Extends: o2.widget.O2Group,
+    getPersonData: function(){
+        return this.data;
+    },
+    createInforNode: function(){
+        if( !this.data.appType )return false;
+
+        this.inforNode = new Element("div", {
+            "styles": this.style.identityInforNode
+        });
+        var nameNode = new Element("div", {
+            "text": o2.LP[this.data.appType+"Name"]
+        }).inject(this.inforNode);
+        var nameTextNode = new Element("div", {
+            "text": this.data.applicationName || this.data.appName
+        }).inject(this.inforNode);
+        this.tooltip = new mBox.Tooltip({
+            content: this.inforNode,
+            setStyles: {content: {padding: 15, lineHeight: 20}},
+            attach: this.node,
+            transition: 'flyin'
+        });
+    },
+    open : function (e) {
+        if( this.data.id && this.data.appId && this.data.appType){
+            var appName;
+            if( this.data.appType === "cms" ){
+                appName = "cms.DictionaryDesigner";
+            }else if( this.data.appType === "process" ) {
+                appName = "process.DictionaryDesigner";
+            }
+            var appId = appName + this.data.id;
+            if (layout.desktop.apps[appId]){
+                layout.desktop.apps[appId].setCurrent();
+            }else {
+                var options = {"id": this.data.id, "appId": appId, "application":this.data.appId};
+                layout.desktop.openApplication(e, appName, options);
+            }
+        }
+    }
+});
+
+
 o2.widget.O2Other = new Class({
     Extends: o2.widget.O2Group,
     getPersonData: function(){

+ 18 - 0
o2web/source/o2_core/o2/xScript/CMSEnvironment.js

@@ -874,6 +874,24 @@ MWF.xScript.CMSEnvironment = function(ev){
         scriptAction.getScriptByName( application, name, includedScripts, function(json){
             if (json.data){
                 includedScripts.push( key );
+
+                //名称、别名、id
+                json.data.importedList.each( function ( flag ) {
+                    if( type === "portal" ){
+                        includedScripts.push( type + "-" + json.data.portal + "-" + flag );
+                        if( json.data.portalName )includedScripts.push( type + "-" + json.data.portalName + "-" + flag );
+                        if( json.data.portalAlias )includedScripts.push( type + "-" + json.data.portalAlias + "-" + flag );
+                    }else if( type === "cms" ){
+                        includedScripts.push( type + "-" + json.data.appId + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }else if( type === "process" ){
+                        includedScripts.push( type + "-" + json.data.application + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }
+                });
+
                 includedScripts = includedScripts.concat(json.data.importedList);
                 MWF.CMSMacro.exec(json.data.text, this);
                 if (callback) callback.apply(this);

+ 18 - 0
o2web/source/o2_core/o2/xScript/Environment.js

@@ -926,7 +926,25 @@ debugger;
         scriptAction.getScriptByName( application, name, includedScripts, function(json){
             if (json.data){
                 includedScripts.push( key );
+
+                //名称、别名、id
+                json.data.importedList.each( function ( flag ) {
+                    if( type === "portal" ){
+                        includedScripts.push( type + "-" + json.data.portal + "-" + flag );
+                        if( json.data.portalName )includedScripts.push( type + "-" + json.data.portalName + "-" + flag );
+                        if( json.data.portalAlias )includedScripts.push( type + "-" + json.data.portalAlias + "-" + flag );
+                    }else if( type === "cms" ){
+                        includedScripts.push( type + "-" + json.data.appId + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }else if( type === "process" ){
+                        includedScripts.push( type + "-" + json.data.application + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }
+                });
                 includedScripts = includedScripts.concat(json.data.importedList);
+
                 MWF.Macro.exec(json.data.text, this);
                 if (callback) callback.apply(this);
             }else{

+ 18 - 0
o2web/source/o2_core/o2/xScript/PageEnvironment.js

@@ -811,6 +811,24 @@ MWF.xScript.PageEnvironment = function (ev) {
         scriptAction.getScriptByName( application, name, includedScripts, function(json){
             if (json.data){
                 includedScripts.push( key );
+
+                //名称、别名、id
+                json.data.importedList.each( function ( flag ) {
+                    if( type === "portal" ){
+                        includedScripts.push( type + "-" + json.data.portal + "-" + flag );
+                        if( json.data.portalName )includedScripts.push( type + "-" + json.data.portalName + "-" + flag );
+                        if( json.data.portalAlias )includedScripts.push( type + "-" + json.data.portalAlias + "-" + flag );
+                    }else if( type === "cms" ){
+                        includedScripts.push( type + "-" + json.data.appId + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }else if( type === "process" ){
+                        includedScripts.push( type + "-" + json.data.application + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }
+                });
+
                 includedScripts = includedScripts.concat(json.data.importedList);
                 MWF.Macro.exec(json.data.text, this);
                 if (callback) callback.apply(this);

+ 18 - 0
o2web/source/o2_core/o2/xScript/ViewEnvironment.js

@@ -727,6 +727,24 @@ MWF.xScript.ViewEnvironment = function (ev) {
         scriptAction.getScriptByName(application, name, includedScripts, function (json) {
             if (json.data) {
                 includedScripts.push(key);
+
+                //名称、别名、id
+                json.data.importedList.each( function ( flag ) {
+                    if( type === "portal" ){
+                        includedScripts.push( type + "-" + json.data.portal + "-" + flag );
+                        if( json.data.portalName )includedScripts.push( type + "-" + json.data.portalName + "-" + flag );
+                        if( json.data.portalAlias )includedScripts.push( type + "-" + json.data.portalAlias + "-" + flag );
+                    }else if( type === "cms" ){
+                        includedScripts.push( type + "-" + json.data.appId + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }else if( type === "process" ){
+                        includedScripts.push( type + "-" + json.data.application + "-" + flag );
+                        if( json.data.appName )includedScripts.push( type + "-" + json.data.appName + "-" + flag );
+                        if( json.data.appAlias )includedScripts.push( type + "-" + json.data.appAlias + "-" + flag );
+                    }
+                });
+
                 includedScripts = includedScripts.concat(json.data.importedList);
                 MWF.Macro.exec(json.data.text, this);
                 if (callback) callback.apply(this);

+ 6 - 0
o2web/source/x_component_Selector/Dictionary.js

@@ -48,9 +48,15 @@ MWF.xApplication.Selector.Dictionary = new Class({
                 }.bind(this));
                 for (var application in json) {
                     if (json[application].dictionaryList && json[application].dictionaryList.length) {
+                        json[application].dictionaryList.sort(function (a, b) {
+                            return (a.name||"").localeCompare((b.name||""));
+                        });
                         array.push(json[application]);
                     }
                 }
+                array.sort( function (a, b) {
+                    return (a.name||"").localeCompare((b.name||""));
+                });
 
                 if( this.options.appType.length === 1 ){
                     array.each( function (data) {

+ 6 - 0
o2web/source/x_component_Selector/FormStyle.js

@@ -54,9 +54,15 @@ MWF.xApplication.Selector.FormStyle = new Class({
                         }.bind(this));
                         for (var application in json) {
                             if (json[application].scriptList && json[application].scriptList.length) {
+                                json[application].scriptList.sort(function (a, b) {
+                                    return (a.name||"").localeCompare((b.name||""));
+                                });
                                 array.push(json[application]);
                             }
                         }
+                        array.sort( function (a, b) {
+                            return (a.name||"").localeCompare((b.name||""));
+                        });
 
                         var category = this._newItemCategory({
                             name : "自定义样式(脚本)",

+ 7 - 1
o2web/source/x_component_Selector/Script.js

@@ -8,7 +8,7 @@ MWF.xApplication.Selector.Script = new Class({
         "title": MWF.xApplication.Selector.LP.selectScript,
         "values": [],
         "names": [],
-        "appType" : ["process","portal"],
+        "appType" : ["process","portal","cms"],
         "expand": false,
         "forceSearchInItem" : true
     },
@@ -50,9 +50,15 @@ MWF.xApplication.Selector.Script = new Class({
                 }.bind(this));
                 for (var application in json) {
                     if (json[application].scriptList && json[application].scriptList.length) {
+                        json[application].scriptList.sort(function (a, b) {
+                            return (a.name||"").localeCompare((b.name||""));
+                        });
                         array.push(json[application]);
                     }
                 }
+                array.sort( function (a, b) {
+                    return (a.name||"").localeCompare((b.name||""));
+                });
 
                 if( this.options.appType.length === 1 ){
                     array.each( function (data) {

+ 1 - 1
o2web/source/x_component_portal_PageDesigner/Module/View/view.html

@@ -196,7 +196,7 @@
 			<div style="display:none; height: 20px; line-height: 20px; text-align:center; background-color: #eeeeee">自定义过滤数据</div>
 			<div class="fieldListAreaNode_vf" style="display:none; min-height: 56px; border-bottom:1px solid #CCCCCC; overflow: hidden;"></div>
 		</div>
-
+		<div class="MWFScriptArea" name="defaultSelectedScript" title="默认选中行脚本"></div>
 	</div>
 	<div title="事件"  class="MWFTab">
 		<div class="MWFEventsArea" name="events"></div>

+ 14 - 4
o2web/source/x_component_process_FormDesigner/Module/Form/form.html

@@ -65,7 +65,16 @@
                     <div class="MWFFormSelect" name="printForm"></div>
                 </td>
             </tr>
+            <tr>
+                <td class="editTableTitle">数据字典:</td>
+                <td class="editTableValue">
+                    <div class="MWFDictionarySelect" name="dictionaries"></div>
+                </td>
+            </tr>
         </table>
+        <div style="height:24px; text-align: center; line-height: 24px; background-color: #EEE; border-top: 1px solid #999;font-weight:bold;">加载脚本</div>
+        <div class="MWFScriptIncluder" name="scripts"></div>
+
 
 		<!--<div class="MWFArraylist" name="cssLinks" title="CSS引用"></div>-->
 		<!--<div class="MWFArraylist" name="scriptSrc" title="JS引用"></div>-->
@@ -76,10 +85,6 @@
         <div class="MWFCssArea" name="css" title="CSS"></div>
 		<!--<div class="MWFScriptArea" name="jsheader" title="JS Header"></div>-->
 
-        <div class="MWFScriptArea" name="validationOpinion" title="校验意见 (S)"></div>
-        <div class="MWFScriptArea" name="validationRoute" title="校验路由 (S)"></div>
-        <div class="MWFScriptArea" name="validationFormCustom" title="流转校验 (S)"></div>
-
 	</div>
 	<div title="提交" class="MWFTab">
 
@@ -201,6 +206,11 @@
             <span>(返回一个URL用于重定向)</span>
         </div>
 
+        <div style="height:24px; text-align: center; line-height: 24px; background-color: #EEE; border-top: 1px solid #999; font-weight: bold">校验</div>
+        <div class="MWFScriptArea" name="validationOpinion" title="校验意见 (S)"></div>
+        <div class="MWFScriptArea" name="validationRoute" title="校验路由 (S)"></div>
+        <div class="MWFScriptArea" name="validationFormCustom" title="流转校验 (S)"></div>
+
     </div>
     <div title="操作"  class="MWFTab" style="overflow: hidden; display: text{($.mode=='Mobile')?'block':'none'}">
         <div class="MWFDefaultActionArea" name="defaultTools" data-target="mobileForm"></div>

+ 1 - 1
o2web/source/x_component_process_FormDesigner/Module/View/view.html

@@ -257,7 +257,7 @@
 			<div style="display:none; height: 20px; line-height: 20px; text-align:center; background-color: #eeeeee">自定义过滤数据</div>
 			<div class="fieldListAreaNode_vf" style="display:none; min-height: 56px; border-bottom:1px solid #CCCCCC; overflow: hidden;"></div>
 		</div>
-
+		<div class="MWFScriptArea" name="defaultSelectedScript" title="默认选中行脚本"></div>
 	</div>
 
 	<div title="事件"  class="MWFTab">

+ 1 - 0
o2web/source/x_component_process_FormDesigner/Module/ViewSelector/ViewSelector.html

@@ -107,6 +107,7 @@
         <div id="text{$.pid}selectedScriptArea" style="display: text{($.result=='script')?'block':'none'};">
             <div class="MWFScriptArea" name="selectedScript" title="选择结果 (S)"></div>
         </div>
+        <div class="MWFScriptArea" name="defaultSelectedScript" title="默认选中行脚本"></div>
 	</div>
     <div title="过滤"  class="MWFTab">
         <div class="MWFViewFilter">

+ 54 - 0
o2web/source/x_component_process_FormDesigner/Property.js

@@ -85,6 +85,7 @@ MWF.xApplication.process.FormDesigner.Property = MWF.FCProperty = new Class({
                     this.loadSidebarPosition();
                     this.loadViewFilter();
                     this.loadDocumentTempleteSelect();
+                    this.loadScriptIncluder();
                     //this.testRestful();
 //			this.loadScriptInput();
                     //MWF.process.widget.EventsEditor
@@ -1244,6 +1245,8 @@ debugger;
         var processFileNodes = this.propertyContent.getElements(".MWFProcessImageFileSelect");
         var scriptNodes = this.propertyContent.getElements(".MWFScriptSelect");
         var formStyleNodes = this.propertyContent.getElements(".MWFFormStyleSelect");
+        var dictionaryNodes = this.propertyContent.getElements(".MWFDictionarySelect");
+
 
         MWF.xDesktop.requireApp("process.ProcessDesigner", "widget.PersonSelector", function(){
             personIdentityNodes.each(function(node){
@@ -1403,6 +1406,39 @@ debugger;
                 }
             }.bind(this));
 
+            dictionaryNodes.each(function(node){
+                debugger;
+                var data = this.data[node.get("name")];
+                new MWF.xApplication.process.ProcessDesigner.widget.PersonSelector(node, this.form.designer, {
+                    "type": "Dictionary",
+                    "count": 0,
+                    "names": typeOf(data)==="array" ? data : [data],
+                    "onChange": function(ids){
+                        var data = [];
+                        var name = node.get("name");
+                        if( ids.length > 0 ){
+                            // var d = ids[0].data;
+                            ids.each( function (id) {
+                                var d = id.data;
+                                data.push({
+                                    "type" : "dictionary",
+                                    "name": d.name,
+                                    "alias": d.alias,
+                                    "id": d.id,
+                                    "appName" : d.appName || d.applicationName,
+                                    "appId": d.appId,
+                                    "application": d.application,
+                                    "appType" : d.appType
+                                })
+                            });
+                        }
+                        var oldValue = this.data[name];
+                        this.data[name] = data;
+                        this.changeData(name, node, oldValue);
+                    }.bind(this)
+                });
+            }.bind(this));
+
             fileNodes.each(function(node){
                 var d = this.data[node.get("name")];
                 var data = d || {};
@@ -1446,6 +1482,24 @@ debugger;
 
         }.bind(this));
     },
+    loadScriptIncluder : function(){
+        var nodes = this.propertyContent.getElements(".MWFScriptIncluder");
+        if (nodes.length){
+            nodes.each(function(node){
+                var name = node.get("name");
+                MWF.xDesktop.requireApp("process.FormDesigner", "widget.ScriptIncluder", function(){
+                    var scriptIncluder = new MWF.xApplication.process.FormDesigner.widget.ScriptIncluder(node, this.designer, {
+                        "onChange": function(){
+                            var data = scriptIncluder.getData();
+                            this.data[name] = data;
+                        }.bind(this)
+                    });
+                    scriptIncluder.load(this.data[name])
+                }.bind(this));
+            }.bind(this));
+        }
+
+    },
     saveFileItem: function(node, ids){
         if (ids[0]){
             var file = ids[0].data;

+ 12 - 0
o2web/source/x_component_process_FormDesigner/lp/zh-cn.js

@@ -90,6 +90,18 @@ MWF.xApplication.process.FormDesigner.LP = {
             "selectDefaultTool" : "选择系统操作"
         },
         "isSave": "正在保存,请稍候...",
+        "scriptIncluder" : {
+		    "yes" : "是",
+            "no" : "否",
+		    "selectScript" : "选择脚本:",
+		    "repeatAddScriptNotice" : "请不要重复添加脚本",
+		    "selectScriptNotice" : "请先选择脚本",
+            "asyncLoad" : "异步加载:",
+		    "asyncLoadScript" : "异步加载脚本:",
+            "syncLoadScript" : "同步加载脚本:",
+            "delete_title": "取消加载脚本确认",
+            "delete_text": "您确定要取消加载选择的脚本?"
+        },
         "validation": {
             "validation": "校验",
             "anytime": "任何时候",

+ 150 - 0
o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/css.wcss

@@ -0,0 +1,150 @@
+{
+    "titleNode": {
+        "height": "24px",
+        "background-color": "#eeeeee",
+        "line-height": "24px",
+        "text-align": "center",
+        "border-top": "1px solid #999"
+    },
+    "editorNode": {
+        "border-top": "0px",
+        "overflow": "hidden"
+    },
+    "actionNode":{
+        "height": "30px",
+        "text-align": "center"
+    },
+    "listNode": {
+        "border-top": "1px solid #bbb",
+        "min-height": "60px",
+        "padding-top": "2px",
+        "overflow": "hidden"
+    },
+    "editTableTdValue": {
+        "height": "24px",
+        "line-height": "24px",
+        "border-bottom": "1px dashed #CCC"
+    },
+    "decisionNameInput": {
+        "color": "#666",
+        "width": "90%",
+        "border-top": "1px solid #AAA",
+        "border-left": "1px solid #AAA",
+        "border-bottom": "1px solid #CCC",
+        "border-right": "1px solid #CCC"
+    },
+    "valueInput":{
+        "color": "#666",
+        "width": "90%",
+        "border-top": "1px solid #AAA",
+        "border-left": "1px solid #AAA",
+        "border-bottom": "1px solid #CCC",
+        "border-right": "1px solid #CCC"
+    },
+    "promptInput": {
+        "color": "#666",
+        "width": "90%",
+        "border-top": "1px solid #AAA",
+        "border-left": "1px solid #AAA",
+        "border-bottom": "1px solid #CCC",
+        "border-right": "1px solid #CCC"
+    },
+    "valueSelect": {
+        "color": "#666",
+        "width": "auto",
+        "border-top": "1px solid #AAA",
+        "border-left": "1px solid #AAA",
+        "border-bottom": "1px solid #CCC",
+        "border-right": "1px solid #CCC"
+    },
+    "titleTd": {
+        "width": "60px",
+        "font-weight": "bold",
+        "font-size": "12px",
+        "height": "24px",
+        "line-height": "24px"
+    },
+    "actionAreaNode": {
+        "width": "110px",
+        "height": "22px",
+        "margin": "auto",
+        "margin-top": "4px"
+    },
+    "addAction": {
+        "width": "50px",
+        "height": "20px",
+        "line-height": "20px",
+        "float": "left",
+        "cursor": "pointer",
+        "border-radius": "3px",
+        "border": "1px solid #999",
+        "background-color": "#798795",
+        "color": "#FFF"
+    },
+    "modifyAction": {
+        "width": "50px",
+        "height": "20px",
+        "line-height": "20px",
+        "float": "right",
+        "cursor": "pointer",
+        "border-radius": "3px",
+        "border": "1px solid #999",
+        "background-color": "#798795",
+        "color": "#FFF"
+    },
+    "modifyAction_disabled": {
+        "width": "50px",
+        "height": "20px",
+        "line-height": "20px",
+        "float": "right",
+        "cursor": "pointer",
+        "border-radius": "3px",
+        "border": "1px solid #999",
+        "background-color": "#d1dee9",
+        "color": "#999"
+    },
+    "errorNode": {
+        "height": "24px",
+        "background-color": "#fbe8e8",
+        "color": "#FF0000"
+    },
+    "errorTextNode": {
+        "height": "24px",
+        "line-height": "24px",
+        "background": "url("+"../x_component_process_FormDesigner/widget/$ValidationEditor/default/icon/error.png) no-repeat 5px center",
+        "padding-left": "30px"
+    },
+    "scriptNode" : {
+        "padding-left" : "5px",
+        "padding-top" : "5px"
+    },
+    "itemNode": {
+        "cursor": "pointer",
+        "height": "auto",
+        "margin": "2px 4px",
+        "background-color": "#fff",
+        "border": "1px solid #ddd"
+    },
+    "itemNode_current": {
+        "cursor": "pointer",
+        "height": "auto",
+        "margin": "2px 4px",
+        "background-color": "#eee",
+        "border": "1px solid #bbb"
+    },
+    "itemDeleteNode": {
+        "width": "20px",
+        "height": "24px",
+        "float": "right",
+        "background": "url("+"../x_component_process_FormDesigner/widget/$ValidationEditor/default/icon/delete1.png) no-repeat center center",
+        "cursor": "pointer"
+    },
+    "itemContentNode": {
+        "padding": "5px",
+        "margin-right": "20px",
+        "height": "auto",
+        "overflow": "hidden",
+        "text-overflow": "ellipsis",
+        "white-space": "nowrap"
+    }
+}

BIN
o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/icon/delete1.png


BIN
o2web/source/x_component_process_FormDesigner/widget/$ScriptIncluder/default/icon/error.png


+ 286 - 0
o2web/source/x_component_process_FormDesigner/widget/ScriptIncluder.js

@@ -0,0 +1,286 @@
+MWF.xApplication.process.FormDesigner.widget = MWF.xApplication.process.FormDesigner.widget || {};
+MWF.require("MWF.widget.UUID", null, false);
+MWF.require("MWF.widget.O2Identity", null, false);
+MWF.xApplication.process.FormDesigner.widget.ScriptIncluder = new Class({
+	Implements: [Options, Events],
+	Extends: MWF.widget.Common,
+	options: {
+		"style": "default",
+		"maxObj": document.body
+	},
+	initialize: function(node, designer, options){
+		this.setOptions(options);
+		this.node = $(node);
+        this.designer = designer;
+		
+		this.path = "../x_component_process_FormDesigner/widget/$ScriptIncluder/";
+		this.cssPath = "../x_component_process_FormDesigner/widget/$ScriptIncluder/"+this.options.style+"/css.wcss";
+		this._loadCss();
+		this.lp = this.designer.lp.scriptIncluder;
+		
+		this.items = [];
+	},
+    load: function(data){
+		this.editorNode = new Element("div", {"styles": this.css.editorNode}).inject(this.node);
+        this.actionNode = new Element("div", {"styles": this.css.actionNode}).inject(this.node);
+        this.listNode = new Element("div", {"styles": this.css.listNode}).inject(this.node);
+        this.loadEditorNode();
+        this.loadActionNode();
+        this.loadListNode(data);
+	},
+    loadEditorNode: function(){
+	    debugger;
+        var html = "<table width='100%' border='0' cellpadding='5' cellspacing='0' class='editTable'>" +
+            "<tr><td style='width: 60px; '>"+this.lp.asyncLoad+"</td><td align='left'>"+
+            "<input type='radio' name='"+(this.designer.appId||"")+"asyncLoadScript' value='true' checked/>"+this.lp.yes+
+            "<input type='radio' name='"+(this.designer.appId||"")+"asyncLoadScript' value='false'/>"+this.lp.no+
+            "</td></tr><tr><td>"+this.lp.selectScript+"</td><td><div class='scriptSelectorArea'></div></td></tr></table>";
+        this.editorNode.set("html", html);
+        var tds = this.editorNode.getElements("td").setStyles(this.css.editTableTdValue);
+        this.asyncLoadScript = this.editorNode.getElements("[type='radio']");
+        this.scriptSelectorArea = this.editorNode.getElement(".scriptSelectorArea");
+        this.loadScriptSelector();
+    },
+    loadScriptSelector: function( data ){
+        MWF.xDesktop.requireApp("process.ProcessDesigner", "widget.PersonSelector", function(){
+            var _self = this;
+            if( !data )data = [];
+            this.scriptSelector = new MWF.xApplication.process.ProcessDesigner.widget.PersonSelector(this.scriptSelectorArea, this.designer, {
+                "type": "Script",
+                "count": 0,
+                "names": data,
+                "onChange": function(ids){
+                    var value = [];
+                    ids.each( function (id) {
+                        var d = id.data;
+                        value.push({
+                            "type" : "script",
+                            "name": d.name,
+                            "alias": d.alias,
+                            "id": d.id,
+                            "appName" : d.appName || d.applicationName,
+                            "appId": d.appId || d.application,
+                            "appType" : d.appType
+                        });
+                    })
+                    this.currentSelectScripts = value;
+                }.bind(this)
+            });
+        }.bind(this));
+    },
+    loadActionNode: function(){
+        this.actionAreaNode = new Element("div", {"styles": this.css.actionAreaNode}).inject(this.actionNode);
+        this.addAction = new Element("div", {"styles": this.css.addAction, "text": this.designer.lp.validation.add}).inject(this.actionAreaNode);
+        this.modifyAction = new Element("div", {"styles": this.css.modifyAction_disabled, "text": this.designer.lp.validation.modify}).inject(this.actionAreaNode);
+
+        this.addAction.addEvent("click", function(){
+            this.add();
+        }.bind(this));
+        this.modifyAction.addEvent("click", function(){
+            this.modify();
+        }.bind(this));
+    },
+    getCurrentData: function(){
+	    var async = true;
+        this.asyncLoadScript.each( function (el) {
+            if( el.checked ){
+                async = el.get("value") === "true";
+            }
+        });
+
+        return {
+            "async": async,
+            "scriptList": this.currentSelectScripts || []
+        };
+    },
+    add: function(){
+        this.hideErrorNode();
+        var data = this.getCurrentData();
+
+        if ( data.scriptList.length === 0 ){
+            this.showErrorNode(this.lp.selectScriptNotice);
+            return false;
+        }
+        for( var i=0; i<this.items.length; i++ ){
+            var scriptList = this.items[i].data.scriptList;
+            for( var j=0; j<scriptList.length; j++ ){
+                for( var k=0; k< data.scriptList.length; k++ )
+                if( scriptList[j].id === data.scriptList[i].id ){
+                    this.showErrorNode(this.lp.repeatAddScriptNotice);
+                    return false;
+                }
+            }
+        }
+        var item = new MWF.xApplication.process.FormDesigner.widget.ScriptIncluder.Item(data, this);
+        this.items.push(item);
+        item.selected();
+        this.empty();
+        this.fireEvent("change");
+    },
+    empty: function(){
+        this.asyncLoadScript.each( function (el) {
+            if( el.get("value") === "true" ){
+                el.set("checked", true)
+            }
+        });
+        if(this.scriptSelector)this.scriptSelector.setData( [] );
+        this.currentSelectScripts = [];
+    },
+    showErrorNode: function(text){
+        this.errorNode = new Element("div", {"styles": this.css.errorNode}).inject(this.actionNode, "before");
+        this.errorTextNode = new Element("div", {"styles": this.css.errorTextNode}).inject(this.errorNode);
+        this.errorTextNode.set("text", text);
+        this.errorNode.addEvent("click", function(){this.hideErrorNode();}.bind(this));
+    },
+    hideErrorNode: function(){
+        if (this.errorNode) this.errorNode.destroy();
+    },
+    modify: function(){
+        if (this.currentItem){
+            this.hideErrorNode();
+
+            var data = this.getCurrentData();
+
+            if ( data.scriptList.length === 0 ){
+                this.showErrorNode(this.lp.selectScriptNotice);
+                return false;
+            }
+            for( var i=0; i<this.items.length; i++ ){
+                if( this.currentItem !== this.items[i] ){
+                    var scriptList = this.items[i].data.scriptList;
+                    for( var j=0; j< scriptList.length; j++ ){
+                        for( var k=0; k< data.scriptList.length; k++ )
+                            if( scriptList[j].id === data.scriptList[i].id ){
+                                this.showErrorNode(this.lp.repeatAddScriptNotice);
+                                return false;
+                            }
+                    }
+                }
+            }
+
+            this.currentItem.reload(data);
+            this.currentItem.unSelected();
+            this.disabledModify();
+            this.empty();
+            this.fireEvent("change");
+        }
+    },
+    loadListNode: function(data){
+        if (data){
+            if (data.length){
+                data.each(function(itemData){
+                    var item = new MWF.xApplication.process.FormDesigner.widget.ScriptIncluder.Item(itemData, this);
+                    this.items.push(item);
+                }.bind(this));
+            }
+        }
+    },
+    enabledModify: function(){
+        this.modifyAction.setStyles(this.css.modifyAction);
+    },
+    disabledModify: function(){
+        this.modifyAction.setStyles(this.css.modifyAction_disabled);
+    },
+    setData: function(data){
+        this.asyncLoadScript.each( function (el) {
+            if( el.get("value") === "true" && data.async ){
+                el.set("checked", true)
+            }else if( el.get("value") === "false" && !data.async ){
+                el.set("checked", true)
+            }
+        });
+        if( !this.scriptSelector ){
+            this.loadScriptSelector( data.scriptList );
+        }else{
+            this.scriptSelector.setData( data.scriptList );
+        }
+        this.currentSelectScripts = data.scriptList;
+    },
+
+    deleteItem: function(item){
+        if (this.currentItem == item) item.unSelected();
+        this.items.erase(item);
+        item.node.destroy();
+        MWF.release(item);
+        this.fireEvent("change");
+    },
+    getData: function(){
+        var data = [];
+        this.items.each(function(item){
+            data.push(item.data);
+        });
+        return data;
+    }
+
+});
+MWF.xApplication.process.FormDesigner.widget.ScriptIncluder.Item = new Class({
+    initialize: function(data, editor){
+        this.data = data;
+        this.editor = editor;
+        this.container = this.editor.listNode;
+        this.css = this.editor.css;
+        this.lp = this.editor.designer.lp;
+        this.load();
+    },
+    load: function(){
+        debugger;
+        this.node = new Element("div", {"styles": this.css.itemNode}).inject(this.container);
+        this.deleteNode = new Element("div", {"styles": this.css.itemDeleteNode}).inject(this.node);
+        this.contentNode = new Element("div", {"styles": this.css.itemContentNode}).inject(this.node);
+
+        this.asyncNode = new Element("div", {"styles": {}}).inject(this.contentNode);
+        this.asyncNode.set({
+            "text": this.data.async ? this.lp.scriptIncluder.asyncLoadScript : this.lp.scriptIncluder.syncLoadScript
+        });
+        this.scriptNode = new Element("div", {
+            styles : this.css.scriptNode
+        }).inject(this.contentNode);
+        this.data.scriptList.each( function (scipt) {
+            new MWF.widget.O2Script(scipt, this.scriptNode)
+        }.bind(this));
+
+        this.contentNode.addEvent("click", function(){
+            this.selected();
+        }.bind(this));
+
+        this.deleteNode.addEvent("click", function(e){
+            this.deleteItem(e);
+        }.bind(this));
+    },
+    reload: function(data){
+        this.data = data;
+        this.asyncNode.set({
+            "text": this.data.async ? this.lp.scriptIncluder.asyncLoadScript : this.lp.scriptIncluder.syncLoadScript
+        });
+        this.scriptNode.empty();
+        this.data.scriptList.each( function (scipt) {
+            new MWF.widget.O2Script(scipt, this.scriptNode)
+        }.bind(this));
+    },
+    selected: function(){
+        if (this.editor.currentItem) this.editor.currentItem.unSelected();
+        this.node.setStyles(this.css.itemNode_current);
+        this.editor.currentItem = this;
+        this.editor.setData(this.data);
+        this.editor.enabledModify();
+    },
+    unSelected: function(){
+        this.node.setStyles(this.css.itemNode);
+        this.editor.currentItem = this;
+        //this.editor.modifyValidation();
+        this.editor.disabledModify();
+    },
+    deleteItem: function(e){
+        var _self = this;
+        this.editor.designer.confirm("warn", e, this.lp.scriptIncluder.delete_title, this.lp.scriptIncluder.delete_text, 300, 120, function(){
+            _self.destroy();
+            this.close();
+        }, function(){
+            this.close();
+        });
+    },
+    destroy: function(){
+        this.editor.deleteItem(this);
+    }
+
+});

+ 12 - 4
o2web/source/x_component_process_ProcessDesigner/widget/PersonSelector.js

@@ -37,6 +37,12 @@ MWF.xApplication.process.ProcessDesigner.widget.PersonSelector = new Class({
         this.createAddNode();
         this.loadIdentitys();
     },
+    setData: function( data ){
+        this.node.empty();
+        this.identitys = [];
+        this.options.names = data;
+        this.loadIdentitys();
+    },
     loadIdentitys: function(){
         if (this.options.names){
             if (this.options.type.toLowerCase()==="duty"){
@@ -88,8 +94,9 @@ MWF.xApplication.process.ProcessDesigner.widget.PersonSelector = new Class({
                             if (this.options.type.toLowerCase()==="portalfile") this.identitys.push(new MWF.widget.O2File(data, this.node));
                             if (this.options.type.toLowerCase()==="processfile") this.identitys.push(new MWF.widget.O2File(data, this.node));
 
-                            if (this.options.type.toLowerCase()==="script") this.identitys.push(new MWF.widget.O2Other(data, this.node));
-                            if (this.options.type.toLowerCase()==="formstyle") this.identitys.push(new MWF.widget.O2Other(data, this.node));
+                            if (this.options.type.toLowerCase()==="dictionary") this.identitys.push(new MWF.widget.O2Dictionary(data, this.node));
+                            if (this.options.type.toLowerCase()==="script") this.identitys.push(new MWF.widget.O2Script(data, this.node));
+                            if (this.options.type.toLowerCase()==="formstyle") this.identitys.push(new MWF.widget.O2FormStyle(data, this.node));
                         }.bind(this));
                     }
                 }.bind(this));
@@ -154,8 +161,9 @@ MWF.xApplication.process.ProcessDesigner.widget.PersonSelector = new Class({
                             if (this.options.type.toLowerCase()==="portalfile") this.identitys.push(new MWF.widget.O2File(item.data, this.node));
                             if (this.options.type.toLowerCase()==="processfile") this.identitys.push(new MWF.widget.O2File(item.data, this.node));
 
-                            if (this.options.type.toLowerCase()==="script") this.identitys.push(new MWF.widget.O2Other(item.data, this.node));
-                            if (this.options.type.toLowerCase()==="formstyle") this.identitys.push(new MWF.widget.O2Other(item.data, this.node));
+                            if (this.options.type.toLowerCase()==="dictionary") this.identitys.push(new MWF.widget.O2Dictionary(item.data, this.node));
+                            if (this.options.type.toLowerCase()==="script") this.identitys.push(new MWF.widget.O2Script(item.data, this.node));
+                            if (this.options.type.toLowerCase()==="formstyle") this.identitys.push(new MWF.widget.O2FormStyle(item.data, this.node));
                         }.bind(this));
                         if (this.options.type.toLowerCase()==="duty") {
                             items.each(function(item){

+ 1 - 1
o2web/source/x_component_process_Xform/Attachment.js

@@ -495,7 +495,7 @@ MWF.xApplication.process.Xform.AttachmentController = new Class({
 
         if (!att.data.person && att.data.creatorUid) att.data.person = att.data.creatorUid;
 
-        if ((!att.data.control.allowControl) && att.data.person !== user) { //|| !att.data.control.allowEdit
+        if (!att.data.control.allowControl && att.data.person !== user) {
             flag = false;
         }
         return flag;

+ 88 - 7
o2web/source/x_component_process_Xform/Form.js

@@ -215,17 +215,98 @@ MWF.xApplication.process.Xform.Form = MWF.APPForm = new Class({
 
                 this._loadEvents();
 
-                this.fireEvent("queryLoad");
-                if (this.event_resolve){
-                    this.event_resolve(function(){
+                this.loadResource( function () {
+                    this.fireEvent("queryLoad");
+                    if (this.event_resolve){
+                        this.event_resolve(function(){
+                            this.loadForm(callback)
+                        }.bind(this));
+                    }else{
                         this.loadForm(callback);
-                    }.bind(this));
-                }else{
-                    this.loadForm(callback);
-                }
+                    }
+                }.bind(this));
+
             }.bind(this));
         }.bind(this));
     },
+    loadResource : function( callback ){
+        var cb = function () {
+            if( this.syncScriptLoaded && this.asyncScriptLoaded && this.dictionaryLoaded ){
+                if(callback)callback();
+            }
+        }.bind(this);
+        this.loadScriptList( cb );
+        this.loadDictionaryList( cb );
+    },
+    loadDictionaryList: function( callback ){
+        this.dictionaryLoaded = false;
+        var loadedCount = 0;
+        if( this.json.dictionaries && this.json.dictionaries.length ){
+            this.json.dictionaries.map(function (d) {
+                d.type = d.appType;
+                d.application = d.application || d.appId || d.appName;
+                new this.Macro.environment.Dict( d ).get( "", function(){
+                    loadedCount++;
+                    if (this.json.dictionaries.length <= loadedCount){
+                        this.dictionaryLoaded = true;
+                        if(callback)callback();
+                    }
+                }.bind(this), null, true);
+            }.bind(this));
+        }else{
+            this.dictionaryLoaded = true;
+            if(callback)callback();
+        }
+    },
+    loadScriptList : function( callback ){
+        var asyncList = [];
+        var syncList = [];
+
+        this.syncScriptLoaded = false;
+        this.asyncScriptLoaded = false;
+
+        if( this.json.scripts && this.json.scripts.length ){
+            for( var i=0; i<this.json.scripts.length; i++ ){
+                var script = this.json.scripts[i];
+                script.scriptList.map( function ( s ) {
+                    s.type = s.appType;
+                    s.application = s.application || s.appId || s.appName;
+                });
+                if( script.async ){
+                    asyncList = asyncList.concat( script.scriptList );
+                }else{
+                    syncList = syncList.concat( script.scriptList );
+                }
+            }
+        }
+
+        var loadSyncList = function () {
+            if( syncList.length === 0 ){
+                this.syncScriptLoaded = true;
+                if(callback)callback();
+            }else{
+                this.Macro.environment.include(syncList, function(){
+                    this.syncScriptLoaded = true;
+                    if(callback)callback();
+                }.bind(this), false);
+            }
+        }.bind(this);
+
+        var loadAsyncList = function () {
+            if( asyncList.length === 0 ){
+                this.asyncScriptLoaded = true;
+                if(callback)callback();
+            }else{
+                this.Macro.environment.include(asyncList, function(){
+                    this.asyncScriptLoaded = true;
+                    if(callback)callback();
+                }.bind(this), true);
+            }
+        }.bind(this);
+
+        loadAsyncList();
+        loadSyncList();
+    },
     loadForm: function(callback){
         if (this.lockDataPerson){
             var text = MWF.xApplication.process.Xform.LP.keyLockInfor;

+ 4 - 1
o2web/source/x_component_process_Xform/View.js

@@ -50,6 +50,8 @@ MWF.xApplication.process.Xform.View = MWF.APPView =  new Class({
             }.bind(this));
         }
 
+        debugger;
+
         //var data = JSON.parse(this.json.data);
         var viewJson = {
             "application": (this.json.queryView) ? this.json.queryView.appName : this.json.application,
@@ -60,7 +62,8 @@ MWF.xApplication.process.Xform.View = MWF.APPView =  new Class({
             "itemStyles": this.json.itemStyles,
             "isExpand": this.json.isExpand || "no",
             "showActionbar" : this.json.actionbar === "show",
-            "filter": filter
+            "filter": filter,
+            "defaultSelectedScript" : this.json.defaultSelectedScript ? this.json.defaultSelectedScript.code : null
         };
 
         //MWF.xDesktop.requireApp("query.Query", "Viewer", function(){

+ 2 - 1
o2web/source/x_component_process_Xform/ViewSelector.js

@@ -283,7 +283,8 @@ MWF.xApplication.process.Xform.ViewSelector = MWF.APPViewSelector =  new Class({
                 "itemStyles": this.json.itemStyles,
                 "isExpand": this.json.isExpand || "no",
                 "showActionbar" : this.json.actionbar === "show",
-                "filter": filter
+                "filter": filter,
+                "defaultSelectedScript" : this.json.defaultSelectedScript ? this.json.defaultSelectedScript.code : null
             };
             var options = {};
             var width = options.width || "850";

+ 32 - 9
o2web/source/x_component_query_Query/Viewer.js

@@ -191,7 +191,7 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
             this.createExportNode();
         }
     },
-    createViewNode: function(data){
+    createViewNode: function(data, callback){
         this.viewAreaNode.empty();
 
         this.selectedItems = [];
@@ -268,20 +268,20 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
 
                 if (column.allowOpen) this.openColumns.push(column.column);
             }.bind(this));
-            this.lookup(data);
+            this.lookup(data, callback);
         }else{
             this.viewJson.selectList.each(function(column){
                 if (column.hideColumn) this.hideColumns.push(column.column);
                 if (!column.allowOpen) this.openColumns.push(column.column);
             }.bind(this));
-            this.lookup(data);
+            this.lookup(data, callback);
         }
     },
     isSelectTdHidden :function(){
         if( !this.viewJson.firstTdHidden ){
             return false;
         }
-        if( this.json.select === "single" || this.json.select === "multi"  ){
+        if( this.json.select === "single" || this.json.select === "multi" || this.json.defaultSelectedScript || this.viewJson.defaultSelectedScript ){
             return false;
         }
         if( this.viewJson.select === "single" || this.viewJson.select === "multi"  ){
@@ -391,7 +391,7 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
         this.currentPage = this.options.defaultPage || 1;
         this.options.defaultPage = null;
     },
-    lookup: function(data){
+    lookup: function(data, callback){
         this.getLookupAction(function(){
             if (this.json.application){
 
@@ -405,6 +405,7 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
                         if( this.noDataTextNode )this.noDataTextNode.destroy();
                         this.loadCurrentPageData( function () {
                             this.fireEvent("postLoad"); //用户配置的事件
+                            if(callback)callback(this);
                         }.bind(this));
                     }else{
                         //this._loadPageNode();
@@ -424,6 +425,7 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
                             this.loadingAreaNode = null;
                         }
                         this.fireEvent("postLoad"); //用户配置的事件
+                        if(callback)callback(this);
                     }
                 }.bind(this));
             }
@@ -1246,12 +1248,12 @@ MWF.xApplication.query.Query.Viewer = MWF.QViewer = new Class({
             })
         }
     },
-    setFilter : function( filter ){
+    setFilter : function( filter, callback ){
         if( !filter )filter = [];
         if( typeOf( filter ) === "object" )filter = [ filter ];
         this.json.filter = filter;
         if( this.viewAreaNode ){
-            this.createViewNode({"filterList": this.json.filter  ? this.json.filter.clone() : null});
+            this.createViewNode({"filterList": this.json.filter  ? this.json.filter.clone() : null}, callback);
         }
     },
     switchView : function( json ){
@@ -1381,6 +1383,27 @@ MWF.xApplication.query.Query.Viewer.Item = new Class({
             //}
         }.bind(this));
 
+        //默认选中
+        var defaultSelectedScript = this.view.json.defaultSelectedScript || this.view.viewJson.defaultSelectedScript;
+        if( !this.isSelected && defaultSelectedScript ){
+            // var flag = this.view.json.select || this.view.viewJson.select ||  "none";
+            // if ( flag ==="single" || flag==="multi"){
+            //
+            // }
+            var flag = this.view.Macro.exec( defaultSelectedScript,
+                {"node" : this.node, "data" : this.data, "view": this.view, "row" : this});
+            if( flag ){
+                if( flag === "multi" || flag === "single" ){
+                    this.select( flag );
+                }else if( flag.toString() === "true" ){
+                    var f = this.view.json.select || this.view.viewJson.select ||  "none";
+                    if ( f ==="single" || f==="multi"){
+                        this.select();
+                    }
+                }
+            }
+        }
+
         // Object.each(this.data.data, function(cell, k){
         //     if (this.view.hideColumns.indexOf(k)===-1){
         //         var td = new Element("td", {"styles": this.css.viewContentTdNode}).inject(this.node);
@@ -1587,8 +1610,8 @@ MWF.xApplication.query.Query.Viewer.Item = new Class({
         }
     },
 
-    select: function(){
-        var flag = this.view.json.select || this.view.viewJson.select ||  "none";
+    select: function(  force ){
+        var flag = force || this.view.json.select || this.view.viewJson.select ||  "none";
         if (this.isSelected){
             if (flag==="single"){
                 this.unSelectedSingle();

+ 2 - 0
o2web/source/x_component_query_ViewDesigner/$View/view.html

@@ -117,6 +117,8 @@
             <!--</tr>-->
         </table>
 
+        <div class="MWFFormulaArea" name="data.defaultSelectedScript" title="默认选中行脚本"></div>
+
 
 
         <!--<div class="MWFApplicationSelect" title="选择应用"></div>-->

+ 18 - 2
o2web/source/x_component_query_ViewDesigner/Property.js

@@ -362,7 +362,14 @@ MWF.xApplication.query.ViewDesigner.Property = MWF.FVProperty = new Class({
         scriptAreas.each(function (node) {
             var title = node.get("title");
             var name = node.get("name");
-            var scriptContent = this.data[name];
+            var names = name.split(".");
+
+            var scriptContent = this.data;
+            Array.each(names, function (n) {
+                if (scriptContent) scriptContent = scriptContent[n];
+            });
+
+            // var scriptContent = this.data[name];
 
             MWF.require("MWF.widget.ScriptArea", function () {
                 var scriptArea = new MWF.widget.ScriptArea(node, {
@@ -370,7 +377,16 @@ MWF.xApplication.query.ViewDesigner.Property = MWF.FVProperty = new Class({
                     //"maxObj": this.propertyNode.parentElement.parentElement.parentElement,
                     "maxObj": this.designer.editContentNode,
                     "onChange": function () {
-                        this.data[name] = scriptArea.toJson().code;
+
+                        var scriptObj = this.data;
+                        Array.each(names, function (n, idx) {
+                            if( idx === names.length -1 )return;
+                            if (scriptObj) scriptObj = scriptObj[n];
+                        });
+
+                        scriptObj[names[names.length -1]] = scriptArea.toJson().code;
+
+                        // this.data[name] = scriptArea.toJson().code;
                     }.bind(this),
                     "onSave": function () {
                         this.designer.saveView();